Skip to main content
Visitor II
August 8, 2025
Question

Bizarre bootloader invocation every other debug session

  • August 8, 2025
  • 2 replies
  • 457 views

I'm experiencing a very, very strange behavior when running debug sessions in STM32CubeIDE. Sequential sessions alternate between correct execution of my main() entry point (and execution stops there, as expected) and unexpected entry into the bootloader.

Everything has worked absolutely correctly up until just a few days ago. Before that, I last compiled and programmed firmware maybe a week and a half ago. I made a git branch at that point to capture the state of the software prior to making changes for a new PCB revision. Now, after experiencing this issue with new code, I've even switched back to that historical branch, and that now also exhibits the issue. I've also rebooted and power cycled my programmer and boards. I have two PCBs, and they both behave the same way.

I'm using STM32CubeIDE v. 1.19.0 build 25607_20250703_0907.

Target is an STM32L431CC (CCT6). Program/debug is via an ST-LINK/V2 and SWD. Nothing has changed in my debug configuration (and reset behavior is "connect under reset", and I have the "set breakpoint at" checkbox checked, with the symbol "main").

On the board, BOOT0 (pin 44) is tied to GND with 10 KΩ.

Nothing has changed with the hardware or the software. And I made the historical branch after having programmed and tested the software. I also verified that in the "failure" case, my reset handler is in fact not being called - a breakpoint at the first instruction of the handler gets hit every other session.

This is the typical sequence I see:

1) I perform a clean and a build to verify compilation (debug configuration, not release).

2) I start a debug session (nothing gets rebuilt). In the debug console, I see everything as expected, up to the message, "Download verified successfully". However, execution does not halt in main(), and the code is running. If I then suspend execution, I'll see an address like 0x1fff2cdc. That's bootloader territory!

3) I terminate and relaunch (nothing gets rebuilt). I see everything as expected, but this time execution halts just inside of main(), as it's supposed to.

4) Behavior in subsequent relaunches alternates between (2) and (3).

This one has me flummoxed. I've found nothing in the forums or elsewhere online that's similar.

Has anyone else experienced anything remotely similar?? (And many thanks in advance to anyone taking the time to share some ideas.)

 

 

 

    This topic has been closed for replies.

    2 replies

    Graduate II
    August 9, 2025

    Power cycling and reset are subtly different. Some of this stems from security and integrity against attack vectors.

    The bootloader comes up and checks if the vector table is viable, and it can latch that regardless of BOOT0 pin state.

    The flashing and debugging can lead to latched conditions. 

     

    Visitor II
    August 10, 2025

    I get there's a difference. However I'm really not certain what you're talking about. What do you mean "the bootloader comes up"? And "is viable"?

    I'm not aware of any execution of bootloader code in any circumstances on a pin reset (short of asserting BOOT0). That doesn't seem to make any sense. Could you point me to any documentation?

    Incidentally, for you and for anyone else reading, I've also tried building and debugging from an absolutely fresh checkout, and I have the same behavior. Strictly alternating, jump-into-bootloader and halt-in-main.

    This makes no sense.

    Visitor II
    August 10, 2025

    Also, my FLASH_OPTR value is 0xFFFF'F8AA.

    The RM (RM0394) says the production value of that register is 0xFFEF'F8AA. (The difference is with bit 20, a reserved bit.)

     

    Super User
    August 11, 2025

    Always post which STM32 model are you using (RM0394 partially gives it away, but for example the following text does not apply to the "mid-range" 'L4).

    @Tesla DeLorean  refers to the infamous PEMPTY mechanism.

    waclawekjan_0-1754917336505.png

     

    The exact mechanism with debugger depends heavily on the particular debugger and its exact behaviour.

    Try setting the nBOOT0/nSWBOOT0 option bits to 1/0 respectively.

    JW

    Visitor II
    August 11, 2025

    Always post the STM32 model? You mean like "STM32L431CC" as in my original post?

    I understand what the PEMPTY mechanism is. This behavior occurs during the launch of a debug session, after program/verify and debugger script release of reset. The flash by definition is not empty.

    Edit, added:

    Plus, currently (this is the manufacturer original setting) nBOOT0 is 1. I don't want to set nSWBOOT0 to 0, because that will cause the BOOT0 value to be taken from the nBOOT0 bit and I'll have the bootloader all the time. I need nBOOT0 / nSWBOOT0 to be set as they are now (original default) as 1 / 1. When nSWBOOT0 is 1, the BOOT0 value comes from the PH3/BOOT0 pin, which is what I want.

     

    Super User
    August 11, 2025

    > model

    I've overlooked that, sorry.

    > The flash by definition is not empty.

    It may be the case at the point of "launch", but the issue is, that the PEMPTY bit is not cleared by any other but power-on reset. Or OBL_LAUNCH; but what any debugger does is often undocumented in the details.

    > I don't want to set nSWBOOT0 to 0, because that will cause the BOOT0 value to be taken from the nBOOT0 bit and I'll have the bootloader all the time.

    If nBOOT is 1, you won't have the bootloader ever. OTOH, the nSWBOOT0=0&BOOT0=0 combination *does get* overridden by PEMPTY. See the table I've posted above.

    JW