Writing to STM32 flash

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.

#define FLASH_FKEY1 //keys as described in the data-sheets
#define FLASH_FKEY2
// 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; /* (6) */

4). Lock flash

Really easy, just set one bit.

FLASH->CR |= FLASH_CR_LOCK
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s