cancel
Showing results for 
Search instead for 
Did you mean: 

NUCLEO-WL55JC1 Dual-Core project: CM4 runs, CM0+ doesn’t start after reset

ilazzaro
Associate II

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:

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:

  1. Flashing appears correct
    Using STM32CubeProgrammer, I verified that the CM0+ image is programmed in the expected flash region (according to STM32WL55XX_FLASH_CM0P.ld).

  2. 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.

  3. 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:

  1. What is the recommended and reset-safe way to ensure CM0+ boots every time on STM32WL55 dual-core projects?

  2. Are there any required Option Bytes for dual-core boot on STM32WL55, or is CM0+ startup purely controlled by CM4?

  3. Is there a CubeIDE configuration required to ensure both cores are started after programming and after reset?

  4. 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

1 ACCEPTED SOLUTION

Accepted Solutions
bmckenney
Associate III

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.

 

View solution in original post

4 REPLIES 4
bmckenney
Associate III

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]

ilazzaro
Associate II

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:

  • CPU1 (CM4) is running correctly in all cases.
  • The CM4 firmware explicitly releases CPU2, following the same sequence used in ST dual-core templates and examples (including the CubeMX-generated dual-core projects and LoRaWAN_End_Node_DualCore examples).
  • Despite this, CPU2 does not start after reset or power-on reset.

What I am observing is:

  • CM0+ only executes when:
    • Its ELF is programmed using STM32CubeProgrammer
    • AND the option “Execute after programming” is enabled
  • If I then press the hardware RESET button or power-cycle the board, CM0+ no longer runs, while CM4 continues to run normally.

Additional observations that may be relevant:

  • CM0+ LED blinking only works reliably when using a crude busy-wait loop (no SysTick / timer dependency).
  • When CM0+ code depends on clock-based delays, it appears that CM0+ either does not start or its clocking is not properly initialized.
  • Flashing location for CM0+ has been verified using STM32CubeProgrammer and matches the linker script (STM32WL55XX_FLASH_CM0P.ld).

Because CPU1 is clearly running and releasing CPU2, my suspicion is not that CPU2 is “never released”, but rather one of the following:

  • CPU2 boot address or vector table is not correctly taken into account after reset
  • CPU2 is released but does not start executing from the expected reset vector
  • A reset-type difference (debug reset vs hardware reset vs power-on reset) affects CPU2 startup
  • A required step is missing to re-release CPU2 after a hardware reset
bmckenney
Associate III

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.

 

ilazzaro
Associate II

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.