Skip to content

Commit cc88e1d

Browse files
committed
Simplify MyMainESP8266 for core 3.0.x (mysensors#1496)
and replace ICACHE_RAM_ATTR by IRAM_ATTR
1 parent 423b9d7 commit cc88e1d

File tree

4 files changed

+23
-334
lines changed

4 files changed

+23
-334
lines changed

examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino

-6
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ MyMessage wattMsg(CHILD_ID, V_WATT);
6868
MyMessage kWhMsg(CHILD_ID, V_KWH);
6969
MyMessage pcMsg(CHILD_ID, V_VAR1);
7070

71-
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
72-
#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR
73-
#else
74-
#define IRQ_HANDLER_ATTR
75-
#endif
76-
7771
void IRQ_HANDLER_ATTR onPulse()
7872
{
7973
if (!SLEEP_MODE) {

examples/WaterMeterPulseSensor/WaterMeterPulseSensor.ino

-6
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,6 @@ double oldvolume =0;
7575
uint32_t lastSend =0;
7676
uint32_t lastPulse =0;
7777

78-
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
79-
#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR
80-
#else
81-
#define IRQ_HANDLER_ATTR
82-
#endif
83-
8478
void IRQ_HANDLER_ATTR onPulse()
8579
{
8680
if (!SLEEP_MODE) {

hal/architecture/ESP8266/MyMainESP8266.cpp

+19-322
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* network topology allowing messages to be routed to nodes.
77
*
88
* Created by Henrik Ekblad <[email protected]>
9-
* Copyright (C) 2013-2020 Sensnology AB
9+
* Copyright (C) 2013-2022 Sensnology AB
1010
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
1111
*
1212
* Documentation: http://www.mysensors.org
@@ -17,332 +17,29 @@
1717
* version 2 as published by the Free Software Foundation.
1818
*/
1919

20-
//This may be used to change user task stack size:
21-
//#define CONT_STACKSIZE 4096
22-
#include <Arduino.h>
23-
#include "Schedule.h"
24-
extern "C" {
25-
#include "ets_sys.h"
26-
#include "os_type.h"
27-
#include "osapi.h"
28-
#include "mem.h"
29-
#include "user_interface.h"
30-
#include "cont.h"
31-
}
32-
#include <core_version.h>
33-
#include "gdb_hooks.h"
34-
35-
#define LOOP_TASK_PRIORITY 1
36-
#define LOOP_QUEUE_SIZE 1
37-
#define OPTIMISTIC_YIELD_TIME_US 16000
38-
39-
extern "C" void call_user_start();
40-
extern void loop();
41-
extern void setup();
42-
extern void(*__init_array_start)(void);
43-
extern void(*__init_array_end)(void);
44-
45-
/* Not static, used in Esp.cpp */
46-
struct rst_info resetInfo;
47-
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-
cont_t* g_pcont __attribute__((section(".noinit")));
53-
54-
/* Event queue used by the main (arduino) task */
55-
static os_event_t s_loop_queue[LOOP_QUEUE_SIZE];
56-
57-
/* Used to implement optimistic_yield */
58-
static uint32_t s_micros_at_task_start;
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-
67-
68-
extern "C" {
69-
extern const uint32_t __attribute__((section(".ver_number"))) core_version =
70-
ARDUINO_ESP8266_GIT_VER;
71-
const char* core_release =
72-
#ifdef ARDUINO_ESP8266_RELEASE
73-
ARDUINO_ESP8266_RELEASE;
74-
#else
75-
NULL;
76-
#endif
77-
} // extern "C"
78-
79-
void initVariant() __attribute__((weak));
80-
void initVariant()
81-
{
82-
}
83-
84-
void preloop_update_frequency() __attribute__((weak));
85-
void preloop_update_frequency()
86-
{
87-
#if defined(F_CPU) && (F_CPU == 160000000L)
88-
REG_SET_BIT(0x3ff00014, BIT(0));
89-
ets_update_cpu_frequency(160);
90-
#endif
91-
}
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-
}
104-
105-
extern "C" void esp_yield()
106-
{
107-
if (can_yield()) {
108-
esp_yield_within_cont();
109-
}
110-
}
111-
112-
extern "C" void esp_schedule()
113-
{
114-
// always on CONT stack here
115-
ets_post(LOOP_TASK_PRIORITY, 0, 0);
116-
}
117-
118-
extern "C" void __yield()
119-
{
120-
if (can_yield()) {
121-
esp_schedule();
122-
esp_yield_within_cont();
123-
} else {
124-
panic();
125-
}
126-
}
127-
128-
extern "C" void yield(void) __attribute__((weak, alias("__yield")));
129-
130-
extern "C" void optimistic_yield(uint32_t interval_us)
131-
{
132-
if (can_yield() &&
133-
(system_get_time() - s_micros_at_task_start) > interval_us) {
134-
yield();
135-
}
136-
}
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)
20+
inline void _my_sensors_loop()
17321
{
174-
run_scheduled_functions();
175-
run_scheduled_recurrent_functions();
176-
}
177-
178-
extern "C" void loop_end(void) __attribute__((weak, alias("__loop_end")));
179-
180-
static void loop_wrapper()
181-
{
182-
static bool setup_done = false;
183-
preloop_update_frequency();
184-
if (!setup_done) {
185-
_begin(); // Startup MySensors library
186-
setup_done = true;
187-
}
188-
_process(); // Process incoming data
22+
// Process incoming data
23+
_process();
24+
// Call of loop() in the Arduino sketch
18925
loop();
190-
run_scheduled_functions();
191-
esp_schedule();
19226
}
19327

194-
static void loop_task(os_event_t *events)
195-
{
196-
(void)events;
197-
s_micros_at_task_start = system_get_time();
198-
cont_run(g_pcont, &loop_wrapper);
199-
if (cont_check(g_pcont) != 0) {
200-
panic();
201-
}
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-
}
211-
212-
static void do_global_ctors(void)
213-
{
214-
static struct object ob;
215-
__register_frame_info(__eh_frame, &ob);
216-
217-
void(**p)(void) = &__init_array_end;
218-
while (p != &__init_array_start) {
219-
(*--p)();
220-
}
221-
}
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-
249-
void init_done()
250-
{
251-
system_set_os_print(1);
252-
gdb_init();
253-
std::set_terminate(__unhandled_exception_cpp);
254-
do_global_ctors();
255-
esp_schedule();
256-
}
257-
258-
/* This is the entry point of the application.
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-
*/
26628
/*
267-
A bit of explanation for this entry point:
268-
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.
273-
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.
277-
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.
282-
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.
286-
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).
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-
{
306-
/* Allocate continuation context on this SYS stack,
307-
and save pointer to it. */
308-
cont_t s_cont __attribute__((aligned(16)));
309-
g_pcont = &s_cont;
310-
311-
/* Call the entry point of the SDK code. */
312-
call_user_start();
313-
}
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-
328-
extern "C" void user_init(void)
329-
{
330-
struct rst_info *rtc_info_ptr = system_get_rst_info();
331-
memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo));
332-
333-
uart_div_modify(0, UART_CLK_FREQ / (115200));
334-
335-
init(); // in core_esp8266_wiring.c, inits hw regs and sdk timer
336-
337-
initVariant();
338-
339-
cont_init(g_pcont);
29+
* Use preprocessor defines for injection of the MySensors calls
30+
* to _begin() and _process() in file core_esp8266_main.cpp.
31+
* These functions implement the "magic" how the MySensors stack
32+
* is setup and executed in background without need
33+
* for explicit calls from the Arduino sketch.
34+
*/
34035

341-
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
36+
// Start up MySensors library including call of setup() in the Arduino sketch
37+
#define setup _begin
38+
// Helper function to _process() and call of loop() in the Arduino sketch
39+
#define loop _my_sensors_loop
34240

343-
ets_task(loop_task,
344-
LOOP_TASK_PRIORITY, s_loop_queue,
345-
LOOP_QUEUE_SIZE);
41+
#include <core_esp8266_main.cpp>
34642

347-
system_init_done_cb(&init_done);
348-
}
43+
// Tidy up injection defines
44+
#undef loop
45+
#undef setup

hal/architecture/MyHwHAL.h

+4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@
4343
* @brief ESP8266/ESP32 IRQ handlers need to be stored in IRAM
4444
*/
4545
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
46+
#if defined(ARDUINO_ARCH_ESP8266) && ARDUINO_ESP8266_MAJOR == 3
47+
#define IRQ_HANDLER_ATTR IRAM_ATTR
48+
#else
4649
#define IRQ_HANDLER_ATTR ICACHE_RAM_ATTR
50+
#endif
4751
#else
4852
#define IRQ_HANDLER_ATTR
4953
#endif

0 commit comments

Comments
 (0)