2025-11-21 11:33 AM - last edited on 2025-11-22 4:31 AM by Andrew Neil
From the ES0335 errata there are two errata that look pretty significant for dual bank boot (which I'm planning to use as the basis of field firmware update):
2.2.8 Dual-bank boot not working when the boot in flash memory is selected by BOOT0 pin
Description
When the nSWBoot0 option bit is set and the BOOT0 pin level is low, the dual‑bank boot does not work (BFB2
option bit = 1).
The user code is only executed when BANK 0 is valid.
Workaround
Do not rely on the BOOT0 pin to select the boot in flash memory. Instead, use the option bytes for that purpose,
setting the nSWBoot0 option bit to 0, the nBOOT0 option bit to 1, and the BFB2 option bit to 1. This setting allows
the correct check of the address 0 of the two memory banks, in order to execute from the correct one.
2.2.9 Dual-bank boot fails with stack pointer placed within aliased SRAM2
Description
If dual-bank boot is selected through option bits, the bootloader checks the contents of either flash memory bank
for validity. It considers a bank content valid if its first word (determining the stack pointer address) contains a
value from 0x2000 0000 to 0x2003 FFFF (SRAM1) or from 0x1000 0000 to 0x1000 FFFF (SRAM2). Any other
value is invalid.
As a consequence, the dual-bank boot fails if the first word of either flash memory bank points to a location within
the SRAM2 aliased at the address 0x2004 0000.
This limitation applies to STM32L496xx and STM32L4A6xx.
Workaround
Do not use aliased SRAM2 address range in conjunction with dual-bank boot.
To check these out I ported a test app I built for the STM32L475 (to which the above doesn't apply) and to my surprise it worked with no modification on a Nucleo-L496ZG.
The initial stack pointer in the image is 0x20040000 - which should apparently not work according to 2.2.9 above.
In the flash option bytes nSWBoot0 is set to 1 (the factory default), where 2.2.8 above suggests that I should need to set it to 0 to enable dual bank boot to work correctly. I have set BFB2 to using Cube programmer.
I verified that the Errata applies to my chip - according to Table 2. Device variants in the errata.
My test procedure is to
The test program detects which bank it is running from using
READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE)0 means running from bank 1 (not swapped), 1 means running from bank 2.
If it detects it's running from bank 2 it erases bank 1 and copies itself to bank 1 then reboots, at which point it is running in bank 1.
I'm kind of surprised that it's working - I had expected to have to modify the initial stack pointer and set nSWBoot0 to 0, but none of that seems to be necessary.
I've also tried loading a different binary at 0x0800000 to see if the device still preferentially boots from bank2 when BFB2 is set.
So my conclusion is that maybe I don't understand the meaning of the two errata above. In what way does dual-bank boot not work ? Thanks in advance for any pointers.
2025-11-21 12:03 PM
> Mass erase Flash
> Set BFB2 to 1 (and no other changes) in the User and read protection option bytes.
> Load my binary at 0x08080000 using Cube Programmer.
> Reset the board.
The "empty flash" flag gets set on power-on (or OB launch), not reset, so you'll have to power cycle the chip after resetting the flash to get this flag set correctly.
Empty check mechanism on STM32 - STMicroelectronics Community
Little hard to parse everything going on here, but that could be the reason. Try a power cycle instead of board reset on the last step.
2025-11-21 12:58 PM
Thanks - I should have been clearer - the dual bank boot appears to be working as described in AN2606, without the limitations described in the errata.
When I said reset the board I should have been clearer - I have tried disconnecting Cube Programmer, hitting the reset button on the Nucleo, and power cycling. Dual bank boot appears to work per AN2606 in all cases - with the result that I don't understand the errata warnings (which worries me as they may bite me later on).
2025-12-09 1:18 AM
From my experience regarding the dual-bank boot, it fails with >0x20040000. So for instance you want to use the complete aliased region of 320KB, it won't work (0x20050000). (seems to be off by one from what is described)
This can be bypassed though by patching the binary to point to 0x20040000 (with _estack in linker) and in the Reset Handler modifying it back to 0x20050000. Alternatively, use the approach defined in the errata, where you don't use the aliased region, and instead use the non aliased memory, and explicitly place data in that region.
Reset_Handler:
ldr sp, =_estack
ldr sp, =0x20050000 /* Add */
2025-12-09 6:32 AM
Thanks - I'm not completely certain of what you mean by "seems to be off by one from what is described", but perhaps it's describing what I'm seeing. As mentioned in my OP my initial stack pointer is 0x20040000 - the errata says that valid values are "from 0x2000 0000 to 0x2003 FFFF", but I think the errata is incorrect and should have read "from 0x2000 0000 to 0x2004 0000".
I suspect the wording of the errata 2.2.8 is also misleading, because I have found the value of nSWBoot0 does not affect BFB2 behavior (in my case):
When the nSWBoot0 option bit is set and the BOOT0 pin level is low, the dual‑bank boot does not work (BFB2
option bit = 1). The user code is only executed when BANK 0 is valid.
I suspect what might be meant is that BFB2 will not function correctly if "the nSWBoot0 option bit is set and the BOOT0 pin level is low and the first word of bank 1 does not contain an address within SRAM 1".
In my case the first word of both banks 1 and 2 contains 0x20040000: setting BFB2 results in booting from bank 2, and clearing BFB2 results in booting from bank 1 - regardless of the value of nSWBoot0.
Perhaps ST could publish an STM32L496 errata errata !?
2025-12-09 7:07 AM
Yes, I mean that values of 0x2000 0000 to 0x2004 0000 seem to be accepted by the internal boot-loader. Values greater than 0x2004 0000 are not. I have for instance tried to use 0x2005 0000 in an application previously and stumbled upon this errata bug.
This essentially means that when using the RAM2 region, you can not use the aliased area (without work-arounds), and thus you don't have a continuous 320KB region, bur rather a disjoint RAM on the RAM1/RAM2 boundary address (0x2000 0000 RAM1 and 0x1000 000 RAM2).
I have only used the boot-option bytes, so I have not stumbled upon the errata in 2.2.8.