How to use FLASH in STM32 to save explored maze instead of using EEPROM

As we all know, STM32 doesn’t build in EEPROM in the package. When I was designing my current mouse, I added a external I2C interface EEPROM to save explored maze to prevent crash. Unfortunately, the EEPROM library from ST is too complected for me to use, so I have to give up on using external EEPROM that my mouse had.

Instead, I heard from the other contestants at APEC 2013 that we can use internal flash to emulate EEPROM to store explored maze to prevent crash. I looked over several tutorial online, and the documentary from ST as well, about how the emulated EEPROM in STM32 works. Turned out that I realized the whole process is not efficient at all. Because the library ST provided wasn’t like write every thing straightly in sequence, instead, they use several pages in FLASH and use them alternatively. Though the emulating process is simpler than the I2C eeprom library that ST provided, but I want it be even simpler.

Since the data I would like to store to flash in just a 16 by 16 two-dimension-array, and the overall size is smaller than a single page that the flash has in STM32, I decided to directly manipulate FLASH instead emulate EEPROM by using flash.

There is something we must know for the Flash on STM32. The flash starts from address 0x8040000, and separated to several pages. The size for each page depends on the density. The low and medium density version is1KB per page, and the high density is 2KB per page. every time the you write data to FLSAH, you need to erase everything on the page that you are going to use, even if you only use just one byte on it. But for reading, it acts just as normal as other process in your program.

you can only write as 16 bit data type otherwise it will cause error.

At the end everything is quite easy for me, and most importantly, the code is very compact.

//note that the starting address for flash is 0x8000000 for F103 and F4

//you need to include flash.h in ST library

//what I did here is write a 16 by 16 2D array to FLASH starting at address 0x8040000(256KB, in the middle of FLASH since my STM32 has 512K FLASH) and then read it back to memory afterwards.

//notice you will lose the data in flash if you erase all flash when you download new code from computer

uint32_t startAddress = 0x8040000;//starting from 256KB
                                  //0x8020000 starting 128KB
void writeFlash(void)
{
    u32 i, j;
    FLASH_Unlock();//unlock flash writing
       FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
    FLASH_ErasePage(startAddress);//erase the entire page before you can write as I //mentioned
    
    for(i=0; i<mSize; i++)
        for(j=0; j<mSize; j++)              
            FLASH_ProgramHalfWord((startAddress + (i*mSize+j)*2),mazeWalls[i][j]);

    FLASH_Lock();//lock the flash for writing

}

void readFlash(void)
{
    u32 i, j;    
    for(i=0; i<mSize; i++)
        for(j=0; j<mSize; j++)       
            mazeWalls[i][j] = *(uint16_t *)(startAddress + (i*mSize+j)*2);
}

I tested the time consumption for each precess for my code. The writing process took little bit long, at about 15ms by writing 16×16 elements with 16 bit unsigned integer(512Bytes). The reading was significantly faster since we just simply access the data in flash like other programs do, and the whole process for reading is just 59us by read and copy all 256 elements of 16 bit unsigned integer.

Since we usually do data store and recover when mouse is stopped, 15ms wasn’t even a noticeable time for us. Besides, 15ms is faster than the time spent of emulating EEPROM. I didn’t have chance to test the time for emulating EEPROM, but as what I’ve heard from students at Lunghwa University of Science and Technology, the emulating process takes about 200ms to finish. I wasn’t sure how much data that he wrote but still, theoretically, acess FLASH directly should be faster than emulating EEPROM in this case.

here is the official document about how emulating the EEPROM on STM32 works

STM32 EEPROM

I plan to post several articles about calibrating strategies for the next couple of weeks since all regional competitions are approaching.

13 thoughts on “How to use FLASH in STM32 to save explored maze instead of using EEPROM

    • I read the file, I think it’s same code from ST to emulate EEPROM, or at least same style/name for functions. I think you can just easily use my code above by including flash_stm32.h in EEPROM.0.12.rar.

  1. I have a problem with writing to and reading from the user configured section of flash memory through hall_stm32f4xx library. After I wrote a value to the starting address of the user configured memory , I read it null or (not saved after programming).

    This is the code

    void writeFlash(void)
    {
    HAL_StatusTypeDef status;
    status = HAL_FLASH_Unlock();
    status = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, (uint32_t) userConfig,
    status = HAL_FLASH_Lock();
    }

    void readFlash(void)
    {
    tempvalue = *(uint8_t *)(userConfig);

    }

    and this is the part of the linker for the user configured flash
    MEMORY
    {
    RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
    CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
    FLASH1 (rx) : ORIGIN = 0x08000000, LENGTH = 32k
    DATA (xrw) : ORIGIN = 0x08008000, LENGTH = 32k
    FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 512K-64k
    FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
    EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
    EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
    EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
    EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
    MEMORY_ARRAY (xrw) : ORIGIN = 0x20002000, LENGTH = 32
    }

    SECTIONS
    {
    /////// > FLASH
    /////// > FLASH1
    .user_data :
    {
    . = ALIGN(4);
    *(.user_data)
    . = ALIGN(4);
    } > DATA
    /////// > MEMORY_ARRAY
    /////// > RAM
    }

  2. help me! i need some advices.
    i have a problem with Erase flash function, i’m using st – library.
    sometime, error happen when i call FLASH_ErasePage(Addr);
    when error happen, my chip does not work about 1 minute then it working again.
    I don’t understand why? is any interrupt break Erase flash function.

    Sorry if I rack someone’s eyes because of my terrible english.

    program size: 30, 36 kbyte
    Here is write flash function:

    #define ADDR 0x08010000
    uint16_t mydata = 345;
    void WriteFlash(void)
    {
    FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
    FLASH_ErasePage(ADDR); // sometime program stop working here
    FLASH_ProgramHalfWord(ADDR, mydata);
    }

    • did you try my code? you code looks different.
      did you use code on stm32F1? if the problem is still unsolved, read the comments in the st library file can be helpful especially when you are using specific function of register/flag.

  3. Hi I am using stm32f103 plz tell me the mistake

    uint32_t startAddress = 0x8000000;//starting from 256KB
    //0x8020000 starting 128KB
    void writeFlash(void)
    {
    u32 i, j;
    FLASH_Unlock();//unlock flash writing
    FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
    FLASH_ErasePage(0x8000000);//erase the entire page before you can write as I //mentioned

    for(i=0; i<16; i++)
    for(j=0; j<16; j++)
    FLASH_ProgramHalfWord((0x8000000 + (i*16+j)*2),16[i][j]);
    FLASH_Lock();//lock the flash for writing

    }

    void readFlash(void)
    {
    u32 i, j;
    for(i=0; i<16; i++)
    for(j=0; j<16; j++)
    16[i][j] = *(uint16_t *)(0x8000000 + (i*16+j)*2);
    }

    ERROR:
    Build target 'STM32F103C8'
    compiling main.c…
    main.c(33): error: #142: expression must have pointer-to-object type
    main.c(44): error: #142: expression must have pointer-to-object type
    main.c(322): warning: #940-D: missing return statement at end of non-void function "fputc"
    Target not created

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.