diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h index 27a080581d..eeb15208dd 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h @@ -44,3 +44,26 @@ extern void ets_install_uart_printf(void); * @param c character to be printed */ void lp_core_print_char(char c); + +/** + * @brief Print a null-terminated string from the LP core + * + * @param str null-terminated string to be printed + */ +void lp_core_print_str(const char *str); + +/** + * @brief Print a hex value from the LP core + * + * @param h hex value to be printed + * + * @note Does not print '0x', only the digits (will always print 8 digits) + */ +void lp_core_print_hex(int h); + +/** + * @brief Print a two digit integer from the LP-Core + * + * @param d integer to be printed + */ +void lp_core_print_dec_two_digits(int d); diff --git a/components/ulp/lp_core/lp_core/lp_core_panic.c b/components/ulp/lp_core/lp_core/lp_core_panic.c index 70fac05483..f85f6f3088 100644 --- a/components/ulp/lp_core/lp_core/lp_core_panic.c +++ b/components/ulp/lp_core/lp_core/lp_core_panic.c @@ -16,16 +16,19 @@ static void dump_stack(RvExcFrame *frame, int exccause) { uint32_t i = 0; uint32_t sp = frame->sp; - lp_core_printf("\n\nStack memory:\n"); + lp_core_print_str("\n\nStack memory:\n"); const int per_line = 8; for (i = 0; i < 1024; i += per_line * sizeof(uint32_t)) { uint32_t *spp = (uint32_t *)(sp + i); - lp_core_printf("%08x: ", sp + i); + lp_core_print_hex(sp + i); + lp_core_print_str(": "); for (int y = 0; y < per_line; y++) { - lp_core_printf("0x%08x%c", spp[y], y == per_line - 1 ? '\n' : ' '); + lp_core_print_str("0x"); + lp_core_print_hex(spp[y]); + lp_core_print_char(y == per_line - 1 ? '\n' : ' '); } } - lp_core_printf("\n"); + lp_core_print_str("\n"); } static const char *desc[] = { @@ -57,21 +60,26 @@ void ulp_lp_core_panic_handler(RvExcFrame *frame, int exccause) exccause_str = reason[exccause]; } - lp_core_printf("Guru Meditation Error: LP Core panic'ed (%s)\n", exccause_str); - lp_core_printf("Core 0 register dump:\n"); + lp_core_print_str("Guru Meditation Error: LP Core panic'ed "); + lp_core_print_str(exccause_str); + lp_core_print_str("\n"); + lp_core_print_str("Core 0 register dump:\n"); uint32_t* frame_ints = (uint32_t*) frame; for (int x = 0; x < DIM(desc); x++) { if (desc[x][0] != 0) { const int not_last = (x + 1) % 4; - lp_core_printf("%-8s: 0x%08x %c", desc[x], frame_ints[x], not_last ? ' ' : '\n'); + lp_core_print_str(desc[x]); + lp_core_print_str(": 0x"); + lp_core_print_hex(frame_ints[x]); + lp_core_print_char(not_last ? ' ' : '\n'); } } dump_stack(frame, exccause); /* idf-monitor uses this string to mark the end of a panic dump */ - lp_core_printf("ELF file SHA256: No SHA256 Embedded\n"); + lp_core_print_str("ELF file SHA256: No SHA256 Embedded\n"); while (1) { } diff --git a/components/ulp/lp_core/lp_core/lp_core_print.c b/components/ulp/lp_core/lp_core/lp_core_print.c index 0a704c28a3..64d07b783f 100644 --- a/components/ulp/lp_core/lp_core/lp_core_print.c +++ b/components/ulp/lp_core/lp_core/lp_core_print.c @@ -298,3 +298,40 @@ int lp_core_printf(const char* format, ...) } #endif /* !CONFIG_ULP_ROM_PRINT_ENABLE */ + +void lp_core_print_str(const char *str) +{ + for (int i = 0; str[i] != 0; i++) { + lp_core_print_char(str[i]); + } +} + +void lp_core_print_hex(int h) +{ + int x; + int c; + // Does not print '0x', only the digits (8 digits to print) + for (x = 0; x < 8; x++) { + c = (h >> 28) & 0xf; // extract the leftmost byte + if (c < 10) { + lp_core_print_char('0' + c); + } else { + lp_core_print_char('a' + c - 10); + } + h <<= 4; // move the 2nd leftmost byte to the left, to be extracted next + } +} + +void lp_core_print_dec_two_digits(int d) +{ + // can print at most 2 digits! + int n1, n2; + n1 = d % 10; // extract ones digit + n2 = d / 10; // extract tens digit + if (n2 == 0) { + lp_core_print_char(' '); + } else { + lp_core_print_char(n2 + '0'); + } + lp_core_print_char(n1 + '0'); +} diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt index 6fce89dfdd..87918dae18 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/CMakeLists.txt @@ -1,5 +1,6 @@ set(app_sources "test_app_main.c" "test_lp_core.c") -set(lp_core_sources "lp_core/test_hello_main.c") +set(lp_core_sources "lp_core/test_hello_main.c") +set(lp_core_sources_panic "lp_core/test_panic_main.c") idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" @@ -9,3 +10,4 @@ idf_component_register(SRCS ${app_sources} set(lp_core_exp_dep_srcs ${app_sources}) ulp_embed_binary(lp_core_test_app "${lp_core_sources}" "${lp_core_exp_dep_srcs}") +ulp_embed_binary(lp_core_test_app_panic "${lp_core_sources_panic}" "${lp_core_exp_dep_srcs}") diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_hello_main.c b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_hello_main.c index 3c844cec7d..504aedd026 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_hello_main.c +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_hello_main.c @@ -8,9 +8,18 @@ #include #include "ulp_lp_core_print.h" +volatile int hex_value = 0x1234ABCD; +volatile int dec_value = 56; + int main(void) { lp_core_printf("Hello, World!\n"); + lp_core_print_hex(hex_value); + lp_core_print_char('\n'); + + lp_core_print_dec_two_digits(dec_value); + lp_core_print_char('\n'); + return 0; } diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_panic_main.c b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_panic_main.c new file mode 100644 index 0000000000..4985426beb --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/lp_core/test_panic_main.c @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int main(void) +{ + asm volatile("ebreak"); + + return 0; +} diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c index 0d3949cd59..bdd1e863c7 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/main/test_lp_core.c @@ -19,6 +19,9 @@ extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_bin_start"); extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_bin_end"); +extern const uint8_t lp_core_panic_bin_start[] asm("_binary_lp_core_test_app_panic_bin_start"); +extern const uint8_t lp_core_panic_bin_end[] asm("_binary_lp_core_test_app_panic_bin_end"); + static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end) { TEST_ASSERT(ulp_lp_core_load_binary(firmware_start, @@ -41,3 +44,17 @@ TEST_CASE("lp-print can output to hp-uart", "[lp_core]") // We simply wait to allow the lp-core to run once vTaskDelay(1000 / portTICK_PERIOD_MS); } + +TEST_CASE("LP-Core panic", "[lp_core]") +{ + /* Load ULP firmware and start the coprocessor */ + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + + load_and_start_lp_core_firmware(&cfg, lp_core_panic_bin_start, lp_core_panic_bin_end); + + // Actual test output on UART is checked by pytest, not unity test-case + // We simply wait to allow the lp-core to run once + vTaskDelay(1000 / portTICK_PERIOD_MS); +} diff --git a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py index df0edfec74..974a9d108a 100644 --- a/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py +++ b/components/ulp/test_apps/lp_core/lp_core_hp_uart/pytest_lp_core_hp_uart.py @@ -12,3 +12,18 @@ def test_lp_core_hp_uart_print(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('"lp-print can output to hp-uart"') dut.expect_exact('Hello, World!') + dut.expect_exact('1234abcd') + dut.expect_exact('56') + + +@pytest.mark.esp32c5 +@pytest.mark.esp32c6 +@pytest.mark.esp32p4 +@pytest.mark.generic +def test_lp_core_panic(dut: Dut) -> None: + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('"LP-Core panic"') + + dut.expect_exact("Guru Meditation Error: LP Core panic'ed Breakpoint") + dut.expect_exact('Core 0 register dump:') + dut.expect_exact('ELF file SHA256:')