cancel
Showing results for 
Search instead for 
Did you mean: 

How to debug STM32H7 dual-core using VS Code

B.Montanari
ST Employee

Summary

This article provides a step-by-step guide to debugging STM32H7 Dual-Core applications using VS Code. It covers configuring the project with CMake, setting up debugging for both Cortex®-M7 and Cortex®-M4 cores, and managing their interaction effectively within VS Code.

Introduction

This article provides a practical introduction to debugging projects based on STM32H7 dual-core microcontrollers using modern tools such as CMake and Visual Studio Code. STM32H7 dual-core devices combine a high-performance Arm Cortex®-M7 core with a flexible Cortex®-M4 core, offering significant processing power and versatility for advanced embedded applications. The project structure for these devices is hierarchical, with separate subprojects and binaries for each core, allowing independent build and debug configurations for both the Cortex®-M7 and Cortex®-M4.

A critical aspect of dual-core development is understanding the boot and synchronization sequence. Typically, the Cortex®-M7 core is responsible for system initialization and resource setup, after which it releases the Cortex®-M4 core from reset or low-power mode. Respecting this sequence during debugging is essential to avoid synchronization issues and ensure correct system behavior.
The following content covers the complete workflow, including:

  • Setting up your development environment.
  • Configuring your project with CMake.
  • Preparing dual-core debug sessions in Visual Studio Code using the STM32CubeExtension.
  • Applying best practices for core synchronization and debugging order.

By following these steps, you are able to develop, build, and debug robust applications for STM32H7 dual-core microcontrollers.

Prerequisites

This article assumes that you have installed:

1. Create an STM32H7 CMake project

  • Create a new STM32CubeMX project, open VS Code, and launch STM32CubeMX:
BMontanari_0-1762168579826.png
 
The hardware used in this showcase is the NUCLEO-H745ZI-Q, but you can use any STM32H7 board with a Dual-Core architecture.
  • Select the NUCLEO-H745ZI-Q:
BMontanari_1-1762168579835.png
  • Enable the HMI and generate the demonstration code:
BMontanari_2-1762168579840.png
  • Before the code generation, select the CMake toolchain:
BMontanari_3-1762168579841.png
  • In VS Code, import the project folder:
BMontanari_4-1762168579844.png
  • Configure the preset [Debug], Ctrl+Shift+P and choose [CMake: Select Configure Preset]:
BMontanari_5-1762168579845.png

 

BMontanari_6-1762168579845.png
  • Configure the CMake discovered project as an STM32Cube project:
BMontanari_7-1762168579847.png
  • Add [CM7] and [CM4] to your environment, save and close:
BMontanari_8-1762168579848.png

2. Create and modify launch.json

  • Open the Run and Debug view (Ctrl+Shift+D).
  • Click [create a launch.json file].
BMontanari_9-1762168579849.png
  • Select [STM32Cube: STLink GDB Server] from the list of debuggers provided by STM32CubeExtension.
BMontanari_10-1762168579850.png
  • The extension generates a default launch.json with configurations tailored for STLINK debugging.
  • Edit the generated launch.json to support debugging with all features enabled.

(Before)

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "stlinkgdbtarget",
            "request": "launch",
            "name": "STM32Cube: STM32 Launch ST-Link GDB Server",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}"
                }
            ]
        }
    ]
}

(After)

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "CM7_Debug",
            "type": "stlinkgdbtarget", // Debugger type (STMicroelectronics ST-LINK GDB server)
            "request": "launch", // Launch a new debug session
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "runEntry": "main",
            "serverShared": true, // Allows sharing the debug server with other sessions (needed for multi-core)
            "serverHaltAllCores": true, // Halts all cores when starting the debug session
            "svdPath": "C:/ST/STM32CubeCLT_1.19.0/STMicroelectronics_CMSIS_SVD/STM32H745_CM7.svd", // SVD file for CM7 core
            "imagesAndSymbols": [
                {
                    "imageFileName": "${workspaceFolder}/CM4/build/STM32H745ZI_DualCore_Example_CM4.elf" // Loads the CM4.elf image
                },
                {
                    "imageFileName": "${workspaceFolder}/CM7/build/STM32H745ZI_DualCore_Example_CM7.elf" // Loads the CM7.elf image
                }
            ],
            "verbose": false // Disables verbose logging
        },
        {
            "name": "CM4_Debug",
            "type": "stlinkgdbtarget",
            "request": "launch",
            "cwd": "${workspaceFolder}",
            "runEntry": "main",
            "serverShared": true,
            "serverApID": "3", // Specifies the Access Port ID for the CM4 core (core selection)
            "serverPort": "61239", // Port for the GDB server to connect (must be unique if running multiple sessions)
            "serverReset": "None", // No reset when starting this debug session
            "svdPath": "C:/ST/STM32CubeCLT_1.19.0/STMicroelectronics_CMSIS_SVD/STM32H745_CM4.svd", // SVD file for CM4 core
            "imagesAndSymbols": [
                {
                    "symbolFileName": "${workspaceFolder}/CM4/build/STM32H745ZI_DualCore_Example_CM4.elf" // Loads the CM4.elf symbols
                }
            ],
            "verbose": false
        }
    ],
    "compounds": [ // Compound configurations allow (attempted) simultaneous debug sessions
    {
      "name": "DualCore_Debug",
      "configurations": ["CM7_Debug", "CM4_Debug"] // List of configurations to launch together
    }
  ]
}

Explanation of the changes:

  • Added dedicated debug configurations for each core:

Two separate configurations, “CM7_Debug” and “CM4_Debug" are introduced to target the Cortex®-M7 and Cortex®-M4 cores, enabling independent or coordinated debugging for dual-core development.

  • Enabled multicore debug server sharing:

The “serverShared” property is set to “true” in both configurations, allowing the debug server to be shared between sessions.

  • Synchronized core startup:

The “serverHaltAllCores” property is set to “true” in the CM7 configuration, ensuring that both cores are halted at the start of the debug session for proper synchronization.

  • Added SVD files for enhanced peripheral view:

The “svdPath” property is included for both cores, pointing to their respective SVD files. This enables detailed peripheral register inspection in the debugger.

  • Explicitly defined images and symbols:

The “imagesAndSymbols” arrays now specify the exact paths to the *.elf binaries for each core, ensuring the correct firmware and symbols are loaded for each debug session.

  • Order of images in CM7_Debug is extremely important:

The order in which the .elf files are listed in the “imagesAndSymbols” array of the CM7_Debug configuration is critical. The CM4 image must appear before the CM7 image. This ensures that the debugger loads the CM7 firmware and its symbols first, followed by the CM4 firmware.

This order is necessary because the debugger relies on the first image for proper symbol resolution and memory mapping for the secondary core. The debug does not work if the order is reversed.

  • Specified access port ID for CM4:

The “serverApID” property is set to "3" in the CM4 configuration, directing the debugger to connect specifically to the Cortex®-M4 core.

  • Assigned unique GDB server port for CM4:

The “serverPort” property is set in the CM4 configuration to avoid port conflicts when debugging both cores simultaneously.

  • Set server reset behavior for CM4:

The “serverReset” property is set to "None" for the CM4 configuration, preventing the core from being reset at the start of the CM4_Debug session.

  • Added a compound configuration for dual-core debugging:

A “DualCore_Debug” compound configuration was introduced, allowing both core debug sessions to be launched together for streamlined dual-core development.

3. Start debugging

  • Connect your STM32 board to your PC using the STLINK debugger.
BMontanari_11-1762168579850.png
  • In VS Code, select the debug configuration you created.
BMontanari_12-1762168579851.png

 

On STM32H7 dual-core devices, the boot sequence is designed so that the CM4 core starts first and enters its main.c. It quickly configures itself to wait for the CM7 core to complete system initialization. During this process, CM4 enables the hardware semaphore clock, activates notifications, and then enters a low-power STOP mode, effectively pausing its execution until CM7 signals that initialization is complete.

  • Press [F5] Continue or click the green [Start Debugging] button.
  • The debugger should first halt at [CM4] “startup_stm32h745xx_CM4”:
BMontanari_13-1762168579855.png
  • Press [F5] Continue. The debugger should now halt at [CM4] “main.c”:
BMontanari_14-1762168579860.png
  • Press [F5] Continue. The debugger displays “Unknown Source”:
BMontanari_15-1762168579862.png

At this point, if you continue execution, you see "Unknown Source" in the debugger because CM4 is halted in STOP mode, waiting for the release signal from CM7. To proceed, you need to run the CM7_Debug session.

  • Switch to the CM7_Debug session:
BMontanari_16-1762168579863.png

 

BMontanari_17-1762168579868.png

The CM7 core performs its own initialization, including system configuration and memory setup, and eventually releases CM4 from STOP mode by clearing the hardware semaphore.

Once this happens, CM4 resumes normal execution, and you can continue debugging both cores as intended. If you do not start and run CM4 to its waiting state before running CM7, the dual-core synchronization fails, and debugging does not work. Maintaining this order is essential for the correct execution of the dual-core boot process and for reliable debugging of both cores.

  • Press [F5] Continue, the debugger automatically switches back to the CM4_Debug session:
BMontanari_18-1762168579872.png
  • Press [F5] Continue, now both cores run simultaneously:
BMontanari_19-1762168579872.png

Once both cores are synchronized and running, all standard debugging features become available, allowing you to:

  • Set breakpoints on either core.
  • Step through your program flow.
  • Inspect variables, registers, and memory for each core.
  • View and analyze the call stacks to track execution context.
BMontanari_20-1762168579879.png

 

Conclusion

By following these steps, you can successfully debug code running on the STM32H7 dual-core device using VS Code. This guide offers a practical approach. It covers environment setup, dual-core debugger configuration, and validation of the boot sequence to ensure a smooth and effective debugging experience for both the CM7 and CM4 cores.

Related Links

Version history
Last update:
‎2025-11-06 12:57 AM
Updated by: