Debug ULP
Overview
This example demonstrates how to build, flash and debug a simple application on the LP core.
This sample also provides a custom gdbinit
file to be loaded by GDB to set up the debugging environment.
It connects with the remote OpenOCD server, loads the symbols from the LP Core application
and sets an initial breakpoint.
Limitations
Currently debugging is not supported when either HP or LP core enters any sleep mode. So this limits debugging scenarios.
OS support is disabled when debugging the LP core, so you won’t be able to see tasks running in the system. Instead there will be two threads representing HP (‘esp32c6.cpu0’) and LP (‘esp32c6.cpu1’) cores:
(gdb) info thread
Id Target Id Frame
1 Thread 1 "esp32c6.hp.cpu0" (Name: esp32c6.hp.cpu0, state: debug-request) arch_irq_unlock (key=8) at zephyr/include/zephyr/arch/riscv/arch.h:259
* 2 Thread 2 "esp32c6.lp.cpu" (Name: esp32c6.lp.cpu, state: breakpoint) do_things (max=1000000000) at zephyr/samples/boards/espressif/ulp/lp_core/debug_ulp/remote/src/main.c:28
When setting HW breakpoint in GDB it is set on both cores, so the number of available HW breakpoints is limited to the number of them supported by LP core (2 for ESP32-C6).
Sysbuild
Sysbuild is in charge of building the application located in the remote
folder for the LP Core target.
The build and flashing orders are as follows:
Build:
MCUboot bootloader
LP Core application
HP Core application
Flash:
MCUboot bootloader
HP Core application
LP Core application
Building and Flashing
Build the sample code as follows:
west build -b esp32c6_devkitc/esp32c6/hpcore --sysbuild samples/boards/espressif/ulp/lp_core/debug_ulp
Flash it to the device with the command:
west build -b esp32c6_devkitc/esp32c6/hpcore --sysbuild samples/boards/espressif/ulp/lp_core/debug_ulp
west flash
Debugging
Connect the USB cable to the USB port of the ESP32-C6 Devkitc board.
The ESP32-C6 modules require patches to OpenOCD that are not upstreamed yet. Espressif maintains their own fork of the project. The custom OpenOCD can be obtained at OpenOCD ESP32 [1].
In one terminal instance run the Espressif’s OpenOCD:
<path/to/openocd-esp32>/bin/openocd -f board/esp32c6-lpcore-builtin.cfg
Wait for the following output to show up in the console:
Info : Listening on port 3333 for gdb connections
On another terminal instance, run the GDB:
<path/to/zephyr/sdk>/riscv64-zephyr-elf/bin/riscv64-zephyr-elf-gdb -x samples/boards/espressif/ulp/lp_core/debug_ulp/gdbinit build/debug_ulp/zephyr/zephyr.elf
The following output should be displayed:
[esp32c6.hp.cpu0] Reset cause (24) - (JTAG CPU reset)
add symbol table from file "build/debug_ulp_lpcore/zephyr/zephyr.elf"
Hardware assisted breakpoint 1 at 0x500000ec: file zephyr/samples/boards/espressif/ulp/lp_core/debug_ulp/remote/src/main.c, line 28.
(gdb)
From now on you can use the GDB commands to debug the application. By using the command continue
the LP Core application stop at the assigned breakpoint:
(gdb) continue
Continuing.
[Switching to Thread 2]
Thread 2 "esp32c6.lp.cpu" hit Temporary breakpoint 1, do_things (max=1000000000) at zephyr/samples/boards/espressif/ulp/lp_core/debug_ulp/remote/src/main.c:28
28 for (int i = 0; i < max; i++) {
(gdb)
When the application reaches the abort()
function it will automatically break.