diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 835ef9538b..4cf6992ba4 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -574,7 +574,7 @@ msgstr "" #: shared-bindings/displayio/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c -#: shared-bindings/is31fl3741/is31fl3741.c +#: shared-bindings/is31fl3741/IS31FL3741.c #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "Brightness must be 0-1.0" msgstr "" @@ -1462,7 +1462,7 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/is31fl3741/is31fl3741.c +#: shared-module/is31fl3741/IS31FL3741.c msgid "LED mappings must match display size" msgstr "" @@ -2090,7 +2090,7 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" -#: shared-bindings/is31fl3741/is31fl3741.c +#: shared-bindings/is31fl3741/IS31FL3741.c msgid "Scale dimensions must divide by 3" msgstr "" @@ -2351,7 +2351,7 @@ msgstr "" msgid "Unable to create lock" msgstr "" -#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/is31fl3741.c +#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c #, c-format msgid "Unable to find I2C Display at %x" msgstr "" @@ -3950,6 +3950,7 @@ msgstr "" #: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h #: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h #: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h +#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h #: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h #: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h #: ports/espressif/boards/artisense_rd00/mpconfigboard.h @@ -4462,7 +4463,7 @@ msgstr "" msgid "width must be from 2 to 8 (inclusive), not %d" msgstr "" -#: shared-bindings/is31fl3741/is31fl3741.c +#: shared-bindings/is31fl3741/IS31FL3741.c #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "width must be greater than zero" msgstr "" diff --git a/main.c b/main.c index b1b482f985..8b5b19faf0 100644 --- a/main.c +++ b/main.c @@ -122,7 +122,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(); @@ -170,7 +170,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 @@ -308,7 +309,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 @@ -347,7 +348,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(); @@ -630,6 +631,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 @@ -651,7 +654,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. @@ -728,12 +733,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(); @@ -846,28 +851,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/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);