@@ -38,6 +38,8 @@ extern cont_t g_cont;
38
38
static const char * s_panic_file = 0 ;
39
39
static int s_panic_line = 0 ;
40
40
static const char * s_panic_func = 0 ;
41
+ static const char * s_panic_what = 0 ;
42
+
41
43
static bool s_abort_called = false;
42
44
43
45
void abort () __attribute__((noreturn ));
@@ -60,12 +62,28 @@ extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack,
60
62
61
63
extern void custom_crash_callback ( struct rst_info * rst_info , uint32_t stack , uint32_t stack_end ) __attribute__ ((weak , alias ("__custom_crash_callback" )));
62
64
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__); \
69
87
}
70
88
71
89
void __wrap_system_restart_local () {
@@ -92,21 +110,25 @@ void __wrap_system_restart_local() {
92
110
ets_install_putc1 (& uart_write_char_d );
93
111
94
112
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' );
100
122
}
101
123
else if (s_abort_called ) {
102
- ets_puts_P ( PSTR ( "Abort called\n") );
124
+ ets_printf_P ( "\nAbort called\n" );
103
125
}
104
126
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" ,
106
128
rst_info .exccause , rst_info .epc1 , rst_info .epc2 , rst_info .epc3 , rst_info .excvaddr , rst_info .depc );
107
129
}
108
130
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" );
110
132
}
111
133
112
134
uint32_t cont_stack_start = (uint32_t ) & (g_cont .stack );
@@ -128,17 +150,17 @@ void __wrap_system_restart_local() {
128
150
}
129
151
130
152
if (sp > cont_stack_start && sp < cont_stack_end ) {
131
- ets_puts_P ( PSTR ( "\nctx: cont \n" ) );
153
+ ets_printf_P ( "\nctx: cont \n" );
132
154
stack_end = cont_stack_end ;
133
155
}
134
156
else {
135
- ets_puts_P (( "\nctx: sys \n" ) );
157
+ ets_printf_P ( "\nctx: sys \n" );
136
158
stack_end = 0x3fffffb0 ;
137
159
// it's actually 0x3ffffff0, but the stuff below ets_run
138
160
// is likely not really relevant to the crash
139
161
}
140
162
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 );
142
164
143
165
print_stack (sp + offset , stack_end );
144
166
@@ -154,18 +176,18 @@ void __wrap_system_restart_local() {
154
176
}
155
177
156
178
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" );
159
181
for (uint32_t pos = start ; pos < end ; pos += 0x10 ) {
160
182
uint32_t * values = (uint32_t * )(pos );
161
183
162
184
// rough indicator: stack frames usually have SP saved as the second word
163
185
bool looksLikeStackFrame = (values [2 ] == pos + 0x10 );
164
186
165
- ets_printf ("%08x: %08x %08x %08x %08x %c\n" ,
187
+ ets_printf_P ("%08x: %08x %08x %08x %08x %c\n" ,
166
188
pos , values [0 ], values [1 ], values [2 ], values [3 ], (looksLikeStackFrame )?'<' :' ' );
167
189
}
168
- ets_puts_P ( PSTR ( "<<<stack<<<\n" ) );
190
+ ets_printf_P ( "<<<stack<<<\n" );
169
191
}
170
192
171
193
static void uart_write_char_d (char c ) {
@@ -202,10 +224,10 @@ void abort() {
202
224
}
203
225
204
226
void __assert_func (const char * file , int line , const char * func , const char * what ) {
205
- (void ) what ;
206
227
s_panic_file = file ;
207
228
s_panic_line = line ;
208
229
s_panic_func = func ;
230
+ s_panic_what = what ;
209
231
gdb_do_break (); /* if GDB is not present, this is a no-op */
210
232
raise_exception ();
211
233
}
@@ -214,6 +236,7 @@ void __panic_func(const char* file, int line, const char* func) {
214
236
s_panic_file = file ;
215
237
s_panic_line = line ;
216
238
s_panic_func = func ;
239
+ s_panic_what = 0 ;
217
240
gdb_do_break (); /* if GDB is not present, this is a no-op */
218
241
raise_exception ();
219
242
}
0 commit comments