From 143890cd385fad79fabcb5a858c10a9d3c3d1a0b Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Thu, 1 Aug 2024 13:40:59 -0600 Subject: [PATCH 1/3] Ability to use real auto light sleep until alarms for ESP32 --- ports/espressif/common-hal/alarm/__init__.c | 26 +++++++- .../esp-idf-config/sdkconfig.defaults | 3 +- ports/espressif/supervisor/port.c | 65 ++++++++++--------- shared-bindings/alarm/__init__.c | 53 ++++++++------- 4 files changed, 87 insertions(+), 60 deletions(-) diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index fdf8aaea6d62..e64d7704e1b2 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -4,11 +4,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Dan Halbert for Adafruit Industries // // SPDX-License-Identifier: MIT - +#include #include "py/gc.h" #include "py/obj.h" #include "py/objtuple.h" #include "py/runtime.h" +#include "py/mpprint.h" #include "shared-bindings/alarm/__init__.h" #include "shared-bindings/alarm/SleepMemory.h" @@ -29,6 +30,7 @@ #include "supervisor/shared/workflow.h" #include "esp_sleep.h" +#include "esp_pm.h" #include "components/driver/gpio/include/driver/gpio.h" #include "components/driver/uart/include/driver/uart.h" @@ -91,7 +93,8 @@ mp_obj_t common_hal_alarm_record_wake_alarm(void) { // If woken from deep sleep, create a copy alarm similar to what would have // been passed in originally. Otherwise, just return none esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(true); - switch (cause) { + switch (cause) + { case ESP_SLEEP_WAKEUP_TIMER: { return alarm_time_timealarm_record_wake_alarm(); } @@ -139,13 +142,26 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj mp_obj_t wake_alarm = mp_const_none; + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) + esp_pm_config_t pm; + esp_pm_config_t old_pm; + esp_pm_get_configuration(&pm); + esp_pm_get_configuration(&old_pm); + pm.light_sleep_enable = true; + pm.max_freq_mhz = 240; + pm.min_freq_mhz = 80; + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_pm_configure(&pm)); + #endif + + port_disable_tick(); // We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals. while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(false); - switch (cause) { + switch (cause) + { case ESP_SLEEP_WAKEUP_TIMER: { wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms, alarms); break; @@ -176,6 +192,10 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj port_idle_until_interrupt(); } + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) + esp_pm_configure(&old_pm); + #endif + port_enable_tick(); if (mp_hal_is_interrupted()) { return mp_const_none; // Shouldn't be given to python code because exception handling should kick in. } diff --git a/ports/espressif/esp-idf-config/sdkconfig.defaults b/ports/espressif/esp-idf-config/sdkconfig.defaults index c11591b3cf92..a8d8360dc832 100644 --- a/ports/espressif/esp-idf-config/sdkconfig.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig.defaults @@ -32,7 +32,7 @@ CONFIG_GPTIMER_ISR_IRAM_SAFE=y # Power Management # CONFIG_PM_ENABLE=y # required for CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY - +CONFIG_PM_PROFILING=y # # ESP System Settings # @@ -56,6 +56,7 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 # Kernel # CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y # end of Kernel # diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 0b39302675bc..a1b0712a057b 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -117,39 +117,39 @@ void sleep_timer_cb(void *arg); // WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines // hardcode the flash pins as well, making this code incompatible with either a setup // that has the flash on non-standard pins or ESP32s with built-in flash. -#define PSRAM_SPIQ_SD0_IO 7 -#define PSRAM_SPID_SD1_IO 8 -#define PSRAM_SPIWP_SD3_IO 10 -#define PSRAM_SPIHD_SD2_IO 9 - -#define FLASH_HSPI_CLK_IO 14 -#define FLASH_HSPI_CS_IO 15 -#define PSRAM_HSPI_SPIQ_SD0_IO 12 -#define PSRAM_HSPI_SPID_SD1_IO 13 -#define PSRAM_HSPI_SPIWP_SD3_IO 2 -#define PSRAM_HSPI_SPIHD_SD2_IO 4 +#define PSRAM_SPIQ_SD0_IO 7 +#define PSRAM_SPID_SD1_IO 8 +#define PSRAM_SPIWP_SD3_IO 10 +#define PSRAM_SPIHD_SD2_IO 9 + +#define FLASH_HSPI_CLK_IO 14 +#define FLASH_HSPI_CS_IO 15 +#define PSRAM_HSPI_SPIQ_SD0_IO 12 +#define PSRAM_HSPI_SPID_SD1_IO 13 +#define PSRAM_HSPI_SPIWP_SD3_IO 2 +#define PSRAM_HSPI_SPIHD_SD2_IO 4 #ifdef CONFIG_SPIRAM // PSRAM clock and cs IO should be configured based on hardware design. // For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is IO16, // they are the default value for these two configs. -#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17 -#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16 +#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17 +#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16 -#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9 -#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10 +#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9 +#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10 // There is no reason to change the pin of an embedded psram. // So define the number of pin directly, instead of configurable. -#define D0WDR2_V3_PSRAM_CLK_IO 6 -#define D0WDR2_V3_PSRAM_CS_IO 16 +#define D0WDR2_V3_PSRAM_CLK_IO 6 +#define D0WDR2_V3_PSRAM_CS_IO 16 // For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is fixed, which is IO6. -#define PICO_PSRAM_CLK_IO 6 -#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10 +#define PICO_PSRAM_CLK_IO 6 +#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10 -#define PICO_V3_02_PSRAM_CLK_IO 10 -#define PICO_V3_02_PSRAM_CS_IO 9 +#define PICO_V3_02_PSRAM_CLK_IO 10 +#define PICO_V3_02_PSRAM_CS_IO 9 #endif // CONFIG_SPIRAM static void _never_reset_spi_ram_flash(void) { @@ -208,6 +208,7 @@ safe_mode_t port_init(void) { args.arg = NULL; args.dispatch_method = ESP_TIMER_TASK; args.name = "CircuitPython Tick"; + args.skip_unhandled_events = true; esp_timer_create(&args, &_tick_timer); args.callback = &sleep_timer_cb; @@ -219,16 +220,16 @@ safe_mode_t port_init(void) { circuitpython_task = xTaskGetCurrentTaskHandle(); #if !defined(DEBUG) - #define DEBUG (0) +#define DEBUG (0) #endif - // Send the ROM output out of the UART. This includes early logs. +// Send the ROM output out of the UART. This includes early logs. #if DEBUG esp_rom_install_uart_printf(); #endif - #define pin_GPIOn(n) pin_GPIO##n - #define pin_GPIOn_EXPAND(x) pin_GPIOn(x) +#define pin_GPIOn(n) pin_GPIO##n +#define pin_GPIOn_EXPAND(x) pin_GPIOn(x) #ifdef CONFIG_CONSOLE_UART_TX_GPIO common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_TX_GPIO)); @@ -239,7 +240,7 @@ safe_mode_t port_init(void) { #endif #if DEBUG - // debug UART +// debug UART #if defined(CONFIG_IDF_TARGET_ESP32C3) common_hal_never_reset_pin(&pin_GPIO20); common_hal_never_reset_pin(&pin_GPIO21); @@ -253,12 +254,12 @@ safe_mode_t port_init(void) { #endif #ifndef ENABLE_JTAG - #define ENABLE_JTAG (0) +#define ENABLE_JTAG (0) #endif #if ENABLE_JTAG ESP_LOGI(TAG, "Marking JTAG pins never_reset"); - // JTAG +// JTAG #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) common_hal_never_reset_pin(&pin_GPIO4); common_hal_never_reset_pin(&pin_GPIO5); @@ -275,7 +276,8 @@ safe_mode_t port_init(void) { _never_reset_spi_ram_flash(); esp_reset_reason_t reason = esp_reset_reason(); - switch (reason) { + switch (reason) + { case ESP_RST_BROWNOUT: return SAFE_MODE_BROWNOUT; case ESP_RST_PANIC: @@ -303,7 +305,7 @@ void *port_malloc(size_t size, bool dma_capable) { } void *ptr = NULL; - // Try SPIRAM first when available. +// Try SPIRAM first when available. #ifdef CONFIG_SPIRAM ptr = heap_caps_malloc(size, caps | MALLOC_CAP_SPIRAM); #endif @@ -327,7 +329,7 @@ size_t port_heap_get_largest_free_size(void) { } void reset_port(void) { - // TODO deinit for esp32-camera +// TODO deinit for esp32-camera #if CIRCUITPY_ESPCAMERA esp_camera_deinit(); #endif @@ -488,7 +490,6 @@ void port_post_boot_py(bool heap_valid) { } } - #if CIRCUITPY_CONSOLE_UART static int vprintf_adapter(const char *fmt, va_list ap) { return mp_vprintf(&mp_plat_print, fmt, ap); diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 7cdc2f7750e5..49b350a5da29 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -58,7 +58,8 @@ // wake_alarm is implemented as a dictionary entry, so there's no code here. static void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { - for (size_t i = 0; i < n_args; i++) { + for (size_t i = 0; i < n_args; i++) + { if (mp_obj_is_type(objs[i], &alarm_pin_pinalarm_type) || #if CIRCUITPY_ALARM_TOUCH mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type) || @@ -173,9 +174,12 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OB //| ... //| static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_preserve_dios }; + enum + { + ARG_preserve_dios + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_preserve_dios, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple} }, + {MP_QSTR_preserve_dios, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple}}, }; // args will contain only the value for preserve_dios. The *alarms args are in pos_args. @@ -188,7 +192,8 @@ static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o const size_t num_dios = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(preserve_dios)); digitalio_digitalinout_obj_t *dios_array[num_dios]; - for (mp_uint_t i = 0; i < num_dios; i++) { + for (mp_uint_t i = 0; i < num_dios; i++) + { mp_obj_t dio = mp_obj_subscr(preserve_dios, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL); dios_array[i] = mp_arg_validate_type(dio, &digitalio_digitalinout_type, MP_QSTR_alarm); } @@ -204,64 +209,64 @@ static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o MP_DEFINE_CONST_FUN_OBJ_KW(alarm_exit_and_deep_sleep_until_alarms_obj, 0, alarm_exit_and_deep_sleep_until_alarms); static const mp_map_elem_t alarm_pin_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin)}, - { MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pinalarm_type) }, + {MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pinalarm_type)}, }; static MP_DEFINE_CONST_DICT(alarm_pin_globals, alarm_pin_globals_table); static const mp_obj_module_t alarm_pin_module = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t *)&alarm_pin_globals, }; static const mp_map_elem_t alarm_time_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time)}, - { MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_timealarm_type) }, + {MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_timealarm_type)}, }; static MP_DEFINE_CONST_DICT(alarm_time_globals, alarm_time_globals_table); static const mp_obj_module_t alarm_time_module = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t *)&alarm_time_globals, }; #if CIRCUITPY_ALARM_TOUCH static const mp_map_elem_t alarm_touch_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touch) }, - { MP_ROM_QSTR(MP_QSTR_TouchAlarm), MP_OBJ_FROM_PTR(&alarm_touch_touchalarm_type) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touch)}, + {MP_ROM_QSTR(MP_QSTR_TouchAlarm), MP_OBJ_FROM_PTR(&alarm_touch_touchalarm_type)}, }; static MP_DEFINE_CONST_DICT(alarm_touch_globals, alarm_touch_globals_table); static const mp_obj_module_t alarm_touch_module = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t *)&alarm_touch_globals, }; #endif // The module table is mutable because .wake_alarm is a mutable attribute. static mp_map_elem_t alarm_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm)}, // wake_alarm is a mutable attribute. - { MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none }, + {MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none}, - { MP_ROM_QSTR(MP_QSTR_light_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_light_sleep_until_alarms_obj) }, - { MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep_until_alarms), - MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_alarms_obj) }, + {MP_ROM_QSTR(MP_QSTR_light_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_light_sleep_until_alarms_obj)}, + {MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep_until_alarms), + MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_alarms_obj)}, - { MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module) }, - { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) }, + {MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module)}, + {MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module)}, #if CIRCUITPY_ALARM_TOUCH - { MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module) }, + {MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module)}, #endif - { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, - { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, + {MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type)}, + {MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj)}, }; static MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); @@ -288,7 +293,7 @@ void shared_alarm_save_wake_alarm(mp_obj_t alarm) { } const mp_obj_module_t alarm_module = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t *)&alarm_module_globals, }; From d11a01181dfffe1f08a0f8643bb9fc537c849c76 Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Tue, 6 Aug 2024 12:07:01 -0600 Subject: [PATCH 2/3] Formatting fix --- ports/espressif/common-hal/alarm/__init__.c | 6 +- ports/espressif/supervisor/port.c | 64 ++++++++++----------- shared-bindings/alarm/__init__.c | 53 ++++++++--------- 3 files changed, 58 insertions(+), 65 deletions(-) diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index e64d7704e1b2..eb0abd06f8a9 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -93,8 +93,7 @@ mp_obj_t common_hal_alarm_record_wake_alarm(void) { // If woken from deep sleep, create a copy alarm similar to what would have // been passed in originally. Otherwise, just return none esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(true); - switch (cause) - { + switch (cause) { case ESP_SLEEP_WAKEUP_TIMER: { return alarm_time_timealarm_record_wake_alarm(); } @@ -160,8 +159,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(false); - switch (cause) - { + switch (cause) { case ESP_SLEEP_WAKEUP_TIMER: { wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms, alarms); break; diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index a1b0712a057b..9b86128d364d 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -117,39 +117,39 @@ void sleep_timer_cb(void *arg); // WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines // hardcode the flash pins as well, making this code incompatible with either a setup // that has the flash on non-standard pins or ESP32s with built-in flash. -#define PSRAM_SPIQ_SD0_IO 7 -#define PSRAM_SPID_SD1_IO 8 -#define PSRAM_SPIWP_SD3_IO 10 -#define PSRAM_SPIHD_SD2_IO 9 - -#define FLASH_HSPI_CLK_IO 14 -#define FLASH_HSPI_CS_IO 15 -#define PSRAM_HSPI_SPIQ_SD0_IO 12 -#define PSRAM_HSPI_SPID_SD1_IO 13 -#define PSRAM_HSPI_SPIWP_SD3_IO 2 -#define PSRAM_HSPI_SPIHD_SD2_IO 4 +#define PSRAM_SPIQ_SD0_IO 7 +#define PSRAM_SPID_SD1_IO 8 +#define PSRAM_SPIWP_SD3_IO 10 +#define PSRAM_SPIHD_SD2_IO 9 + +#define FLASH_HSPI_CLK_IO 14 +#define FLASH_HSPI_CS_IO 15 +#define PSRAM_HSPI_SPIQ_SD0_IO 12 +#define PSRAM_HSPI_SPID_SD1_IO 13 +#define PSRAM_HSPI_SPIWP_SD3_IO 2 +#define PSRAM_HSPI_SPIHD_SD2_IO 4 #ifdef CONFIG_SPIRAM // PSRAM clock and cs IO should be configured based on hardware design. // For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is IO16, // they are the default value for these two configs. -#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17 -#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16 +#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17 +#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16 -#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9 -#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10 +#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9 +#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10 // There is no reason to change the pin of an embedded psram. // So define the number of pin directly, instead of configurable. -#define D0WDR2_V3_PSRAM_CLK_IO 6 -#define D0WDR2_V3_PSRAM_CS_IO 16 +#define D0WDR2_V3_PSRAM_CLK_IO 6 +#define D0WDR2_V3_PSRAM_CS_IO 16 // For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is fixed, which is IO6. -#define PICO_PSRAM_CLK_IO 6 -#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10 +#define PICO_PSRAM_CLK_IO 6 +#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10 -#define PICO_V3_02_PSRAM_CLK_IO 10 -#define PICO_V3_02_PSRAM_CS_IO 9 +#define PICO_V3_02_PSRAM_CLK_IO 10 +#define PICO_V3_02_PSRAM_CS_IO 9 #endif // CONFIG_SPIRAM static void _never_reset_spi_ram_flash(void) { @@ -220,16 +220,16 @@ safe_mode_t port_init(void) { circuitpython_task = xTaskGetCurrentTaskHandle(); #if !defined(DEBUG) -#define DEBUG (0) + #define DEBUG (0) #endif -// Send the ROM output out of the UART. This includes early logs. + // Send the ROM output out of the UART. This includes early logs. #if DEBUG esp_rom_install_uart_printf(); #endif -#define pin_GPIOn(n) pin_GPIO##n -#define pin_GPIOn_EXPAND(x) pin_GPIOn(x) + #define pin_GPIOn(n) pin_GPIO##n + #define pin_GPIOn_EXPAND(x) pin_GPIOn(x) #ifdef CONFIG_CONSOLE_UART_TX_GPIO common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_TX_GPIO)); @@ -240,7 +240,7 @@ safe_mode_t port_init(void) { #endif #if DEBUG -// debug UART + // debug UART #if defined(CONFIG_IDF_TARGET_ESP32C3) common_hal_never_reset_pin(&pin_GPIO20); common_hal_never_reset_pin(&pin_GPIO21); @@ -254,12 +254,12 @@ safe_mode_t port_init(void) { #endif #ifndef ENABLE_JTAG -#define ENABLE_JTAG (0) + #define ENABLE_JTAG (0) #endif #if ENABLE_JTAG ESP_LOGI(TAG, "Marking JTAG pins never_reset"); -// JTAG + // JTAG #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) common_hal_never_reset_pin(&pin_GPIO4); common_hal_never_reset_pin(&pin_GPIO5); @@ -276,8 +276,7 @@ safe_mode_t port_init(void) { _never_reset_spi_ram_flash(); esp_reset_reason_t reason = esp_reset_reason(); - switch (reason) - { + switch (reason) { case ESP_RST_BROWNOUT: return SAFE_MODE_BROWNOUT; case ESP_RST_PANIC: @@ -305,7 +304,7 @@ void *port_malloc(size_t size, bool dma_capable) { } void *ptr = NULL; -// Try SPIRAM first when available. + // Try SPIRAM first when available. #ifdef CONFIG_SPIRAM ptr = heap_caps_malloc(size, caps | MALLOC_CAP_SPIRAM); #endif @@ -329,7 +328,7 @@ size_t port_heap_get_largest_free_size(void) { } void reset_port(void) { -// TODO deinit for esp32-camera + // TODO deinit for esp32-camera #if CIRCUITPY_ESPCAMERA esp_camera_deinit(); #endif @@ -490,6 +489,7 @@ void port_post_boot_py(bool heap_valid) { } } + #if CIRCUITPY_CONSOLE_UART static int vprintf_adapter(const char *fmt, va_list ap) { return mp_vprintf(&mp_plat_print, fmt, ap); diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 49b350a5da29..7cdc2f7750e5 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -58,8 +58,7 @@ // wake_alarm is implemented as a dictionary entry, so there's no code here. static void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { - for (size_t i = 0; i < n_args; i++) - { + for (size_t i = 0; i < n_args; i++) { if (mp_obj_is_type(objs[i], &alarm_pin_pinalarm_type) || #if CIRCUITPY_ALARM_TOUCH mp_obj_is_type(objs[i], &alarm_touch_touchalarm_type) || @@ -174,12 +173,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OB //| ... //| static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum - { - ARG_preserve_dios - }; + enum { ARG_preserve_dios }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_preserve_dios, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple}}, + { MP_QSTR_preserve_dios, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_tuple} }, }; // args will contain only the value for preserve_dios. The *alarms args are in pos_args. @@ -192,8 +188,7 @@ static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o const size_t num_dios = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(preserve_dios)); digitalio_digitalinout_obj_t *dios_array[num_dios]; - for (mp_uint_t i = 0; i < num_dios; i++) - { + for (mp_uint_t i = 0; i < num_dios; i++) { mp_obj_t dio = mp_obj_subscr(preserve_dios, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL); dios_array[i] = mp_arg_validate_type(dio, &digitalio_digitalinout_type, MP_QSTR_alarm); } @@ -209,64 +204,64 @@ static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o MP_DEFINE_CONST_FUN_OBJ_KW(alarm_exit_and_deep_sleep_until_alarms_obj, 0, alarm_exit_and_deep_sleep_until_alarms); static const mp_map_elem_t alarm_pin_globals_table[] = { - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin) }, - {MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pinalarm_type)}, + { MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pinalarm_type) }, }; static MP_DEFINE_CONST_DICT(alarm_pin_globals, alarm_pin_globals_table); static const mp_obj_module_t alarm_pin_module = { - .base = {&mp_type_module}, + .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&alarm_pin_globals, }; static const mp_map_elem_t alarm_time_globals_table[] = { - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) }, - {MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_timealarm_type)}, + { MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_timealarm_type) }, }; static MP_DEFINE_CONST_DICT(alarm_time_globals, alarm_time_globals_table); static const mp_obj_module_t alarm_time_module = { - .base = {&mp_type_module}, + .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&alarm_time_globals, }; #if CIRCUITPY_ALARM_TOUCH static const mp_map_elem_t alarm_touch_globals_table[] = { - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touch)}, - {MP_ROM_QSTR(MP_QSTR_TouchAlarm), MP_OBJ_FROM_PTR(&alarm_touch_touchalarm_type)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touch) }, + { MP_ROM_QSTR(MP_QSTR_TouchAlarm), MP_OBJ_FROM_PTR(&alarm_touch_touchalarm_type) }, }; static MP_DEFINE_CONST_DICT(alarm_touch_globals, alarm_touch_globals_table); static const mp_obj_module_t alarm_touch_module = { - .base = {&mp_type_module}, + .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&alarm_touch_globals, }; #endif // The module table is mutable because .wake_alarm is a mutable attribute. static mp_map_elem_t alarm_module_globals_table[] = { - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, // wake_alarm is a mutable attribute. - {MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none}, + { MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none }, - {MP_ROM_QSTR(MP_QSTR_light_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_light_sleep_until_alarms_obj)}, - {MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep_until_alarms), - MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_alarms_obj)}, + { MP_ROM_QSTR(MP_QSTR_light_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_light_sleep_until_alarms_obj) }, + { MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep_until_alarms), + MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_alarms_obj) }, - {MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module)}, - {MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module)}, + { MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module) }, + { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) }, #if CIRCUITPY_ALARM_TOUCH - {MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module)}, + { MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module) }, #endif - {MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type)}, - {MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj)}, + { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, + { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, }; static MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); @@ -293,7 +288,7 @@ void shared_alarm_save_wake_alarm(mp_obj_t alarm) { } const mp_obj_module_t alarm_module = { - .base = {&mp_type_module}, + .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&alarm_module_globals, }; From 46439800ca7aa1e0761d6dd7d3a4004eb062437c Mon Sep 17 00:00:00 2001 From: Daniel Dunn Date: Wed, 7 Aug 2024 15:47:42 -0600 Subject: [PATCH 3/3] UART wakeup, don't mess with tick settings --- ports/espressif/common-hal/alarm/__init__.c | 21 ++++++++++++++++----- ports/espressif/common-hal/busio/UART.c | 4 +++- supervisor/shared/serial.c | 10 +++++++++- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index eb0abd06f8a9..af569c1cd9eb 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -28,6 +28,7 @@ #include "supervisor/port.h" #include "supervisor/shared/workflow.h" +#include "supervisor/shared/serial.h" #include "esp_sleep.h" #include "esp_pm.h" @@ -141,18 +142,27 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj mp_obj_t wake_alarm = mp_const_none; + bool use_real_sleep = !serial_connected(); + + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) - esp_pm_config_t pm; esp_pm_config_t old_pm; - esp_pm_get_configuration(&pm); esp_pm_get_configuration(&old_pm); - pm.light_sleep_enable = true; + + esp_pm_config_t pm; + esp_pm_get_configuration(&pm); + pm.max_freq_mhz = 240; pm.min_freq_mhz = 80; + + if (use_real_sleep) { + pm.light_sleep_enable = true; + } + ESP_ERROR_CHECK_WITHOUT_ABORT(esp_pm_configure(&pm)); #endif - port_disable_tick(); + // We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals. while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; @@ -193,7 +203,8 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) esp_pm_configure(&old_pm); #endif - port_enable_tick(); + + if (mp_hal_is_interrupted()) { return mp_const_none; // Shouldn't be given to python code because exception handling should kick in. } diff --git a/ports/espressif/common-hal/busio/UART.c b/ports/espressif/common-hal/busio/UART.c index 3967af44dbd1..54cadf2b87aa 100644 --- a/ports/espressif/common-hal/busio/UART.c +++ b/ports/espressif/common-hal/busio/UART.c @@ -19,6 +19,7 @@ #include "py/stream.h" #include "supervisor/port.h" #include "supervisor/shared/tick.h" +#include "esp_sleep.h" static uint8_t never_reset_uart_mask = 0; @@ -215,7 +216,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (uart_param_config(self->uart_num, &uart_config) != ESP_OK) { mp_raise_RuntimeError(MP_ERROR_TEXT("UART init")); } - + uart_set_wakeup_threshold(self->uart_num, 1); + esp_sleep_enable_uart_wakeup(self->uart_num); self->tx_pin = NULL; self->rx_pin = NULL; self->rts_pin = NULL; diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index 4e4dae3d855d..31764b3b68d7 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -13,6 +13,7 @@ #include "supervisor/shared/cpu.h" #include "supervisor/shared/display.h" #include "shared-bindings/terminalio/Terminal.h" +#include "supervisor/port.h" #include "supervisor/shared/serial.h" #include "shared-bindings/microcontroller/Pin.h" @@ -46,6 +47,10 @@ byte console_uart_rx_buf[64]; #endif #endif +#if CIRCUITPY_CONSOLE_UART +static uint64_t _console_uart_rx_timestamp = 0; +#endif + #if CIRCUITPY_USB_DEVICE || CIRCUITPY_CONSOLE_UART // Flag to note whether this is the first write after connection. // Delay slightly on the first write to allow time for the host to set up things, @@ -175,7 +180,9 @@ bool serial_connected(void) { #endif #if CIRCUITPY_CONSOLE_UART - return true; + if (_console_uart_rx_timestamp && (_console_uart_rx_timestamp + (60 * 1024 * 5) > port_get_raw_ticks(NULL))) { + return true; + } #endif #if CIRCUITPY_SERIAL_BLE @@ -232,6 +239,7 @@ char serial_read(void) { int uart_errcode; char text; common_hal_busio_uart_read(&console_uart, (uint8_t *)&text, 1, &uart_errcode); + _console_uart_rx_timestamp = port_get_raw_ticks(NULL); return text; } #endif