STM32L4 only boots every other flash – CubeProgrammer PEMPTY bug with odd number of flash pages
This post is in response to the following post which has been closed so I am unable to reply...
Update – root cause found: STM32CubeProgrammer flash loader / FLASH_SR.PEMPTY
I have finally found the cause of this issue and a reproducible workaround.
The problem is related to the PEMPTY bit (bit 17) in FLASH_SR.
On a failed debug/programming attempt I measured:
FLASH_SR = 0x00020000 (PEMPTY = 1)
SYSCFG->MEMRMP = 0x1
SCB->VTOR = 0x1FFFF000
PC = 0x1FFFxxxxThe MCU had therefore booted into System Memory rather than the application.
On the next, successful attempt:
FLASH_SR = 0x00000000 (PEMPTY = 0)
SYSCFG->MEMRMP = 0x0
PC = 0x0800xxxxThe option bytes were identical in both cases:
FLASH->OPTR = 0xFFFF98AAI could reproduce this indefinitely: one programming attempt failed, the next worked, then failed, then worked.
As a test, on a failed attempt I manually executed:
set *(int*)0x40022010 = *(int*)0x40022010This changed FLASH_SR from:
0x00020000to:
0x00000000After subsequently resetting the MCU from CubeIDE, the application booted normally.
The important discovery was that the behaviour depends on the number of flash pages programmed/erased by STM32CubeProgrammer.
My normal image resulted in:
Size : 120.07 KB
Erasing internal memory sectors [0 60]This is 61 flash pages (an odd number). With this image, PEMPTY alternated between set and clear on successive programming operations, giving the every-other-upload behaviour.
I then deliberately added data in page 61 so that CubeProgrammer had to process one additional page. It reported:
Erasing internal memory sectors [0 60]
Erasing internal memory sector 61i.e. 62 pages (an even number).
With 62 pages the problem disappeared and the MCU started correctly every time.
I then replaced the test with an automatic linker workaround which pads the programmed image to an even number of STM32L433 2-Kbyte flash pages:
/*
* STM32CubeProgrammer 2.23.0 workaround:
* Ensure programmed FLASH image occupies an even number
* of 2-Kbyte FLASH pages.
*/
.flash_page_pad :
{
. = ALIGN(0x1000) - 1;
BYTE(0xFF);
} >FLASHAfter rebuilding, CubeProgrammer now reports:
Size : 124.00 KB
Erasing internal memory sectors [0 61]and debugging/programming now works consistently without any manual FLASH_SR command.
This strongly suggests that the STM32CubeProgrammer flash loader is incorrectly handling FLASH_SR.PEMPTY during flash programming. The observed behaviour is consistent with PEMPTY effectively being toggled once for each flash page operation: an odd number of pages leaves the bit in the opposite state, whereas an even number returns it to the correct state. When it is left set, the STM32L433 subsequently boots System Memory; when it is clear, it boots the application normally.
Setup:
MCU: STM32L433
Debugger: STLINK-V3MINIE
ST-LINK firmware: V3J17M10
STM32CubeIDE: 2.2.0
ST-LINK GDB server: 7.14.0
STM32CubeProgrammer: 2.23.0
Interface: SWD
Connect mode: Under Reset
Reset mode: Hardware resetSTM32CubeProgrammer 2.23.0 is currently the latest version available, so for the moment I am using the linker padding workaround.
Hopefully ST can confirm whether the flash loader is incorrectly writing/toggling PEMPTY after each page operation and provide a fix.
