chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:04:25 +08:00
commit 548b49ebc0
20937 changed files with 5455372 additions and 0 deletions
@@ -0,0 +1,9 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.22)
list(APPEND SDKCONFIG_DEFAULTS "sdkconfig.defaults")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(lp_debugging_example)
@@ -0,0 +1,81 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
| ----------------- | -------- | -------- | -------- | --------- |
# LP Core Debugging Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview
This example demonstrates how to debug application running on the LP core.
## How to use example
### Hardware Required
To run this example, you should have an ESP based development board that integrates an LP core.
### Build and Flash
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Debugging Session
1) Run OpenOCD `openocd -f board/esp32c6-lpcore-builtin.cfg`.
2) Run GDB `riscv32-esp-elf-gdb -x gdbinit build/lp_debugging_example.elf`
3) `gdbinit` file will tell GDB to load debug info and symbols and set a number of breakpoints.
4) Type `c` upon hitting every breakpoint.
5) Finally LP core application should stop in `abort()`.
### LP Core Debugging Specifics
1) For convenient debugging, `-O0` compile option for ULP app in its CMakeLists.txt can be added. Beware that this change may cause the built binary to be too large to fit in the available memory.
```
target_compile_options(${ULP_APP_NAME} PRIVATE -O0)
```
2) LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app add `-fsanitize=undefined -fno-sanitize=shift-base` compile option to its CMakeLists.txt.
```
target_compile_options(${ULP_APP_NAME} PRIVATE -fsanitize=undefined -fno-sanitize=shift-base)
```
3) To be able to debug program running on LP core debug info and symbols need to be loaded to GDB. So there is special GDB command in `gdbinit`:
```
add-symbol build/esp-idf/main/ulp_debug_example/ulp_debug_example.elf
```
4) Upon startup LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function. So `gdbinit` file used in this example sets temporary HW breakpoint on `main` and then set a bunch of other breakpoints when it hit.
```
thb main
commands
b do_crash
b do_things
commands
c
end
b ulp_lp_core_delay_us
commands
c
end
c
end
```
## Limitations
1) Currently debugging is not supported when either HP or LP core enters any sleep mode. So this limits debugging scenarios.
2) FreeRTOS support in OpenOCD is disabled when debugging 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) 0x4080261c in esp_cpu_wait_for_intr ()
at /home/user/projects/esp/esp-idf/components/esp_hw_support/cpu.c:64
* 2 Thread 2 "esp32c6.lp.cpu" (Name: esp32c6.lp.cpu, state: breakpoint) do_things (max=1000000000)
at /home/user/projects/esp/esp-idf/examples/system/ulp/lp_core/debugging/main/ulp/main.c:22
```
3) 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, ESP32-C5 or ESP32-P4).
## Troubleshooting
(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)
@@ -0,0 +1,22 @@
set pagination off
target extended-remote :3333
mon reset halt
maintenance flush register-cache
add-symbol build/esp-idf/main/ulp_debug_example/ulp_debug_example.elf
thb main
commands
b do_crash
b do_things
commands
c
end
b ulp_lp_core_delay_us
commands
c
end
c
end
c
@@ -0,0 +1,8 @@
# Set usual component variables
set(app_sources "lp_debug_main.c")
idf_component_register(SRCS ${app_sources}
REQUIRES ulp
WHOLE_ARCHIVE)
ulp_add_project("ulp_debug_example" "${CMAKE_SOURCE_DIR}/main/ulp/")
@@ -0,0 +1,43 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "esp_sleep.h"
#include "esp_err.h"
#include "ulp_lp_core.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
extern const uint8_t ulp_build_debug_bin_start[] asm("_binary_ulp_debug_example_bin_start");
extern const uint8_t ulp_build_debug_bin_end[] asm("_binary_ulp_debug_example_bin_end");
static void lp_core_init(void)
{
/* Set LP core wakeup source as the HP CPU */
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
};
/* Load LP core firmware */
ESP_ERROR_CHECK(ulp_lp_core_load_binary(ulp_build_debug_bin_start, (ulp_build_debug_bin_end - ulp_build_debug_bin_start)));
/* Run LP core */
ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));
printf("LP core loaded with firmware and running successfully\n");
}
void app_main(void)
{
printf("Initializing LP core...\n");
/* Load LP Core binary and start the coprocessor */
lp_core_init();
printf("Do some work on HP core...\n");
while(1) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
@@ -0,0 +1,37 @@
# This CMakelists.txt is included in the ULP project
# so we have access to the ULP target: ULP_APP_NAME
cmake_minimum_required(VERSION 3.22)
# Project/target name is passed from the main project to allow IDF to have a dependency on this target
# as well as embed the binary into the main app
project(${ULP_APP_NAME})
add_executable(${ULP_APP_NAME} main.c)
# Import the ULP project helper functions
include(IDFULPProject)
# Apply default compile options
ulp_apply_default_options(${ULP_APP_NAME})
# Apply default sources provided by the IDF ULP component
ulp_apply_default_sources(${ULP_APP_NAME})
# Add targets for building the binary, as well as the linkerscript which exports ULP shared variables to the main app
ulp_add_build_binary_targets(${ULP_APP_NAME})
# Set custom compile flags
# By default ULP sources are compiled with -Os which is set in toolchain file in IDF build system.
# These options will appear on command line after default ones effectively overriding them.
# Therefore '-Os' can be overridden here with '-O0' for this example for convenient debugging.
target_compile_options(${ULP_APP_NAME} PRIVATE -fsanitize=undefined -fno-sanitize=shift-base)
add_custom_command(
TARGET ${ULP_APP_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${ULP_APP_NAME}>
$<TARGET_FILE_DIR:${ULP_APP_NAME}>/../../../gdbinit/$<TARGET_FILE_NAME:${ULP_APP_NAME}>
)
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_lp_core_utils.h"
void do_crash(void)
{
volatile int *p = (int *)0x0;
// if ubsan is enabled (-fsanitize=undefined) line below will cause ubsan check failure
// and finally app will be stopped in abort()
*p = 32;
// if ubsan is disabled app will be stopped in abort() call below
abort();
}
void do_things(int max)
{
while (1) {
for (int i = 0; i < max; i++) {
ulp_lp_core_delay_us(100000);
if (i > 0)
do_crash();
}
}
}
int main (void)
{
do_things(1000000000);
return 0;
}
@@ -0,0 +1,58 @@
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import os.path
import time
import typing
import pexpect.fdpexpect
import pytest
from pytest_embedded_idf import IdfDut
from pytest_embedded_idf.utils import idf_parametrize
if typing.TYPE_CHECKING:
from conftest import OpenOCD
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4', 'esp32s31'], indirect=['target'])
@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='s31-lpcore not supported in latest OpenOCD release yet')
@pytest.mark.usb_serial_jtag
def test_lp_core_debugging(openocd_dut: 'OpenOCD', dut: IdfDut) -> None:
dut.expect('Do some work on HP core...')
# Prepare gdbinit file
gdb_logfile = os.path.join(dut.logdir, 'gdb.txt')
gdbinit_orig = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gdbinit')
gdbinit = os.path.join(dut.logdir, 'gdbinit')
with open(gdbinit_orig) as f_r, open(gdbinit, 'w') as f_w:
for line in f_r:
if line.startswith('add-symbol'):
f_w.write(f'add-symbol {dut.app.binary_path}/gdbinit/ulp_debug_example.elf\n')
else:
f_w.write(line)
# Launch with gdbinit and check abort function is called
with (
openocd_dut.run() as oocd,
open(gdb_logfile, 'w') as gdb_log,
pexpect.spawn(
f'idf.py -B {dut.app.binary_path} gdb --batch -x {gdbinit}',
timeout=60,
logfile=gdb_log,
encoding='utf-8',
codec_errors='ignore',
) as p,
):
p.expect('hit Breakpoint 2, do_crash')
# dont intercept ebreak in abort
oocd.write(f'{dut.target}.lp.cpu configure -ebreak exception')
# let the panic handler finish
oocd.write('resume')
time.sleep(2)
# Validate GDB logs
with open(gdb_logfile, encoding='utf-8') as fr: # pylint: disable=protected-access
gdb_pexpect_proc = pexpect.fdpexpect.fdspawn(fr.fileno())
gdb_pexpect_proc.expect('hit Temporary breakpoint 1, main')
gdb_pexpect_proc.expect('hit Breakpoint 3, do_things')
gdb_pexpect_proc.expect('hit Breakpoint 4, ulp_lp_core_delay_us')
gdb_pexpect_proc.expect('hit Breakpoint 2, do_crash')
@@ -0,0 +1,4 @@
# Enable LP Core
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=14000