From 4cbc790628777f1c1d131a4203ec87c4195f5d5e Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Fri, 27 Sep 2024 19:11:30 +0800 Subject: [PATCH] feat(temperature_sensor): Add sleep retention support for temperature sensor --- .../include/driver/temperature_sensor.h | 8 ++- .../esp_driver_tsens/src/temperature_sensor.c | 52 +++++++++++++++ .../src/temperature_sensor_private.h | 5 +- .../temperature_sensor/main/CMakeLists.txt | 2 +- .../main/test_temperature_sensor.c | 63 ++++++++++++++++++- .../temperature_sensor/sdkconfig.ci.release | 1 + .../temperature_sensor/sdkconfig.defaults | 2 + .../include/esp_private/regi2c_ctrl.h | 9 ++- components/esp_hw_support/regi2c_ctrl.c | 21 ++++++- components/esp_hw_support/sleep_modes.c | 6 ++ .../esp32c5/include/soc/Kconfig.soc_caps.in | 8 +++ .../include/soc/retention_periph_defs.h | 3 + components/soc/esp32c5/include/soc/soc_caps.h | 2 + .../soc/esp32c5/temperature_sensor_periph.c | 24 +++++++ .../esp32c6/include/soc/Kconfig.soc_caps.in | 8 +++ .../include/soc/retention_periph_defs.h | 3 + components/soc/esp32c6/include/soc/soc_caps.h | 2 + .../soc/esp32c6/temperature_sensor_periph.c | 26 +++++++- .../esp32h2/include/soc/Kconfig.soc_caps.in | 8 +++ .../include/soc/retention_periph_defs.h | 3 + components/soc/esp32h2/include/soc/soc_caps.h | 2 + .../soc/esp32h2/temperature_sensor_periph.c | 27 +++++++- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32p4/include/soc/soc_caps.h | 2 + components/soc/include/soc/regdma.h | 2 + .../include/soc/temperature_sensor_periph.h | 17 ++++- .../api-reference/peripherals/temp_sensor.rst | 1 + .../api-reference/system/power_management.rst | 1 + .../api-reference/peripherals/temp_sensor.rst | 1 + .../api-reference/system/power_management.rst | 1 + 30 files changed, 305 insertions(+), 9 deletions(-) diff --git a/components/esp_driver_tsens/include/driver/temperature_sensor.h b/components/esp_driver_tsens/include/driver/temperature_sensor.h index 3c2c18dc1c5..fc968dfb0fa 100644 --- a/components/esp_driver_tsens/include/driver/temperature_sensor.h +++ b/components/esp_driver_tsens/include/driver/temperature_sensor.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,12 @@ typedef struct { int range_min; /**< the minimum value of the temperature you want to test */ int range_max; /**< the maximum value of the temperature you want to test */ temperature_sensor_clk_src_t clk_src; /**< the clock source of the temperature sensor. */ + struct { + uint32_t allow_pd; /**< If set, the driver will backup/restore the temperature sensor registers before/after entering/exist sleep mode. + By this approach, the system can power off temperature sensor's power domain. + This can save power, but at the expense of more RAM being consumed */ + } flags; /**< Temperature sensor config flags */ + } temperature_sensor_config_t; /** diff --git a/components/esp_driver_tsens/src/temperature_sensor.c b/components/esp_driver_tsens/src/temperature_sensor.c index 2bf39ca9bf2..39e44afb9b5 100644 --- a/components/esp_driver_tsens/src/temperature_sensor.c +++ b/components/esp_driver_tsens/src/temperature_sensor.c @@ -29,6 +29,9 @@ #include "soc/temperature_sensor_periph.h" #include "esp_memory_utils.h" #include "esp_private/sar_periph_ctrl.h" +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK +#include "esp_private/sleep_retention.h" +#endif static const char *TAG = "temperature_sensor"; @@ -93,6 +96,26 @@ static void IRAM_ATTR temperature_sensor_isr(void *arg) } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK +static esp_err_t s_temperature_sensor_sleep_retention_init(void *arg) +{ + esp_err_t ret = sleep_retention_entries_create(temperature_sensor_regs_retention.link_list, temperature_sensor_regs_retention.link_num, REGDMA_LINK_PRI_TEMPERATURE_SENSOR, temperature_sensor_regs_retention.module_id); + ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention"); + return ret; +} + +void temperature_sensor_create_retention_module(temperature_sensor_handle_t tsens) +{ + sleep_retention_module_t module_id = temperature_sensor_regs_retention.module_id; + if ((sleep_retention_get_inited_modules() & BIT(module_id)) && !(sleep_retention_get_created_modules() & BIT(module_id))) { + if (sleep_retention_module_allocate(module_id) != ESP_OK) { + // even though the sleep retention module_id create failed, temperature sensor driver should still work, so just warning here + ESP_LOGW(TAG, "create retention link failed, power domain won't be turned off during sleep"); + } + } +} +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens) { #if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG @@ -110,6 +133,24 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co tsens->clk_src = tsens_config->clk_src; } +#if !SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + ESP_RETURN_ON_FALSE(tsens_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); +#endif // SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = s_temperature_sensor_sleep_retention_init, .arg = (void *)tsens } } + }; + ret = sleep_retention_module_init(temperature_sensor_regs_retention.module_id, &init_param); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep"); + } + + if (tsens_config->flags.allow_pd != 0) { + temperature_sensor_create_retention_module(tsens); + } +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + temperature_sensor_power_acquire(); temperature_sensor_ll_clk_sel(tsens->clk_src); @@ -147,6 +188,17 @@ esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens) ESP_RETURN_ON_ERROR(esp_intr_free(tsens->temp_sensor_isr_handle), TAG, "uninstall interrupt service failed"); } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + +#if TEMPERATURE_SENSOR_USE_RETENTION_LINK + sleep_retention_module_t module_id = temperature_sensor_regs_retention.module_id; + if (sleep_retention_get_created_modules() & BIT(module_id)) { + sleep_retention_module_free(temperature_sensor_regs_retention.module_id); + } + if (sleep_retention_get_inited_modules() & BIT(module_id)) { + sleep_retention_module_deinit(temperature_sensor_regs_retention.module_id); + } +#endif // TEMPERATURE_SENSOR_USE_RETENTION_LINK + temperature_sensor_power_release(); free(tsens); diff --git a/components/esp_driver_tsens/src/temperature_sensor_private.h b/components/esp_driver_tsens/src/temperature_sensor_private.h index b511505ffba..28b84be5f8e 100644 --- a/components/esp_driver_tsens/src/temperature_sensor_private.h +++ b/components/esp_driver_tsens/src/temperature_sensor_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,9 @@ typedef enum { #define TEMPERATURE_SENSOR_MEM_ALLOC_CAPS (MALLOC_CAP_DEFAULT) #endif +// Use retention link only when the target supports sleep retention and PM is enabled +#define TEMPERATURE_SENSOR_USE_RETENTION_LINK (SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN) + typedef struct temperature_sensor_obj_t temperature_sensor_obj_t; struct temperature_sensor_obj_t { diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt b/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt index 5d45e0615ad..57b6fd425c6 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/CMakeLists.txt @@ -9,5 +9,5 @@ endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity esp_wifi test_utils nvs_flash esp_driver_tsens esp_driver_gpio + PRIV_REQUIRES unity esp_wifi test_utils nvs_flash esp_driver_tsens esp_driver_gpio esp_pm WHOLE_ARCHIVE) diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c index 6bc7fe4e86e..15b38613c8b 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,11 @@ #include "freertos/task.h" #include "soc/soc_caps.h" #include "unity_test_utils_cache.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" +#include "esp_pm.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]") { @@ -146,3 +151,59 @@ TEST_CASE("Temperature sensor callback test", "[temperature_sensor]") } #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + +#if SOC_LIGHT_SLEEP_SUPPORTED && CONFIG_PM_ENABLE +static void test_temperature_sensor_sleep_retention(bool allow_pd) +{ + printf("Initializing Temperature sensor\n"); + float tsens_result0; + float tsens_result1; + temperature_sensor_config_t temp_sensor = { + .range_min = 10, + .range_max = 50, + .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, + .flags.allow_pd = allow_pd, + }; + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_enable(temp_handle)); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_result0)); + printf("Temperature out celsius %f°C\n", tsens_result0); + + esp_sleep_context_t sleep_ctx; + esp_sleep_set_sleep_context(&sleep_ctx); + +#if ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(true)); +#endif + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); +#if ESP_SLEEP_POWER_DOWN_CPU + TEST_ESP_OK(sleep_cpu_configure(false)); +#endif + printf("check if the sleep happened as expected\r\n"); + TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); +#if SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + // check if the power domain also is powered down + TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#elif CONFIG_IDF_TARGET_ESP32P4 + TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); +#endif + + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_result1)); + printf("Temperature out celsius %f°C\n", tsens_result1); + TEST_ASSERT_FLOAT_WITHIN(6.0, tsens_result0, tsens_result1); + + TEST_ESP_OK(temperature_sensor_disable(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} + +TEST_CASE("temperature sensor sleep retention test", "[temperature_sensor]") +{ + test_temperature_sensor_sleep_retention(false); +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + test_temperature_sensor_sleep_retention(true); +#endif +} +#endif diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release index 91d93f163e6..eb643d4d06b 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.ci.release @@ -1,4 +1,5 @@ CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults index e4bfc208a55..a89cab2af3b 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/sdkconfig.defaults @@ -1 +1,3 @@ CONFIG_ESP_TASK_WDT_EN=n +# primitives for checking sleep internal state +CONFIG_ESP_SLEEP_DEBUG=y diff --git a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h index def755d8156..e77322677f8 100644 --- a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h +++ b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -70,6 +70,13 @@ void regi2c_analog_cali_reg_read(void); void regi2c_analog_cali_reg_write(void); #endif //#if ADC_CALI_PD_WORKAROUND +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +// regi2c would be powered down in light sleep, but measure range is recorded +// in regi2c, so this function is used for record. +void regi2c_tsens_reg_read(void); +void regi2c_tsens_reg_write(void); +#endif + /* Enable/Disable regi2c_saradc with calling these two functions. With reference count protection inside. Internal use only. diff --git a/components/esp_hw_support/regi2c_ctrl.c b/components/esp_hw_support/regi2c_ctrl.c index 1d63f666864..14c8e403451 100644 --- a/components/esp_hw_support/regi2c_ctrl.c +++ b/components/esp_hw_support/regi2c_ctrl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,7 @@ #include "hal/regi2c_ctrl.h" #include "hal/regi2c_ctrl_ll.h" #include "esp_hw_log.h" +#include "soc/soc_caps.h" static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; @@ -109,3 +110,21 @@ void regi2c_saradc_disable(void) regi2c_exit_critical(); } + +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + +#include "soc/regi2c_saradc.h" + +static DRAM_ATTR uint8_t dac_offset_regi2c; + +void IRAM_ATTR regi2c_tsens_reg_read(void) +{ + dac_offset_regi2c = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); +} + +void IRAM_ATTR regi2c_tsens_reg_write(void) +{ + REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset_regi2c); +} + +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ed81134542d..3a4ee01c9c0 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -679,6 +679,9 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_read(); +#endif +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + regi2c_tsens_reg_read(); #endif } @@ -724,6 +727,9 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags) #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_write(); #endif +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + regi2c_tsens_reg_write(); +#endif } static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp) diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 3ca17508c5d..d8776c93c85 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1407,6 +1407,14 @@ config SOC_TEMPERATURE_SENSOR_INTR_SUPPORT bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_WIFI_HW_TSF bool default y diff --git a/components/soc/esp32c5/include/soc/retention_periph_defs.h b/components/soc/esp32c5/include/soc/retention_periph_defs.h index b21f1d3edea..8f3db9db68b 100644 --- a/components/soc/esp32c5/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c5/include/soc/retention_periph_defs.h @@ -38,6 +38,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_UART1 = 15, SLEEP_RETENTION_MODULE_I2S0 = 16, SLEEP_RETENTION_MODULE_ETM0 = 17, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18, /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -78,6 +79,7 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), @@ -100,6 +102,7 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_UART1 \ | SLEEP_RETENTION_MODULE_BM_I2S0 \ | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ ) #ifdef __cplusplus } diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index b98bce60b93..ba33e35b99d 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -591,6 +591,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*------------------------------------ WI-FI CAPS ------------------------------------*/ #define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ diff --git a/components/soc/esp32c5/temperature_sensor_periph.c b/components/soc/esp32c5/temperature_sensor_periph.c index b0b6cfef7eb..45410347bda 100644 --- a/components/soc/esp32c5/temperature_sensor_periph.c +++ b/components/soc/esp32c5/temperature_sensor_periph.c @@ -4,7 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +17,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 396d8ff0e07..297b260f12b 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1459,6 +1459,14 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_RNG_CLOCK_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index 5bba74ce353..c7c3a452a13 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -38,6 +38,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_UART1 = 15, SLEEP_RETENTION_MODULE_I2S0 = 16, SLEEP_RETENTION_MODULE_ETM0 = 17, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -72,6 +73,7 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), @@ -96,6 +98,7 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_UART1 \ | SLEEP_RETENTION_MODULE_BM_I2S0 \ | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ ) #ifdef __cplusplus diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 70835692ee8..bdae84ebd29 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -574,6 +574,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*--------------------------------- RNG CAPS --------------------------------------------*/ #define SOC_RNG_CLOCK_IS_INDEPENDENT (1) diff --git a/components/soc/esp32c6/temperature_sensor_periph.c b/components/soc/esp32c6/temperature_sensor_periph.c index f5ad36f5a9f..b1a189fe9b4 100644 --- a/components/soc/esp32c6/temperature_sensor_periph.c +++ b/components/soc/esp32c6/temperature_sensor_periph.c @@ -1,10 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +17,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 1330fbf2332..a2254cbb3cf 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1423,6 +1423,14 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN + bool + default y + config SOC_RNG_CLOCK_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index 372e43e981c..e3b7c020762 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -39,6 +39,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_UART1 = 16, SLEEP_RETENTION_MODULE_I2S0 = 17, SLEEP_RETENTION_MODULE_ETM0 = 18, + SLEEP_RETENTION_MODULE_TEMP_SENSOR = 19, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -72,6 +73,7 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), + SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), /* modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), @@ -95,6 +97,7 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_UART1 \ | SLEEP_RETENTION_MODULE_BM_I2S0 \ | SLEEP_RETENTION_MODULE_BM_ETM0 \ + | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ ) #ifdef __cplusplus diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 26110b48eba..1fc679eea08 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -559,6 +559,8 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) +#define SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN (1) /*--------------------------------- RNG CAPS --------------------------------------------*/ #define SOC_RNG_CLOCK_IS_INDEPENDENT (1) diff --git a/components/soc/esp32h2/temperature_sensor_periph.c b/components/soc/esp32h2/temperature_sensor_periph.c index e75c60b3178..348567d3f2f 100644 --- a/components/soc/esp32h2/temperature_sensor_periph.c +++ b/components/soc/esp32h2/temperature_sensor_periph.c @@ -1,10 +1,14 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" +#include "soc/apb_saradc_reg.h" + const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ @@ -14,3 +18,24 @@ const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_S { 1, 11, -30, 50, 2}, { 2, 10, -40, 20, 3}, }; + +// Temperature sensor sleep retention entries +// Temperature sensor registers require set the reg_update bit to make the configuration take effect + +/* Temperature sensor Registers Context + Include: APB_SARADC_INT_ENA_REG / + APB_SARADC_APB_TSENS_CTRL_REG / APB_SARADC_TSENS_CTRL2_REG / APB_TSENS_WAKE_REG / APB_TSENS_SAMPLE_REG +*/ +#define TEMPERATURE_SENSOR_RETENTION_REGS_CNT 5 +#define TEMPERATURE_SENSOR_RETENTION_MAP_BASE APB_SARADC_INT_ENA_REG +static const uint32_t temperature_sensor_regs_map[4] = {0x6c1, 0, 0, 0}; +static const regdma_entries_config_t temperature_sensor_regs_entries[] = { + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TSENS_LINK(0x00), TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_MAP_BASE, TEMPERATURE_SENSOR_RETENTION_REGS_CNT, 0, 0, temperature_sensor_regs_map[0], temperature_sensor_regs_map[1], temperature_sensor_regs_map[2], temperature_sensor_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +}; + +const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention = { + .link_list = temperature_sensor_regs_entries, + .link_num = ARRAY_SIZE(temperature_sensor_regs_entries), + .module_id = SLEEP_RETENTION_MODULE_TEMP_SENSOR, +}; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index f8319e722ee..fcc964add8b 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1907,6 +1907,10 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_ETM bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_MEM_TCM_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a8a90bda867..70755ca405f 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -722,6 +722,8 @@ #define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1) #define SOC_TSENS_IS_INDEPENDENT_FROM_ADC (1) /*!< Temperature sensor is a separate module, not share regs with ADC */ #define SOC_TEMPERATURE_SENSOR_SUPPORT_ETM (1) +// temperature sensor on esp32p4 in under low power domain. +#define SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- Memory CAPS --------------------------*/ #define SOC_MEM_TCM_SUPPORTED (1) diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 15186cbb95a..6dbc3cbc78b 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -55,6 +55,7 @@ extern "C" { #define REGDMA_TG1_TIMER_LINK(_pri) ((0x1D << 8) | _pri) #define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri) #define REGDMA_ETM_LINK(_pri) ((0x1F << 8) | _pri) +#define REGDMA_TSENS_LINK(_pri) ((0x20 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 @@ -74,6 +75,7 @@ extern "C" { #define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/soc/include/soc/temperature_sensor_periph.h b/components/soc/include/soc/temperature_sensor_periph.h index 73742819350..d5273925541 100644 --- a/components/soc/include/soc/temperature_sensor_periph.h +++ b/components/soc/include/soc/temperature_sensor_periph.h @@ -1,11 +1,16 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include "soc/regdma.h" +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +#include "soc/retention_periph_defs.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -22,6 +27,16 @@ typedef struct { extern const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM]; +#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION +typedef struct { + const regdma_entries_config_t *link_list; + uint32_t link_num; + periph_retention_module_t module_id; +} temperature_sensor_reg_ctx_link_t; + +extern const temperature_sensor_reg_ctx_link_t temperature_sensor_regs_retention; +#endif // SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION + #ifdef __cplusplus } #endif diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index 22b7e1a6ce3..ca7231e6e1e 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -59,6 +59,7 @@ In order to install a built-in temperature sensor instance, the first thing is t - :cpp:member:`range_min`: The minimum value of the testing range you have evaluated. - :cpp:member:`range_max`: The maximum value of the testing range you have evaluated. +- :cpp:member:`allow_pd` configures if the driver allows the system to power down the peripheral in light sleep mode. Before entering sleep, the system will backup the temperature sensor register context, which will be restored later when the system exit the sleep mode. Powering down the peripheral can save more power, but at the cost of more memory consumed to save the register context. It's a tradeoff between power consumption and memory consumption. This configuration option relies on specific hardware feature, if you enable it on an unsupported chip, you will see error message like ``not able to power down in light sleep``. After the ranges are set, the structure could be passed to :cpp:func:`temperature_sensor_install`, which will instantiate the temperature sensor instance and return a handle. diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index f583b86718c..7f72750dcf5 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -156,6 +156,7 @@ The following peripheral drivers are not aware of DFS yet. Applications need to :SOC_I2C_SUPPORT_SLEEP_RETENTION: - I2C :SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S :SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs + :SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor The following peripherals are not yet supported: diff --git a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst index bffe7b66943..a53aace2fbd 100644 --- a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst +++ b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst @@ -59,6 +59,7 @@ - :cpp:member:`range_min`:所测量温度范围的最小值。 - :cpp:member:`range_max`:所测量温度范围的最大值。 +- :cpp:member:`allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前,系统将备份温度传感器寄存器上下文,当系统退出睡眠模式时,这些上下文将被恢复。关闭外设可以节省更多功耗,但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能,如果在不支持的芯片上启用它,你将看到类似 ``not able to power down in light sleep`` 的错误消息。 设置好温度范围后,将配置结构体传递给 :cpp:func:`temperature_sensor_install`,该函数将创建温度传感器模块并返回句柄。 diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index 3ea51dc30bb..0d64025cd98 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -156,6 +156,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, :SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S :SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM :SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs + :SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor 以下外设尚未支持: