diff --git a/main.c b/main.c index c019237362..a962405498 100644 --- a/main.c +++ b/main.c @@ -123,7 +123,7 @@ static void reset_devices(void) { #endif } -STATIC void start_mp(supervisor_allocation *heap) { +STATIC void start_mp(supervisor_allocation *heap, bool first_run) { autoreload_stop(); supervisor_workflow_reset(); @@ -171,7 +171,8 @@ 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(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. alarm_reset(); #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 printed_safe_mode_message = false; #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(); // Prepare the VM state. Includes an alarm check/reset for sleep. - start_mp(heap); + start_mp(heap, first_run); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -631,6 +632,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { #if CIRCUITPY_ALARM if (fake_sleeping) { board_init(); + // Pretend that the next run is the first run, as if we were reset. + *simulate_reset = true; } #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. 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 // 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 } -STATIC int run_repl(void) { +STATIC int run_repl(bool first_run) { int exit_code = PYEXEC_FORCED_EXIT; stack_resize(); filesystem_flush(); supervisor_allocation *heap = allocate_remaining_memory(); - start_mp(heap); + start_mp(heap, first_run); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -847,28 +852,34 @@ int __attribute__((used)) main(void) { supervisor_start_bluetooth(); #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; bool skip_repl = true; bool first_run = true; + bool simulate_reset; for (;;) { + simulate_reset = false; if (!skip_repl) { - exit_code = run_repl(); + exit_code = run_repl(first_run); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); } if (exit_code == PYEXEC_FORCED_EXIT) { if (!first_run) { serial_write_compressed(translate("soft reboot\n")); } - first_run = false; 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 { skip_repl = false; } } else if (exit_code != 0) { 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(); return 0; diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index 8d12cb1b09..b24a91a03e 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -62,11 +62,6 @@ void alarm_reset(void) { 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) { // First check if the modules remember what last woke up 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, // so check the deep wakeup cause manually - if (!soft_wakeup) { - soft_wakeup = true; - return esp_sleep_get_wakeup_cause(); - } - return ESP_SLEEP_WAKEUP_UNDEFINED; + return esp_sleep_get_wakeup_cause(); } bool common_hal_alarm_woken_from_sleep(void) { diff --git a/requirements-dev.txt b/requirements-dev.txt index 6a4f5617a8..a57794ce1a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,8 +2,7 @@ huffman # For nvm.toml -cascadetoml==0.3.1 -tomlkit==0.7.2 +cascadetoml jinja2 typer diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 4160f6a334..9f9e01885a 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -64,8 +64,10 @@ //| This object is the sole instance of `alarm.SleepMemory`.""" //| -//| wake_alarm: Alarm -//| """The most recently triggered alarm. If CircuitPython was sleeping, the alarm the woke it from sleep.""" +//| wake_alarm: Optional[Alarm] +//| """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. @@ -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); - 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);