Debugging Initialization Code of Multi-Core STM32H7 Devices

This tutorial explains the initialization process of the multi-core STM32H7 devices and shows how to reliably debug both cores using VisualGDB.

In this tutorial we will clone the OpenAMP demonstration project for the STM32H7-Discovery board, will show how both cores are initialized and how to reliably debug them.

Before you begin, install VisualGDB 5.5 Preview 3 or later.

  1. Start Visual Studio and open the VisualGDB Embedded Project Wizard:
  2. Specify the name and the location for the project targeting the Cortex-M7 core. Note that we will create another project targeting the Cortex-M4 core later:
  3. Proceed with creating the project based on MSBuild:
  4. On the Device Selection page pick the Cortex-M7 core of your STM32H7 device (the one that does not have the _M4 suffix):
  5. On the Sample Selection page switch to the “STM32CubeMX Samples” view and pick the OpenAMP_PingPong example:Double-check that the “Device” column does not have the _M4 suffix.
  6. Connect your board to the USB port and let VisualGDB recognize it. Ensure that the “Debugged Core” option has “Cortex-M7” selected:
  7. Press “Finish” to create the project. Once it is generated, open another Visual Studio instance and create a project for the  Cortex-M4 core of the same chip (STM32H7xxxx_M4 variant on the Device Selection page) and make sure you select the same sample on the Sample Selection page:Note that the “Device” column should now show the _M4 variant.
  8. Select the Cortex-M4 core on the Debug Method page and click “Finish” to generate the second project:
  9. Now we will try debugging both projects. First launch the one corresponding to the Cortex-M7 core. If it doesn’t start correctly, try setting the “Connect under reset” checkbox in the VisualGDB Project Properties:
  10. Once the Cortex-M7 core starts, begin debugging the Cortex-M4 project by pressing F5 in the second Visual Studio instance. Most likely, the project will immediately stop, reporting a breakpoint at the address 0xa05f0000
  11. If you stop the Cortex-M7 core via the Debug->Break All command in the first Visual Studio instance, you will see that it has encountered an error at the beginning of the initialization:
  12. In order to understand what is going on, take a note of the initialization code in the beginning of the Cortex-M4’s main() function:

    The Cortex-M4 core enables the inter-core notification mechanism and then stops itself, waiting for the Cortex-M7 core to wake it up. This is done to avoid accessing any peripherals before they have been fully initialized by the Cortex-M7 core. The OpenOCD tool reports the “Core powered down” event as a stop at address 0xa05f0000.
  13. The initialization code for he Cortex-M7 core expects the Cortex-M4 core to enter the sleep mode, however that check is designed to time out after 64K iterations:

    When both cores are started without a debugger, the default initialization logic will work as expected: the Cortex-M4 core will power itself down, then the Cortex-M7 core will initialize the peripherals and finally wake up the Cortex-M4 core. However, if the Cortex-M4 core is not started immediately after the Cortex-M7 core (which is the case when using the debugger), the Cortex-M7 initialization will fail with an error.
  14. In order to work around this, modify the Cortex-M7 initialization code to wait for the Cortex-M4 powerdown indefinitely:

  15. Now you will be able to debug both cores at the same time. Set a breakpoint in the Cortex-M7 project at the MAILBOX_Init() call (after the Cortex-M7 core resumes the Cortex-M4 one) and start the M7 project:
  16. Set a breakpoint at the MAILBOX_Init() call in the Cortex-M4 project and launch it as well. Now both breakpoints will hit:
  17. You can now debug both cores independently (each Visual Studio instance will debug one of the cores). E.g. try setting a breakpoint before the first call to OPENAMP_send() in the Cortex-M7 project, change the value of the message, and step over the send call:
  18. The Cortex-M4 project will receive the modified message as expected:

If you are planning to explore other project examples for the multi-core STM32H7 devices, always remember to create both Cortex-M7 and Cortex-M4 projects. Programming just the Cortex-M7 part (while keeping the Cortex-M4 logic from the previous project) may lead to unpredictable behavior.

To facilitate multi-core debugging, we recommend removing the timeout check from the Cortex-M7 initialization logic in the debug builds of your projects, as we have done in this tutorial.