feat(ulp): add lp core panic handler

This commit is contained in:
Marius Vikhammer
2024-05-30 14:41:31 +08:00
parent 7f9b5deae1
commit 87d4172ee5
14 changed files with 198 additions and 49 deletions
@@ -1466,3 +1466,7 @@ config SOC_PHY_COMBO_MODULE
config SOC_CAPS_NO_RESET_BY_ANA_BOD
bool
default y
config SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR
bool
default y
@@ -583,3 +583,7 @@
/*------------------------------------- No Reset CAPS -------------------------------------*/
#define SOC_CAPS_NO_RESET_BY_ANA_BOD (1)
/*------------------------------------- ULP CAPS -------------------------------------*/
#define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */
+16
View File
@@ -92,4 +92,20 @@ menu "Ultra Low Power (ULP) Co-processor"
Note: For LP ROM prints to work properly, make sure that the LP core boots
from the LP ROM.
menu "ULP Debugging Options"
config ULP_PANIC_OUTPUT_ENABLE
depends on ULP_COPROC_TYPE_LP_CORE && SOC_ULP_LP_UART_SUPPORTED
bool
prompt "Enable panic handler which outputs over LP UART"
default "y" if IDF_TARGET_ESP32P4
help
Set this option to enable panic handler functionality. If this option is
enabled then the LP Core will output a panic dump over LP UART,
similar to what the main core does. Output depends on LP UART already being
initialized and configured.
Disabling this option will reduce the LP core binary size by not
linking in panic handler functionality.
endmenu
endmenu # Ultra Low Power (ULP) Co-processor
+3 -1
View File
@@ -101,7 +101,8 @@ if(ULP_COCPU_IS_RISCV)
elseif(ULP_COCPU_IS_LP_CORE)
list(APPEND ULP_S_SOURCES
"${IDF_PATH}/components/ulp/lp_core/lp_core/start.S"
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/${IDF_TARGET}/vector.S"
"${IDF_PATH}/components/ulp/lp_core/lp_core/vector.S"
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/${IDF_TARGET}/vector_table.S"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_memory_shared.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_startup.c"
@@ -111,6 +112,7 @@ elseif(ULP_COCPU_IS_LP_CORE)
"${IDF_PATH}/components/hal/uart_hal.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_uart.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_print.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_panic.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_interrupt.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_i2c.c")
@@ -5,11 +5,11 @@ set(CMAKE_C_COMPILER "riscv32-esp-elf-gcc")
set(CMAKE_CXX_COMPILER "riscv32-esp-elf-g++")
set(CMAKE_ASM_COMPILER "riscv32-esp-elf-gcc")
set(CMAKE_C_FLAGS "-Os -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffunction-sections"
set(CMAKE_C_FLAGS "-Os -ggdb -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffunction-sections"
CACHE STRING "C Compiler Base Flags")
set(CMAKE_CXX_FLAGS "-Os -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffunction-sections"
set(CMAKE_CXX_FLAGS "-Os -ggdb -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffunction-sections"
CACHE STRING "C++ Compiler Base Flags")
set(CMAKE_ASM_FLAGS "-march=rv32imac_zicsr_zifencei -x assembler-with-cpp"
set(CMAKE_ASM_FLAGS "-Os -ggdb -march=rv32imac_zicsr_zifencei -x assembler-with-cpp"
CACHE STRING "Assembler Base Flags")
set(CMAKE_EXE_LINKER_FLAGS "-march=rv32imac_zicsr_zifencei --specs=nano.specs --specs=nosys.specs"
CACHE STRING "Linker Base Flags")
@@ -9,6 +9,7 @@
#include "sdkconfig.h"
#include "hal/lp_core_ll.h"
#include "riscv/rv_utils.h"
#include "riscv/rvruntime-frames.h"
#if CONFIG_IDF_TARGET_ESP32C6
/* Enable interrupt 30, which all external interrupts are routed to*/
@@ -36,6 +37,11 @@ void ulp_lp_core_intr_disable(void)
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
}
void __attribute__((weak)) ulp_lp_core_panic_handler(RvExcFrame *frame, int exccause)
{
abort();
}
static void ulp_lp_core_default_intr_handler(void)
{
abort();
@@ -60,11 +66,6 @@ void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_cor
void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_core_lp_rtc_intr_handler(void);
void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_core_sw_intr_handler(void);
void ulp_lp_core_panic_handler(void)
{
abort();
}
#if CONFIG_IDF_TARGET_ESP32C6
static void* s_intr_handlers[] = {
@@ -0,0 +1,80 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stdint.h>
#include <stddef.h>
#include "ulp_lp_core_print.h"
#include "riscv/rvruntime-frames.h"
#if CONFIG_ULP_PANIC_OUTPUT_ENABLE
static void dump_stack(RvExcFrame *frame, int exccause)
{
uint32_t i = 0;
uint32_t sp = frame->sp;
lp_core_printf("\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);
for (int y = 0; y < per_line; y++) {
lp_core_printf("0x%08x%c", spp[y], y == per_line - 1 ? '\n' : ' ');
}
}
lp_core_printf("\n");
}
static const char *desc[] = {
"MEPC ", "RA ", "SP ", "GP ", "TP ", "T0 ", "T1 ", "T2 ",
"S0/FP ", "S1 ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
"A6 ", "A7 ", "S2 ", "S3 ", "S4 ", "S5 ", "S6 ", "S7 ",
"S8 ", "S9 ", "S10 ", "S11 ", "T3 ", "T4 ", "T5 ", "T6 ",
"MSTATUS ", "MTVEC ", "MCAUSE ", "MTVAL ", "MHARTID "
};
static const char *reason[] = {
NULL,
NULL,
"Illegal instruction",
"Breakpoint",
"Load address misaligned",
"Load access fault",
"Store address misaligned",
"Store access fault",
};
void ulp_lp_core_panic_handler(RvExcFrame *frame, int exccause)
{
#define DIM(arr) (sizeof(arr)/sizeof(*arr))
const char *exccause_str = "Unhandled interrupt/Unknown cause";
if (exccause < DIM(reason) && reason[exccause] != NULL) {
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");
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');
}
}
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");
while (1) {
}
}
#endif //#if CONFIG_ULP_PANIC_OUTPUT_ENABLE
@@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
.section .init.vector,"ax"
.global _vector_table
.type _vector_table, @function
_vector_table:
.option push
.option norvc
.rept 30
j _panic_handler
.endr
j _interrupt_handler // All interrupts are routed to mtvec + 4*30, i.e. the 31st entry
j _panic_handler
.option pop
.size _vector_table, .-_vector_table
@@ -47,13 +47,3 @@ _vector_table:
.option pop
.size _vector_table, .-_vector_table
/* _panic_handler: handle all exception */
.section .text.handlers,"ax"
.global _panic_handler
.type _panic_handler, @function
_panic_handler:
call ulp_lp_core_panic_handler
_end:
j _end /* loop forever */
@@ -5,6 +5,7 @@
*/
#include "riscv/rvruntime-frames.h"
#include "soc/soc_caps.h"
.equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
@@ -92,47 +93,54 @@
.endm
.section .init.vector,"ax"
.global _vector_table
.type _vector_table, @function
_vector_table:
.option push
.option norvc
.rept 30
j _panic_handler
.endr
j _interrupt_handler // All interrupts are routed to mtvec + 4*30, i.e. the 31st entry
j _panic_handler
.option pop
.size _vector_table, .-_vector_table
/* _panic_handler: handle all exception */
.section .text.handlers,"ax"
.global _panic_handler
.type _panic_handler, @function
_panic_handler:
call ulp_lp_core_panic_handler
_end:
j _end /* loop forever */
save_general_regs RV_STK_FRMSZ
save_mepc
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
/* Save CSRs */
sw t0, RV_STK_SP(sp)
csrr t0, mstatus
sw t0, RV_STK_MSTATUS(sp)
csrr t0, mcause
sw t0, RV_STK_MCAUSE(sp)
csrr t0, mtvec
sw t0, RV_STK_MTVEC(sp)
csrr t0, mhartid
sw t0, RV_STK_MHARTID(sp)
csrr t0, mtval
sw t0, RV_STK_MTVAL(sp)
csrr a1, mcause /* exception cause */
mv a0, sp /* RvExcFrame *regs */
call ulp_lp_core_panic_handler
_end:
j _end /* loop forever */
#if SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR
/* interrupt_handler: handle all interrupt */
.section .text.handlers,"ax"
.global _interrupt_handler
.type _interrupt_handler, @function
.section .text.handlers,"ax"
.global _interrupt_handler
.type _interrupt_handler, @function
_interrupt_handler:
/* save registers & mepc to stack */
save_general_regs
save_mepc
call ulp_lp_core_intr_handler
call ulp_lp_core_intr_handler
/* restore registers & mepc from stack */
/* restore registers & mepc from stack */
restore_mepc
restore_general_regs
/* exit, this will also re-enable the interrupts */
mret
mret
#endif // SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR
@@ -20,12 +20,15 @@ int main(void)
ulp_lp_core_gpio_output_enable(LP_IO_NUM_0);
ulp_lp_core_gpio_set_level(LP_IO_NUM_0, 0);
ulp_lp_core_delay_us(100);
gpio_test_succeeded = (ulp_lp_core_gpio_get_level(LP_IO_NUM_0) == 0);
ulp_lp_core_gpio_set_level(LP_IO_NUM_0, 1);
ulp_lp_core_delay_us(100);
gpio_test_succeeded &= (ulp_lp_core_gpio_get_level(LP_IO_NUM_0) == 1);
ulp_lp_core_gpio_set_level(LP_IO_NUM_0, 0);
ulp_lp_core_delay_us(100);
gpio_test_succeeded &= (ulp_lp_core_gpio_get_level(LP_IO_NUM_0) == 0);
gpio_test_finished = 1;
@@ -2,4 +2,5 @@ CONFIG_ESP_TASK_WDT_INIT=n
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=4096
CONFIG_ULP_COPROC_RESERVE_MEM=12000
CONFIG_ULP_PANIC_OUTPUT_ENABLE=y