Merge pull request #4503 from hierophect/sleep-api-update

Sleep API changes and fix for main.c silent issue
This commit is contained in:
Dan Halbert 2021-04-06 16:53:25 -04:00 committed by GitHub
commit 82479b6a2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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
// 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.
alarm_reset();
#endif
@ -305,8 +305,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
}
#endif
// TODO: on deep sleep, make sure display is refreshed before sleeping (for e-ink).
cleanup_after_vm(heap);
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;
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
bool asleep = false;
bool fake_sleeping = false;
while (true) {
RUN_BACKGROUND_TASKS;
if (reload_requested) {
#if CIRCUITPY_ALARM
if (asleep) {
if (fake_sleeping) {
board_init();
}
#endif
@ -345,7 +343,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (serial_connected() && serial_bytes_available()) {
#if CIRCUITPY_ALARM
if (asleep) {
if (fake_sleeping) {
board_init();
}
#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
// sleep.
#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"));
board_init();
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) {
// 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);
if (connecting_delay_ticks > 0) {
// Set when we've waited long enough so that we wake up from the
// port_idle_until_interrupt below and loop around to the real deep
// 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;
// Until it's safe to decide whether we're real/fake sleeping, just run the RGB
if (connecting_delay_ticks < 0 && !fake_sleeping) {
fake_sleeping = true;
new_status_color(BLACK);
board_deinit();
if (!supervisor_workflow_active()) {
// Enter true deep sleep. When we wake up we'll be back at the
// top of main(), not in this loop.
alarm_enter_deep_sleep();
common_hal_alarm_enter_deep_sleep();
// Does not return.
} else {
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
if (!asleep) {
if (!fake_sleeping) {
tick_rgb_status_animation(&animation);
} else {
// 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
// for deep sleep alarms above. If it wasn't a deep sleep alarm,
// 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();
}
bool alarm_woken_from_sleep(void) {
bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
}
@ -120,8 +120,8 @@ STATIC void _idle_until_alarm(void) {
while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Allow ctrl-C interrupt.
if (alarm_woken_from_sleep()) {
alarm_save_wake_alarm();
if (common_hal_alarm_woken_from_sleep()) {
shared_alarm_save_wake_alarm();
return;
}
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);
}
void NORETURN alarm_enter_deep_sleep(void) {
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_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) {
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,
//| 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,
// 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);
// 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_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP);
if (elem) {
@ -228,7 +228,7 @@ mp_obj_t alarm_get_wake_alarm(void) {
}
// Initialize .wake_alarm value.
void alarm_save_wake_alarm(void) {
void shared_alarm_save_wake_alarm(void) {
// Equivalent of:
// alarm.wake_alarm = alarm
mp_map_elem_t *elem =
@ -242,3 +242,8 @@ const mp_obj_module_t alarm_module = {
.base = { &mp_type_module },
.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,
// 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);
// 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.
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 mp_obj_t common_hal_alarm_get_wake_alarm(void);
// 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.
extern bool alarm_woken_from_sleep(void);
extern bool common_hal_alarm_woken_from_sleep(void);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H