@@ -75,18 +75,33 @@ extern int umm_last_fail_alloc_line;
7575
7676static 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.
90105static 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+
102119static 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 (" \n To 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
116137static 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 (" \n Panic %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 (" \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 );
189210 }
190211 else if (rst_info.reason == REASON_SOFT_WDT_RST) {
191212 ets_printf_P (PSTR (" \n Soft 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 (" \n Exception (%d):\n epc1=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 (" \n last 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