@@ -45,10 +45,10 @@ extern void(*__init_array_end)(void);
45
45
/* Not static, used in Esp.cpp */
46
46
struct rst_info resetInfo;
47
47
48
- /* Not static, used in core_esp8266_postmortem.c.
49
- * Placed into noinit section because we assign value to this variable
50
- * before .bss is zero-filled, and need to preserve the value.
51
- */
48
+ /* Not static, used in core_esp8266_postmortem.c and other places .
49
+ * Placed into noinit section because we assign value to this variable
50
+ * before .bss is zero-filled, and need to preserve the value.
51
+ */
52
52
cont_t * g_pcont __attribute__ ((section(" .noinit" )));
53
53
54
54
/* Event queue used by the main (arduino) task */
@@ -57,6 +57,13 @@ static os_event_t s_loop_queue[LOOP_QUEUE_SIZE];
57
57
/* Used to implement optimistic_yield */
58
58
static uint32_t s_micros_at_task_start;
59
59
60
+ /* For ets_intr_lock_nest / ets_intr_unlock_nest
61
+ * Max nesting seen by SDK so far is 2.
62
+ */
63
+ #define ETS_INTR_LOCK_NEST_MAX 7
64
+ static uint16_t ets_intr_lock_stack[ETS_INTR_LOCK_NEST_MAX];
65
+ static byte ets_intr_lock_stack_ptr = 0 ;
66
+
60
67
61
68
extern " C" {
62
69
extern const uint32_t __attribute__ ((section(" .ver_number" ))) core_version =
@@ -83,24 +90,36 @@ void preloop_update_frequency()
83
90
#endif
84
91
}
85
92
93
+ extern " C" bool can_yield ()
94
+ {
95
+ return cont_can_yield (g_pcont);
96
+ }
97
+
98
+ static inline void esp_yield_within_cont () __attribute__((always_inline));
99
+ static void esp_yield_within_cont ()
100
+ {
101
+ cont_yield (g_pcont);
102
+ run_scheduled_recurrent_functions ();
103
+ }
86
104
87
105
extern " C" void esp_yield ()
88
106
{
89
- if (cont_can_yield (g_pcont )) {
90
- cont_yield (g_pcont );
107
+ if (can_yield ( )) {
108
+ esp_yield_within_cont ( );
91
109
}
92
110
}
93
111
94
112
extern " C" void esp_schedule ()
95
113
{
114
+ // always on CONT stack here
96
115
ets_post (LOOP_TASK_PRIORITY, 0 , 0 );
97
116
}
98
117
99
118
extern " C" void __yield ()
100
119
{
101
- if (cont_can_yield (g_pcont )) {
120
+ if (can_yield ( )) {
102
121
esp_schedule ();
103
- esp_yield ();
122
+ esp_yield_within_cont ();
104
123
} else {
105
124
panic ();
106
125
}
@@ -110,12 +129,54 @@ extern "C" void yield(void) __attribute__((weak, alias("__yield")));
110
129
111
130
extern " C" void optimistic_yield (uint32_t interval_us)
112
131
{
113
- if (cont_can_yield (g_pcont ) &&
132
+ if (can_yield ( ) &&
114
133
(system_get_time () - s_micros_at_task_start) > interval_us) {
115
134
yield ();
116
135
}
117
136
}
118
137
138
+
139
+ // Replace ets_intr_(un)lock with nestable versions
140
+ extern " C" void IRAM_ATTR ets_intr_lock ()
141
+ {
142
+ if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) {
143
+ ets_intr_lock_stack[ets_intr_lock_stack_ptr++] = xt_rsil (3 );
144
+ } else {
145
+ xt_rsil (3 );
146
+ }
147
+ }
148
+
149
+ extern " C" void IRAM_ATTR ets_intr_unlock ()
150
+ {
151
+ if (ets_intr_lock_stack_ptr > 0 ) {
152
+ xt_wsr_ps (ets_intr_lock_stack[--ets_intr_lock_stack_ptr]);
153
+ } else {
154
+ xt_rsil (0 );
155
+ }
156
+ }
157
+
158
+
159
+ // Save / Restore the PS state across the rom ets_post call as the rom code
160
+ // does not implement this correctly.
161
+ extern " C" bool ets_post_rom (uint8 prio, ETSSignal sig, ETSParam par);
162
+
163
+ extern " C" bool IRAM_ATTR ets_post (uint8 prio, ETSSignal sig, ETSParam par)
164
+ {
165
+ uint32_t saved;
166
+ asm volatile (" rsr %0,ps" :" =a" (saved));
167
+ bool rc = ets_post_rom (prio, sig, par);
168
+ xt_wsr_ps (saved);
169
+ return rc;
170
+ }
171
+
172
+ extern " C" void __loop_end (void )
173
+ {
174
+ run_scheduled_functions ();
175
+ run_scheduled_recurrent_functions ();
176
+ }
177
+
178
+ extern " C" void loop_end (void ) __attribute__((weak, alias(" __loop_end" )));
179
+
119
180
static void loop_wrapper ()
120
181
{
121
182
static bool setup_done = false ;
@@ -139,101 +200,146 @@ static void loop_task(os_event_t *events)
139
200
panic ();
140
201
}
141
202
}
203
+ extern " C" {
204
+
205
+ struct object {
206
+ long placeholder[10 ];
207
+ };
208
+ void __register_frame_info (const void *begin, struct object *ob);
209
+ extern char __eh_frame[];
210
+ }
142
211
143
212
static void do_global_ctors (void )
144
213
{
214
+ static struct object ob;
215
+ __register_frame_info (__eh_frame, &ob);
216
+
145
217
void (**p)(void ) = &__init_array_end;
146
218
while (p != &__init_array_start) {
147
219
(*--p)();
148
220
}
149
221
}
150
222
223
+ extern " C" {
224
+ extern void __unhandled_exception (const char *str);
225
+
226
+ static void __unhandled_exception_cpp ()
227
+ {
228
+ #ifndef __EXCEPTIONS
229
+ abort ();
230
+ #else
231
+ static bool terminating;
232
+ if (terminating) {
233
+ abort ();
234
+ }
235
+ terminating = true ;
236
+ /* Use a trick from vterminate.cc to get any std::exception what() */
237
+ try {
238
+ __throw_exception_again;
239
+ } catch (const std::exception& e) {
240
+ __unhandled_exception (e.what ());
241
+ } catch (...) {
242
+ __unhandled_exception (" " );
243
+ }
244
+ #endif
245
+ }
246
+
247
+ }
248
+
151
249
void init_done ()
152
250
{
153
251
system_set_os_print (1 );
154
252
gdb_init ();
253
+ std::set_terminate (__unhandled_exception_cpp);
155
254
do_global_ctors ();
156
255
esp_schedule ();
157
256
}
158
257
159
258
/* This is the entry point of the application.
160
- * It gets called on the default stack, which grows down from the top
161
- * of DRAM area.
162
- * .bss has not been zeroed out yet, but .data and .rodata are in place.
163
- * Cache is not enabled, so only ROM and IRAM functions can be called.
164
- * Peripherals (except for SPI0 and UART0) are not initialized.
165
- * This function does not return.
166
- */
259
+ * It gets called on the default stack, which grows down from the top
260
+ * of DRAM area.
261
+ * .bss has not been zeroed out yet, but .data and .rodata are in place.
262
+ * Cache is not enabled, so only ROM and IRAM functions can be called.
263
+ * Peripherals (except for SPI0 and UART0) are not initialized.
264
+ * This function does not return.
265
+ */
167
266
/*
168
- A bit of explanation for this entry point:
169
-
170
- SYS is the SDK task/context used by the upperlying system to run its
171
- administrative tasks (at least WLAN and lwip's receive callbacks and
172
- Ticker). NONOS-SDK is designed to run user's non-threaded code in
173
- another specific task/context with its own stack in BSS.
174
-
175
- Some clever fellows found that the SYS stack was a large and quite unused
176
- piece of ram that we could use for the user's stack instead of using user's
177
- main memory, thus saving around 4KB on ram/heap.
178
-
179
- A problem arose later, which is that this stack can heavily be used by
180
- the SDK for some features. One of these features is WPS. We still don't
181
- know if other features are using this, or if this memory is going to be
182
- used in future SDK releases.
183
-
184
- WPS beeing flawed by its poor security, or not beeing used by lots of
185
- users, it has been decided that we are still going to use that memory for
186
- user's stack and disable the use of WPS, with an option to revert that
187
- back at the user's discretion. This selection can be done with the
188
- global define NO_EXTRA_4K_HEAP. An option has been added to the board
189
- generator script.
190
-
191
- References:
192
- https://github.com/esp8266/Arduino/pull/4553
193
- https://github.com/esp8266/Arduino/pull/4622
194
- https://github.com/esp8266/Arduino/issues/4779
195
- https://github.com/esp8266/Arduino/pull/4889
267
+ A bit of explanation for this entry point:
196
268
197
- */
269
+ SYS is the SDK task/context used by the upperlying system to run its
270
+ administrative tasks (at least WLAN and lwip's receive callbacks and
271
+ Ticker). NONOS-SDK is designed to run user's non-threaded code in
272
+ another specific task/context with its own stack in BSS.
198
273
199
- #ifdef NO_EXTRA_4K_HEAP
200
- /* this is the default NONOS-SDK user's heap location */
201
- cont_t g_cont __attribute__ ((aligned(16 )));
202
- #endif
274
+ Some clever fellows found that the SYS stack was a large and quite unused
275
+ piece of ram that we could use for the user's stack instead of using user's
276
+ main memory, thus saving around 4KB on ram/heap.
203
277
204
- extern " C" void ICACHE_RAM_ATTR app_entry (void )
205
- {
206
- #ifdef NO_EXTRA_4K_HEAP
278
+ A problem arose later, which is that this stack can heavily be used by
279
+ the SDK for some features. One of these features is WPS. We still don't
280
+ know if other features are using this, or if this memory is going to be
281
+ used in future SDK releases.
207
282
208
- /* this is the default NONOS-SDK user's heap location */
209
- g_pcont = &g_cont;
283
+ WPS beeing flawed by its poor security, or not beeing used by lots of
284
+ users, it has been decided that we are still going to use that memory for
285
+ user's stack and disable the use of WPS.
210
286
211
- #else
287
+ app_entry() jumps to app_entry_custom() defined as "weakref" calling
288
+ itself a weak customizable function, allowing to use another one when
289
+ this is required (see core_esp8266_app_entry_noextra4k.cpp, used by WPS).
212
290
291
+ (note: setting app_entry() itself as "weak" is not sufficient and always
292
+ ends up with the other "noextra4k" one linked, maybe because it has a
293
+ default ENTRY(app_entry) value in linker scripts).
294
+
295
+ References:
296
+ https://github.com/esp8266/Arduino/pull/4553
297
+ https://github.com/esp8266/Arduino/pull/4622
298
+ https://github.com/esp8266/Arduino/issues/4779
299
+ https://github.com/esp8266/Arduino/pull/4889
300
+
301
+ */
302
+
303
+ extern " C" void app_entry_redefinable (void ) __attribute__((weak));
304
+ extern " C" void app_entry_redefinable (void )
305
+ {
213
306
/* Allocate continuation context on this SYS stack,
214
- and save pointer to it. */
307
+ and save pointer to it. */
215
308
cont_t s_cont __attribute__ ((aligned (16 )));
216
309
g_pcont = &s_cont;
217
310
218
- #endif
219
-
220
311
/* Call the entry point of the SDK code. */
221
312
call_user_start ();
222
313
}
223
314
315
+ static void app_entry_custom (void ) __attribute__((weakref(" app_entry_redefinable" )));
316
+
317
+ extern " C" void app_entry (void )
318
+ {
319
+ return app_entry_custom ();
320
+ }
321
+
322
+ extern " C" void preinit (void ) __attribute__((weak));
323
+ extern " C" void preinit (void )
324
+ {
325
+ /* do nothing by default */
326
+ }
327
+
224
328
extern " C" void user_init (void )
225
329
{
226
330
struct rst_info *rtc_info_ptr = system_get_rst_info ();
227
331
memcpy ((void *)&resetInfo, (void *)rtc_info_ptr, sizeof (resetInfo));
228
332
229
333
uart_div_modify (0 , UART_CLK_FREQ / (115200 ));
230
334
231
- init ();
335
+ init (); // in core_esp8266_wiring.c, inits hw regs and sdk timer
232
336
233
337
initVariant ();
234
338
235
339
cont_init (g_pcont);
236
340
341
+ preinit (); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
342
+
237
343
ets_task (loop_task,
238
344
LOOP_TASK_PRIORITY, s_loop_queue,
239
345
LOOP_QUEUE_SIZE);
0 commit comments