diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2020-12-22 16:13:02 -0800 |
|---|---|---|
| committer | Scott Shawcroft <scott@tannewt.org> | 2020-12-22 16:13:02 -0800 |
| commit | 1fca297a2d2bfefb1cdef3ecbac05f54d15e08eb (patch) | |
| tree | e9273efad20b60e5a7e2864ffc3f0fd53ed531c9 /ports | |
| parent | d4e9eea397c887d9eceb5f4c6aba117a4dc3d03b (diff) | |
A couple sleep fixes
* Better messaging when code is stopped by an auto-reload.
* Auto-reload works during sleeps on ESP32-S2. Ticks wake up the
main task each time.
* Made internal naming consistent. CamelCase Python names are NOT
separated by an underscore.
Diffstat (limited to 'ports')
| -rw-r--r-- | ports/esp32s2/common-hal/alarm/__init__.c | 31 | ||||
| -rw-r--r-- | ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 60 | ||||
| -rw-r--r-- | ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 12 | ||||
| -rw-r--r-- | ports/esp32s2/common-hal/alarm/time/TimeAlarm.c | 26 | ||||
| -rw-r--r-- | ports/esp32s2/common-hal/alarm/time/TimeAlarm.h | 2 | ||||
| -rw-r--r-- | ports/esp32s2/supervisor/port.c | 28 |
6 files changed, 75 insertions, 84 deletions
diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 9f19f1afc..f2686cf18 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -54,7 +54,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { void alarm_reset(void) { alarm_time_timealarm_reset(); - alarm_pin_pin_alarm_reset(); + alarm_pin_pinalarm_reset(); alarm_sleep_memory_reset(); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -63,7 +63,7 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { if (alarm_time_timealarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_TIMER; } - if (alarm_pin_pin_alarm_woke_us_up()) { + if (alarm_pin_pinalarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_GPIO; } @@ -84,7 +84,7 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { case ESP_SLEEP_WAKEUP_GPIO: case ESP_SLEEP_WAKEUP_EXT0: case ESP_SLEEP_WAKEUP_EXT1: { - return alarm_pin_pin_alarm_get_wakeup_alarm(n_alarms, alarms); + return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); } case ESP_SLEEP_WAKEUP_TOUCHPAD: @@ -106,7 +106,7 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) { // 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_pin_alarm_set_alarms(deep_sleep, n_alarms, alarms); + alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms); alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms); } @@ -123,25 +123,14 @@ STATIC void _idle_until_alarm(void) { } } -// Is it safe to do a light sleep? Check whether WiFi is on or there are -// other ongoing tasks that should not be shut down. -STATIC bool _light_sleep_ok(void) { - int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); - return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) && - !supervisor_workflow_active() && - connecting_delay_ticks <= 0; -} - 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); - // Light sleep can break some functionality so only do it when possible. Otherwise we idle. - if (_light_sleep_ok()) { - // Flush the UART to complete the log line. - uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); - esp_light_sleep_start(); - } else { - _idle_until_alarm(); + // 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); @@ -154,7 +143,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala } void NORETURN alarm_enter_deep_sleep(void) { - alarm_pin_pin_alarm_prepare_for_deep_sleep(); + alarm_pin_pinalarm_prepare_for_deep_sleep(); // The ESP-IDF caches the deep sleep settings and applies them before sleep. // We don't need to worry about resetting them in the interim. esp_deep_sleep_start(); diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 01e2faeb8..df8d10ef9 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -38,7 +38,7 @@ #include "components/soc/src/esp32s2/include/hal/gpio_ll.h" #include "components/xtensa/include/esp_debug_helpers.h" -void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (edge) { mp_raise_ValueError(translate("Cannot wake on pin edge. Only level.")); } @@ -51,41 +51,41 @@ void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, m self->pull = pull; } -mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self) { +mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { return self->pin; } -bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) { return self->value; } -bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) { return false; } -bool common_hal_alarm_pin_pin_alarm_get_pull(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) { return self->pull; } gpio_isr_handle_t gpio_interrupt_handle; // Low and high are relative to pin number. 32+ is high. <32 is low. -static volatile uint32_t low_pin_status = 0; -static volatile uint32_t high_pin_status = 0; +static volatile uint32_t pin_31_0_status = 0; +static volatile uint32_t pin_63_32_status = 0; void gpio_interrupt(void *arg) { (void) arg; - gpio_ll_get_intr_status(&GPIO, xPortGetCoreID(), (uint32_t*) &low_pin_status); - gpio_ll_clear_intr_status(&GPIO, low_pin_status); - gpio_ll_get_intr_status_high(&GPIO, xPortGetCoreID(), (uint32_t*) &high_pin_status); - gpio_ll_clear_intr_status_high(&GPIO, high_pin_status); + gpio_ll_get_intr_status(&GPIO, xPortGetCoreID(), (uint32_t*) &pin_31_0_status); + gpio_ll_clear_intr_status(&GPIO, pin_31_0_status); + gpio_ll_get_intr_status_high(&GPIO, xPortGetCoreID(), (uint32_t*) &pin_63_32_status); + gpio_ll_clear_intr_status_high(&GPIO, pin_63_32_status); // disable the interrupts that fired, maybe all of them for (size_t i = 0; i < 32; i++) { uint32_t mask = 1 << i; - if ((low_pin_status & mask) != 0) { + if ((pin_31_0_status & mask) != 0) { gpio_ll_intr_disable(&GPIO, i); } - if ((high_pin_status & mask) != 0) { + if ((pin_63_32_status & mask) != 0) { gpio_ll_intr_disable(&GPIO, 32 + i); } } @@ -96,18 +96,18 @@ void gpio_interrupt(void *arg) { } } -bool alarm_pin_pin_alarm_woke_us_up(void) { - return low_pin_status != 0 || high_pin_status != 0; +bool alarm_pin_pinalarm_woke_us_up(void) { + return pin_31_0_status != 0 || pin_63_32_status != 0; } -mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { +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. - uint64_t pin_status = ((uint64_t) high_pin_status) << 32 | low_pin_status; + 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_pin_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { continue; } - alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); if ((pin_status & (1ull << alarm->pin->number)) != 0) { return alarms[i]; } @@ -131,8 +131,8 @@ mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *a } } - alarm_pin_pin_alarm_obj_t *alarm = m_new_obj(alarm_pin_pin_alarm_obj_t); - alarm->base.type = &alarm_pin_pin_alarm_type; + alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); + alarm->base.type = &alarm_pin_pinalarm_type; alarm->pin = NULL; // Map the pin number back to a pin object. for (size_t i = 0; i < mcu_pin_globals.map.used; i++) { @@ -151,7 +151,7 @@ static uint64_t high_alarms = 0; static uint64_t low_alarms = 0; static uint64_t pull_pins = 0; -void alarm_pin_pin_alarm_reset(void) { +void alarm_pin_pinalarm_reset(void) { if (gpio_interrupt_handle != NULL) { esp_intr_free(gpio_interrupt_handle); gpio_interrupt_handle = NULL; @@ -168,21 +168,21 @@ void alarm_pin_pin_alarm_reset(void) { high_alarms = 0; low_alarms = 0; pull_pins = 0; - high_pin_status = 0; - low_pin_status = 0; + pin_63_32_status = 0; + pin_31_0_status = 0; } -void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { +void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { // Bitmask of wake up settings. size_t high_count = 0; size_t low_count = 0; for (size_t i = 0; i < n_alarms; i++) { // TODO: Check for ULP or touch alarms because they can't coexist with GPIO alarms. - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { continue; } - alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); gpio_num_t pin_number = alarm->pin->number; if (alarm->value) { @@ -239,8 +239,8 @@ void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_o } // Set GPIO interrupts so they wake us from light sleep or from idle via the // interrupt handler above. - low_pin_status = 0; - high_pin_status = 0; + pin_31_0_status = 0; + pin_63_32_status = 0; if (gpio_isr_register(gpio_interrupt, NULL, 0, &gpio_interrupt_handle) != ESP_OK) { mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); } @@ -282,7 +282,7 @@ void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_o } -void alarm_pin_pin_alarm_prepare_for_deep_sleep(void) { +void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { if (pull_pins == 0) { return; } diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index 8b14931ca..93672c1f2 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -32,10 +32,10 @@ typedef struct { mcu_pin_obj_t *pin; bool value; bool pull; -} alarm_pin_pin_alarm_obj_t; +} alarm_pin_pinalarm_obj_t; -void alarm_pin_pin_alarm_reset(void); -void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); -void alarm_pin_pin_alarm_prepare_for_deep_sleep(void); -mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); -bool alarm_pin_pin_alarm_woke_us_up(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); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c index a7abde6a4..bcde0ab3c 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c @@ -34,23 +34,23 @@ #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/time/__init__.h" -void common_hal_alarm_time_time_alarm_construct(alarm_time_time_alarm_obj_t *self, mp_float_t monotonic_time) { +void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { self->monotonic_time = monotonic_time; } -mp_float_t common_hal_alarm_time_time_alarm_get_monotonic_time(alarm_time_time_alarm_obj_t *self) { +mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self) { 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 for (size_t i = 0; i < n_alarms; i++) { - if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { return alarms[i]; } } - alarm_time_time_alarm_obj_t *timer = m_new_obj(alarm_time_time_alarm_obj_t); - timer->base.type = &alarm_time_time_alarm_type; + 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. timer->monotonic_time = 0.0f; return timer; @@ -78,20 +78,20 @@ 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 time_alarm_set = false; - alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL; + bool timealarm_set = false; + alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { continue; } - if (time_alarm_set) { + if (timealarm_set) { mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); } - time_alarm = MP_OBJ_TO_PTR(alarms[i]); - time_alarm_set = true; + timealarm = MP_OBJ_TO_PTR(alarms[i]); + timealarm_set = true; } - if (!time_alarm_set) { + if (!timealarm_set) { return; } @@ -109,7 +109,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ // Compute how long to actually sleep, considering the time now. mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f; - mp_float_t wakeup_in_secs = MAX(0.0f, time_alarm->monotonic_time - now_secs); + mp_float_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs); const uint64_t sleep_for_us = (uint64_t) (wakeup_in_secs * 1000000); esp_sleep_enable_timer_wakeup(sleep_for_us); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h index 277ababc2..dfd75524f 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h @@ -30,7 +30,7 @@ typedef struct { mp_obj_base_t base; mp_float_t monotonic_time; // values compatible with time.monotonic_time() -} alarm_time_time_alarm_obj_t; +} 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); diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 8a87180cd..17a413a2e 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -74,6 +74,10 @@ extern void esp_restart(void) NORETURN; void tick_timer_cb(void* arg) { supervisor_tick(); + + // CircuitPython's VM is run in a separate FreeRTOS task from timer callbacks. So, we have to + // notify the main task every time in case it's waiting for us. + xTaskNotifyGive(circuitpython_task); } void sleep_timer_cb(void* arg); @@ -92,6 +96,8 @@ safe_mode_t port_init(void) { args.name = "CircuitPython Sleep"; esp_timer_create(&args, &_sleep_timer); + circuitpython_task = xTaskGetCurrentTaskHandle(); + // Send the ROM output out of the UART. This includes early logs. #ifdef DEBUG ets_install_uart_printf(); @@ -114,17 +120,17 @@ safe_mode_t port_init(void) { } esp_reset_reason_t reason = esp_reset_reason(); - if (reason == ESP_RST_BROWNOUT) { - return BROWNOUT; - } - if (reason == ESP_RST_PANIC || - reason == ESP_RST_INT_WDT || - reason == ESP_RST_WDT) { - return HARD_CRASH; + switch (reason) { + case ESP_RST_BROWNOUT: + return BROWNOUT; + case ESP_RST_PANIC: + case ESP_RST_INT_WDT: + case ESP_RST_WDT: + return HARD_CRASH; + default: + break; } - circuitpython_task = xTaskGetCurrentTaskHandle(); - return NO_SAFE_MODE; } @@ -262,10 +268,6 @@ void port_enable_tick(void) { // Disable 1/1024 second tick. void port_disable_tick(void) { esp_timer_stop(_tick_timer); - - // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. - // Tick disable can happen via auto-reload so poke the main task here. - xTaskNotifyGive(circuitpython_task); } void sleep_timer_cb(void* arg) { |
