Skip to content

Commit 3fff954

Browse files
authored
ESP8266: Update to 2.6.1 (#1370)
1 parent 60d62ca commit 3fff954

File tree

1 file changed

+165
-59
lines changed

1 file changed

+165
-59
lines changed

hal/architecture/ESP8266/MyMainESP8266.cpp

Lines changed: 165 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ extern void(*__init_array_end)(void);
4545
/* Not static, used in Esp.cpp */
4646
struct rst_info resetInfo;
4747

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+
*/
5252
cont_t* g_pcont __attribute__((section(".noinit")));
5353

5454
/* Event queue used by the main (arduino) task */
@@ -57,6 +57,13 @@ static os_event_t s_loop_queue[LOOP_QUEUE_SIZE];
5757
/* Used to implement optimistic_yield */
5858
static uint32_t s_micros_at_task_start;
5959

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+
6067

6168
extern "C" {
6269
extern const uint32_t __attribute__((section(".ver_number"))) core_version =
@@ -83,24 +90,36 @@ void preloop_update_frequency()
8390
#endif
8491
}
8592

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+
}
86104

87105
extern "C" void esp_yield()
88106
{
89-
if (cont_can_yield(g_pcont)) {
90-
cont_yield(g_pcont);
107+
if (can_yield()) {
108+
esp_yield_within_cont();
91109
}
92110
}
93111

94112
extern "C" void esp_schedule()
95113
{
114+
// always on CONT stack here
96115
ets_post(LOOP_TASK_PRIORITY, 0, 0);
97116
}
98117

99118
extern "C" void __yield()
100119
{
101-
if (cont_can_yield(g_pcont)) {
120+
if (can_yield()) {
102121
esp_schedule();
103-
esp_yield();
122+
esp_yield_within_cont();
104123
} else {
105124
panic();
106125
}
@@ -110,12 +129,54 @@ extern "C" void yield(void) __attribute__((weak, alias("__yield")));
110129

111130
extern "C" void optimistic_yield(uint32_t interval_us)
112131
{
113-
if (cont_can_yield(g_pcont) &&
132+
if (can_yield() &&
114133
(system_get_time() - s_micros_at_task_start) > interval_us) {
115134
yield();
116135
}
117136
}
118137

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+
119180
static void loop_wrapper()
120181
{
121182
static bool setup_done = false;
@@ -139,101 +200,146 @@ static void loop_task(os_event_t *events)
139200
panic();
140201
}
141202
}
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+
}
142211

143212
static void do_global_ctors(void)
144213
{
214+
static struct object ob;
215+
__register_frame_info(__eh_frame, &ob);
216+
145217
void(**p)(void) = &__init_array_end;
146218
while (p != &__init_array_start) {
147219
(*--p)();
148220
}
149221
}
150222

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+
151249
void init_done()
152250
{
153251
system_set_os_print(1);
154252
gdb_init();
253+
std::set_terminate(__unhandled_exception_cpp);
155254
do_global_ctors();
156255
esp_schedule();
157256
}
158257

159258
/* 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+
*/
167266
/*
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:
196268
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.
198273
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.
203277
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.
207282
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.
210286
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).
212290
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+
{
213306
/* Allocate continuation context on this SYS stack,
214-
and save pointer to it. */
307+
and save pointer to it. */
215308
cont_t s_cont __attribute__((aligned(16)));
216309
g_pcont = &s_cont;
217310

218-
#endif
219-
220311
/* Call the entry point of the SDK code. */
221312
call_user_start();
222313
}
223314

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+
224328
extern "C" void user_init(void)
225329
{
226330
struct rst_info *rtc_info_ptr = system_get_rst_info();
227331
memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo));
228332

229333
uart_div_modify(0, UART_CLK_FREQ / (115200));
230334

231-
init();
335+
init(); // in core_esp8266_wiring.c, inits hw regs and sdk timer
232336

233337
initVariant();
234338

235339
cont_init(g_pcont);
236340

341+
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
342+
237343
ets_task(loop_task,
238344
LOOP_TASK_PRIORITY, s_loop_queue,
239345
LOOP_QUEUE_SIZE);

0 commit comments

Comments
 (0)