8000 Merge pull request #4606 from hierophect/sleep-revamp · domdfcoding/circuitpython@f5aa55c · GitHub
[go: up one dir, main page]

Skip to content

Commit f5aa55c

Browse files
authored
Merge pull request adafruit#4606 from hierophect/sleep-revamp
Internal API revisions to sleep
2 parents 74355e8 + bce541d commit f5aa55c

File tree

22 files changed

+203
-141
lines changed

22 files changed

+203
-141
lines changed

main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ STATIC void start_mp(supervisor_allocation* heap) {
162162

163163
#if CIRCUITPY_ALARM
164164
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
165-
shared_alarm_save_wake_alarm();
165+
shared_alarm_save_wake_alarm(common_hal_alarm_create_wake_alarm());
166166
// Reset alarm module only after we retrieved the wakeup alarm.
167167
alarm_reset();
168168
#endif

ports/esp32s2/common-hal/alarm/__init__.c

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,39 +63,42 @@ void alarm_reset(void) {
6363
}
6464

6565
STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
66-
if (alarm_pin_pinalarm_woke_us_up()) {
66+
// First check if the modules remember what last woke up
67+
if (alarm_pin_pinalarm_woke_this_cycle()) {
6768
return ESP_SLEEP_WAKEUP_GPIO;
6869
}
69-
if (alarm_time_timealarm_woke_us_up()) {
70+
if (alarm_time_timealarm_woke_this_cycle()) {
7071
return ESP_SLEEP_WAKEUP_TIMER;
7172
}
72-
if (alarm_touch_touchalarm_woke_us_up()) {
73+
if (alarm_touch_touchalarm_woke_this_cycle()) {
7374
return ESP_SLEEP_WAKEUP_TOUCHPAD;
7475
}
76+
// If waking from true deep sleep, modules will have lost their state,
77+
// so check the deep wakeup cause manually
7578
return esp_sleep_get_wakeup_cause();
7679
}
7780

7881
bool common_hal_alarm_woken_from_sleep(void) {
7982
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
8083
}
8184

82-
// When called to populate the global dict, the module functions create new alarm objects.
83-
// Otherwise, they scan the existing alarms for matches.
84-
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
85+
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
86+
// If woken from deep sleep, create a copy alarm similar to what would have
87+
// been passed in originally. Otherwise, just return none
8588
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
8689
switch (cause) {
8790
case ESP_SLEEP_WAKEUP_TIMER: {
88-
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
91+
return alarm_time_timealarm_create_wakeup_alarm();
8992
}
9093

9194
case ESP_SLEEP_WAKEUP_GPIO:
9295
case ESP_SLEEP_WAKEUP_EXT0:
9396
case ESP_SLEEP_WAKEUP_EXT1: {
94-
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
97+
return alarm_pin_pinalarm_create_wakeup_alarm();
9598
}
9699

97100
case ESP_SLEEP_WAKEUP_TOUCHPAD: {
98-
return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
101+
return alarm_touch_touchalarm_create_wakeup_alarm();
99102
}
100103

101104
case ESP_SLEEP_WAKEUP_UNDEFINED:
@@ -106,44 +109,51 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
106109
return mp_const_none;
107110
}
108111

109-
// This function is used to create a new alarm object for the global dict after deep sleep,
110-
// rather than finding an existing one during runtime.
111-
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
112-
return _get_wake_alarm(0, NULL);
113-
}
114-
115112
// Set up light sleep or deep sleep alarms.
116113
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
117114
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
118115
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
119116
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
120117
}
121118

122-
STATIC void _idle_until_alarm(void) {
123-
// Poll for alarms.
119+
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
120+
_setup_sleep_alarms(false, n_alarms, alarms);
121+
122+
mp_obj_t wake_alarm = mp_const_none;
123+
124+
// We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals.
124125
while (!mp_hal_is_interrupted()) {
125126
RUN_BACKGROUND_TASKS;
126-
// Allow ctrl-C interrupt.
127+
// Detect if interrupt was alarm or ctrl-C interrupt.
127128
if (common_hal_alarm_woken_from_sleep()) {
128-
// This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings
129-
shared_alarm_save_wake_alarm();
130-
return;
129+
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
130+
switch (cause) {
131+
case ESP_SLEEP_WAKEUP_TIMER: {
132+
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
133+
break;
134+
}
135+
case ESP_SLEEP_WAKEUP_GPIO: {
136+
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
137+
break;
138+
}
139+
case ESP_SLEEP_WAKEUP_TOUCHPAD: {
140+
wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms,alarms);
141+
break;
142+
}
143+
default:
144+
// Should not reach this, if all light sleep types are covered correctly
145+
break;
146+
}
147+
shared_alarm_save_wake_alarm(wake_alarm);
148+
break;
131149
}
132150
port_idle_until_interrupt();
133151
}
134-
}
135-
136-
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
137-
_setup_sleep_alarms(false, n_alarms, alarms);
138-
139-
// We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals.
140-
_idle_until_alarm();
141152

142153
if (mp_hal_is_interrupted()) {
143154
return mp_const_none; // Shouldn't be given to python code because exception handling should kick in.
144155
}
145156

146-
mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
147157
alarm_reset();
148158
return wake_alarm;
149159
}

ports/esp32s2/common-hal/alarm/pin/PinAlarm.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,11 @@ void gpio_interrupt(void *arg) {
9696
}
9797
}
9898

99-
bool alarm_pin_pinalarm_woke_us_up(void) {
99+
bool alarm_pin_pinalarm_woke_this_cycle(void) {
100100
return pin_31_0_status != 0 || pin_63_32_status != 0;
101101
}
102102

103-
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
104-
// For light sleep, we check if we match any existing alarms
103+
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
105104
uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status;
106105
for (size_t i = 0; i < n_alarms; i++) {
107106
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
@@ -112,9 +111,16 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
112111
return alarms[i];
113112
}
114113
}
115-
// For deep sleep, a new alarm must be created
114+
return mp_const_none;
115+
}
116+
117+
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
116118
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
119+
120+
// Pin status will persist into a fake deep sleep
121+
uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status;
117122
size_t pin_number = 64;
123+
118124
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
119125
pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL);
120126
} else {

ports/esp32s2/common-hal/alarm/pin/PinAlarm.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ typedef struct {
3434
bool pull;
3535
} alarm_pin_pinalarm_obj_t;
3636

37+
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
38+
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void);
39+
40+
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
3741
void alarm_pin_pinalarm_reset(void);
3842
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
39-
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
40-
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
41-
bool alarm_pin_pinalarm_woke_us_up(void);
43+
bool alarm_pin_pinalarm_woke_this_cycle(void);

ports/esp32s2/common-hal/alarm/time/TimeAlarm.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,16 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala
4242
return self->monotonic_time;
4343
}
4444

45-
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
46-
// First, check to see if we match
45+
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
4746
for (size_t i = 0; i < n_alarms; i++) {
4847
if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
4948
return alarms[i];
5049
}
5150
}
51+
return mp_const_none;
52+
}
53+
54+
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
5255
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
5356
timer->base.type = &alarm_time_timealarm_type;
5457
// TODO: Set monotonic_time based on the RTC state.
@@ -66,7 +69,7 @@ void timer_callback(void *arg) {
6669
xTaskNotifyGive(circuitpython_task);
6770
}
6871

69-
bool alarm_time_timealarm_woke_us_up(void) {
72+
bool alarm_time_timealarm_woke_this_cycle(void) {
7073
return woke_up;
7174
}
7275

ports/esp32s2/common-hal/alarm/time/TimeAlarm.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ typedef struct {
3232
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
3333
} alarm_time_timealarm_obj_t;
3434

35-
// Find the alarm object that caused us to wake up or create an equivalent one.
36-
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
37-
// Check for the wake up alarm from pretend deep sleep.
38-
bool alarm_time_timealarm_woke_us_up(void);
39-
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
35+
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
36+
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
37+
4038
void alarm_time_timealarm_reset(void);
39+
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
40+
bool alarm_time_timealarm_woke_this_cycle(void);

ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,16 @@ void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *s
4242
self->pin = pin;
4343
}
4444

45-
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
46-
// First, check to see if we match any given alarms.
45+
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
4746
for (size_t i = 0; i < n_alarms; i++) {
4847
if (mp_obj_is_type(alarms[i], &alarm_touch_touchalarm_type)) {
4948
return alarms[i];
5049
}
5150
}
51+
return mp_const_none;
52+
}
5253

54+
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) {
5355
// Create TouchAlarm object.
5456
alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t);
5557
alarm->base.type = &alarm_touch_touchalarm_type;
@@ -168,7 +170,7 @@ void alarm_touch_touchalarm_prepare_for_deep_sleep(void) {
168170
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
169171
}
170172

171-
bool alarm_touch_touchalarm_woke_us_up(void) {
173+
bool alarm_touch_touchalarm_woke_this_cycle(void) {
172174
return woke_up;
173175
}
174176

ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ typedef struct {
3535
const mcu_pin_obj_t *pin;
3636
} alarm_touch_touchalarm_obj_t;
3737

38-
// Find the alarm object that caused us to wake up or create an equivalent one.
39-
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms);
40-
// Check for the wake up alarm from pretend deep sleep.
41-
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
38+
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms);
39+
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void);
40+
4241
void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
43-
bool alarm_touch_touchalarm_woke_us_up(void);
4442
void alarm_touch_touchalarm_reset(void);
43+
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
44+
bool alarm_touch_touchalarm_woke_this_cycle(void);
4545

4646
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

ports/nrf/common-hal/alarm/__init__.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,18 @@ void alarm_reset(void) {
6969

7070
extern uint32_t reset_reason_saved;
7171
STATIC nrf_sleep_source_t _get_wakeup_cause(void) {
72-
if (alarm_pin_pinalarm_woke_us_up()) {
72+
// First check if the modules remember what last woke up
73+
if (alarm_pin_pinalarm_woke_this_cycle()) {
7374
return NRF_SLEEP_WAKEUP_GPIO;
7475
}
75-
if (alarm_time_timealarm_woke_us_up()) {
76+
if (alarm_time_timealarm_woke_this_cycle()) {
7677
return NRF_SLEEP_WAKEUP_TIMER;
7778
}
78-
if (alarm_touch_touchalarm_woke_us_up()) {
79+
if (alarm_touch_touchalarm_woke_this_cycle()) {
7980
return NRF_SLEEP_WAKEUP_TOUCHPAD;
8081
}
82+
// If waking from true deep sleep, modules will have lost their state,
83+
// so check the deep wakeup cause manually
8184
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
8285
return NRF_SLEEP_WAKEUP_RESETPIN;
8386
} else if (reset_reason_saved & NRF_POWER_RESETREAS_OFF_MASK) {
@@ -116,29 +119,26 @@ bool common_hal_alarm_woken_from_sleep(void) {
116119
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD;
117120
}
118121

119-
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
122+
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
123+
// If woken from deep sleep, create a copy alarm similar to what would have
124+
// been passed in originally. Otherwise, just return none
120125
nrf_sleep_source_t cause = _get_wakeup_cause();
121126
switch (cause) {
122127
case NRF_SLEEP_WAKEUP_TIMER: {
123-
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
128+
return alarm_time_timealarm_create_wakeup_alarm();
124129
}
125130
case NRF_SLEEP_WAKEUP_TOUCHPAD: {
126-
return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
131+
return alarm_touch_touchalarm_create_wakeup_alarm();
127132
}
128133
case NRF_SLEEP_WAKEUP_GPIO: {
129-
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
134+
return alarm_pin_pinalarm_create_wakeup_alarm();
130135
}
131136
default:
132137
break;
133138
}
134139
return mp_const_none;
135140
}
136141

137-
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
138-
mp_obj_t obj = _get_wake_alarm(0, NULL);
139-
return obj;
140-
}
141-
142142
// Set up light sleep or deep sleep alarms.
143143
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
144144
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
@@ -257,7 +257,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
257257
}
258258

259259
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
260-
mp_obj_t wake_alarm;
260+
mp_obj_t wake_alarm = mp_const_none;
261261
alarm_time_timealarm_clear_wakeup_time();
262262
_setup_sleep_alarms(false, n_alarms, alarms);
263263

@@ -271,7 +271,23 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
271271
if (mp_hal_is_interrupted()) {
272272
wake_alarm = mp_const_none;
273273
} else {
274-
wake_alarm = _get_wake_alarm(n_alarms, alarms);
274+
if (common_hal_alarm_woken_from_sleep()) {
275+
nrf_sleep_source_t cause = _get_wakeup_cause();
276+
switch (cause) {
277+
case NRF_SLEEP_WAKEUP_TIMER: {
278+
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
279+
break;
280+
}
281+
case NRF_SLEEP_WAKEUP_GPIO: {
282+
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
283+
break;
284+
}
285+
default:
286+
// Should not reach this, if all light sleep types are covered correctly
287+
break;
288+
}
289+
shared_alarm_save_wake_alarm(wake_alarm);
290+
}
275291
}
276292
alarm_reset();
277293
return wake_alarm;

ports/nrf/common-hal/alarm/pin/PinAlarm.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t
8585
sleepmem_wakeup_pin = pin & 0xFF;
8686
}
8787

88-
bool alarm_pin_pinalarm_woke_us_up(void) {
88+
bool alarm_pin_pinalarm_woke_this_cycle(void) {
8989
return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_PIN &&
9090
sleepmem_wakeup_pin != WAKEUP_PIN_UNDEF;
9191
}
9292

93-
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
93+
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
9494
// First, check to see if we match any given alarms.
9595
for (size_t i = 0; i < n_alarms; i++) {
9696
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
@@ -101,6 +101,10 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
101101
return alarms[i];
102102
}
103103
}
104+
return mp_const_none;
105+
}
106+
107+
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
104108
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
105109
alarm->base.type = &alarm_pin_pinalarm_type;
106110
alarm->pin = NULL;

ports/nrf/common-hal/alarm/pin/PinAlarm.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ typedef struct {
3434
bool pull;
3535
} alarm_pin_pinalarm_obj_t;
3636

37+
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
38+
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void);
39+
3740
void alarm_pin_pinalarm_reset(void);
3841
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
3942
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
40-
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
41-
bool alarm_pin_pinalarm_woke_us_up(void);
43+
bool alarm_pin_pinalarm_woke_this_cycle(void);

0 commit comments

Comments
 (0)
0