@@ -38,6 +38,8 @@ extern cont_t g_cont;
3838static const char * s_panic_file = 0 ;
3939static int s_panic_line = 0 ;
4040static const char * s_panic_func = 0 ;
41+ static const char * s_panic_what = 0 ;
42+
4143static bool s_abort_called = false;
4244
4345void abort () __attribute__((noreturn ));
@@ -60,12 +62,28 @@ extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack,
6062
6163extern void custom_crash_callback ( struct rst_info * rst_info , uint32_t stack , uint32_t stack_end ) __attribute__ ((weak , alias ("__custom_crash_callback" )));
6264
63- static void ets_puts_P (const char * romString ) {
64- char c = pgm_read_byte (romString ++ );
65- while (c ) {
66- ets_putc (c );
67- c = pgm_read_byte (romString ++ );
68- }
65+ // Single, non-inlined copy of pgm_read_byte to save IRAM space (as this is not timing critical)
66+ static char ICACHE_RAM_ATTR iram_read_byte (const char * addr ) {
67+ return pgm_read_byte (addr );
68+ }
69+
70+ // Required to output the s_panic_file, it's stored in PMEM
71+ #define ets_puts_P (pstr ) \
72+ { \
73+ char c; \
74+ do { \
75+ c = iram_read_byte(pstr++); \
76+ if (c) ets_putc(c); \
77+ } while (c); \
78+ }
79+
80+ // Place these strings in .text because the SPI interface may be in bad shape during an exception.
81+ #define ets_printf_P (str , ...) \
82+ { \
83+ static const char istr[] ICACHE_RAM_ATTR = (str); \
84+ char mstr[sizeof(str)]; \
85+ for (size_t i=0; i < sizeof(str); i++) mstr[i] = iram_read_byte(&istr[i]); \
86+ ets_printf(mstr, ##__VA_ARGS__); \
6987}
7088
7189void __wrap_system_restart_local () {
@@ -92,21 +110,25 @@ void __wrap_system_restart_local() {
92110 ets_install_putc1 (& uart_write_char_d );
93111
94112 if (s_panic_line ) {
95- ets_puts_P (PSTR ("\nPanic " ));
96- ets_puts_P (s_panic_file );
97- ets_printf (":%d " , s_panic_line );
98- ets_puts_P (s_panic_func );
99- ets_puts_P (PSTR ("\n" ));
113+ ets_printf_P ("\nPanic " );
114+ ets_puts_P (s_panic_file ); // This is in PROGMEM, need special output because ets_printf can't handle ROM parameters
115+ ets_printf_P (":%d %s" , s_panic_line , s_panic_func );
116+ if (s_panic_what ) {
117+ ets_printf_P (": Assertion '" );
118+ ets_puts_P (s_panic_what ); // This is also in PMEM
119+ ets_printf_P ("' failed." );
120+ }
121+ ets_putc ('\n' );
100122 }
101123 else if (s_abort_called ) {
102- ets_puts_P ( PSTR ( "Abort called\n") );
124+ ets_printf_P ( "\nAbort called\n" );
103125 }
104126 else if (rst_info .reason == REASON_EXCEPTION_RST ) {
105- ets_printf ("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n" ,
127+ ets_printf_P ("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n" ,
106128 rst_info .exccause , rst_info .epc1 , rst_info .epc2 , rst_info .epc3 , rst_info .excvaddr , rst_info .depc );
107129 }
108130 else if (rst_info .reason == REASON_SOFT_WDT_RST ) {
109- ets_puts_P ( PSTR ( "\nSoft WDT reset\n" ) );
131+ ets_printf_P ( "\nSoft WDT reset\n" );
110132 }
111133
112134 uint32_t cont_stack_start = (uint32_t ) & (g_cont .stack );
@@ -128,17 +150,17 @@ void __wrap_system_restart_local() {
128150 }
129151
130152 if (sp > cont_stack_start && sp < cont_stack_end ) {
131- ets_puts_P ( PSTR ( "\nctx: cont \n" ) );
153+ ets_printf_P ( "\nctx: cont \n" );
132154 stack_end = cont_stack_end ;
133155 }
134156 else {
135- ets_puts_P (( "\nctx: sys \n" ) );
157+ ets_printf_P ( "\nctx: sys \n" );
136158 stack_end = 0x3fffffb0 ;
137159 // it's actually 0x3ffffff0, but the stuff below ets_run
138160 // is likely not really relevant to the crash
139161 }
140162
141- ets_printf ("sp: %08x end: %08x offset: %04x\n" , sp , stack_end , offset );
163+ ets_printf_P ("sp: %08x end: %08x offset: %04x\n" , sp , stack_end , offset );
142164
143165 print_stack (sp + offset , stack_end );
144166
@@ -154,18 +176,18 @@ void __wrap_system_restart_local() {
154176}
155177
156178
157- static void print_stack (uint32_t start , uint32_t end ) {
158- ets_puts_P ( PSTR ( "\n>>>stack>>>\n" ) );
179+ static void ICACHE_RAM_ATTR print_stack (uint32_t start , uint32_t end ) {
180+ ets_printf_P ( "\n>>>stack>>>\n" );
159181 for (uint32_t pos = start ; pos < end ; pos += 0x10 ) {
160182 uint32_t * values = (uint32_t * )(pos );
161183
162184 // rough indicator: stack frames usually have SP saved as the second word
163185 bool looksLikeStackFrame = (values [2 ] == pos + 0x10 );
164186
165- ets_printf ("%08x: %08x %08x %08x %08x %c\n" ,
187+ ets_printf_P ("%08x: %08x %08x %08x %08x %c\n" ,
166188 pos , values [0 ], values [1 ], values [2 ], values [3 ], (looksLikeStackFrame )?'<' :' ' );
167189 }
168- ets_puts_P ( PSTR ( "<<<stack<<<\n" ) );
190+ ets_printf_P ( "<<<stack<<<\n" );
169191}
170192
171193static void uart_write_char_d (char c ) {
@@ -202,10 +224,10 @@ void abort() {
202224}
203225
204226void __assert_func (const char * file , int line , const char * func , const char * what ) {
205- (void ) what ;
206227 s_panic_file = file ;
207228 s_panic_line = line ;
208229 s_panic_func = func ;
230+ s_panic_what = what ;
209231 gdb_do_break (); /* if GDB is not present, this is a no-op */
210232 raise_exception ();
211233}
@@ -214,6 +236,7 @@ void __panic_func(const char* file, int line, const char* func) {
214236 s_panic_file = file ;
215237 s_panic_line = line ;
216238 s_panic_func = func ;
239+ s_panic_what = 0 ;
217240 gdb_do_break (); /* if GDB is not present, this is a no-op */
218241 raise_exception ();
219242}
0 commit comments