2026-01-12 2:15 PM - last edited on 2026-01-13 5:00 AM by Andrew Neil
Hello ST Community and ST Engineers,
I am currently working with a NUCLEO-WL55JC1 (STM32WL55 dual-core: Cortex-M4 + Cortex-M0+) and I am facing an issue when using dual-core projects generated with STM32CubeMX. I would really appreciate any guidance or confirmation from ST engineers or experienced users.
Hardware / Software:
Board: NUCLEO-WL55JC1 (STM32WL55 CM4 + CM0+)
Tools: STM32CubeIDE, STM32CubeMX, STM32CubeProgrammer
Also tested using VSCode with STM32 extensions
Firmware packages tested:
STM32Cube_FW_WL_V1.3.0
STM32Cube_FW_WL_V1.4.0
Examples tested:
LoRaWAN_End_Node
LoRaWAN_End_Node_FreeRTOS
LoRaWAN_End_Node_DualCore
LoRaWAN_End_Node_DualCoreFreeRTOS
References followed:
YouTube (LoRaWAN workflow overview): https://www.youtube.com/watch?v=8KNfrWoa1fw
Dual-core from scratch and CM4/CM0+ LED blink walkthroughs:
Summary of the issue:
Single-core projects work perfectly on my board (including LoRaWAN and FreeRTOS). However, when I generate a dual-core project, CM4 always runs but CM0+ does not start after reset or after programming from STM32CubeIDE.
What works:
Single-core CubeMX projects: OK.
Dual-core LED blink examples sometimes show CM0+ activity, but only under very specific conditions.
What fails:
In dual-core projects generated by CubeMX:
After pressing the hardware RESET button, only CM4 firmware runs.
After power cycling the board, only CM4 firmware runs.
After programming from STM32CubeIDE, only CM4 firmware runs.
Observations:
Flashing appears correct
Using STM32CubeProgrammer, I verified that the CM0+ image is programmed in the expected flash region (according to STM32WL55XX_FLASH_CM0P.ld).
CM0+ only runs when forced to execute after programming
If I program the CM0+ ELF using STM32CubeProgrammer and enable "Execute after programming", CM0+ runs (LED blink visible). However, this behavior does not survive reset or power cycling.
Clock-dependent behavior on CM0+
CM0+ LED blinking works only when using a crude busy-wait for-loop delay (no timer or SysTick). When using clock-based delays, CM0+ seems not to execute unless manually forced after flashing.
Things already tried:
CPU2 release and dual-core boot sequences following ST templates (HSEM usage, release timing, etc.)
Different placement of CPU2 release in CM4 main()
Multiple clock configurations in CubeMX
Verification of IPCC configuration and IRQs
Verification of CM0+ linker script and vector table location
Multiple flashing orders (CM4 first, CM0+ first)
CubeProgrammer vs CubeIDE programming
Key suspicion:
It looks like CM0+ is not being started automatically after reset, and it only runs when CubeProgrammer forces execution immediately after flashing.
Questions:
What is the recommended and reset-safe way to ensure CM0+ boots every time on STM32WL55 dual-core projects?
Are there any required Option Bytes for dual-core boot on STM32WL55, or is CM0+ startup purely controlled by CM4?
Is there a CubeIDE configuration required to ensure both cores are started after programming and after reset?
Is the observed behavior (CM0+ only running when manually executed after programming) expected or indicative of a configuration issue?
I can provide CubeMX .ioc files, ELF/MAP files, and CubeProgrammer screenshots if needed.
Thank you very much in advance for your help.
Best regards,
Ignacio
Solved! Go to Solution.
2026-01-13 6:59 PM
CPU2's interrupt vector is taken from FLASH->SRRVR, which should look like 0xFFFF8000 to provide a flash address of 0x08020000. [Ref RM0453 sec 4.10.20]. This is loaded from the Option bytes (0x1FFF7878 per Table 16) at POR.
I wonder if something has gone wrong with your Option bytes. It may be worth peeking at those two fields (and maybe the contents of the interrupt vector at 0x08020000) to see if something has been corrupted.
2026-01-12 4:37 PM - edited 2026-01-12 5:10 PM
CPU2 (C-M0) stays in reset until CPU1 (C-M4) explicitly starts it. [Ref RM0453 (r6) Sec 2.3]
I.e. CPU1 must be running before CPU2 can start.
[Edit: Minor clarification]
2026-01-13 1:38 PM
Hello,
thank you for the clarification.
I fully agree with the statement from RM0453: CPU2 (Cortex-M0+) remains in reset until CPU1 (Cortex-M4) explicitly starts it, and that CPU1 must be running before CPU2 can start.
However, this condition is already satisfied in my setup, and this is precisely why I am still blocked.
To clarify:
What I am observing is:
Additional observations that may be relevant:
Because CPU1 is clearly running and releasing CPU2, my suspicion is not that CPU2 is “never released”, but rather one of the following:
2026-01-13 6:59 PM
CPU2's interrupt vector is taken from FLASH->SRRVR, which should look like 0xFFFF8000 to provide a flash address of 0x08020000. [Ref RM0453 sec 4.10.20]. This is loaded from the Option bytes (0x1FFF7878 per Table 16) at POR.
I wonder if something has gone wrong with your Option bytes. It may be worth peeking at those two fields (and maybe the contents of the interrupt vector at 0x08020000) to see if something has been corrupted.
2026-01-15 4:58 AM
Hi,
Thanks a lot for the explanation.
The issue is now resolved. The problem was indeed the SRRVR value: it was set to 0x00000040, so CPU2 was not reading the interrupt vector from the correct flash address.
After updating it to 0xFFFF8000 (so that CPU2 correctly maps to 0x08020000), CPU2 started executing properly and everything works as expected.
Thanks again for pointing me in the right direction and for your help.