HAL drivers erase/read/write flash on STM32F4 nucleo

0
uint32_t PAGEError = 0;
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase   = FLASH_TYPEERASE_SECTORS ;
EraseInitStruct.Sector   = FLASH_SECTOR_0;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08000000, counter)
HAL_FLASH_Lock();

counter2 = *(__IO uint32_t *)0x08000000;
counter3 = *(__IO uint32_t *)0x08000001;
counter4 = *(__IO uint32_t *)0x08000002;

sprintf(buf, "%d", counter2); //gets send to the OLED with I2C
sprintf(buf2, "%d", counter3);
sprintf(buf3, "%d", counter4);

I want to write the variable counter to the flash and then read it as counter2. The first flash sector starts at 0x08000000.

counter2, 3 and 4 are display trough an OLED screen. Displaying counter2 works and shows me the value of counter-1, but it works only once. If I write again to the flash nothing seems to happen.

counter3 and counter4 don't work at all.

Output on the OLED when counter=0x00000008 after I have erased the flash but not written anything:

counter2: 536873624
counter3: -652214262
counter4: 31006720

And after writting and ressetting:

counter2: 8
counter3: -654311424
counter4: 30998528

What is going on here? Can someone tell me why all variables change? Do I have to configure the linker?

c
stm32f4
asked on Stack Overflow Aug 8, 2017 by Alex M. • edited Aug 3, 2019 by glts

3 Answers

8

I will treat you now as begineer, but will say sorry if you are not.

STM32 devices have flash on 0x08000000 and by erasing this sector, you did failure on startup because you erased actual part from where CPU loads instructions.

When you tried to erase sectors, you did not specify how many sectors to erase.

Reading of counters is wrong. Since you have uint32_t variable, you have to do 4-bytes between readings, something like:

counter2 = *(__IO uint32_t *)0x08000000;
counter3 = *(__IO uint32_t *)0x08000004;
counter4 = *(__IO uint32_t *)0x08000008;

Correct erasing is shown below.

EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_0; //Specify sector number
EraseInitStruct.NbSectors = 1; //This is also important!
if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
    //Erase error!
}

So, find out how long is your program and do your operations in sector after your program.

You can find example for EraseProgram in STM32CubeF4 package.

STM32Cube_FW_F4_V1.16.0\Projects\STM324x9I_EVAL\Examples\FLASH\FLASH_EraseProgram\Src\main.c

Concept will work also on your nucleo, just make sure you set correct address for flash erasing.

answered on Stack Overflow Aug 8, 2017 by tilz0R • edited Aug 8, 2017 by tilz0R
0

Thanks to @phoenix!

In Stm32CubF3 reference erasing flash works as follows:

There is to mention how a memory page address is looking:

/* Base address of the Flash sectors */
#define ADDR_FLASH_PAGE_0   ((uint32_t)0x08000000) /* Base @ of Page 0, 2 Kbytes */
#define ADDR_FLASH_PAGE_1   ((uint32_t)0x08000800) /* Base @ of Page 1, 2 Kbytes */
#define ADDR_FLASH_PAGE_2   ((uint32_t)0x08001000) /* Base @ of Page 2, 2 Kbytes */
#define ADDR_FLASH_PAGE_3   ((uint32_t)0x08001800) /* Base @ of Page 3, 2 Kbytes */
#define ADDR_FLASH_PAGE_4   ((uint32_t)0x08002000) /* Base @ of Page 4, 2 Kbytes */
#define ADDR_FLASH_PAGE_5   ((uint32_t)0x08002800) /* Base @ of Page 5, 2 Kbytes */
#define ADDR_FLASH_PAGE_6   ((uint32_t)0x08003000) /* Base @ of Page 6, 2 Kbytes */

So your minimal code looks as follows:

I want to delete my application @ 0x08003000 --> FLASH_PAGE_6. The erasing is done 2kB wise:

/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS  ((uint32_t)ADDR_FLASH_PAGE_32) /* EEPROM emulation start address */

/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
//#define PAGE0_ID               ADDR_FLASH_PAGE_32


/* Clear flash flags */
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP    |
                       FLASH_FLAG_WRPERR |
                       FLASH_FLAG_PGERR);


uint32_t *flash_ptr = 0x8003000;
uint32_t page_error = 0;

HAL_StatusTypeDef  flashstatus;
FLASH_EraseInitTypeDef s_eraseinit;
/* Fill EraseInit structure*/
s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
s_eraseinit.NbPages     = 1;             // seems to be 1 !!!!

/* I want to delete 54kB in my flash --> 52kB / 2kB (per erase) = 26 iterations
   After erasing one page, increment page by 0x800 = 2048 byte = 2kB = pagesize */
for(int pageCount = 0;  pageCount < 26; pageCount++){
   s_eraseinit.PageAddress = ADDR_FLASH_PAGE_6 + pageCount * 0x800;
   flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);

}
answered on Stack Overflow Jun 5, 2019 by 0x4C70F • edited Jun 5, 2019 by 0x4C70F
-1
  1. The best way is to create the new segment of flash in the linkescriptr and place the data there. It is the safest.

  2. If do not know linker scripts create a table of the one segment size, and place it at the end of the flash using your compiler directives.

  3. If you do not know both I suggest a ready made STM eeprom emulation example from the Cube

answered on Stack Overflow Aug 8, 2017 by 0___________

User contributions licensed under CC BY-SA 3.0