Using Flash memory on the STM32F103

Some microcontrollers have a dedicated Non-Volatile-Memory (NVM) bank for storing calibration data, program settings and so on. The STM32F103C8T6 does not have NVM like this but it’s Flash program memory can be used with care for the same purpose. The Flash memory in this chip is divided into 1kiB sectors and there are 64 if them (0 to 63). The code to erase, write and read a sector is shown below:

int  writeSector(uint32_t Address,void * values, uint16_t size)
{              
    uint16_t *AddressPtr;
    uint16_t *valuePtr;
    AddressPtr = (uint16_t *)Address;
    valuePtr=(uint16_t *)values;
    size = size / 2;  // incoming value is expressed in bytes, not 16 bit words
    while(size) {        
        // unlock the flash 
        // Key 1 : 0x45670123
        // Key 2 : 0xCDEF89AB
        FLASH->KEYR = 0x45670123;
        FLASH->KEYR = 0xCDEF89AB;
        FLASH->CR &= ~BIT1; // ensure PER is low
        FLASH->CR |= BIT0;  // set the PG bit        
        *(AddressPtr) = *(valuePtr);
        while(FLASH->SR & BIT0); // wait while busy
        if (FLASH->SR & BIT2)
            return -1; // flash not erased to begin with
        if (FLASH->SR & BIT4)
            return -2; // write protect error
        AddressPtr++;
        valuePtr++;
        size--;
    }    
    return 0;    
}
void eraseSector(uint32_t SectorStartAddress)
{
    FLASH->KEYR = 0x45670123;
    FLASH->KEYR = 0xCDEF89AB;
    FLASH->CR &= ~BIT0;  // Ensure PG bit is low
    FLASH->CR |= BIT1; // set the PER bit
    FLASH->AR = SectorStartAddress;
    FLASH->CR |= BIT6; // set the start bit 
    while(FLASH->SR & BIT0); // wait while busy
}
void readSector(uint32_t SectorStartAddress, void * values, uint16_t size)
{
    uint16_t *AddressPtr;
    uint16_t *valuePtr;
    AddressPtr = (uint16_t *)SectorStartAddress;
    valuePtr=(uint16_t *)values;
    size = size/2; // incoming value is expressed in bytes, not 16 bit words
    while(size)
    {
        *((uint16_t *)valuePtr)=*((uint16_t *)AddressPtr);
        valuePtr++;
        AddressPtr++;
        size--;
    }
}

Writes and reads must be performed in 16 bit (half word) chunks so a little bit of type casting is necessary. The data type for the values to be read or written is void *. This allows a pointer to any type be passed without generating warnings. The sector start address must be on a 1k boundary. In this chip, Flash memory starts at 0x8000000 so sector start addresses can be 0x8000000, 0x8000400, 0x8000800, 0x8000c00, etc.
The data sheet states that the flash can withstand at least 10000 write cycles (does this include erases?). This seems like a pretty large amount but you would be surprised how quickly it can get used up. If your program requires to write to Flash memory regularly consider some wear leveling scheme.
Full code is available over here on GitHub

2 thoughts on “Using Flash memory on the STM32F103

  1. Daniel May 23, 2018 / 10:59 pm

    Usually it’s not called “write cycle” but P/E cycle (program/erase). And while only whole blocks of flash can be erased (which are rather small for NOR flash and vastly bigger for NAND flash) you can actually write them as you go and piecemeal wise. After erasing all bits of the erased block will be logical 1 and you can individually set them to 0 by writing to them (the other way around will require an erase again). There’re a few typical way how to use flash best without constantly having to erase it, e.g. you can cancel out previous data by overwriting it with 0s to let the system know to look further behind. Or you can subdivide the block and store a used bitmap at the beginning/end of the block cancelling out bits to indicates which is the last written/next free piece. Or you can use a special marker and scan for the latest version/next free space…

    Like

    • fduignan May 24, 2018 / 6:39 am

      Thanks for the clarification and suggestions Daniel

      Like

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 )

Google+ photo

You are commenting using your Google+ 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 )

w

Connecting to %s