Skip to content

Commit d4b00d2

Browse files
committed
Merge branch 'bugfix/fix_cpu_sleep_reject_proc_v3.3' into 'release/v3.3'
esp8266: fix CPU light sleep process (backport v3.3) See merge request sdk/ESP8266_RTOS_SDK!1226
2 parents 8146bfc + 1a51815 commit d4b00d2

File tree

2 files changed

+89
-24
lines changed

2 files changed

+89
-24
lines changed

components/esp8266/include/driver/rtc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ void rtc_init_clk(uint8_t *init_param);
5555
*/
5656
void rtc_lightsleep_init(void);
5757

58+
/**
59+
* @brief Configure CPU sleep mode
60+
*/
61+
void pm_set_sleep_mode(uint32_t mode);
62+
5863
/**
5964
* @brief Initialize hardware when CPU wakes up from light sleep
6065
*/

components/esp8266/source/esp_sleep.c

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include "FreeRTOS.h"
2222
#include "freertos/task.h"
2323
#include "driver/soc.h"
24+
#include "driver/gpio.h"
2425
#include "esp8266/timer_struct.h"
26+
#include "esp8266/gpio_struct.h"
2527
#include "esp8266/rom_functions.h"
2628
#include "driver/rtc.h"
2729
#include "rom/uart.h"
@@ -37,10 +39,11 @@
3739
#define FRC2_TICKS_PER_US (5)
3840
#define FRC2_TICKS_MAX (UINT32_MAX / 4)
3941

40-
#define SLEEP_MIN_TIME (1000)
41-
#define SLEEP_PROC_TIME (4450)
42+
#define SLEEP_PROC_TIME (3072)
4243
#define WAKEUP_EARLY_TICKS (264) // PLL and STAL wait ticks
43-
#define MIN_SLEEP_US (SLEEP_MIN_TIME + SLEEP_PROC_TIME)
44+
#define MIN_SLEEP_US (6500)
45+
#define RTC_TICK_CAL (100)
46+
#define RTC_TICK_OFF (1245 + RTC_TICK_CAL)
4447

4548
#define TAG "esp8266_pm"
4649

@@ -51,6 +54,11 @@ typedef struct pm_soc_clk {
5154
uint32_t frc2_cnt;
5255

5356
uint32_t wdev_cnt;
57+
58+
uint32_t rtc_val;
59+
uint32_t cal_period;
60+
61+
uint32_t sleep_us;
5462
} pm_soc_clk_t;
5563

5664
static uint16_t s_lock_cnt = 1;
@@ -76,6 +84,8 @@ static inline void restore_local_wdev(uint32_t reg)
7684

7785
static inline void save_soc_clk(pm_soc_clk_t *clk)
7886
{
87+
clk->rtc_val = REG_READ(RTC_SLP_CNT_VAL);
88+
7989
clk->ccount = soc_get_ccount();
8090

8191
clk->frc2_enable = REG_READ(FRC2_CTL) & FRC2_CNTL_ENABLE;
@@ -96,24 +106,50 @@ static inline uint32_t min_sleep_us(pm_soc_clk_t *clk)
96106
const uint32_t frc2_sleep_ticks = REG_READ(FRC2_ALARM) - clk->frc2_cnt;
97107
const uint32_t frc2_sleep_us = frc2_sleep_ticks < FRC2_TICKS_MAX ? frc2_sleep_ticks / FRC2_TICKS_PER_US : 0;
98108

99-
return MIN(ccompare_sleep_us, frc2_sleep_us);
109+
clk->sleep_us = MIN(ccompare_sleep_us, frc2_sleep_us);
100110
} else {
101-
return ccompare_sleep_us;
111+
clk->sleep_us = ccompare_sleep_us;
102112
}
113+
114+
return clk->sleep_us;
115+
}
116+
117+
static inline uint32_t sleep_rtc_ticks(pm_soc_clk_t *clk)
118+
{
119+
uint32_t rtc_ticks;
120+
121+
clk->cal_period = pm_rtc_clock_cali_proc();
122+
123+
rtc_ticks = pm_usec2rtc(clk->sleep_us - SLEEP_PROC_TIME, clk->cal_period);
124+
125+
return rtc_ticks;
103126
}
104127

105-
static inline void update_soc_clk(pm_soc_clk_t *clk, uint32_t us)
128+
static inline void update_soc_clk(pm_soc_clk_t *clk)
106129
{
107130
extern uint32_t WdevTimOffSet;
108131

109-
const uint32_t os_ccount = us * g_esp_ticks_per_us + clk->ccount;
132+
uint32_t slept_us, total_rtc, end_rtc = REG_READ(RTC_SLP_CNT_VAL);
133+
134+
if (end_rtc > clk->rtc_val)
135+
total_rtc = end_rtc - clk->rtc_val;
136+
else
137+
total_rtc = UINT32_MAX - clk->rtc_val + end_rtc;
138+
slept_us = pm_rtc2usec(total_rtc, clk->cal_period) + RTC_TICK_OFF;
139+
140+
if (slept_us > clk->sleep_us)
141+
slept_us = clk->sleep_us;
142+
else
143+
slept_us -= RTC_TICK_CAL;
144+
145+
const uint32_t os_ccount = slept_us * g_esp_ticks_per_us + clk->ccount;
110146

111147
if (os_ccount >= _xt_tick_divisor)
112148
soc_set_ccompare(os_ccount + 32);
113149
soc_set_ccount(os_ccount);
114150

115151
if (clk->frc2_enable) {
116-
const uint32_t frc2_cnt = us * FRC2_TICKS_PER_US + clk->frc2_cnt - 1;
152+
const uint32_t frc2_cnt = slept_us * FRC2_TICKS_PER_US + clk->frc2_cnt - 1;
117153

118154
REG_WRITE(FRC2_LOAD, frc2_cnt);
119155
}
@@ -122,9 +158,9 @@ static inline void update_soc_clk(pm_soc_clk_t *clk, uint32_t us)
122158
uint32_t wdev_cnt = REG_READ(WDEV_COUNT_REG);
123159

124160
if (clk->wdev_cnt < wdev_cnt)
125-
wdev_us = us - (wdev_cnt - clk->wdev_cnt);
161+
wdev_us = slept_us - (wdev_cnt - clk->wdev_cnt);
126162
else
127-
wdev_us = us - (UINT32_MAX - clk->wdev_cnt + wdev_cnt);
163+
wdev_us = slept_us - (UINT32_MAX - clk->wdev_cnt + wdev_cnt);
128164

129165
WdevTimOffSet += wdev_us;
130166
}
@@ -134,6 +170,32 @@ static int cpu_is_wait_mode(void)
134170
return (s_sleep_mode == ESP_CPU_WAIT) || s_lock_cnt;
135171
}
136172

173+
static int cpu_reject_sleep(void)
174+
{
175+
int ret = 0;
176+
177+
if (s_sleep_wakup_triggers & RTC_GPIO_TRIG_EN) {
178+
for (int gpio = 0; gpio < 16; gpio++) {
179+
if (!GPIO.pin[gpio].wakeup_enable)
180+
continue;
181+
182+
if (GPIO.pin[gpio].int_type == GPIO_INTR_LOW_LEVEL) {
183+
if (!((GPIO.in >> gpio) & 1)) {
184+
ret = 1;
185+
break;
186+
}
187+
} else if (GPIO.pin[gpio].int_type == GPIO_INTR_HIGH_LEVEL) {
188+
if ((GPIO.in >> gpio) & 1) {
189+
ret = 1;
190+
break;
191+
}
192+
}
193+
}
194+
}
195+
196+
return ret;
197+
}
198+
137199
void esp_wifi_hw_open(void)
138200
{
139201
phy_open_rf();
@@ -209,13 +271,13 @@ esp_err_t esp_light_sleep_start(void)
209271
esp_irqflag_t irqflag = soc_save_local_irq();
210272
uint32_t wdevflag = save_local_wdev();
211273
uint32_t period = pm_rtc_clock_cali_proc();
212-
const uint32_t sleep_rtc_ticks = pm_usec2rtc(s_sleep_duration, period);
274+
const uint32_t rtc_ticks = pm_usec2rtc(s_sleep_duration, period);
213275

214-
if (sleep_rtc_ticks > WAKEUP_EARLY_TICKS + 1) {
276+
if (rtc_ticks > WAKEUP_EARLY_TICKS + 1) {
215277
const rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
216278

217-
rtc_lightsleep_init();
218-
pm_set_sleep_cycles(sleep_rtc_ticks - WAKEUP_EARLY_TICKS);
279+
pm_set_sleep_mode(2);
280+
pm_set_sleep_cycles(rtc_ticks - WAKEUP_EARLY_TICKS);
219281
rtc_light_sleep_start(s_sleep_wakup_triggers, 0);
220282
rtc_wakeup_init();
221283

@@ -253,7 +315,7 @@ void esp_sleep_set_mode(esp_sleep_mode_t mode)
253315

254316
void esp_sleep_start(void)
255317
{
256-
if (cpu_is_wait_mode()) {
318+
if (cpu_is_wait_mode() || cpu_reject_sleep()) {
257319
soc_wait_int();
258320
return ;
259321
}
@@ -266,7 +328,7 @@ void esp_sleep_start(void)
266328
const esp_irqflag_t irqflag = soc_save_local_irq();
267329
const uint32_t wdevflag = save_local_wdev();
268330

269-
if (cpu_is_wait_mode()) {
331+
if (cpu_is_wait_mode() || cpu_reject_sleep()) {
270332
cpu_wait = 0;
271333
goto exit;
272334
}
@@ -275,20 +337,18 @@ void esp_sleep_start(void)
275337

276338
const uint32_t sleep_us = min_sleep_us(&clk);
277339
if (sleep_us > MIN_SLEEP_US) {
278-
uint32_t period = pm_rtc_clock_cali_proc();
279-
const uint32_t sleep_rtc_ticks = pm_usec2rtc(sleep_us - SLEEP_PROC_TIME, period);
280-
281-
if (sleep_rtc_ticks > WAKEUP_EARLY_TICKS + 1) {
340+
uint32_t rtc_ticks = sleep_rtc_ticks(&clk);
341+
if (rtc_ticks > WAKEUP_EARLY_TICKS + 1) {
282342
const rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get();
283-
284-
rtc_lightsleep_init();
285-
pm_set_sleep_cycles(sleep_rtc_ticks - WAKEUP_EARLY_TICKS);
343+
344+
pm_set_sleep_mode(2);
345+
pm_set_sleep_cycles(rtc_ticks - WAKEUP_EARLY_TICKS);
286346
rtc_light_sleep_start(s_sleep_wakup_triggers | RTC_TIMER_TRIG_EN, 0);
287347
rtc_wakeup_init();
288348

289349
rtc_clk_cpu_freq_set(cpu_freq);
290350

291-
update_soc_clk(&clk, sleep_us);
351+
update_soc_clk(&clk);
292352

293353
cpu_wait = 0;
294354
}

0 commit comments

Comments
 (0)