From 7eeea869ac36a65502e785a821bb334ac8a84d98 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Tue, 13 Apr 2021 18:31:57 -0400 Subject: [PATCH 1/3] Fix light sleep global alarms, API revisions --- main.c | 2 +- ports/esp32s2/common-hal/alarm/__init__.c | 67 ++++++++++++------- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 13 +++- ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 8 ++- .../esp32s2/common-hal/alarm/time/TimeAlarm.c | 9 ++- .../esp32s2/common-hal/alarm/time/TimeAlarm.h | 10 +-- .../common-hal/alarm/touch/TouchAlarm.c | 8 ++- .../common-hal/alarm/touch/TouchAlarm.h | 10 +-- shared-bindings/alarm/__init__.c | 4 +- shared-bindings/alarm/__init__.h | 21 ++++-- 10 files changed, 94 insertions(+), 58 deletions(-) diff --git a/main.c b/main.c index 1e828a1aa7..12801a535e 100755 --- a/main.c +++ b/main.c @@ -161,7 +161,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 diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 63a19ab948..f1d4bb36f5 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -63,15 +63,18 @@ 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(); } @@ -79,21 +82,23 @@ bool common_hal_alarm_woken_from_sleep(void) { return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED; } -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: @@ -104,10 +109,6 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { return mp_const_none; } -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); @@ -115,30 +116,44 @@ STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms); } -STATIC void _idle_until_alarm(void) { - // Poll for alarms. - while (!mp_hal_is_interrupted()) { - RUN_BACKGROUND_TASKS; - // Allow ctrl-C interrupt. - if (common_hal_alarm_woken_from_sleep()) { - shared_alarm_save_wake_alarm(); - return; - } - 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); + mp_obj_t wake_alarm = mp_const_none; + // We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals. - _idle_until_alarm(); + while (!mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + // Detect if interrupt was alarm or ctrl-C interrupt. + if (common_hal_alarm_woken_from_sleep()) { + 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(); + } 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; } diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 9ccb5700cb..34b4a2f918 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -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) { - // First, check to see if we match any given 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)) { @@ -112,8 +111,16 @@ 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) { 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 { diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index 93672c1f2d..b2326ed0d3 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -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); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c index 93e4f18091..24cc254032 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c @@ -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. @@ -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; } diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h index dfd75524fd..36986e06b2 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h @@ -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); diff --git a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c index 8c139afaf3..12c835b73c 100644 --- a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c @@ -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; @@ -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; } diff --git a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h index 755a3977ad..df2521c12a 100644 --- a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h +++ b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h @@ -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 diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 11b96ff240..58b67bc8d6 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -228,13 +228,13 @@ mp_obj_t shared_alarm_get_wake_alarm(void) { } // Initialize .wake_alarm value. -void shared_alarm_save_wake_alarm(void) { +void shared_alarm_save_wake_alarm(mp_obj_t alarm) { // Equivalent of: // alarm.wake_alarm = alarm mp_map_elem_t *elem = mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP); if (elem) { - elem->value = common_hal_alarm_get_wake_alarm(); + elem->value = alarm; } } diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index 9c85b2e212..b1fc3ed05f 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -31,6 +31,9 @@ #include "common-hal/alarm/__init__.h" +// Light sleep fully self-contained and does not exit user code. It will return +// the same alarm object that was orignally passed in, unlike deep sleep, which +// must create an identical copy due to the VM reset extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms); // Deep sleep is a two step process. Alarms are set when the VM is valid but @@ -38,22 +41,26 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const // not actually happen if the user is connected to the device. In this case, the // supervisor will idle using `port_wait_for_interrupt`. After each call, it will // call alarm_woken_from_sleep to see if we've been woken by an alarm and if so, -// it will exit idle as if deep sleep was exited. +// it will exit idle as if deep sleep was exited extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms); - extern NORETURN void common_hal_alarm_enter_deep_sleep(void); + +// May be used to re-initialize peripherals like GPIO, if the VM reset returned +// them to a default state extern void common_hal_alarm_pretending_deep_sleep(void); // Fetches value from module dict. extern mp_obj_t shared_alarm_get_wake_alarm(void); -extern void common_hal_alarm_gc_collect(void); -extern mp_obj_t common_hal_alarm_get_wake_alarm(void); +// Creates a new alarm object after exiting deep sleep (real or fake) +extern mp_obj_t common_hal_alarm_create_wake_alarm(void); -// Used by wake-up code. -void shared_alarm_save_wake_alarm(void); +// Saves alarm to global array +void shared_alarm_save_wake_alarm(mp_obj_t alarm); -// True if an alarm is alerting. This is most useful for pretend deep sleep. +// True if an alarm is alerting. Used in light sleep/fake deep sleep extern bool common_hal_alarm_woken_from_sleep(void); +extern void common_hal_alarm_gc_collect(void); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H From 715f7ee49022f39e7d988e4eeb4a1cb68a5525a8 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 14 May 2021 14:34:35 -0400 Subject: [PATCH 2/3] Add STM32 and NRF52 compatibility --- ports/nrf/common-hal/alarm/__init__.c | 44 ++++++++---- ports/nrf/common-hal/alarm/pin/PinAlarm.c | 8 ++- ports/nrf/common-hal/alarm/pin/PinAlarm.h | 6 +- ports/nrf/common-hal/alarm/time/TimeAlarm.c | 9 ++- ports/nrf/common-hal/alarm/time/TimeAlarm.h | 7 +- ports/nrf/common-hal/alarm/touch/TouchAlarm.c | 8 ++- ports/nrf/common-hal/alarm/touch/TouchAlarm.h | 5 +- ports/stm/common-hal/alarm/__init__.c | 71 +++++++++---------- ports/stm/common-hal/alarm/pin/PinAlarm.c | 8 ++- ports/stm/common-hal/alarm/pin/PinAlarm.h | 6 +- ports/stm/common-hal/alarm/time/TimeAlarm.c | 8 ++- ports/stm/common-hal/alarm/time/TimeAlarm.h | 7 +- 12 files changed, 110 insertions(+), 77 deletions(-) diff --git a/ports/nrf/common-hal/alarm/__init__.c b/ports/nrf/common-hal/alarm/__init__.c index 4a0fdeb8a0..a601e8768e 100644 --- a/ports/nrf/common-hal/alarm/__init__.c +++ b/ports/nrf/common-hal/alarm/__init__.c @@ -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) { @@ -116,17 +119,19 @@ 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; @@ -134,11 +139,6 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { 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); @@ -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); @@ -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; diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.c b/ports/nrf/common-hal/alarm/pin/PinAlarm.c index be4df66172..b09e217c22 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.c +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.c @@ -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)) { @@ -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; diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.h b/ports/nrf/common-hal/alarm/pin/PinAlarm.h index 42f9f115c8..87b7b9833c 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.h +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.h @@ -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); diff --git a/ports/nrf/common-hal/alarm/time/TimeAlarm.c b/ports/nrf/common-hal/alarm/time/TimeAlarm.c index 1d30065529..54d9a8921f 100644 --- a/ports/nrf/common-hal/alarm/time/TimeAlarm.c +++ b/ports/nrf/common-hal/alarm/time/TimeAlarm.c @@ -40,13 +40,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. @@ -54,7 +57,7 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t * return timer; } -bool alarm_time_timealarm_woke_us_up(void) { +bool alarm_time_timealarm_woke_this_cycle(void) { return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_TIMER; } diff --git a/ports/nrf/common-hal/alarm/time/TimeAlarm.h b/ports/nrf/common-hal/alarm/time/TimeAlarm.h index 2f65764e19..a2c33be6fb 100644 --- a/ports/nrf/common-hal/alarm/time/TimeAlarm.h +++ b/ports/nrf/common-hal/alarm/time/TimeAlarm.h @@ -36,10 +36,11 @@ extern volatile int rtc_woke_up_counter; extern void port_disable_interrupt_after_ticks_ch(uint32_t channel); extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks); -// 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); +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); + // Check for the wake up alarm from pretend deep sleep. -bool alarm_time_timealarm_woke_us_up(void); +bool alarm_time_timealarm_woke_this_cycle(void); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_reset(void); diff --git a/ports/nrf/common-hal/alarm/touch/TouchAlarm.c b/ports/nrf/common-hal/alarm/touch/TouchAlarm.c index 2d7ee89bd3..f8daf50f54 100644 --- a/ports/nrf/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/nrf/common-hal/alarm/touch/TouchAlarm.c @@ -35,7 +35,11 @@ void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *s (void)pin; } -mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(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) { + return mp_const_none; +} + +mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) { return mp_const_none; } @@ -45,7 +49,7 @@ void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alar void alarm_touch_touchalarm_prepare_for_deep_sleep(void) { } -bool alarm_touch_touchalarm_woke_us_up(void) { +bool alarm_touch_touchalarm_woke_this_cycle(void) { return false; } diff --git a/ports/nrf/common-hal/alarm/touch/TouchAlarm.h b/ports/nrf/common-hal/alarm/touch/TouchAlarm.h index 755a3977ad..58ad8c20fe 100644 --- a/ports/nrf/common-hal/alarm/touch/TouchAlarm.h +++ b/ports/nrf/common-hal/alarm/touch/TouchAlarm.h @@ -36,11 +36,12 @@ typedef struct { } 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); +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); // 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); void alarm_touch_touchalarm_prepare_for_deep_sleep(void); -bool alarm_touch_touchalarm_woke_us_up(void); +bool alarm_touch_touchalarm_woke_this_cycle(void); void alarm_touch_touchalarm_reset(void); #endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index e0b900bbfc..70a2c63e56 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -48,10 +48,8 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }; STATIC stm_sleep_source_t true_deep_wake_reason; -STATIC mp_obj_t most_recent_alarm; void alarm_reset(void) { - most_recent_alarm = NULL; // Reset the alarm flag STM_ALARM_FLAG = 0x00; alarm_pin_pinalarm_reset(); @@ -66,10 +64,10 @@ void alarm_set_wakeup_reason(stm_sleep_source_t reason) { STATIC stm_sleep_source_t _get_wakeup_cause(void) { // If in light/fake sleep, check modules - if (alarm_pin_pinalarm_woke_us_up()) { + if (alarm_pin_pinalarm_woke_this_cycle()) { return STM_WAKEUP_GPIO; } - if (alarm_time_timealarm_woke_us_up()) { + if (alarm_time_timealarm_woke_this_cycle()) { return STM_WAKEUP_RTC; } // Check to see if we woke from deep sleep (reason set in port_init) @@ -83,14 +81,16 @@ bool common_hal_alarm_woken_from_sleep(void) { return _get_wakeup_cause() != STM_WAKEUP_UNDEF; } -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 stm_sleep_source_t cause = _get_wakeup_cause(); switch (cause) { case STM_WAKEUP_RTC: { - return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); + return alarm_time_timealarm_create_wakeup_alarm(); } case STM_WAKEUP_GPIO: { - return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); + return alarm_pin_pinalarm_create_wakeup_alarm(); } case STM_WAKEUP_UNDEF: default: @@ -100,58 +100,51 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { return mp_const_none; } -mp_obj_t common_hal_alarm_get_wake_alarm(void) { - // If we woke from light sleep, override with that alarm - if (most_recent_alarm != NULL) { - return most_recent_alarm; - } - 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); } -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; + + // TODO: add more dynamic clock shutdown/restart logic while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { - return; + stm_sleep_source_t cause = _get_wakeup_cause(); + switch (cause) { + case STM_WAKEUP_RTC: { + wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms); + break; + } + case STM_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); + break; } + // HAL_PWR_EnterSLEEPMode is just a WFI anyway so don't bother port_idle_until_interrupt(); } -} -mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { - // If USB is active, only pretend to sleep. Otherwise, light sleep - if (supervisor_workflow_active()) { - _setup_sleep_alarms(false, n_alarms, alarms); - _idle_until_alarm(); - } else { - _setup_sleep_alarms(false, n_alarms, alarms); - port_disable_tick(); - HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); - port_enable_tick(); + 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); - - // TODO: make assignment to global array less roundabout - most_recent_alarm = wake_alarm; - shared_alarm_save_wake_alarm(); - - // Can't use alarm_reset since it resets most_recent_alarm - alarm_pin_pinalarm_reset(); - alarm_time_timealarm_reset(); + alarm_reset(); return wake_alarm; } void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) { - most_recent_alarm = NULL; _setup_sleep_alarms(true, n_alarms, alarms); } diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index 381a13b220..799922ae8f 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -85,11 +85,11 @@ bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) { return self->pull; } -bool alarm_pin_pinalarm_woke_us_up(void) { +bool alarm_pin_pinalarm_woke_this_cycle(void) { return woke_up; } -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) { for (size_t i = 0; i < n_alarms; i++) { if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; @@ -99,8 +99,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; +} - // If the above isn't true, we woke from deep sleep, so create a new alarm +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; // TODO: replace this if/when other WKUP pins are supported diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.h b/ports/stm/common-hal/alarm/pin/PinAlarm.h index bd18c840ff..bc52849a53 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.h +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.h @@ -37,10 +37,12 @@ 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); #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index 2c38066d3a..6fb1fc629d 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -44,13 +44,17 @@ 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) { +mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) { // First, check to see if we match 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. @@ -63,7 +67,7 @@ STATIC void timer_callback(void) { woke_up = true; } -bool alarm_time_timealarm_woke_us_up(void) { +bool alarm_time_timealarm_woke_this_cycle(void) { return woke_up; } diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h index 0d0c25deae..1dd217edd6 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.h +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -34,10 +34,11 @@ 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); +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); + // Check for the wake up alarm from pretend deep sleep. -bool alarm_time_timealarm_woke_us_up(void); +bool alarm_time_timealarm_woke_this_cycle(void); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_reset(void); From bce541dcc5a3c95902780de697c51818bd2cbaa3 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Tue, 18 May 2021 15:16:25 -0400 Subject: [PATCH 3/3] Minor text fixes --- ports/nrf/common-hal/alarm/time/TimeAlarm.h | 1 - ports/stm/common-hal/alarm/time/TimeAlarm.h | 1 - 2 files changed, 2 deletions(-) diff --git a/ports/nrf/common-hal/alarm/time/TimeAlarm.h b/ports/nrf/common-hal/alarm/time/TimeAlarm.h index a2c33be6fb..734feb1c87 100644 --- a/ports/nrf/common-hal/alarm/time/TimeAlarm.h +++ b/ports/nrf/common-hal/alarm/time/TimeAlarm.h @@ -39,7 +39,6 @@ extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks); 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); -// Check for the wake up alarm from pretend deep sleep. bool alarm_time_timealarm_woke_this_cycle(void); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_reset(void); diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h index 1dd217edd6..48531ebdf6 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.h +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -37,7 +37,6 @@ typedef struct { 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); -// Check for the wake up alarm from pretend deep sleep. bool alarm_time_timealarm_woke_this_cycle(void); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_reset(void);