Merge pull request #5761 from adafruit/7.1.x

Bring 7.1.x changes into main - cascadetoml undo + alarm fixes
This commit is contained in:
Jeff Epler 2021-12-23 06:30:05 -07:00 committed by GitHub
commit 900ec91fa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 26 deletions

33
main.c
View File

@ -123,7 +123,7 @@ static void reset_devices(void) {
#endif #endif
} }
STATIC void start_mp(supervisor_allocation *heap) { STATIC void start_mp(supervisor_allocation *heap, bool first_run) {
autoreload_stop(); autoreload_stop();
supervisor_workflow_reset(); supervisor_workflow_reset();
@ -171,7 +171,8 @@ 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.
shared_alarm_save_wake_alarm(common_hal_alarm_create_wake_alarm()); // There is no alarm if this is not the first time code.py or the REPL has been run.
shared_alarm_save_wake_alarm(first_run ? common_hal_alarm_create_wake_alarm() : mp_const_none);
// 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
@ -309,7 +310,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
} }
} }
STATIC bool run_code_py(safe_mode_t safe_mode) { STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_reset) {
bool serial_connected_at_start = serial_connected(); bool serial_connected_at_start = serial_connected();
bool printed_safe_mode_message = false; bool printed_safe_mode_message = false;
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 #if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
@ -348,7 +349,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
// Prepare the VM state. Includes an alarm check/reset for sleep. // Prepare the VM state. Includes an alarm check/reset for sleep.
start_mp(heap); start_mp(heap, first_run);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -631,6 +632,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (fake_sleeping) { if (fake_sleeping) {
board_init(); board_init();
// Pretend that the next run is the first run, as if we were reset.
*simulate_reset = true;
} }
#endif #endif
@ -652,7 +655,9 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
// Do USB setup even if boot.py is not run. // Do USB setup even if boot.py is not run.
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap);
// true means this is the first set of VM's after a hard reset.
start_mp(heap, true);
#if CIRCUITPY_USB #if CIRCUITPY_USB
// Set up default USB values after boot.py VM starts but before running boot.py. // Set up default USB values after boot.py VM starts but before running boot.py.
@ -729,12 +734,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
#endif #endif
} }
STATIC int run_repl(void) { STATIC int run_repl(bool first_run) {
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;
stack_resize(); stack_resize();
filesystem_flush(); filesystem_flush();
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap); start_mp(heap, first_run);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -847,28 +852,34 @@ int __attribute__((used)) main(void) {
supervisor_start_bluetooth(); supervisor_start_bluetooth();
#endif #endif
// Boot script is finished, so now go into REPL/main mode. // Boot script is finished, so now go into REPL or run code.py.
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;
bool skip_repl = true; bool skip_repl = true;
bool first_run = true; bool first_run = true;
bool simulate_reset;
for (;;) { for (;;) {
simulate_reset = false;
if (!skip_repl) { if (!skip_repl) {
exit_code = run_repl(); exit_code = run_repl(first_run);
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
} }
if (exit_code == PYEXEC_FORCED_EXIT) { if (exit_code == PYEXEC_FORCED_EXIT) {
if (!first_run) { if (!first_run) {
serial_write_compressed(translate("soft reboot\n")); serial_write_compressed(translate("soft reboot\n"));
} }
first_run = false;
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
skip_repl = run_code_py(safe_mode); skip_repl = run_code_py(safe_mode, first_run, &simulate_reset);
} else { } else {
skip_repl = false; skip_repl = false;
} }
} else if (exit_code != 0) { } else if (exit_code != 0) {
break; break;
} }
// Either the REPL or code.py has run and finished.
// If code.py did a fake deep sleep, pretend that we are running code.py for
// the first time after a hard reset. This will preserve any alarm information.
first_run = simulate_reset;
} }
mp_deinit(); mp_deinit();
return 0; return 0;

View File

@ -62,11 +62,6 @@ void alarm_reset(void) {
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
} }
// This will be reset to false by full resets when bss is cleared. Otherwise, the
// reload is due to CircuitPython and the ESP wakeup cause will be stale. This
// can happen if USB is connected after a deep sleep.
STATIC bool soft_wakeup = false;
STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
// First check if the modules remember what last woke up // First check if the modules remember what last woke up
if (alarm_pin_pinalarm_woke_this_cycle()) { if (alarm_pin_pinalarm_woke_this_cycle()) {
@ -80,11 +75,7 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
} }
// If waking from true deep sleep, modules will have lost their state, // If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually // so check the deep wakeup cause manually
if (!soft_wakeup) {
soft_wakeup = true;
return esp_sleep_get_wakeup_cause(); return esp_sleep_get_wakeup_cause();
}
return ESP_SLEEP_WAKEUP_UNDEFINED;
} }
bool common_hal_alarm_woken_from_sleep(void) { bool common_hal_alarm_woken_from_sleep(void) {

View File

@ -2,8 +2,7 @@
huffman huffman
# For nvm.toml # For nvm.toml
cascadetoml==0.3.1 cascadetoml
tomlkit==0.7.2
jinja2 jinja2
typer typer

View File

@ -64,8 +64,10 @@
//| This object is the sole instance of `alarm.SleepMemory`.""" //| This object is the sole instance of `alarm.SleepMemory`."""
//| //|
//| wake_alarm: Alarm //| wake_alarm: Optional[Alarm]
//| """The most recently triggered alarm. If CircuitPython was sleeping, the alarm the woke it from sleep.""" //| """The most recently triggered alarm. If CircuitPython was sleeping, the alarm that woke it from sleep.
//| If no alarm occured since the last hard reset or soft restart, value is ``None``.
//| """
//| //|
// wake_alarm is implemented as a dictionary entry, so there's no code here. // wake_alarm is implemented as a dictionary entry, so there's no code here.
@ -103,7 +105,9 @@ STATIC mp_obj_t alarm_light_sleep_until_alarms(size_t n_args, const mp_obj_t *ar
validate_objs_are_alarms(n_args, args); validate_objs_are_alarms(n_args, args);
return common_hal_alarm_light_sleep_until_alarms(n_args, args); mp_obj_t alarm = common_hal_alarm_light_sleep_until_alarms(n_args, args);
shared_alarm_save_wake_alarm(alarm);
return alarm;
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_light_sleep_until_alarms); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_light_sleep_until_alarms);