@@ -62,32 +62,25 @@ extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack,
62
62
63
63
extern void custom_crash_callback ( struct rst_info * rst_info , uint32_t stack , uint32_t stack_end ) __attribute__ ((weak , alias ("__custom_crash_callback" )));
64
64
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
65
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__); \
66
+ // Prints need to use our library function to allow for file and function
67
+ // to be safely accessed from flash. This function encapsulates snprintf()
68
+ // [which by definition will 0-terminate] and dumping to the UART
69
+ static void ets_printf_P (const char * str , ...) {
70
+ char destStr [160 ];
71
+ char * c = destStr ;
72
+ va_list argPtr ;
73
+ va_start (argPtr , str );
74
+ vsnprintf (destStr , sizeof (destStr ), str , argPtr );
75
+ va_end (argPtr );
76
+ while (* c ) {
77
+ ets_putc (* (c ++ ));
78
+ }
87
79
}
88
80
89
81
void __wrap_system_restart_local () {
90
82
register uint32_t sp asm("a1" );
83
+ uint32_t sp_dump = sp ;
91
84
92
85
if (gdb_present ()) {
93
86
/* When GDBStub is present, exceptions are handled by GDBStub,
@@ -110,28 +103,24 @@ void __wrap_system_restart_local() {
110
103
ets_install_putc1 (& uart_write_char_d );
111
104
112
105
if (s_panic_line ) {
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 );
106
+ ets_printf_P (PSTR ("\nPanic %S:%d %S" ), s_panic_file , s_panic_line , s_panic_func );
116
107
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." );
108
+ ets_printf_P (PSTR (": Assertion '%S' failed." ), s_panic_what );
120
109
}
121
110
ets_putc ('\n' );
122
111
}
123
112
else if (s_unhandled_exception ) {
124
- ets_printf_P ("\nUnhandled exception: %s \n" , s_unhandled_exception );
113
+ ets_printf_P (PSTR ( "\nUnhandled C++ exception: %S \n" ) , s_unhandled_exception );
125
114
}
126
115
else if (s_abort_called ) {
127
- ets_printf_P ("\nAbort called\n" );
116
+ ets_printf_P (PSTR ( "\nAbort called\n" ) );
128
117
}
129
118
else if (rst_info .reason == REASON_EXCEPTION_RST ) {
130
- ets_printf_P ("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n" ,
119
+ ets_printf_P (PSTR ( "\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n" ) ,
131
120
rst_info .exccause , rst_info .epc1 , rst_info .epc2 , rst_info .epc3 , rst_info .excvaddr , rst_info .depc );
132
121
}
133
122
else if (rst_info .reason == REASON_SOFT_WDT_RST ) {
134
- ets_printf_P ("\nSoft WDT reset\n" );
123
+ ets_printf_P (PSTR ( "\nSoft WDT reset\n" ) );
135
124
}
136
125
137
126
uint32_t cont_stack_start = (uint32_t ) & (g_pcont -> stack );
@@ -152,54 +141,53 @@ void __wrap_system_restart_local() {
152
141
offset = 0x10 ;
153
142
}
154
143
155
- ets_printf_P ("\n>>>stack>>>\n" );
144
+ ets_printf_P (PSTR ( "\n>>>stack>>>\n" ) );
156
145
157
- if (sp > stack_thunk_get_stack_bot () && sp <= stack_thunk_get_stack_top ()) {
146
+ if (sp_dump > stack_thunk_get_stack_bot () && sp_dump <= stack_thunk_get_stack_top ()) {
158
147
// BearSSL we dump the BSSL second stack and then reset SP back to the main cont stack
159
- ets_printf_P ("\nctx: bearssl \n" );
160
- ets_printf_P ("sp: %08x end: %08x offset: %04x\n" , sp , stack_thunk_get_stack_top (), offset );
161
- print_stack (sp + offset , stack_thunk_get_stack_top ());
148
+ ets_printf_P (PSTR ("\nctx: bearssl\nsp: %08x end: %08x offset: %04x\n" ), sp_dump , stack_thunk_get_stack_top (), offset );
149
+ print_stack (sp_dump + offset , stack_thunk_get_stack_top ());
162
150
offset = 0 ; // No offset needed anymore, the exception info was stored in the bssl stack
163
- sp = stack_thunk_get_cont_sp ();
151
+ sp_dump = stack_thunk_get_cont_sp ();
164
152
}
165
153
166
- if (sp > cont_stack_start && sp < cont_stack_end ) {
167
- ets_printf_P ("\nctx: cont \n" );
154
+ if (sp_dump > cont_stack_start && sp_dump < cont_stack_end ) {
155
+ ets_printf_P (PSTR ( "\nctx: cont\n" ) );
168
156
stack_end = cont_stack_end ;
169
157
}
170
158
else {
171
- ets_printf_P ("\nctx: sys \n" );
159
+ ets_printf_P (PSTR ( "\nctx: sys\n" ) );
172
160
stack_end = 0x3fffffb0 ;
173
161
// it's actually 0x3ffffff0, but the stuff below ets_run
174
162
// is likely not really relevant to the crash
175
163
}
176
164
177
- ets_printf_P ("sp: %08x end: %08x offset: %04x\n" , sp , stack_end , offset );
165
+ ets_printf_P (PSTR ( "sp: %08x end: %08x offset: %04x\n" ), sp_dump , stack_end , offset );
178
166
179
- print_stack (sp + offset , stack_end );
167
+ print_stack (sp_dump + offset , stack_end );
180
168
181
- ets_printf_P ("<<<stack<<<\n" );
169
+ ets_printf_P (PSTR ( "<<<stack<<<\n" ) );
182
170
183
171
// Use cap-X formatting to ensure the standard EspExceptionDecoder doesn't match the address
184
172
if (umm_last_fail_alloc_addr ) {
185
- ets_printf_P ("\nlast failed alloc call: %08X(%d)\n" , (uint32_t )umm_last_fail_alloc_addr , umm_last_fail_alloc_size );
173
+ ets_printf_P (PSTR ( "\nlast failed alloc call: %08X(%d)\n" ) , (uint32_t )umm_last_fail_alloc_addr , umm_last_fail_alloc_size );
186
174
}
187
175
188
- custom_crash_callback ( & rst_info , sp + offset , stack_end );
176
+ custom_crash_callback ( & rst_info , sp_dump + offset , stack_end );
189
177
190
178
delayMicroseconds (10000 );
191
179
__real_system_restart_local ();
192
180
}
193
181
194
182
195
- static void ICACHE_RAM_ATTR print_stack (uint32_t start , uint32_t end ) {
183
+ static void print_stack (uint32_t start , uint32_t end ) {
196
184
for (uint32_t pos = start ; pos < end ; pos += 0x10 ) {
197
185
uint32_t * values = (uint32_t * )(pos );
198
186
199
187
// rough indicator: stack frames usually have SP saved as the second word
200
188
bool looksLikeStackFrame = (values [2 ] == pos + 0x10 );
201
189
202
- ets_printf_P ("%08x: %08x %08x %08x %08x %c\n" ,
190
+ ets_printf_P (PSTR ( "%08x: %08x %08x %08x %08x %c\n" ) ,
203
191
pos , values [0 ], values [1 ], values [2 ], values [3 ], (looksLikeStackFrame )?'<' :' ' );
204
192
}
205
193
}
0 commit comments