First real blog post!
Over the summer I was having a dreadful time using the runtime flash controller on a stm32 (stm32f042) board that I had made. I was finally able to make it work, so I will post my result here, hopefully it will help someone.
Here is the process (accessing registers directly) this was mostly pulled directly from the reference manual, but I thought their instructions were a little vague.
1). Unlock flash
Unlock the flash memory for write and erase operations. Nothing unexpected.
//keys as described in the data-sheets
#define FLASH_FKEY1 0x45670123
#define FLASH_FKEY2 0xCDEF89AB
// Wait for the flash memory not to be busy
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
// Check if the controller is unlocked already
if ((FLASH->CR & FLASH_CR_LOCK) != 0 ){
// Write the first key
FLASH->KEYR = FLASH_FKEY1;
// Write the second key
FLASH->KEYR = FLASH_FKEY2;
}
2). Erase flash
This does not erase the flash to 0x0000. Instead the memory location goes to 0xffff. I think when writing to flash, only zeros are actually added, so when the memory goes to 0x0000 no more operations are possible. Also no less than a page of flash (1k on the stm32f04x) can be erased at a time.
Code for flash erase on the stm32f04x
FLASH->CR |= FLASH_CR_PER; // Page erase operation
FLASH->AR = page_addr; // Set the address to the page to be written
FLASH->CR |= FLASH_CR_STRT;// Start the page erase
// Wait until page erase is done
while ((FLASH->SR & FLASH_SR_BSY) != 0);
// If the end of operation bit is set...
if ((FLASH->SR & FLASH_SR_EOP) != 0){
// Clear it, the operation was successful
FLASH->SR |= FLASH_SR_EOP;
}
//Otherwise there was an error
else{
// Manage the error cases
}
// Get out of page erase mode
FLASH->CR &= ~FLASH_CR_PER;
3). Write flash
This does as one would expect, writing the flash to the value given to it.
FLASH->CR |= FLASH_CR_PG; // Programing mode
*(__IO uint16_t*)(flash_addr) = data; // Write data
// Wait until the end of the operation
while ((FLASH->SR & FLASH_SR_BSY) != 0);
// If the end of operation bit is set...
if ((FLASH->SR & FLASH_SR_EOP) != 0){
// Clear it, the operation was successful
FLASH->SR |= FLASH_SR_EOP;
}
//Otherwise there was an error
else{
// Manage the error cases
}
FLASH->CR &= ~FLASH_CR_PG;
4). Lock flash
Really easy, just set one bit.
FLASH->CR |= FLASH_CR_LOCK
Thanks a lot, It’s a really clear tutorial. I’ve been looking at this issue for a while as well but with your tutorial it’s been a breeze
LikeLike
Thanks, works on L4
LikeLike