Skip to main content
Visitor II
June 18, 2020
Solved

STM32H7 Flash Memory Corruption During Read/Write

  • June 18, 2020
  • 7 replies
  • 4962 views

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.

    This topic has been closed for replies.
    Best answer by Piranha

    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.

    7 replies

    Graduate II
    June 18, 2020

    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...

    Super User
    June 18, 2020

    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.2Author
    Visitor II
    June 18, 2020

    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.

    Graduate II
    June 19, 2020

    AN4839 and AN4838.

    AAgar.2Author
    Visitor II
    June 20, 2020

    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**)

    Super User
    June 19, 2020

    > 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

    AAgar.2Author
    Visitor II
    June 20, 2020

    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**)

    AAgar.2Author
    Visitor II
    June 20, 2020

    .

    PiranhaAnswer
    Graduate II
    June 20, 2020

    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.

    AAgar.2Author
    Visitor II
    June 20, 2020

    Ok will do.

    Looking under Cortex _M7->CPU ICache/DCache in CubeMX as you have instructed does show that this is disabled. As such I don't think the DCache is an issue.

    I am unsure why this is happening but I have changed my code to do minimal flash operations to the point where this situation in the answer is not occurring. I'm having other issues with flash but not this.

    Appreciate your support.

    Graduate II
    June 20, 2020

    OK. By the way, reconsider whether you really need RTOS in a bootloader. Bootloader should be as simple and robust as possible and bullet-proof. Eliminating multi-threading can significantly reduce amount of potential multi-threading related bugs.

    AAgar.2Author
    Visitor II
    June 20, 2020

    Its mainly to reuse code that I have running on a multi-threaded system. I am minimizing the RTOS significantly to only use the minimal port.

    I am carefully entering/exiting in critical sections.

    RTOS is never initialized when a jump happens.

    My only concern is making the initial ram state consistent but ill deal with that a little later.