Sleep API changes, redundancy fix

This commit is contained in:
Lucian Copeland 2021-03-27 14:08:44 -04:00
parent a13da2ad57
commit 00178ca5e0
5 changed files with 34 additions and 70 deletions

33
main.c
View file

@ -161,7 +161,7 @@ STATIC void start_mp(supervisor_allocation* heap) {
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. An object may be created so the heap must be functional. // Record which alarm woke us up, if any. An object may be created so the heap must be functional.
alarm_save_wake_alarm(); shared_alarm_save_wake_alarm();
// Reset alarm module only after we retrieved the wakeup alarm. // Reset alarm module only after we retrieved the wakeup alarm.
alarm_reset(); alarm_reset();
#endif #endif
@ -305,8 +305,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
} }
#endif #endif
// TODO: on deep sleep, make sure display is refreshed before sleeping (for e-ink).
cleanup_after_vm(heap); cleanup_after_vm(heap);
if (result.return_code & PYEXEC_FORCED_EXIT) { if (result.return_code & PYEXEC_FORCED_EXIT) {
@ -329,12 +327,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
rgb_status_animation_t animation; rgb_status_animation_t animation;
prep_rgb_status_animation(&result, found_main, safe_mode, &animation); prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
bool asleep = false; bool fake_sleeping = false;
while (true) { while (true) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
if (reload_requested) { if (reload_requested) {
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (asleep) { if (fake_sleeping) {
board_init(); board_init();
} }
#endif #endif
@ -345,7 +343,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (serial_connected() && serial_bytes_available()) { if (serial_connected() && serial_bytes_available()) {
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (asleep) { if (fake_sleeping) {
board_init(); board_init();
} }
#endif #endif
@ -361,7 +359,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
// an alarm alerts faster than our USB delay or if we pretended to deep // an alarm alerts faster than our USB delay or if we pretended to deep
// sleep. // sleep.
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (asleep && alarm_woken_from_sleep()) { if (fake_sleeping && common_hal_alarm_woken_from_sleep()) {
serial_write_compressed(translate("Woken up by alarm.\n")); serial_write_compressed(translate("Woken up by alarm.\n"));
board_init(); board_init();
supervisor_set_run_reason(RUN_REASON_STARTUP); supervisor_set_run_reason(RUN_REASON_STARTUP);
@ -400,20 +398,15 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (result.return_code & PYEXEC_DEEP_SLEEP) { if (result.return_code & PYEXEC_DEEP_SLEEP) {
// Make sure we have been awake long enough for USB to connect (enumeration delay). // Make sure we have been awake long enough for USB to connect (enumeration delay).
int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL);
if (connecting_delay_ticks > 0) { // Until it's safe to decide whether we're real/fake sleeping, just run the RGB
// Set when we've waited long enough so that we wake up from the if (connecting_delay_ticks < 0 && !fake_sleeping) {
// port_idle_until_interrupt below and loop around to the real deep fake_sleeping = true;
// sleep in the else clause.
port_interrupt_after_ticks(connecting_delay_ticks);
// Deep sleep if we're not connected to a host.
} else if (!asleep) {
asleep = true;
new_status_color(BLACK); new_status_color(BLACK);
board_deinit(); board_deinit();
if (!supervisor_workflow_active()) { if (!supervisor_workflow_active()) {
// Enter true deep sleep. When we wake up we'll be back at the // Enter true deep sleep. When we wake up we'll be back at the
// top of main(), not in this loop. // top of main(), not in this loop.
alarm_enter_deep_sleep(); common_hal_alarm_enter_deep_sleep();
// Does not return. // Does not return.
} else { } else {
serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n"));
@ -422,7 +415,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
} }
#endif #endif
if (!asleep) { if (!fake_sleeping) {
tick_rgb_status_animation(&animation); tick_rgb_status_animation(&animation);
} else { } else {
// This waits until a pretend deep sleep alarm occurs. They are set // This waits until a pretend deep sleep alarm occurs. They are set
@ -430,7 +423,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
// it may also return due to another interrupt, that's why we check // it may also return due to another interrupt, that's why we check
// for deep sleep alarms above. If it wasn't a deep sleep alarm, // for deep sleep alarms above. If it wasn't a deep sleep alarm,
// then we'll idle here again. // then we'll idle here again.
port_idle_until_interrupt(); #if CIRCUITPY_ALARM
common_hal_alarm_pretending_deep_sleep();
#else
port_idle_until_interrupt();
#endif
} }
} }
} }

View file

@ -75,7 +75,7 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
return esp_sleep_get_wakeup_cause(); return esp_sleep_get_wakeup_cause();
} }
bool alarm_woken_from_sleep(void) { bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED; return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
} }
@ -120,8 +120,8 @@ STATIC void _idle_until_alarm(void) {
while (!mp_hal_is_interrupted()) { while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt. // Allow ctrl-C interrupt.
if (alarm_woken_from_sleep()) { if (common_hal_alarm_woken_from_sleep()) {
alarm_save_wake_alarm(); shared_alarm_save_wake_alarm();
return; return;
} }
port_idle_until_interrupt(); port_idle_until_interrupt();
@ -147,7 +147,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
_setup_sleep_alarms(true, n_alarms, alarms); _setup_sleep_alarms(true, n_alarms, alarms);
} }
void NORETURN alarm_enter_deep_sleep(void) { void NORETURN common_hal_alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_touch_touchalarm_prepare_for_deep_sleep(); alarm_touch_touchalarm_prepare_for_deep_sleep();
@ -164,5 +164,5 @@ void NORETURN alarm_enter_deep_sleep(void) {
} }
void common_hal_alarm_gc_collect(void) { void common_hal_alarm_gc_collect(void) {
gc_collect_ptr(alarm_get_wake_alarm()); gc_collect_ptr(shared_alarm_get_wake_alarm());
} }

View file

@ -1,37 +0,0 @@
#include "shared-bindings/alarm_io/__init__.h"
#include "esp_sleep.h"
#include "driver/rtc_io.h"
mp_obj_t common_hal_alarm_io_pin_state(alarm_io_obj_t *self_in) {
if (!rtc_gpio_is_valid_gpio(self_in->gpio)) {
mp_raise_ValueError(translate("io must be rtc io"));
}
if (self_in->pull && !self_in->level) {
for (uint8_t i = 0; i <= 4; i += 2) {
if (self_in->gpio == i) {
mp_raise_ValueError(translate("IOs 0, 2 & 4 do not support internal pullup in sleep"));
}
}
}
switch (esp_sleep_enable_ext0_wakeup(self_in->gpio, self_in->level)) {
case ESP_ERR_INVALID_ARG:
mp_raise_ValueError(translate("trigger level must be 0 or 1"));
case ESP_ERR_INVALID_STATE:
mp_raise_RuntimeError(translate("wakeup conflict"));
default:
break;
}
if (self_in->pull) {
(self_in->level) ? rtc_gpio_pulldown_en(self_in->gpio) : rtc_gpio_pullup_en(self_in->gpio);
}
return self_in;
}
void common_hal_alarm_io_disable(void) {
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0 | ESP_SLEEP_WAKEUP_EXT1);
}

View file

@ -92,7 +92,7 @@ void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) {
//| This allows the user to interrupt an existing program with ctrl-C, //| This allows the user to interrupt an existing program with ctrl-C,
//| and to edit the files in CIRCUITPY, which would not be possible in true light sleep. //| and to edit the files in CIRCUITPY, which would not be possible in true light sleep.
//| Thus, to use light sleep and save significant power, //| Thus, to use light sleep and save significant power,
// it may be necessary to disconnect from the host. //| it may be necessary to disconnect from the host.
//| """ //| """
//| ... //| ...
//| //|
@ -217,7 +217,7 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = {
STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table);
// Fetch value from module dict. // Fetch value from module dict.
mp_obj_t alarm_get_wake_alarm(void) { mp_obj_t shared_alarm_get_wake_alarm(void) {
mp_map_elem_t *elem = mp_map_elem_t *elem =
mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP); mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP);
if (elem) { if (elem) {
@ -228,7 +228,7 @@ mp_obj_t alarm_get_wake_alarm(void) {
} }
// Initialize .wake_alarm value. // Initialize .wake_alarm value.
void alarm_save_wake_alarm(void) { void shared_alarm_save_wake_alarm(void) {
// Equivalent of: // Equivalent of:
// alarm.wake_alarm = alarm // alarm.wake_alarm = alarm
mp_map_elem_t *elem = mp_map_elem_t *elem =
@ -242,3 +242,8 @@ const mp_obj_module_t alarm_module = {
.base = { &mp_type_module }, .base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&alarm_module_globals, .globals = (mp_obj_dict_t *)&alarm_module_globals,
}; };
extern void port_idle_until_interrupt(void);
MP_WEAK void common_hal_alarm_pretending_deep_sleep(void) {
port_idle_until_interrupt();
}

View file

@ -40,21 +40,20 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const
// call alarm_woken_from_sleep to see if we've been woken by an alarm and if so, // 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 void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms);
// Deep sleep is entered outside of the VM so we omit the `common_hal_` prefix.
extern NORETURN void alarm_enter_deep_sleep(void); extern NORETURN void common_hal_alarm_enter_deep_sleep(void);
extern void common_hal_alarm_pretending_deep_sleep(void);
// Fetches value from module dict. // Fetches value from module dict.
extern mp_obj_t alarm_get_wake_alarm(void); extern mp_obj_t shared_alarm_get_wake_alarm(void);
extern void common_hal_alarm_gc_collect(void); extern void common_hal_alarm_gc_collect(void);
extern mp_obj_t common_hal_alarm_get_wake_alarm(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void);
// Used by wake-up code. // Used by wake-up code.
void alarm_save_wake_alarm(void); void shared_alarm_save_wake_alarm(void);
// True if an alarm is alerting. This is most useful for pretend deep sleep. // True if an alarm is alerting. This is most useful for pretend deep sleep.
extern bool alarm_woken_from_sleep(void); extern bool common_hal_alarm_woken_from_sleep(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H