Skip to content

Commit 703a9f3

Browse files
committed
Print stack on exception and soft WDT reset
1 parent 66b480a commit 703a9f3

File tree

3 files changed

+131
-4
lines changed

3 files changed

+131
-4
lines changed

cores/esp8266/core_esp8266_main.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ void user_init(void) {
129129
uart_div_modify(0, UART_CLK_FREQ / (74480));
130130

131131
system_rtc_mem_read(0, &resetInfo, sizeof(struct rst_info));
132-
if(resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST) {
133-
os_printf("Last Reset:\n - flag=%d\n - Fatal exception (%d):\n - epc1=0x%08x,epc2=0x%08x,epc3=0x%08x,excvaddr=0x%08x,depc=0x%08x\n", resetInfo.reason, resetInfo.exccause, resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, resetInfo.excvaddr, resetInfo.depc);
134-
}
135132
struct rst_info info = { 0 };
136133
system_rtc_mem_write(0, &info, sizeof(struct rst_info));
137134

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
postmortem.c - output of debug info on sketch crash
3+
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
4+
This file is part of the esp8266 core for Arduino environment.
5+
6+
This library is free software; you can redistribute it and/or
7+
modify it under the terms of the GNU Lesser General Public
8+
License as published by the Free Software Foundation; either
9+
version 2.1 of the License, or (at your option) any later version.
10+
11+
This library is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
Lesser General Public License for more details.
15+
16+
You should have received a copy of the GNU Lesser General Public
17+
License along with this library; if not, write to the Free Software
18+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19+
*/
20+
21+
22+
#include <stdint.h>
23+
#include <stddef.h>
24+
#include <stdbool.h>
25+
#include "ets_sys.h"
26+
#include "user_interface.h"
27+
#include "esp8266_peri.h"
28+
#include "cont.h"
29+
30+
extern void __real_system_restart_local();
31+
extern cont_t g_cont;
32+
33+
static void uart0_write_char_d(char c);
34+
static void print_stack(uint32_t start, uint32_t end);
35+
static void print_pcs(uint32_t start, uint32_t end);
36+
37+
void __wrap_system_restart_local() {
38+
register uint32_t sp asm("a1");
39+
40+
struct rst_info rst_info = {0};
41+
system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
42+
if (rst_info.reason != REASON_SOFT_WDT_RST &&
43+
rst_info.reason != REASON_EXCEPTION_RST &&
44+
rst_info.reason != REASON_WDT_RST)
45+
{
46+
return;
47+
}
48+
49+
ets_install_putc1(&uart0_write_char_d);
50+
51+
if (rst_info.reason == REASON_EXCEPTION_RST) {
52+
ets_printf("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n",
53+
rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
54+
}
55+
56+
uint32_t cont_stack_start = (uint32_t) &(g_cont.stack);
57+
uint32_t cont_stack_end = (uint32_t) g_cont.stack_end;
58+
uint32_t stack_end;
59+
60+
// amount of stack taken by interrupt or exception handler
61+
// and everything up to __wrap_system_restart_local
62+
// (determined empirically, might break)
63+
uint32_t offset = 0;
64+
if (rst_info.reason == REASON_SOFT_WDT_RST) {
65+
offset = 0x1b0;
66+
}
67+
else if (rst_info.reason == REASON_EXCEPTION_RST) {
68+
offset = 0x1a0;
69+
}
70+
else if (rst_info.reason == REASON_WDT_RST) {
71+
offset = 0x10;
72+
}
73+
74+
if (sp > cont_stack_start && sp < cont_stack_end) {
75+
ets_printf("\nctx: cont \n");
76+
stack_end = cont_stack_end;
77+
}
78+
else {
79+
ets_printf("\nctx: sys \n");
80+
stack_end = 0x3fffffb0;
81+
// it's actually 0x3ffffff0, but the stuff below ets_run
82+
// is likely not really relevant to the crash
83+
}
84+
85+
ets_printf("sp: %08x end: %08x offset: %04x\n", sp, stack_end, offset);
86+
87+
// print_pcs(sp + offset, stack_end);
88+
print_stack(sp + offset, stack_end);
89+
delayMicroseconds(10000);
90+
__real_system_restart_local();
91+
}
92+
93+
94+
static void print_stack(uint32_t start, uint32_t end) {
95+
ets_printf("\n>>>stack>>>\n");
96+
for (uint32_t pos = start; pos < end; pos += 0x10) {
97+
uint32_t* values = (uint32_t*)(pos);
98+
99+
// rough indicator: stack frames usually have SP saved as the second word
100+
bool looksLikeStackFrame = (values[2] == pos + 0x10);
101+
102+
ets_printf("%08x: %08x %08x %08x %08x %c\n",
103+
pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' ');
104+
}
105+
ets_printf("<<<stack<<<\n");
106+
}
107+
108+
static void print_pcs(uint32_t start, uint32_t end) {
109+
uint32_t n = 0;
110+
ets_printf("\n>>>pc>>>\n");
111+
for (uint32_t pos = start; pos < end; pos += 16, ++n) {
112+
uint32_t* sf = (uint32_t*) pos;
113+
114+
uint32_t pc_ret = sf[3];
115+
uint32_t sp_ret = sf[2];
116+
if (pc_ret < 0x40000000 || pc_ret > 0x40f00000 || sp_ret != pos + 16)
117+
continue;
118+
ets_printf("%08x\n", pc_ret);
119+
}
120+
ets_printf("<<<pc<<<\n");
121+
}
122+
123+
void uart0_write_char_d(char c) {
124+
while (((USS(0) >> USTXC) & 0xff) >= 0x7e) { }
125+
126+
if (c == '\n') {
127+
USF(0) = '\r';
128+
}
129+
USF(0) = c;
130+
}

platform.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ compiler.c.flags=-c -Os -g -Wpointer-arith -Wno-implicit-function-declaration -W
2121
compiler.S.cmd=xtensa-lx106-elf-gcc
2222
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
2323

24-
compiler.c.elf.flags=-g -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}"
24+
compiler.c.elf.flags=-g -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}" -Wl,-wrap,system_restart_local
2525
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
2626
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
2727

0 commit comments

Comments
 (0)