2025-04-07 11:14 PM - last edited on 2025-04-08 1:39 AM by mƎALLEm
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!
Solved! Go to Solution.
2025-04-08 8:38 AM
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;
2025-04-08 2:42 AM
Hello @cuong
Your issue has been reported internally and will get back to you as soon as possible.
2025-04-08 5:32 AM
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...
2025-04-08 8:38 AM
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;
2025-04-08 7:58 PM
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!
2025-04-09 4:49 AM
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.
2025-04-10 4:50 PM
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!
2025-05-22 2:59 AM
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?
2025-05-22 5:10 PM
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.
To write to Bank1 while executing from Bank2, use the remapped address 0x08040000 instead of 0x08000000.
Hope this helps!