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
I plan to post several articles about calibrating strategies for the next couple of weeks since all regional competitions are approaching.
Can you try unofficial Maple library for EEPROM emulation? There’s the link: http://akb77.com/g/files/media/EEPROM.0.12.rar
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.
I used to save the FLASH the EPS Debugger for Code::Blocks 12.11 download here http://www.comsytec.eu/epsdebugger.php
thank you so much.
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
}
Did you ever get this writing to flash working?
Thanks you for your good explanation and your simple code.
Best wishes
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.
what is mSIze and maza Wall??
16 in this case.
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
I don’t know what’s going on on the 33th and 44th line of your main.c according to the compiler.
Hello, very useful article, but can you show the full code? I’m not able to find the flash.h library, where can i get it from?
maybe it is called eeprom.h instead of flash.h