cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 Flash Memory Corruption During Read/Write

AAgar.2
Associate III

I have a custom bootloader in my application. This bootloader write some data in one of the sectors in the STM32H7, lets call this data "bootloader flash data".

This bootloader flash data is written to/read from multiple times during DFU, and to get into bootloader mode, etc.

Whenever the bootloader flash data is updated, I first erase the entire sector. Then I program my data.

I am noticing after 1-3 flash writes the sector containing the bootloader flash data corrupts and the memory goes to 0. All of the HAL functions HAL_FLASH_Unlock, HAL_FLASH_Program, HAL_FLASH_Lock return HAL_OK.

The general sequence by which I update the bootloader is the following

1) taskENTER_CRITICAL

2) Erase bootloader

3) taskEXIT_CRITICAL

4) taskENTER_CRITICAL

5) HAL_FLASH_Unlock

6) HAL_FLASH__Program...

7) HAL_FLASH_Lock

8) taskEXIT_CRITICAL

9) Verify data by reading

Note that I am using FreeRTOS in the bootloader. When ever I am writing to flash I disable interrupts using taskENTER_CRITICAL and taskEXIT_CRITICAL.

a) What could be the reason why the sector containing the bootloader flash data corrupts? (My guess is that flash is locked and unlocked too many times?)

b) How can I debug this?

c) The micro needs to store data even after power off. As such Backup RTC/RAM is not possible. Will write data to flash every ~10 days.

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

Don't post the same multiple times!

Those functions will cause hard fault when D-cache is disabled. Also you should know that 1 KB has 1024 bytes, not 1000. One or multiple subsequent sectors is your choice - the SCB_***() functions work on memory blocks from CPU perspective and don't know/care where those addresses are located and what do they represent to you.

> Do you disable DCache as below?

Read carefully once more: "or don't turn on D-cache"! In a hardware by default it's disabled. If you are using CubeMX bloatware generation, then look for an option under System Core => Cortex-M7.

View solution in original post

12 REPLIES 12
Piranha
Chief II

Probably D-cache related problems. Try to read the same memory after reboot or don't turn on D-cache at all. By default FLASH is configured in write-through mode. Programming works as is, but after erase SCB_InvalidateDCache_by_Addr() must be called. ST's brainless code monkeys who are making their "high level" bloatware library (HAL) will not understand it in this century...

Pavel A.
Evangelist III

I'm seeing a similar issue with STM32H743. Examples in the Cube package work fine when writing to a sector far enough from the running program.

For example when writing in another bank.

Then I wrote to adjacent sector (the program in sector 1 erases & writes to sector 2 in the same bank)

and got compare errors.

Tried few combinations of SCB_InvalidateDCache_by_Addr, disabling D and I caches around write.... nothing of that helped,

so ended up with totally disabling both D and I caches.

Maybe my HAL drivers are too old (v. 1.5) , should update to 1.8.

-- pa

AAgar.2
Associate III

Interesting, will have to read up on D-Cache. Any recommendations?

I will modify the program to remove all flash operations as much as possible and then fall back to this D-Cache disable.

Pavel A.
Evangelist III

> Any recommendations?

A very simple one. Test your program with D-cache disabled. If performance is near satisfactory, leave it disabled.

Avoids a lot of pain.

-- pa

AN4839 and AN4838.

AAgar.2
Associate III

.

Do I have to run SCB_InvalidateDCache_by_Addr on each sector? (Like shown below

**Update im getting a hardfault when I tried this**)

SCB_InvalidateDCache_by_Addr(ADDR_FLASH_BANK_1_SECTOR_3_START, 128000); // 1 sector

Or can I run SCB_InvalidateDCache on multiple sectors? (Like shown below)

SCB_InvalidateDCache_by_Addr(ADDR_FLASH_BANK_1_SECTOR_3_START, 655360); // 5 sectors

Do you disable DCache as below? Do you do this at the start of every bootup or just once?

SCB_DisableDCache (**Getting hardfault when I tried this aswell**)

Do I have to run SCB_InvalidateDCache_by_Addr on each sector? (Like shown below

**Update im getting a hardfault when I tried this**)

SCB_InvalidateDCache_by_Addr(ADDR_FLASH_BANK_1_SECTOR_3_START, 128000); // 1 sector

Or can I run SCB_InvalidateDCache on multiple sectors? (Like shown below)

SCB_InvalidateDCache_by_Addr(ADDR_FLASH_BANK_1_SECTOR_3_START, 655360); // 5 sectors

Do you disable DCache as below? Do you do this at the start of every bootup or just once?

SCB_DisableDCache (**Getting hardfault when I tried this aswell**)

Piranha
Chief II

Don't post the same multiple times!

Those functions will cause hard fault when D-cache is disabled. Also you should know that 1 KB has 1024 bytes, not 1000. One or multiple subsequent sectors is your choice - the SCB_***() functions work on memory blocks from CPU perspective and don't know/care where those addresses are located and what do they represent to you.

> Do you disable DCache as below?

Read carefully once more: "or don't turn on D-cache"! In a hardware by default it's disabled. If you are using CubeMX bloatware generation, then look for an option under System Core => Cortex-M7.