diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index c135442f6001f..0a3ba746d189c 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -99,6 +99,7 @@ msgid "%q contains duplicate pins" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "" @@ -112,6 +113,7 @@ msgstr "" #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -134,6 +136,7 @@ msgstr "" #: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c #: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "" @@ -476,7 +479,7 @@ msgstr "" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "" @@ -583,7 +586,7 @@ msgstr "" msgid "Already scanning for wifi networks" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "" @@ -673,11 +676,6 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "" @@ -720,10 +718,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "" - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "" @@ -864,7 +858,7 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" -#: shared-module/usb/core/Device.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c msgid "Could not allocate DMA capable buffer" msgstr "" @@ -967,6 +961,7 @@ msgstr "" #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -1031,10 +1026,12 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" @@ -1092,7 +1089,6 @@ msgid "File exists" msgstr "" #: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c -#: shared-module/os/getenv.c msgid "File not found" msgstr "" @@ -1243,7 +1239,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1332,6 +1329,10 @@ msgstr "" msgid "Invalid ROS domain ID" msgstr "" +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1340,17 +1341,12 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "" @@ -1381,7 +1377,7 @@ msgstr "" msgid "Invalid state" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "" @@ -1389,10 +1385,6 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "" @@ -1523,7 +1515,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1752,6 +1744,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -2073,10 +2066,13 @@ msgstr "" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c -#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2250,10 +2246,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -3241,10 +3233,6 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" @@ -3326,10 +3314,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3396,10 +3380,6 @@ msgstr "" msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -4055,10 +4035,6 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "" - #: py/emitinlinerv32.c msgid "parameters must be registers in sequence a0 to a3" msgstr "" diff --git a/ports/espressif/common-hal/alarm/SleepMemory.c b/ports/espressif/common-hal/alarm/SleepMemory.c index 938772e53ca94..e98fe97d7bd16 100644 --- a/ports/espressif/common-hal/alarm/SleepMemory.c +++ b/ports/espressif/common-hal/alarm/SleepMemory.c @@ -12,15 +12,34 @@ #include "shared-bindings/alarm/SleepMemory.h" #include "esp_sleep.h" +#include "esp_system.h" // Data storage for singleton instance of SleepMemory. // Might be RTC_SLOW_MEM or RTC_FAST_MEM, depending on setting of CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM. -static RTC_DATA_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH]; +static RTC_NOINIT_ATTR uint8_t _sleep_mem[SLEEP_MEMORY_LENGTH]; void alarm_sleep_memory_reset(void) { - // ESP-IDF build system takes care of doing esp_sleep_pd_config() or the equivalent with - // the correct settings, depending on which RTC mem we are using. - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/system/sleep_modes.html#power-down-of-rtc-peripherals-and-memories + // With RTC_NOINIT_ATTR, the bootloader does not initialize sleep memory. + // Preserve contents on resets where the RTC domain stays powered (software + // reset, watchdog, panic, deep sleep wake). Clear on everything else — + // after power-on, SRAM contents are undefined; after brown-out, the RTC + // domain was reset by hardware (System Reset scope per TRM Figure 6.1-1). + esp_reset_reason_t reason = esp_reset_reason(); + switch (reason) { + case ESP_RST_SW: // microcontroller.reset() / esp_restart() + case ESP_RST_DEEPSLEEP: // deep sleep wake + case ESP_RST_PANIC: // unhandled exception + case ESP_RST_INT_WDT: // interrupt watchdog + case ESP_RST_TASK_WDT: // task watchdog + case ESP_RST_WDT: // other watchdog + // RTC domain was not reset — sleep memory is intact. + break; + default: + // Power-on, brown-out, unknown, or any other reason where + // RTC SRAM contents may be undefined. Clear to zero. + memset(_sleep_mem, 0, sizeof(_sleep_mem)); + break; + } } uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c index e6d65de45551d..5f66a429fbc82 100644 --- a/shared-bindings/alarm/SleepMemory.c +++ b/shared-bindings/alarm/SleepMemory.c @@ -12,9 +12,17 @@ #include "shared-bindings/alarm/SleepMemory.h" //| class SleepMemory: -//| """Store raw bytes in RAM that persists during deep sleep. +//| """Store raw bytes in RAM that persists across deep sleep and software resets. //| The class acts as a ``bytearray``. -//| If power is lost, the memory contents are lost. +//| Contents are preserved across ``microcontroller.reset()``, watchdog resets, +//| and deep sleep wake. Contents are lost when power is removed and restored, +//| or on brown-out reset. +//| +//| .. note:: +//| Programs that call ``microcontroller.reset()`` should wait at least +//| one second after boot before resetting, otherwise CircuitPython's +//| double-reset safe mode detector may activate. See +//| ``supervisor/shared/safe_mode.c``. //| //| Note that this class can't be imported and used directly. The sole //| instance of :class:`SleepMemory` is available at diff --git a/tests/circuitpython-manual/alarm/sleep_memory_persist.py b/tests/circuitpython-manual/alarm/sleep_memory_persist.py new file mode 100644 index 0000000000000..39e6baafca7dc --- /dev/null +++ b/tests/circuitpython-manual/alarm/sleep_memory_persist.py @@ -0,0 +1,100 @@ +"""Reproducer for https://github.com/adafruit/circuitpython/issues/10896 + +Copy to code.py. Sequences through test steps using sleep_memory to +track state. + +The test scoreboard is printed to the magtag e-ink display after every +run so the final display shows cumulative results. +""" + +import alarm +import binascii +import microcontroller +import struct +import supervisor +import time + +# Safe mode avoidance +# On boot CircuitPython writes a SAFE_MODE_USER guard to an RTC register, +# If a second boot occurs before 1000ms elapses then we enter safe mode. +# So, wait for 1000+1ms before calling microcontroller.reset(). +_SAFE_MODE_WINDOW_MS = 1000 + + +def _wait_for_safe_mode_window(): + elapsed_ms = time.monotonic() * 1000 + remaining = _SAFE_MODE_WINDOW_MS + 1 - elapsed_ms + if remaining > 0: + time.sleep(remaining / 1000) + + +# Test result enum +_UNTESTED = 0 +_PASS = 1 +_FAIL = 2 +_LABEL = {_UNTESTED: "-", _PASS: "PASS", _FAIL: "FAIL"} + +# CRC32-protected state in sleep_memory +# [magic:2][step:1][r_reset:1][r_reload:1][pad:1][crc32:4] +_MAGIC = 0xBE01 +_FMT = "