mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/backtrace_dumps' into 'master'
Feature/backtrace dumps Github pull request https://github.com/espressif/esp-idf/pull/149 (Plus reformatting of panic.c, as it hadn't been formatted to our code style yet.) See merge request !290
This commit is contained in:
commit
f807d16310
@ -45,48 +45,59 @@ Note: The linker script will put everything in this file in IRAM/DRAM, so it als
|
||||
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
//printf may be broken, so we fix our own printing fns...
|
||||
inline static void panicPutchar(char c) {
|
||||
inline static void panicPutChar(char c)
|
||||
{
|
||||
while (((READ_PERI_REG(UART_STATUS_REG(0)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
|
||||
WRITE_PERI_REG(UART_FIFO_REG(0), c);
|
||||
}
|
||||
|
||||
inline static void panicPutStr(const char *c) {
|
||||
inline static void panicPutStr(const char *c)
|
||||
{
|
||||
int x = 0;
|
||||
while (c[x] != 0) {
|
||||
panicPutchar(c[x]);
|
||||
panicPutChar(c[x]);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void panicPutHex(int a) {
|
||||
inline static void panicPutHex(int a)
|
||||
{
|
||||
int x;
|
||||
int c;
|
||||
panicPutchar(' ');
|
||||
for (x = 0; x < 8; x++) {
|
||||
c = (a >> 28) & 0xf;
|
||||
if (c<10) panicPutchar('0'+c); else panicPutchar('a'+c-10);
|
||||
if (c < 10) {
|
||||
panicPutChar('0' + c);
|
||||
} else {
|
||||
panicPutChar('a' + c - 10);
|
||||
}
|
||||
a <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void panicPutDec(int a) {
|
||||
inline static void panicPutDec(int a)
|
||||
{
|
||||
int n1, n2;
|
||||
n1 = a % 10;
|
||||
n2 = a / 10;
|
||||
panicPutchar(' ');
|
||||
if (n2==0) panicPutchar(' '); else panicPutchar(n2+'0');
|
||||
panicPutchar(n1+'0');
|
||||
if (n2 == 0) {
|
||||
panicPutChar(' ');
|
||||
} else {
|
||||
panicPutChar(n2 + '0');
|
||||
}
|
||||
panicPutChar(n1 + '0');
|
||||
}
|
||||
#else
|
||||
//No printing wanted. Stub out these functions.
|
||||
inline static void panicPutchar(char c) { }
|
||||
inline static void panicPutChar(char c) { }
|
||||
inline static void panicPutStr(const char *c) { }
|
||||
inline static void panicPutHex(int a) { }
|
||||
inline static void panicPutDec(int a) { }
|
||||
#endif
|
||||
|
||||
|
||||
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) {
|
||||
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
|
||||
{
|
||||
panicPutStr("***ERROR*** A stack overflow in task ");
|
||||
panicPutStr((char *)pcTaskName);
|
||||
panicPutStr(" has been detected.\r\n");
|
||||
@ -117,7 +128,8 @@ static void haltOtherCore()
|
||||
}
|
||||
|
||||
//Returns true when a debugger is attached using JTAG.
|
||||
static int inOCDMode() {
|
||||
static int inOCDMode()
|
||||
{
|
||||
#if CONFIG_ESP32_DEBUG_OCDAWARE
|
||||
int dcr;
|
||||
int reg = 0x10200C; //DSRSET register
|
||||
@ -128,7 +140,8 @@ static int inOCDMode() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void panicHandler(XtExcFrame *frame) {
|
||||
void panicHandler(XtExcFrame *frame)
|
||||
{
|
||||
int *regs = (int *)frame;
|
||||
//Please keep in sync with PANIC_RSN_* defines
|
||||
const char *reasons[] = {
|
||||
@ -142,7 +155,9 @@ void panicHandler(XtExcFrame *frame) {
|
||||
};
|
||||
const char *reason = reasons[0];
|
||||
//The panic reason is stored in the EXCCAUSE register.
|
||||
if (regs[20]<=PANIC_RSN_MAX) reason=reasons[regs[20]];
|
||||
if (regs[20] <= PANIC_RSN_MAX) {
|
||||
reason = reasons[regs[20]];
|
||||
}
|
||||
haltOtherCore();
|
||||
panicPutStr("Guru Meditation Error: Core ");
|
||||
panicPutDec(xPortGetCoreID());
|
||||
@ -156,7 +171,8 @@ void panicHandler(XtExcFrame *frame) {
|
||||
commonErrorHandler(frame);
|
||||
}
|
||||
|
||||
static void setFirstBreakpoint(uint32_t pc) {
|
||||
static void setFirstBreakpoint(uint32_t pc)
|
||||
{
|
||||
asm(
|
||||
"wsr.ibreaka0 %0\n" \
|
||||
"rsr.ibreakenable a3\n" \
|
||||
@ -166,14 +182,19 @@ static void setFirstBreakpoint(uint32_t pc) {
|
||||
::"r"(pc):"a3", "a4");
|
||||
}
|
||||
|
||||
void xt_unhandled_exception(XtExcFrame *frame) {
|
||||
void xt_unhandled_exception(XtExcFrame *frame)
|
||||
{
|
||||
int *regs = (int *)frame;
|
||||
int x;
|
||||
|
||||
haltOtherCore();
|
||||
panicPutStr("Guru Meditation Error of type ");
|
||||
x = regs[20];
|
||||
if (x<40) panicPutStr(edesc[x]); else panicPutStr("Unknown");
|
||||
if (x < 40) {
|
||||
panicPutStr(edesc[x]);
|
||||
} else {
|
||||
panicPutStr("Unknown");
|
||||
}
|
||||
panicPutStr(" occurred on core ");
|
||||
panicPutDec(xPortGetCoreID());
|
||||
if (inOCDMode()) {
|
||||
@ -197,7 +218,8 @@ the risk of somehow halting in the panic handler and not resetting. That is why
|
||||
all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
|
||||
one second.
|
||||
*/
|
||||
static void reconfigureAllWdts() {
|
||||
static void reconfigureAllWdts()
|
||||
{
|
||||
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG0.wdt_feed = 1;
|
||||
TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS
|
||||
@ -217,7 +239,8 @@ static void reconfigureAllWdts() {
|
||||
/*
|
||||
This disables all the watchdogs for when we call the gdbstub.
|
||||
*/
|
||||
static void disableAllWdts() {
|
||||
static void disableAllWdts()
|
||||
{
|
||||
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG0.wdt_config0.en = 0;
|
||||
TIMERG0.wdt_wprotect = 0;
|
||||
@ -228,17 +251,55 @@ static void disableAllWdts() {
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool stackPointerIsSane(uint32_t sp)
|
||||
{
|
||||
return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0));
|
||||
}
|
||||
static void putEntry(uint32_t pc, uint32_t sp)
|
||||
{
|
||||
if (pc & 0x80000000) {
|
||||
pc = (pc & 0x3fffffff) | 0x40000000;
|
||||
}
|
||||
panicPutStr(" 0x");
|
||||
panicPutHex(pc);
|
||||
panicPutStr(":0x");
|
||||
panicPutHex(sp);
|
||||
}
|
||||
void doBacktrace(XtExcFrame *frame)
|
||||
{
|
||||
uint32_t i = 0, pc = frame->pc, sp = frame->a1;
|
||||
panicPutStr("\nBacktrace:");
|
||||
/* Do not check sanity on first entry, PC could be smashed. */
|
||||
putEntry(pc, sp);
|
||||
pc = frame->a0;
|
||||
while (i++ < 100) {
|
||||
uint32_t psp = sp;
|
||||
if (!stackPointerIsSane(sp) || i++ > 100) {
|
||||
break;
|
||||
}
|
||||
sp = *((uint32_t *) (sp - 0x10 + 4));
|
||||
putEntry(pc, sp);
|
||||
pc = *((uint32_t *) (psp - 0x10));
|
||||
if (pc < 0x40000000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
panicPutStr("\n\n");
|
||||
}
|
||||
|
||||
/*
|
||||
We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
|
||||
serial port and either jump to the gdb stub, halt the CPU or reboot.
|
||||
*/
|
||||
void commonErrorHandler(XtExcFrame *frame) {
|
||||
void commonErrorHandler(XtExcFrame *frame)
|
||||
{
|
||||
int *regs = (int *)frame;
|
||||
int x, y;
|
||||
const char *sdesc[] = {
|
||||
"PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
|
||||
"A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
|
||||
"A14 ","A15 ","SAR ","EXCCAUSE","EXCVADDR","LBEG ","LEND ","LCOUNT "};
|
||||
"A14 ", "A15 ", "SAR ", "EXCCAUSE", "EXCVADDR", "LBEG ", "LEND ", "LCOUNT "
|
||||
};
|
||||
|
||||
//Feed the watchdogs, so they will give us time to print out debug info
|
||||
reconfigureAllWdts();
|
||||
@ -249,20 +310,24 @@ void commonErrorHandler(XtExcFrame *frame) {
|
||||
for (y = 0; y < 4; y++) {
|
||||
if (sdesc[x + y][0] != 0) {
|
||||
panicPutStr(sdesc[x + y]);
|
||||
panicPutStr(": ");
|
||||
panicPutStr(": 0x");
|
||||
panicPutHex(regs[x + y + 1]);
|
||||
panicPutStr(" ");
|
||||
}
|
||||
}
|
||||
panicPutStr("\r\n");
|
||||
}
|
||||
/* With windowed ABI backtracing is easy, let's do it. */
|
||||
doBacktrace(frame);
|
||||
#if CONFIG_ESP32_PANIC_GDBSTUB
|
||||
disableAllWdts();
|
||||
panicPutStr("Entering gdb stub now.\r\n");
|
||||
esp_gdbstub_panic_handler(frame);
|
||||
#elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
panicPutStr("Rebooting...\r\n");
|
||||
for (x=0; x<100; x++) ets_delay_us(1000);
|
||||
for (x = 0; x < 100; x++) {
|
||||
ets_delay_us(1000);
|
||||
}
|
||||
software_reset();
|
||||
#else
|
||||
disableAllWdts();
|
||||
@ -272,7 +337,10 @@ void commonErrorHandler(XtExcFrame *frame) {
|
||||
}
|
||||
|
||||
|
||||
void esp_set_breakpoint_if_jtag(void *fn) {
|
||||
if (!inOCDMode()) return;
|
||||
void esp_set_breakpoint_if_jtag(void *fn)
|
||||
{
|
||||
if (!inOCDMode()) {
|
||||
return;
|
||||
}
|
||||
setFirstBreakpoint((uint32_t)fn);
|
||||
}
|
||||
|
0
tools/format.sh
Normal file → Executable file
0
tools/format.sh
Normal file → Executable file
Loading…
Reference in New Issue
Block a user