8000 Internal API revisions to sleep by hierophect · Pull Request #4606 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

Internal API revisions to sleep #4606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ STATIC void start_mp(supervisor_allocation* heap) {

#if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
shared_alarm_save_wake_alarm();
shared_alarm_save_wake_alarm(common_hal_alarm_create_wake_alarm());
// Reset alarm module only after we retrieved the wakeup alarm.
alarm_reset();
#endif
Expand Down
68 changes: 39 additions & 29 deletions ports/esp32s2/common-hal/alarm/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,42 @@ void alarm_reset(void) {
}

STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
// First check if the modules remember what last woke up
if (alarm_pin_pinalarm_woke_this_cycle()) {
return ESP_SLEEP_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
if (alarm_time_timealarm_woke_this_cycle()) {
return ESP_SLEEP_WAKEUP_TIMER;
}
if (alarm_touch_touchalarm_woke_us_up()) {
if (alarm_touch_touchalarm_woke_this_cycle()) {
return ESP_SLEEP_WAKEUP_TOUCHPAD;
}
// If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually
return esp_sleep_get_wakeup_cause();
}

bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
}

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

case ESP_SLEEP_WAKEUP_GPIO:
case ESP_SLEEP_WAKEUP_EXT0:
case ESP_SLEEP_WAKEUP_EXT1: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_pin_pinalarm_create_wakeup_alarm();
}

case ESP_SLEEP_WAKEUP_TOUCHPAD: {
return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_touch_touchalarm_create_wakeup_alarm();
}

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

// This function is used to create a new alarm object for the global dict after deep sleep,
// rather than finding an existing one during runtime.
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
return _get_wake_alarm(0, NULL);
}

// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
}

STATIC void _idle_until_alarm(void) {
// Poll for alarms.
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
_setup_sleep_alarms(false, n_alarms, alarms);

mp_obj_t wake_alarm = mp_const_none;

// We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals.
while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt.
// Detect if interrupt was alarm or ctrl-C interrupt.
if (common_hal_alarm_woken_from_sleep()) {
// This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings
shared_alarm_save_wake_alarm();
return;
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
switch (cause) {
case ESP_SLEEP_WAKEUP_TIMER: {
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
break;
}
case ESP_SLEEP_WAKEUP_GPIO: {
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
break;
}
case ESP_SLEEP_WAKEUP_TOUCHPAD: {
wake_alarm = alarm_touch_touchalarm_find_triggered_alarm(n_alarms,alarms);
break;
}
default:
// Should not reach this, if all light sleep types are covered correctly
break;
}
shared_alarm_save_wake_alarm(wake_alarm);
break;
}
port_idle_until_interrupt();
}
}

mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
_setup_sleep_alarms(false, n_alarms, alarms);

// We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals.
_idle_until_alarm();

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

mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
alarm_reset();
return wake_alarm;
}
Expand Down
14 changes: 10 additions & 4 deletions ports/esp32s2/common-hal/alarm/pin/PinAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,11 @@ void gpio_interrupt(void *arg) {
}
}

bool alarm_pin_pinalarm_woke_us_up(void) {
bool alarm_pin_pinalarm_woke_this_cycle(void) {
return pin_31_0_status != 0 || pin_63_32_status != 0;
}

mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// For light sleep, we check if we match any existing alarms
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status;
for (size_t i = 0; i < n_alarms; i++) {
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
Expand All @@ -112,9 +111,16 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
return alarms[i];
}
}
// For deep sleep, a new alarm must be created
return mp_const_none;
}

mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();

// Pin status will persist into a fake deep sleep
uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status;
size_t pin_number = 64;

if (cause == ESP_SLEEP_WAKEUP_EXT0) {
pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL);
} else {
Expand Down
8 changes: 5 additions & 3 deletions ports/esp32s2/common-hal/alarm/pin/PinAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ typedef struct {
bool pull;
} alarm_pin_pinalarm_obj_t;

mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void);

void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_us_up(void);
bool alarm_pin_pinalarm_woke_this_cycle(void);
9 changes: 6 additions & 3 deletions ports/esp32s2/common-hal/alarm/time/TimeAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala
return self->monotonic_time;
}

mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
for (size_t i = 0; i < n_alarms; i++) {
if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
return alarms[i];
}
}
return mp_const_none;
}

mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
timer->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state.
Expand All @@ -66,7 +69,7 @@ void timer_callback(void *arg) {
xTaskNotifyGive(circuitpython_task);
}

bool alarm_time_timealarm_woke_us_up(void) {
bool alarm_time_timealarm_woke_this_cycle(void) {
return woke_up;
}

Expand Down
10 changes: 5 additions & 5 deletions ports/esp32s2/common-hal/alarm/time/TimeAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ typedef struct {
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
} alarm_time_timealarm_obj_t;

// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
// Check for the wake up alarm from pretend deep sleep.
bool alarm_time_timealarm_woke_us_up(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);

void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
bool alarm_time_timealarm_woke_this_cycle(void);
8 changes: 5 additions & 3 deletions ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *s
self->pin = pin;
}

mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match any given alarms.
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms) {
for (size_t i = 0; i < n_alarms; i++) {
if (mp_obj_is_type(alarms[i], &alarm_touch_touchalarm_type)) {
return alarms[i];
}
}
return mp_const_none;
}

mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) {
// Create TouchAlarm object.
alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t);
alarm->base.type = &alarm_touch_touchalarm_type;
Expand Down Expand Up @@ -168,7 +170,7 @@ void alarm_touch_touchalarm_prepare_for_deep_sleep(void) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
}

bool alarm_touch_touchalarm_woke_us_up(void) {
bool alarm_touch_touchalarm_woke_this_cycle(void) {
return woke_up;
}

Expand Down
10 changes: 5 additions & 5 deletions ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ typedef struct {
const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t;

// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp_obj_t *alarms);
// Check for the wake up alarm from pretend deep sleep.
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void);

void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
bool alarm_touch_touchalarm_woke_us_up(void);
void alarm_touch_touchalarm_reset(void);
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
bool alarm_touch_touchalarm_woke_this_cycle(void);

#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
44 changes: 30 additions & 14 deletions ports/nrf/common-hal/alarm/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,18 @@ void alarm_reset(void) {

extern uint32_t reset_reason_saved;
STATIC nrf_sleep_source_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
// First check if the modules remember what last woke up
if (alarm_pin_pinalarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
if (alarm_time_timealarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_TIMER;
}
if (alarm_touch_touchalarm_woke_us_up()) {
if (alarm_touch_touchalarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_TOUCHPAD;
}
// If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
return NRF_SLEEP_WAKEUP_RESETPIN;
} else if (reset_reason_saved & NRF_POWER_RESETREAS_OFF_MASK) {
Expand Down Expand Up @@ -116,29 +119,26 @@ bool common_hal_alarm_woken_from_sleep(void) {
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD;
}

STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none
nrf_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_time_timealarm_create_wakeup_alarm();
}
case NRF_SLEEP_WAKEUP_TOUCHPAD: {
return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_touch_touchalarm_create_wakeup_alarm();
}
case NRF_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_pin_pinalarm_create_wakeup_alarm();
}
default:
break;
}
return mp_const_none;
}

mp_obj_t common_hal_alarm_get_wake_alarm(void) {
mp_obj_t obj = _get_wake_alarm(0, NULL);
return obj;
}

// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
Expand Down Expand Up @@ -257,7 +257,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
}

mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t wake_alarm;
mp_obj_t wake_alarm = mp_const_none;
alarm_time_timealarm_clear_wakeup_time();
_setup_sleep_alarms(false, n_alarms, alarms);

Expand All @@ -271,7 +271,23 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
if (mp_hal_is_interrupted()) {
wake_alarm = mp_const_none;
} else {
wake_alarm = _get_wake_alarm(n_alarms, alarms);
if (common_hal_alarm_woken_from_sleep()) {
nrf_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
break;
}
case NRF_SLEEP_WAKEUP_GPIO: {
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
break;
}
default:
// Should not reach this, if all light sleep types are covered correctly
break;
}
shared_alarm_save_wake_alarm(wake_alarm);
}
}
alarm_reset();
return wake_alarm;
Expand Down
8 changes: 6 additions & 2 deletions ports/nrf/common-hal/alarm/pin/PinAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t
sleepmem_wakeup_pin = pin & 0xFF;
}

bool alarm_pin_pinalarm_woke_us_up(void) {
bool alarm_pin_pinalarm_woke_this_cycle(void) {
return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_PIN &&
sleepmem_wakeup_pin != WAKEUP_PIN_UNDEF;
}

mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match any given alarms.
for (size_t i = 0; i < n_alarms; i++) {
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
Expand All @@ -101,6 +101,10 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
return alarms[i];
}
}
return mp_const_none;
}

mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL;
Expand Down
6 changes: 4 additions & 2 deletions ports/nrf/common-hal/alarm/pin/PinAlarm.h
5766
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ typedef struct {
bool pull;
} alarm_pin_pinalarm_obj_t;

mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void);

void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_us_up(void);
bool alarm_pin_pinalarm_woke_this_cycle(void);
Loading
0