@@ -75,18 +75,33 @@ extern int umm_last_fail_alloc_line;
75
75
76
76
static void raise_exception () __attribute__((noreturn));
77
77
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) {
79
79
(void ) rst_info;
80
80
(void ) stack;
81
81
(void ) stack_end;
82
82
}
83
83
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
+ }
85
94
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" )));
86
100
87
101
// Prints need to use our library function to allow for file and function
88
102
// 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.
90
105
static void ets_printf_P (const char *str, ...) {
91
106
char destStr[160 ];
92
107
char *c = destStr;
@@ -95,22 +110,28 @@ static void ets_printf_P(const char *str, ...) {
95
110
vsnprintf (destStr, sizeof (destStr), str, argPtr);
96
111
va_end (argPtr);
97
112
while (*c) {
98
- ets_uart_putc1 (*(c++));
113
+ crash_ets_uart_putc1 (*(c++));
99
114
}
100
115
}
101
116
117
+ static inline void ets_println () { ets_printf_P (PSTR (" \n " )); }
118
+
102
119
static void cut_here () {
120
+ #ifdef NO_CUT_HERE
121
+ return ;
122
+ #endif
123
+
103
124
// https://tinyurl.com/8266dcdr => https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html#exception
104
125
ets_printf_P (PSTR (" \n To make this dump useful, DECODE IT - https://tinyurl.com/8266dcdr\n " ));
105
126
106
127
for (auto i = 0 ; i < 15 ; i++ ) {
107
- ets_putc (' -' );
128
+ ets_uart_putc1 (' -' );
108
129
}
109
130
ets_printf_P (PSTR (" CUT HERE FOR EXCEPTION DECODER " ));
110
131
for (auto i = 0 ; i < 15 ; i++ ) {
111
- ets_putc (' -' );
132
+ ets_uart_putc1 (' -' );
112
133
}
113
- ets_putc ( ' \n ' );
134
+ ets_println ( );
114
135
}
115
136
116
137
static inline bool is_pc_valid (uint32_t pc) {
@@ -152,6 +173,7 @@ static void postmortem_report(uint32_t sp_dump) {
152
173
else
153
174
rst_info.reason = s_user_reset_reason;
154
175
176
+ // redirect the output to both UARTs
155
177
ets_install_putc1 (&uart_write_char_d);
156
178
157
179
cut_here ();
@@ -161,7 +183,7 @@ static void postmortem_report(uint32_t sp_dump) {
161
183
if (s_panic_what) {
162
184
ets_printf_P (PSTR (" : Assertion '%S' failed." ), s_panic_what);
163
185
}
164
- ets_putc ( ' \n ' );
186
+ ets_println ( );
165
187
}
166
188
else if (s_panic_file) {
167
189
ets_printf_P (PSTR (" \n Panic %S\n " ), s_panic_file);
@@ -176,16 +198,15 @@ static void postmortem_report(uint32_t sp_dump) {
176
198
// The GCC divide routine in ROM jumps to the address below and executes ILL (00 00 00) on div-by-zero
177
199
// In that case, print the exception as (6) which is IntegerDivZero
178
200
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 );
181
202
if (div_zero) {
182
- exccause = 6 ;
203
+ rst_info. exccause = 6 ;
183
204
// In place of the detached 'ILL' instruction., redirect attention
184
205
// back to the code that called the ROM divide function.
185
206
__asm__ __volatile__ (" rsr.excsave1 %0\n\t " : " =r" (epc1) :: " memory" );
186
207
}
187
208
ets_printf_P (PSTR (" \n Exception (%d):\n epc1=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 );
189
210
}
190
211
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
191
212
ets_printf_P (PSTR (" \n Soft WDT reset" ));
@@ -194,7 +215,7 @@ static void postmortem_report(uint32_t sp_dump) {
194
215
// The SDK is riddled with these. They are usually preceded by an ets_printf.
195
216
ets_printf_P (PSTR (" - deliberate infinite loop detected" ));
196
217
}
197
- ets_putc ( ' \n ' );
218
+ ets_println ( );
198
219
ets_printf_P (PSTR (" \n Exception (%d):\n epc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n " ),
199
220
rst_info.exccause , /* Address executing at time of Soft WDT level-1 interrupt */ rst_info.epc1 , 0 , 0 , 0 , 0 );
200
221
}
@@ -229,7 +250,7 @@ static void postmortem_report(uint32_t sp_dump) {
229
250
// 16 ?unnamed? - index into a table, pull out pointer, and call if non-zero
230
251
// appears near near wDev_ProcessFiq
231
252
// 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 ;
233
254
}
234
255
else if (rst_info.reason == REASON_EXCEPTION_RST) {
235
256
// Stack Tally
@@ -298,7 +319,11 @@ static void postmortem_report(uint32_t sp_dump) {
298
319
ets_printf_P (PSTR (" \n last failed alloc caller: 0x%08x\n " ), (uint32_t )umm_last_fail_alloc_addr);
299
320
}
300
321
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);
302
327
303
328
ets_delay_us (10000 );
304
329
__real_system_restart_local ();
@@ -309,6 +334,7 @@ static void print_stack(uint32_t start, uint32_t end) {
309
334
for (uint32_t pos = start; pos < end; pos += 0x10 ) {
310
335
uint32_t * values = (uint32_t *)(pos);
311
336
337
+ #ifdef CONT_STACKGUARD
312
338
// avoid printing irrelevant data
313
339
if ((values[0 ] == CONT_STACKGUARD)
314
340
&& (values[0 ] == values[1 ])
@@ -317,6 +343,7 @@ static void print_stack(uint32_t start, uint32_t end) {
317
343
{
318
344
continue ;
319
345
}
346
+ #endif
320
347
321
348
// rough indicator: stack frames usually have SP saved as the second word
322
349
const bool looksLikeStackFrame = (values[2 ] == pos + 0x10 );
0 commit comments