cancel
Showing results for 
Search instead for 
Did you mean: 

Writing to Bank1 while running from Bank2 → Flash write fails

cuong
Associate II

Hi everyone,

I'm using STM32G474 with dual-bank Flash enabled (nDBANK = 0) and booting from Bank2 (BFB2 = 1). I'm implementing OTA firmware update by writing to the inactive bank while executing from the active one.

The update from Bank1 → Bank2 works fine.

But in the second update cycle, when running from Bank2 and trying to write to Bank1 (starting at address 0x08000000), HAL_FLASH_Program() always fails on the first double-word.

I have:

  • Verified that Write Protection is disabled (checked in STM32CubeProgrammer)

  • Unlocked Flash properly

  • Erased the target pages beforehand

  • No PCROP or secure area configured on Bank1

  • Flash error flag is HAL_FLASH_ERROR_WRITE_PROTECTION sometimes (even though WRP is not set)

I found some similar cases reported online (e.g. this one) where users mentioned that writing to Bank1 from Bank2 fails silently.

Is there an undocumented silicon limitation on STM32G4 when programming Bank1 from Bank2?

I would appreciate any official clarification or workaround from ST or others who solved this.

Thanks in advance!

1 ACCEPTED SOLUTION

Accepted Solutions
Saket_Om
ST Employee

Hello @cuong and @pikachu 

I updated the example Projects/STM32G474E-EVAL1/Examples/FLASH/FLASH_DualBoot to boot on flash BANK2 and write on flash BANK1. It works fine without errors. 

Please find attached the updated main.c and main.h. 

Also, the linker file shall be updated with the below line to be able to upload directly from IAR the binary data to flash BANK2:

define symbol __ICFEDIT_intvec_start__ = 0x08040000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__     = 0x08040000;

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

View solution in original post

8 REPLIES 8
Saket_Om
ST Employee

Hello @cuong 

Your issue has been reported internally and will get back to you as soon as possible. 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
pikachu
Associate II

I'm not having exactly the same problem, but it feels very similar, I just opened another post today.

https://community.st.com/t5/stm32-mcus-products/stm32g4-dual-bank-page-erase-blocking-interrupts-from-bank-2-to/td-p/791211

In my case the problem is when I erase Bank 1 from Bank 2 (the IRQ stops for too long and this generates a lot of other problems) but the weird thing is that this is also not happening when doing the same actions from Bank 1 to Bank 2. 

Everything works perfectly in Bank 1, but when I'm in Bank 2 doing the same, I have a lot of problems. In my case I'm able to write, but erases are a mess. 

I don't know...

Saket_Om
ST Employee

Hello @cuong and @pikachu 

I updated the example Projects/STM32G474E-EVAL1/Examples/FLASH/FLASH_DualBoot to boot on flash BANK2 and write on flash BANK1. It works fine without errors. 

Please find attached the updated main.c and main.h. 

Also, the linker file shall be updated with the below line to be able to upload directly from IAR the binary data to flash BANK2:

define symbol __ICFEDIT_intvec_start__ = 0x08040000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__     = 0x08040000;

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
cuong
Associate II

Hello @omar,

Thank you very much for sharing the updated example and linker settings.

I have one follow-up question:
In my project, I am using a dual-bank firmware update mechanism, where:

- If the MCU is running from Bank1, it writes firmware to Bank2
- If it's running from Bank2, it writes firmware to Bank1

To simplify the workflow, I am trying to **use the same `.bin` file** (built with vector table at 0x08000000) for both cases — writing it to either Bank1 or Bank2 depending on the current boot bank.

So my question is:
**Is it strictly necessary to change the linker symbols (`__ICFEDIT_intvec_start__ = 0x08040000`) when writing to Bank2,** if I handle the vector table relocation manually in code by setting `SCB->VTOR` accordingly at runtime?

Also, I have checked the `main.c` and `main.h` files that you kindly shared, and I confirmed that they are essentially the same as my current implementation. However, I still cannot write to Bank1 when the MCU is running from Bank2 (even though the reverse direction works fine). So I'm wondering if there might be any subtle configuration differences or flash-related constraints that I'm missing?

Would greatly appreciate your advice or any insights for this scenario — especially for IAR-based projects.

Thanks again!

cuong_0-1744167302499.pngcuong_1-1744167413908.pngcuong_2-1744167439383.png

cuong_3-1744167477651.png

 

Thank you @Saket_Om, but my problem is not exactly the same, so this doesn't fix it. Refer to my post for more info, but the problem in my case is only when erasing a page in Bank 1 when Bank 2 is active (the other way around works perfectly).

There's probably some limitation that I'm not seeing in how dual boot works.

cuong
Associate II

Hello @Saket_Om,

Thank you very much for sharing the updated example and linker settings.

I have one follow-up question:
In my project, I am using a dual-bank firmware update mechanism, where:

- If the MCU is running from Bank1, it writes firmware to Bank2
- If it's running from Bank2, it writes firmware to Bank1

To simplify the workflow, I am trying to **use the same `.bin` file** (built with vector table at 0x08000000) for both cases — writing it to either Bank1 or Bank2 depending on the current boot bank.

So my question is:
**Is it strictly necessary to change the linker symbols (`__ICFEDIT_intvec_start__ = 0x08040000`) when writing to Bank2,** if I handle the vector table relocation manually in code by setting `SCB->VTOR` accordingly at runtime?

Also, I have checked the `main.c` and `main.h` files that you kindly shared, and I confirmed that they are essentially the same as my current implementation. However, I still cannot write to Bank1 when the MCU is running from Bank2 (even though the reverse direction works fine). So I'm wondering if there might be any subtle configuration differences or flash-related constraints that I'm missing?

Would greatly appreciate your advice or any insights for this scenario — especially for IAR-based projects.

Thanks again!

Hi @cuong 
I have the same problem on STM32L4A6. The entire OTA is prepared for DualBoot. The update from BANK1 to BANK2 works correctly.
And suddenly, in the next iteration, the application from BANK2 cannot write to BANK1. Erasing works without any issues.
Were you able to find a solution?

Hi ufolek

Yes, I’ve encountered a very similar issue and managed to solve it.

In my case, the MCU is not an STM32L4A6, but an STM32G474.
The root cause turned out to be related to the remapped memory layout when booting from Bank2 with BFB2 = 1.

When the device starts from Bank2 (with BFB2 = 1 set), the memory map is remapped as follows on STM32G4 series:

  • Bank2 is remapped to 0x08000000 (the usual start address),

  • Bank1 is remapped to 0x08040000 (instead of its usual 0x08000000).

So if you try to write to 0x08000000 from an application running in Bank2, you're actually attempting to write to Bank2 (which is currently executing), not Bank1 — and that causes the write to fail.

Solution:

To write to Bank1 while executing from Bank2, use the remapped address 0x08040000 instead of 0x08000000.

Hope this helps!