Hello-
Our project is on the STM32F411 Discovery board produced and sold by ST. We have a project that is meant to run as a stand-alone image but also can be uploaded via USB to the STM32F411 that is also running our bootloader. To enable this behavior the memory map XML is edited to start the flash space at 0x08008000 instead of the normal 0x08000000. The __VTOR_CONFIG property is also defined for all configurations. This setup worked fine for quite a while but recently stopped running correctly. Currently, our code only correctly executes when building the DEBUG configuration and launching it via the debugger. If we run RELEASE or power cycle the Discovery board after a successful debug session, the code fails to execute (usually, even with debug code loaded, it will run on a power cycle with no debugger attached). Our project involves a lot of external circuits attached to the Discovery board, however, we see this same problem exhibited on a Discovery board with no external circuits. We can still verify if our code is running or not by looking for a COM port to be spawned by connecting the user-USB port on the Discovery board. So even running the code without all of our stuff attached, we will see the COM port appear in Windows only if a debug session is launched (side note: the on-board ST Link is replaced with the Segger J-Link firmware).
To help troubleshoot this issue we implemented the following test code which lights up LD3 connected to PD13:
Display All
We found the problem area by moving this test sequence farther and farther up the execution chain. The following code is in SEGGER_THUMB_startup.s
Display All
If we place our test code at the start of this function, the light turns on, however, if we place it at the end, the light stays off. So something in one of these init functions that are being looped over is blocking the code from running unless it's under a debug session (and the code doesn't have to be stepped line by line, if allowed to run immediately on session start it's fine). Stepping through this code constantly ends up in the __SEGGER_init_zero function and nowhere else (after stepping through this loop a dozen times) but somehow code execution eventually breaks out since if we place a breakpoint on APP_ENTRY_POINT it does get there. Or perhaps this is the core issue, that under RELEASE code the normal process to exit __SEGGER_init_zero never happens? Either way it is unclear how to proceed unless we try editing project settings to stop this function being called to begin with, but it would be nice to avoid that.
Our project is on the STM32F411 Discovery board produced and sold by ST. We have a project that is meant to run as a stand-alone image but also can be uploaded via USB to the STM32F411 that is also running our bootloader. To enable this behavior the memory map XML is edited to start the flash space at 0x08008000 instead of the normal 0x08000000. The __VTOR_CONFIG property is also defined for all configurations. This setup worked fine for quite a while but recently stopped running correctly. Currently, our code only correctly executes when building the DEBUG configuration and launching it via the debugger. If we run RELEASE or power cycle the Discovery board after a successful debug session, the code fails to execute (usually, even with debug code loaded, it will run on a power cycle with no debugger attached). Our project involves a lot of external circuits attached to the Discovery board, however, we see this same problem exhibited on a Discovery board with no external circuits. We can still verify if our code is running or not by looking for a COM port to be spawned by connecting the user-USB port on the Discovery board. So even running the code without all of our stuff attached, we will see the COM port appear in Windows only if a debug session is launched (side note: the on-board ST Link is replaced with the Segger J-Link firmware).
To help troubleshoot this issue we implemented the following test code which lights up LD3 connected to PD13:
Source Code
- movw r3, #14384
- movt r3, #16386
- ldr r2, [r3, #0]
- orr.w r2, r2, #8
- str r2, [r3, #0]
- movw r3, #3072
- movt r3, #16386
- ldr r2, [r3, #0]
- movs r4, #1
- bfi r2, r4, #26, #2
- str r2, [r3, #0]
- movw r3, #3076
- movt r3, #16386
- ldr r2, [r3, #0]
- bic.w r2, r2, #8192
- str r2, [r3, #0]
- movw r3, #3092
- movt r3, #16386
- ldr r2, [r3, #0]
- orr.w r2, r2, #8192
- str r2, [r3, #0]
We found the problem area by moving this test sequence farther and farther up the execution chain. The following code is in SEGGER_THUMB_startup.s
Source Code
- START_FUNC _start
- //
- // Call linker init functions which in turn performs the following:
- // * Perform segment init
- // * Perform heap init (if used)
- // * Call constructors of global Objects (if any exist)
- //
- ldr R4, =__SEGGER_init_table__ // Set table pointer to start of initialization table
- L(RunInit):
- ldr R0, [R4] // Get next initialization function from table
- adds R4, R4, #4 // Increment table pointer to point to function arguments
- blx R0 // Call initialization function
- b L(RunInit)
- //
- MARK_FUNC __SEGGER_init_done
- MARK_FUNC __startup_complete
- //
- // Time to call main(), the application entry point.
- //
- #ifndef FULL_LIBRARY
- //
- // In a real embedded application ("Free-standing environment"),
- // main() does not get any arguments,
- // which means it is not necessary to init R0 and R1.
- //
- bl APP_ENTRY_POINT // Call to application entry point (usually main())
- END_FUNC _start