1212#include < rom/rtc.h>
1313#include < sys/time.h>
1414#include < Wire.h>
15- #include " driver/rtc_io.h"
15+ #include " soc/rtc.h"
16+ #include " esp_system.h"
1617
1718class ESP32Board : public mesh ::MainBoard {
1819protected:
1920 uint8_t startup_reason;
2021 bool inhibit_sleep = false ;
22+ static inline portMUX_TYPE sleepMux = portMUX_INITIALIZER_UNLOCKED;
2123
2224public:
2325 void begin () {
2426 // for future use, sub-classes SHOULD call this from their begin()
25- startup_reason = BD_STARTUP_NORMAL ;
27+ startup_reason = BD_STARTUP_NORMAL ;
2628
2729 #ifdef ESP32_CPU_FREQ
2830 setCpuFrequencyMhz (ESP32_CPU_FREQ );
@@ -45,7 +47,7 @@ class ESP32Board : public mesh::MainBoard {
4547 #endif
4648 #else
4749 Wire.begin ();
48- #endif
50+ #endif
4951 }
5052
5153 // Temperature from ESP32 MCU
@@ -60,25 +62,48 @@ class ESP32Board : public mesh::MainBoard {
6062 return raw / 4 ;
6163 }
6264
63- void enterLightSleep (uint32_t secs) {
64- #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(P_LORA_DIO_1) // Supported ESP32 variants
65- if (rtc_gpio_is_valid_gpio ((gpio_num_t )P_LORA_DIO_1 )) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin
66- esp_sleep_pd_config (ESP_PD_DOMAIN_RTC_PERIPH , ESP_PD_OPTION_ON );
67- esp_sleep_enable_ext1_wakeup ((1L << P_LORA_DIO_1 ), ESP_EXT1_WAKEUP_ANY_HIGH ); // To wake up when receiving a LoRa packet
65+ uint32_t getIRQGpio () override {
66+ return P_LORA_DIO_1 ; // default for SX1262
67+ }
68+
69+ void sleep (uint32_t secs) override {
70+ // Skip if not allow to sleep
71+ if (inhibit_sleep) {
72+ delay (1 ); // Give MCU to OTA to run
73+ return ;
74+ }
6875
69- if (secs > 0 ) {
70- esp_sleep_enable_timer_wakeup (secs * 1000000 ); // To wake up every hour to do periodically jobs
71- }
76+ // Set GPIO wakeup
77+ gpio_num_t wakeupPin = (gpio_num_t )getIRQGpio ();
7278
73- esp_light_sleep_start (); // CPU enters light sleep
79+ // Configure timer wakeup
80+ if (secs > 0 ) {
81+ esp_sleep_enable_timer_wakeup (secs * 1000000ULL ); // Wake up periodically to do scheduled jobs
7482 }
75- #endif
76- }
7783
78- void sleep (uint32_t secs) override {
79- if (!inhibit_sleep) {
80- enterLightSleep (secs); // To wake up after "secs" seconds or when receiving a LoRa packet
84+ // Disable CPU interrupt servicing
85+ portENTER_CRITICAL (&sleepMux);
86+
87+ // Skip sleep if there is a LoRa packet
88+ if (gpio_get_level (wakeupPin) == HIGH ) {
89+ portEXIT_CRITICAL (&sleepMux);
90+ delay (1 );
91+ return ;
8192 }
93+
94+ // Configure GPIO wakeup
95+ esp_sleep_enable_gpio_wakeup ();
96+ gpio_wakeup_enable ((gpio_num_t )wakeupPin, GPIO_INTR_HIGH_LEVEL ); // Wake up when receiving a LoRa packet
97+
98+ // MCU enters light sleep
99+ esp_light_sleep_start ();
100+
101+ // Avoid ISR flood during wakeup due to HIGH LEVEL interrupt
102+ gpio_wakeup_disable (wakeupPin);
103+ gpio_set_intr_type (wakeupPin, GPIO_INTR_POSEDGE );
104+
105+ // Enable CPU interrupt servicing
106+ portEXIT_CRITICAL (&sleepMux);
82107 }
83108
84109 uint8_t getStartupReason () const override { return startup_reason; }
@@ -102,7 +127,7 @@ class ESP32Board : public mesh::MainBoard {
102127#endif
103128
104129 uint16_t getBattMilliVolts () override {
105- #ifdef PIN_VBAT_READ
130+ #ifdef PIN_VBAT_READ
106131 analogReadResolution (12 );
107132
108133 uint32_t raw = 0 ;
@@ -141,16 +166,16 @@ class ESP32RTCClock : public mesh::RTCClock {
141166 // start with some date/time in the recent past
142167 struct timeval tv;
143168 tv.tv_sec = 1715770351 ; // 15 May 2024, 8:50pm
144- tv.tv_usec = 0 ;
145- settimeofday (&tv, NULL );
146- }
169+ tv.tv_usec = 0 ;
170+ settimeofday (&tv, NULL );
171+ }
147172 }
148173 uint32_t getCurrentTime () override {
149174 time_t _now;
150175 time (&_now);
151176 return _now;
152177 }
153- void setCurrentTime (uint32_t time) override {
178+ void setCurrentTime (uint32_t time) override {
154179 struct timeval tv;
155180 tv.tv_sec = time;
156181 tv.tv_usec = 0 ;
0 commit comments