Skip to content

Commit 6765e0d

Browse files
authored
expose more crash reporting apis
1 parent ccea728 commit 6765e0d

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

cores/esp8266/core_esp8266_postmortem.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,33 @@ extern int umm_last_fail_alloc_line;
7575

7676
static void raise_exception() __attribute__((noreturn));
7777

78-
extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
78+
extern void __custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end) {
7979
(void) rst_info;
8080
(void) stack;
8181
(void) stack_end;
8282
}
8383

84-
extern void custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) __attribute__ ((weak, alias("__custom_crash_callback")));
84+
extern void __custom_panic_callback(const char* panic_file, int panic_line, const char* panic_func, const char* panic_what) {
85+
(void) panic_file;
86+
(void) panic_line;
87+
(void) panic_func;
88+
(void) panic_what;
89+
}
90+
91+
extern void __ets_uart_putc1(char c) {
92+
ets_uart_putc1(c);
93+
}
8594

95+
extern void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end) __attribute__ ((weak, alias("__custom_crash_callback")));
96+
97+
extern void custom_panic_callback(const char* panic_file, int panic_line, const char* panic_func, const char* panic_what) __attribute__ ((weak, alias("__custom_panic_callback")));
98+
99+
extern void crash_ets_uart_putc1(char c) __attribute__((weak, alias("__ets_uart_putc1")));
86100

87101
// Prints need to use our library function to allow for file and function
88102
// to be safely accessed from flash. This function encapsulates snprintf()
89-
// [which by definition will 0-terminate] and dumping to the UART
103+
// [which by definition will 0-terminate] and dumping to the UART, or the
104+
// user-specified function.
90105
static void ets_printf_P(const char *str, ...) {
91106
char destStr[160];
92107
char *c = destStr;
@@ -95,22 +110,28 @@ static void ets_printf_P(const char *str, ...) {
95110
vsnprintf(destStr, sizeof(destStr), str, argPtr);
96111
va_end(argPtr);
97112
while (*c) {
98-
ets_uart_putc1(*(c++));
113+
crash_ets_uart_putc1(*(c++));
99114
}
100115
}
101116

117+
static inline void ets_println() { ets_printf_P(PSTR("\n")); }
118+
102119
static void cut_here() {
120+
#ifdef NO_CUT_HERE
121+
return;
122+
#endif
123+
103124
// https://tinyurl.com/8266dcdr => https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html#exception
104125
ets_printf_P(PSTR("\nTo make this dump useful, DECODE IT - https://tinyurl.com/8266dcdr\n"));
105126

106127
for (auto i = 0; i < 15; i++ ) {
107-
ets_putc('-');
128+
ets_uart_putc1('-');
108129
}
109130
ets_printf_P(PSTR(" CUT HERE FOR EXCEPTION DECODER "));
110131
for (auto i = 0; i < 15; i++ ) {
111-
ets_putc('-');
132+
ets_uart_putc1('-');
112133
}
113-
ets_putc('\n');
134+
ets_println();
114135
}
115136

116137
static inline bool is_pc_valid(uint32_t pc) {
@@ -152,6 +173,7 @@ static void postmortem_report(uint32_t sp_dump) {
152173
else
153174
rst_info.reason = s_user_reset_reason;
154175

176+
// redirect the output to both UARTs
155177
ets_install_putc1(&uart_write_char_d);
156178

157179
cut_here();
@@ -161,7 +183,7 @@ static void postmortem_report(uint32_t sp_dump) {
161183
if (s_panic_what) {
162184
ets_printf_P(PSTR(": Assertion '%S' failed."), s_panic_what);
163185
}
164-
ets_putc('\n');
186+
ets_println();
165187
}
166188
else if (s_panic_file) {
167189
ets_printf_P(PSTR("\nPanic %S\n"), s_panic_file);
@@ -176,16 +198,15 @@ static void postmortem_report(uint32_t sp_dump) {
176198
// The GCC divide routine in ROM jumps to the address below and executes ILL (00 00 00) on div-by-zero
177199
// In that case, print the exception as (6) which is IntegerDivZero
178200
uint32_t epc1 = rst_info.epc1;
179-
uint32_t exccause = rst_info.exccause;
180-
bool div_zero = (exccause == 0) && (epc1 == 0x4000dce5u);
201+
const bool div_zero = (rst_info.exccause == 0) && (epc1 == 0x4000dce5u);
181202
if (div_zero) {
182-
exccause = 6;
203+
rst_info.exccause = 6;
183204
// In place of the detached 'ILL' instruction., redirect attention
184205
// back to the code that called the ROM divide function.
185206
__asm__ __volatile__("rsr.excsave1 %0\n\t" : "=r"(epc1) :: "memory");
186207
}
187208
ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
188-
exccause, epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
209+
rst_info.exccause, epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
189210
}
190211
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
191212
ets_printf_P(PSTR("\nSoft WDT reset"));
@@ -194,7 +215,7 @@ static void postmortem_report(uint32_t sp_dump) {
194215
// The SDK is riddled with these. They are usually preceded by an ets_printf.
195216
ets_printf_P(PSTR(" - deliberate infinite loop detected"));
196217
}
197-
ets_putc('\n');
218+
ets_println();
198219
ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
199220
rst_info.exccause, /* Address executing at time of Soft WDT level-1 interrupt */ rst_info.epc1, 0, 0, 0, 0);
200221
}
@@ -229,7 +250,7 @@ static void postmortem_report(uint32_t sp_dump) {
229250
// 16 ?unnamed? - index into a table, pull out pointer, and call if non-zero
230251
// appears near near wDev_ProcessFiq
231252
// 32 pp_soft_wdt_feed_local - gather the specifics and call __wrap_system_restart_local
232-
offset = 32 + 16 + 48 + 256;
253+
offset = 32 + 16 + 48 + 256;
233254
}
234255
else if (rst_info.reason == REASON_EXCEPTION_RST) {
235256
// Stack Tally
@@ -298,7 +319,11 @@ static void postmortem_report(uint32_t sp_dump) {
298319
ets_printf_P(PSTR("\nlast failed alloc caller: 0x%08x\n"), (uint32_t)umm_last_fail_alloc_addr);
299320
}
300321

301-
custom_crash_callback( &rst_info, sp_dump + offset, stack_end );
322+
if (s_panic_line || s_panic_func || s_panic_file || s_panic_what) {
323+
custom_panic_callback(s_panic_file, s_panic_line, s_panic_func, s_panic_what);
324+
}
325+
326+
custom_crash_callback(&rst_info, sp_dump + offset, stack_end);
302327

303328
ets_delay_us(10000);
304329
__real_system_restart_local();
@@ -309,6 +334,7 @@ static void print_stack(uint32_t start, uint32_t end) {
309334
for (uint32_t pos = start; pos < end; pos += 0x10) {
310335
uint32_t* values = (uint32_t*)(pos);
311336

337+
#ifdef CONT_STACKGUARD
312338
// avoid printing irrelevant data
313339
if ((values[0] == CONT_STACKGUARD)
314340
&& (values[0] == values[1])
@@ -317,6 +343,7 @@ static void print_stack(uint32_t start, uint32_t end) {
317343
{
318344
continue;
319345
}
346+
#endif
320347

321348
// rough indicator: stack frames usually have SP saved as the second word
322349
const bool looksLikeStackFrame = (values[2] == pos + 0x10);

0 commit comments

Comments
 (0)