From b248046bcb3e5eba8af688f3c42fabb634c63d91 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 4 Mar 2022 18:04:20 +0800 Subject: [PATCH] Temperature_sensor: Create new temperature sensor API --- components/driver/CMakeLists.txt | 17 +- .../esp32c2/include/driver/temp_sensor.h | 92 -------- .../esp32c3/include/driver/temp_sensor.h | 92 -------- components/driver/esp32c3/rtc_tempsensor.c | 164 -------------- .../esp32h2/include/driver/temp_sensor.h | 91 -------- components/driver/esp32h2/rtc_tempsensor.c | 164 -------------- .../esp32s2/include/driver/temp_sensor.h | 97 --------- components/driver/esp32s2/rtc_tempsensor.c | 187 ---------------- .../include/driver/temperature_sensor.h | 92 ++++++++ components/driver/temperature_sensor.c | 200 ++++++++++++++++++ .../temperature_sensor/CMakeLists.txt | 5 + .../test_apps/temperature_sensor/README.md | 2 + .../temperature_sensor/main/CMakeLists.txt | 7 + .../temperature_sensor/main/test_app_main.c | 40 ++++ .../main/test_temperature_sensor.c | 81 +++++++ .../pytest_temperature_sensor.py | 18 ++ .../temperature_sensor/sdkconfig.ci.release | 5 + .../temperature_sensor/sdkconfig.defaults | 1 + .../efuse/esp32c3/esp_efuse_rtc_calib.c | 13 +- .../esp32c3/include/esp_efuse_rtc_calib.h | 9 +- .../efuse/esp32h2/esp_efuse_rtc_calib.c | 13 +- .../esp32h2/include/esp_efuse_rtc_calib.h | 9 +- .../efuse/esp32s2/esp_efuse_rtc_calib.c | 22 ++ .../esp32s2/include/esp_efuse_rtc_calib.h | 27 +++ components/efuse/esp32s2/sources.cmake | 1 + .../hal/esp32c3/include/hal/clk_gate_ll.h | 24 +-- .../include/hal/temperature_sensor_ll.h | 154 ++++++++++++++ .../hal/esp32h2/include/hal/clk_gate_ll.h | 24 +-- .../include/hal/temperature_sensor_ll.h | 155 ++++++++++++++ .../include/hal/temperature_sensor_ll.h | 147 +++++++++++++ .../include/hal/temperature_sensor_types.h | 38 ++++ .../esp32c3/include/soc/Kconfig.soc_caps.in | 8 + .../soc/esp32c3/include/soc/periph_defs.h | 1 + components/soc/esp32c3/include/soc/soc_caps.h | 4 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 8 + .../soc/esp32h2/include/soc/periph_defs.h | 1 + components/soc/esp32h2/include/soc/soc_caps.h | 4 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s2/include/soc/periph_defs.h | 1 + components/soc/esp32s2/include/soc/soc_caps.h | 3 + examples/peripherals/temp_sensor/README.md | 30 +-- .../temp_sensor/main/temp_sensor_main.c | 55 ++--- .../temp_sensor/pytest_temp_sensor_example.py | 17 ++ tools/ci/check_copyright_ignore.txt | 3 - 44 files changed, 1143 insertions(+), 987 deletions(-) delete mode 100644 components/driver/esp32c2/include/driver/temp_sensor.h delete mode 100644 components/driver/esp32c3/include/driver/temp_sensor.h delete mode 100644 components/driver/esp32c3/rtc_tempsensor.c delete mode 100644 components/driver/esp32h2/include/driver/temp_sensor.h delete mode 100644 components/driver/esp32h2/rtc_tempsensor.c delete mode 100644 components/driver/esp32s2/include/driver/temp_sensor.h delete mode 100644 components/driver/esp32s2/rtc_tempsensor.c create mode 100644 components/driver/include/driver/temperature_sensor.h create mode 100644 components/driver/temperature_sensor.c create mode 100644 components/driver/test_apps/temperature_sensor/CMakeLists.txt create mode 100644 components/driver/test_apps/temperature_sensor/README.md create mode 100644 components/driver/test_apps/temperature_sensor/main/CMakeLists.txt create mode 100644 components/driver/test_apps/temperature_sensor/main/test_app_main.c create mode 100644 components/driver/test_apps/temperature_sensor/main/test_temperature_sensor.c create mode 100644 components/driver/test_apps/temperature_sensor/pytest_temperature_sensor.py create mode 100644 components/driver/test_apps/temperature_sensor/sdkconfig.ci.release create mode 100644 components/driver/test_apps/temperature_sensor/sdkconfig.defaults create mode 100644 components/efuse/esp32s2/esp_efuse_rtc_calib.c create mode 100644 components/efuse/esp32s2/include/esp_efuse_rtc_calib.h create mode 100644 components/hal/esp32c3/include/hal/temperature_sensor_ll.h create mode 100644 components/hal/esp32h2/include/hal/temperature_sensor_ll.h create mode 100644 components/hal/esp32s2/include/hal/temperature_sensor_ll.h create mode 100644 components/hal/include/hal/temperature_sensor_types.h create mode 100644 examples/peripherals/temp_sensor/pytest_temp_sensor_example.py diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index bddd65e1be..2003bcbfde 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -19,7 +19,10 @@ set(srcs "spi_bus_lock.c" "uart.c") -set(includes "include" "${target}/include" "deprecated") +set(includes "include" "deprecated") +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target}/include") + list(APPEND includes "${target}/include") +endif() if(CONFIG_SOC_ADC_SUPPORTED) list(APPEND srcs @@ -59,6 +62,11 @@ if(CONFIG_SOC_I2S_SUPPORTED) list(APPEND srcs "i2s.c") endif() +if(CONFIG_SOC_TEMP_SENSOR_SUPPORTED) + list(APPEND srcs "temperature_sensor.c" + "rtc_temperature_legacy.c") +endif() + if(CONFIG_SOC_TWAI_SUPPORTED) list(APPEND srcs "twai.c") endif() @@ -77,7 +85,6 @@ if(IDF_TARGET STREQUAL "esp32s2") list(APPEND srcs "dac_common.c" "spi_slave_hd.c" "touch_sensor_common.c" - "esp32s2/rtc_tempsensor.c" "esp32s2/touch_sensor.c" "esp32s2/adc.c" "adc_deprecated.c" @@ -95,13 +102,11 @@ endif() if(IDF_TARGET STREQUAL "esp32c3") list(APPEND srcs "spi_slave_hd.c" "usb_serial_jtag.c" - "esp32c3/adc2_init_cal.c" - "esp32c3/rtc_tempsensor.c") + "esp32c3/adc2_init_cal.c") endif() if(IDF_TARGET STREQUAL "esp32h2") - list(APPEND srcs "spi_slave_hd.c" - "esp32h2/rtc_tempsensor.c") + list(APPEND srcs "spi_slave_hd.c") endif() if(IDF_TARGET STREQUAL "esp32c2") diff --git a/components/driver/esp32c2/include/driver/temp_sensor.h b/components/driver/esp32c2/include/driver/temp_sensor.h deleted file mode 100644 index bf9973c6a5..0000000000 --- a/components/driver/esp32c2/include/driver/temp_sensor.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */ - TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */ - TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */ - TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */ - TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */ - TSENS_DAC_MAX, - TSENS_DAC_DEFAULT = TSENS_DAC_L2, -} temp_sensor_dac_offset_t; - -/** - * @brief Configuration for temperature sensor reading - */ -typedef struct { - temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */ - uint8_t clk_div; /*!< Default: 6 */ -} temp_sensor_config_t; - -#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \ - .clk_div = 6} - -/** - * @brief Set parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens); - -/** - * @brief Get parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens); - -/** - * @brief Start temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE if temperature sensor is started already. - */ -esp_err_t temp_sensor_start(void); - -/** - * @brief Stop temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE if temperature sensor is stopped already. - */ -esp_err_t temp_sensor_stop(void); - -/** - * @brief Read temperature sensor raw data. - * @param tsens_out Pointer to raw data, Range: 0 ~ 255 - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG `tsens_out` is NULL - * - ESP_ERR_INVALID_STATE temperature sensor dont start - */ -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out); - -/** - * @brief Read temperature sensor data that is converted to degrees Celsius. - * @note Should not be called from interrupt. - * @param celsius The measure output value. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG ARG is NULL. - * - ESP_ERR_INVALID_STATE The ambient temperature is out of range. - */ -esp_err_t temp_sensor_read_celsius(float *celsius); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32c3/include/driver/temp_sensor.h b/components/driver/esp32c3/include/driver/temp_sensor.h deleted file mode 100644 index d5d3ee3dd2..0000000000 --- a/components/driver/esp32c3/include/driver/temp_sensor.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */ - TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */ - TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */ - TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */ - TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */ - TSENS_DAC_MAX, - TSENS_DAC_DEFAULT = TSENS_DAC_L2, -} temp_sensor_dac_offset_t; - -/** - * @brief Configuration for temperature sensor reading - */ -typedef struct { - temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */ - uint8_t clk_div; /*!< Default: 6 */ -} temp_sensor_config_t; - -#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \ - .clk_div = 6} - -/** - * @brief Set parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens); - -/** - * @brief Get parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens); - -/** - * @brief Start temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE if temperature sensor is started already. - */ -esp_err_t temp_sensor_start(void); - -/** - * @brief Stop temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE if temperature sensor is stopped already. - */ -esp_err_t temp_sensor_stop(void); - -/** - * @brief Read temperature sensor raw data. - * @param tsens_out Pointer to raw data, Range: 0 ~ 255 - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG `tsens_out` is NULL - * - ESP_ERR_INVALID_STATE temperature sensor dont start - */ -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out); - -/** - * @brief Read temperature sensor data that is converted to degrees Celsius. - * @note Should not be called from interrupt. - * @param celsius The measure output value. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG ARG is NULL. - * - ESP_ERR_INVALID_STATE The ambient temperature is out of range. - */ -esp_err_t temp_sensor_read_celsius(float *celsius); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32c3/rtc_tempsensor.c b/components/driver/esp32c3/rtc_tempsensor.c deleted file mode 100644 index d77b75e902..0000000000 --- a/components/driver/esp32c3/rtc_tempsensor.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "esp_log.h" -#include "esp_check.h" -#include "hal/adc_ll.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/apb_saradc_struct.h" -#include "soc/apb_saradc_reg.h" -#include "soc/system_reg.h" -#include "driver/temp_sensor.h" -#include "regi2c_ctrl.h" -#include "esp32c3/rom/ets_sys.h" -#include "esp_efuse_rtc_calib.h" - -static const char *TAG = "tsens"; - -#define TSENS_XPD_WAIT_DEFAULT 0xFF /* Set wait cycle time(8MHz) from power up to reset enable. */ -#define TSENS_ADC_FACTOR (0.4386) -#define TSENS_DAC_FACTOR (27.88) -#define TSENS_SYS_OFFSET (20.52) - -typedef struct { - int index; - int offset; - int set_val; - int range_min; - int range_max; - int error_max; -} tsens_dac_offset_t; - -static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = { - /* DAC Offset reg_val min max error */ - {TSENS_DAC_L0, -2, 5, 50, 125, 3}, - {TSENS_DAC_L1, -1, 7, 20, 100, 2}, - {TSENS_DAC_L2, 0, 15, -10, 80, 1}, - {TSENS_DAC_L3, 1, 11, -30, 50, 2}, - {TSENS_DAC_L4, 2, 10, -40, 20, 3}, -}; - -typedef enum { - TSENS_HW_STATE_UNCONFIGURED, - TSENS_HW_STATE_CONFIGURED, - TSENS_HW_STATE_STARTED, -} tsens_hw_state_t; - -static tsens_hw_state_t tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED; - -static float s_deltaT = NAN; // unused number - -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens) -{ - if (tsens_hw_state == TSENS_HW_STATE_STARTED) { - ESP_LOGE(TAG, "Do not configure the temp sensor when it's running!"); - return ESP_ERR_INVALID_STATE; - } - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); - REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val); - APB_SARADC.apb_tsens_ctrl.tsens_clk_div = tsens.clk_div; - APB_SARADC.apb_tsens_ctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT; - APB_SARADC.apb_tsens_ctrl2.tsens_xpd_force = 1; - ESP_LOGD(TAG, "Config temperature range [%d°C ~ %d°C], error < %d°C", - dac_offset[tsens.dac_offset].range_min, - dac_offset[tsens.dac_offset].range_max, - dac_offset[tsens.dac_offset].error_max); - tsens_hw_state = TSENS_HW_STATE_CONFIGURED; - return ESP_OK; -} - -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens) -{ - ESP_RETURN_ON_FALSE(tsens != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens specified"); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); - tsens->dac_offset = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); - for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) { - if (tsens->dac_offset == dac_offset[i].set_val) { - tsens->dac_offset = dac_offset[i].index; - break; - } - } - tsens->clk_div = APB_SARADC.apb_tsens_ctrl.tsens_clk_div; - return ESP_OK; -} - -esp_err_t temp_sensor_start(void) -{ - if (tsens_hw_state != TSENS_HW_STATE_CONFIGURED) { - ESP_LOGE(TAG, "Temperature sensor is already running or not be configured"); - return ESP_ERR_INVALID_STATE; - } - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN); - APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 1; - APB_SARADC.apb_tsens_ctrl.tsens_pu = 1; - tsens_hw_state = TSENS_HW_STATE_STARTED; - return ESP_OK; -} - -esp_err_t temp_sensor_stop(void) -{ - APB_SARADC.apb_tsens_ctrl.tsens_pu = 0; - APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 0; - return ESP_OK; -} - -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out) -{ - ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens_out specified"); - *tsens_out = APB_SARADC.apb_tsens_ctrl.tsens_out; - return ESP_OK; -} - -static void read_delta_t_from_efuse(void) -{ - uint32_t version = esp_efuse_rtc_calib_get_ver(); - if (version == 1) { - // fetch calibration value for temp sensor from eFuse - s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version); - } else { - // no value to fetch, use 0. - s_deltaT = 0; - } - ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT); -} - -static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset) -{ - if (isnan(s_deltaT)) { //suggests that the value is not initialized - read_delta_t_from_efuse(); - } - float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0; - return result; -} - -esp_err_t temp_sensor_read_celsius(float *celsius) -{ - ESP_RETURN_ON_FALSE(celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "celsius points to nothing"); - temp_sensor_config_t tsens; - uint32_t tsens_out = 0; - esp_err_t ret = temp_sensor_get_config(&tsens); - if (ret == ESP_OK) { - ret = temp_sensor_read_raw(&tsens_out); - ESP_LOGV(TAG, "tsens_out %d", tsens_out); - ESP_RETURN_ON_FALSE(ret == ESP_OK, ret, TAG, "failed to read raw data"); - const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset]; - *celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset); - if (*celsius < dac->range_min || *celsius > dac->range_max) { - ESP_LOGW(TAG, "Exceeding the temperature range!"); - ret = ESP_ERR_INVALID_STATE; - } - } - return ret; -} diff --git a/components/driver/esp32h2/include/driver/temp_sensor.h b/components/driver/esp32h2/include/driver/temp_sensor.h deleted file mode 100644 index 9e227c71d6..0000000000 --- a/components/driver/esp32h2/include/driver/temp_sensor.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */ - TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */ - TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */ - TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */ - TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */ - TSENS_DAC_MAX, - TSENS_DAC_DEFAULT = TSENS_DAC_L2, -} temp_sensor_dac_offset_t; - -/** - * @brief Configuration for temperature sensor reading - */ -typedef struct { - temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */ - uint8_t clk_div; /*!< Default: 6 */ -} temp_sensor_config_t; - -#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \ - .clk_div = 6} - -/** - * @brief Set parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens); - -/** - * @brief Get parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens); - -/** - * @brief Start temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG - */ -esp_err_t temp_sensor_start(void); - -/** - * @brief Stop temperature sensor measure. - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_stop(void); - -/** - * @brief Read temperature sensor raw data. - * @param tsens_out Pointer to raw data, Range: 0 ~ 255 - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG `tsens_out` is NULL - * - ESP_ERR_INVALID_STATE temperature sensor dont start - */ -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out); - -/** - * @brief Read temperature sensor data that is converted to degrees Celsius. - * @note Should not be called from interrupt. - * @param celsius The measure output value. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG ARG is NULL. - * - ESP_ERR_INVALID_STATE The ambient temperature is out of range. - */ -esp_err_t temp_sensor_read_celsius(float *celsius); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32h2/rtc_tempsensor.c b/components/driver/esp32h2/rtc_tempsensor.c deleted file mode 100644 index e447ebaa99..0000000000 --- a/components/driver/esp32h2/rtc_tempsensor.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "esp_log.h" -#include "esp_check.h" -#include "hal/adc_ll.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/apb_saradc_struct.h" -#include "soc/apb_saradc_reg.h" -#include "soc/system_reg.h" -#include "driver/temp_sensor.h" -#include "regi2c_ctrl.h" -#include "esp32h2/rom/ets_sys.h" -#include "esp_efuse_rtc_calib.h" - -static const char *TAG = "tsens"; - -#define TSENS_XPD_WAIT_DEFAULT 0xFF /* Set wait cycle time(8MHz) from power up to reset enable. */ -#define TSENS_ADC_FACTOR (0.4386) -#define TSENS_DAC_FACTOR (27.88) -#define TSENS_SYS_OFFSET (20.52) - -typedef struct { - int index; - int offset; - int set_val; - int range_min; - int range_max; - int error_max; -} tsens_dac_offset_t; - -static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = { - /* DAC Offset reg_val min max error */ - {TSENS_DAC_L0, -2, 5, 50, 125, 3}, - {TSENS_DAC_L1, -1, 7, 20, 100, 2}, - {TSENS_DAC_L2, 0, 15, -10, 80, 1}, - {TSENS_DAC_L3, 1, 11, -30, 50, 2}, - {TSENS_DAC_L4, 2, 10, -40, 20, 3}, -}; - -typedef enum { - TSENS_HW_STATE_UNCONFIGURED, - TSENS_HW_STATE_CONFIGURED, - TSENS_HW_STATE_STARTED, -} tsens_hw_state_t; - -static tsens_hw_state_t tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED; - -static float s_deltaT = NAN; // unused number - -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens) -{ - if (tsens_hw_state == TSENS_HW_STATE_STARTED) { - ESP_LOGE(TAG, "Do not configure the temp sensor when it's running!"); - return ESP_ERR_INVALID_STATE; - } - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); - REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val); - APB_SARADC.apb_tsens_ctrl.tsens_clk_div = tsens.clk_div; - APB_SARADC.apb_tsens_ctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT; - APB_SARADC.apb_tsens_ctrl2.tsens_xpd_force = 1; - ESP_LOGD(TAG, "Config temperature range [%d°C ~ %d°C], error < %d°C", - dac_offset[tsens.dac_offset].range_min, - dac_offset[tsens.dac_offset].range_max, - dac_offset[tsens.dac_offset].error_max); - tsens_hw_state = TSENS_HW_STATE_CONFIGURED; - return ESP_OK; -} - -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens) -{ - ESP_RETURN_ON_FALSE(tsens != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens specified"); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); - tsens->dac_offset = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); - for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) { - if (tsens->dac_offset == dac_offset[i].set_val) { - tsens->dac_offset = dac_offset[i].index; - break; - } - } - tsens->clk_div = APB_SARADC.apb_tsens_ctrl.tsens_clk_div; - return ESP_OK; -} - -esp_err_t temp_sensor_start(void) -{ - if (tsens_hw_state != TSENS_HW_STATE_CONFIGURED) { - ESP_LOGE(TAG, "Temperature sensor is already running or not be configured"); - return ESP_ERR_INVALID_STATE; - } - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN); - APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 1; - APB_SARADC.apb_tsens_ctrl.tsens_pu = 1; - tsens_hw_state = TSENS_HW_STATE_STARTED; - return ESP_OK; -} - -esp_err_t temp_sensor_stop(void) -{ - APB_SARADC.apb_tsens_ctrl.tsens_pu = 0; - APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 0; - return ESP_OK; -} - -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out) -{ - ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens_out specified"); - *tsens_out = APB_SARADC.apb_tsens_ctrl.tsens_out; - return ESP_OK; -} - -static void read_delta_t_from_efuse(void) -{ - uint32_t version = esp_efuse_rtc_calib_get_ver(); - if (version == 1) { - // fetch calibration value for temp sensor from eFuse - s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version); - } else { - // no value to fetch, use 0. - s_deltaT = 0; - } - ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT); -} - -static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset) -{ - if (isnan(s_deltaT)) { //suggests that the value is not initialized - read_delta_t_from_efuse(); - } - float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0; - return result; -} - -esp_err_t temp_sensor_read_celsius(float *celsius) -{ - ESP_RETURN_ON_FALSE(celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "celsius points to nothing"); - temp_sensor_config_t tsens; - uint32_t tsens_out = 0; - esp_err_t ret = temp_sensor_get_config(&tsens); - if (ret == ESP_OK) { - ret = temp_sensor_read_raw(&tsens_out); - ESP_LOGV(TAG, "tsens_out %d", tsens_out); - ESP_RETURN_ON_FALSE(ret == ESP_OK, ret, TAG, "failed to read raw data"); - const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset]; - *celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset); - if (*celsius < dac->range_min || *celsius > dac->range_max) { - ESP_LOGW(TAG, "Exceeding the temperature range!"); - ret = ESP_ERR_INVALID_STATE; - } - } - return ret; -} diff --git a/components/driver/esp32s2/include/driver/temp_sensor.h b/components/driver/esp32s2/include/driver/temp_sensor.h deleted file mode 100644 index c3a87068b6..0000000000 --- a/components/driver/esp32s2/include/driver/temp_sensor.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief temperature sensor range option. - */ -typedef enum { - TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */ - TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */ - TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */ - TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */ - TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */ - TSENS_DAC_MAX, - TSENS_DAC_DEFAULT = TSENS_DAC_L2, -} temp_sensor_dac_offset_t; - -/** - * @brief Configuration for temperature sensor reading - */ -typedef struct { - temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */ - uint8_t clk_div; /*!< Default: 6 */ -} temp_sensor_config_t; - -/** - * @brief temperature sensor default setting. - */ -#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \ - .clk_div = 6} - -/** - * @brief Set parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens); - -/** - * @brief Get parameter of temperature sensor. - * @param tsens - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens); - -/** - * @brief Start temperature sensor measure. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG - */ -esp_err_t temp_sensor_start(void); - -/** - * @brief Stop temperature sensor measure. - * @return - * - ESP_OK Success - */ -esp_err_t temp_sensor_stop(void); - -/** - * @brief Read temperature sensor raw data. - * @param tsens_out Pointer to raw data, Range: 0 ~ 255 - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG `tsens_out` is NULL - * - ESP_ERR_INVALID_STATE temperature sensor dont start - */ -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out); - -/** - * @brief Read temperature sensor data that is converted to degrees Celsius. - * @note Should not be called from interrupt. - * @param celsius The measure output value. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG ARG is NULL. - * - ESP_ERR_INVALID_STATE The ambient temperature is out of range. - */ -esp_err_t temp_sensor_read_celsius(float *celsius); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32s2/rtc_tempsensor.c b/components/driver/esp32s2/rtc_tempsensor.c deleted file mode 100644 index 7e74817904..0000000000 --- a/components/driver/esp32s2/rtc_tempsensor.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include "esp_types.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "esp_log.h" -#include "esp_check.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/rtc_io_reg.h" -#include "soc/rtc_io_struct.h" -#include "soc/sens_reg.h" -#include "soc/sens_struct.h" -#include "driver/temp_sensor.h" -#include "regi2c_ctrl.h" -#include "esp_log.h" -#include "esp_efuse_rtc_table.h" - -static const char *TAG = "tsens"; - -#define TSENS_XPD_WAIT_DEFAULT 0xFF /* Set wait cycle time(8MHz) from power up to reset enable. */ -#define TSENS_ADC_FACTOR (0.4386) -#define TSENS_DAC_FACTOR (27.88) -#define TSENS_SYS_OFFSET (20.52) - -typedef struct { - int index; - int offset; - int set_val; - int range_min; - int range_max; - int error_max; -} tsens_dac_offset_t; - -static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = { - /* DAC Offset reg_val min max error */ - {TSENS_DAC_L0, -2, 5, 50, 125, 3}, - {TSENS_DAC_L1, -1, 7, 20, 100, 2}, - {TSENS_DAC_L2, 0, 15, -10, 80, 1}, - {TSENS_DAC_L3, 1, 11, -30, 50, 2}, - {TSENS_DAC_L4, 2, 10, -40, 20, 3}, -}; - -typedef enum { - TSENS_HW_STATE_UNCONFIGURED, - TSENS_HW_STATE_CONFIGURED, - TSENS_HW_STATE_STARTED, -} tsens_hw_state_t; - -static tsens_hw_state_t tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED; - -static SemaphoreHandle_t rtc_tsens_mux = NULL; - -static float s_deltaT = NAN; // Unused number - -esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens) -{ - esp_err_t err = ESP_OK; - if (tsens_hw_state == TSENS_HW_STATE_STARTED) { - ESP_LOGE(TAG, "Do not configure the temp sensor when it's running!"); - err = ESP_ERR_INVALID_STATE; - } - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); - SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); - REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val); - SENS.sar_tctrl.tsens_clk_div = tsens.clk_div; - SENS.sar_tctrl.tsens_power_up_force = 1; - SENS.sar_tctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT; - SENS.sar_tctrl2.tsens_xpd_force = 1; - SENS.sar_tctrl2.tsens_reset = 1;// Reset the temp sensor. - SENS.sar_tctrl2.tsens_reset = 0;// Clear the reset status. - ESP_LOGI(TAG, "Config temperature range [%d°C ~ %d°C], error < %d°C", - dac_offset[tsens.dac_offset].range_min, - dac_offset[tsens.dac_offset].range_max, - dac_offset[tsens.dac_offset].error_max); - tsens_hw_state = TSENS_HW_STATE_CONFIGURED; - return err; -} - -esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens) -{ - ESP_RETURN_ON_FALSE(tsens != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens specified"); - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); - SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); - SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); - tsens->dac_offset = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); - for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) { - if ((int)tsens->dac_offset == dac_offset[i].set_val) { - tsens->dac_offset = dac_offset[i].index; - break; - } - } - tsens->clk_div = SENS.sar_tctrl.tsens_clk_div; - return ESP_OK; -} - -esp_err_t temp_sensor_start(void) -{ - esp_err_t err = ESP_OK; - if (tsens_hw_state != TSENS_HW_STATE_CONFIGURED) { - ESP_LOGE(TAG, "Temperature sensor is already running or not be configured"); - err = ESP_ERR_INVALID_STATE; - } - if (rtc_tsens_mux == NULL) { - rtc_tsens_mux = xSemaphoreCreateMutex(); - } - ESP_RETURN_ON_FALSE(rtc_tsens_mux != NULL, ESP_ERR_NO_MEM, TAG, "failed to create mutex"); - SENS.sar_tctrl.tsens_dump_out = 0; - SENS.sar_tctrl2.tsens_clkgate_en = 1; - SENS.sar_tctrl.tsens_power_up = 1; - tsens_hw_state = TSENS_HW_STATE_STARTED; - return err; -} - -esp_err_t temp_sensor_stop(void) -{ - SENS.sar_tctrl.tsens_power_up = 0; - SENS.sar_tctrl2.tsens_clkgate_en = 0; - if (rtc_tsens_mux != NULL) { - vSemaphoreDelete(rtc_tsens_mux); - rtc_tsens_mux = NULL; - } - return ESP_OK; -} - -esp_err_t temp_sensor_read_raw(uint32_t *tsens_out) -{ - ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens_out specified"); - ESP_RETURN_ON_FALSE(rtc_tsens_mux != NULL, ESP_ERR_INVALID_STATE, TAG, "mutex not ready"); - xSemaphoreTake(rtc_tsens_mux, portMAX_DELAY); - SENS.sar_tctrl.tsens_dump_out = 1; - while (!SENS.sar_tctrl.tsens_ready); - *tsens_out = SENS.sar_tctrl.tsens_out; - SENS.sar_tctrl.tsens_dump_out = 0; - xSemaphoreGive(rtc_tsens_mux); - return ESP_OK; -} - -static void read_delta_t_from_efuse(void) -{ - uint32_t version = esp_efuse_rtc_table_read_calib_version(); - if (version == 1 || version == 2) { - // fetch calibration value for temp sensor from eFuse - s_deltaT = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false) / 10.0; - } else { - // no value to fetch, use 0. - s_deltaT = 0; - } - ESP_LOGD(TAG, "s_deltaT = %f\n", s_deltaT); -} - -static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset) -{ - if (isnan(s_deltaT)) { //suggests that the value is not initialized - read_delta_t_from_efuse(); - } - float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT; - return result; -} - -esp_err_t temp_sensor_read_celsius(float *celsius) -{ - ESP_RETURN_ON_FALSE(celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "celsius points to nothing"); - temp_sensor_config_t tsens; - uint32_t tsens_out = 0; - esp_err_t ret = temp_sensor_get_config(&tsens); - if (ret == ESP_OK) { - ret = temp_sensor_read_raw(&tsens_out); - ESP_RETURN_ON_FALSE(ret == ESP_OK, ret, TAG, "failed to read raw data"); - const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset]; - *celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset); - if (*celsius < dac->range_min || *celsius > dac->range_max) { - ESP_LOGW(TAG, "Exceeding the temperature range!"); - ret = ESP_ERR_INVALID_STATE; - } - } - return ret; -} diff --git a/components/driver/include/driver/temperature_sensor.h b/components/driver/include/driver/temperature_sensor.h new file mode 100644 index 0000000000..fee0f2bb36 --- /dev/null +++ b/components/driver/include/driver/temperature_sensor.h @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "hal/temperature_sensor_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type of temperature sensor driver handle + */ +typedef struct temperature_sensor_obj_t *temperature_sensor_handle_t; + +/** + * @brief Configuration of measurement range for the temperature sensor. + * + * @note If you see the log `the boundary you gave cannot meet the range of internal temperature sensor`. You may need to refer to + * predefined range listed doc ``api-reference/peripherals/Temperature sensor``. + */ +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. +} temperature_sensor_config_t; + +#define TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(min, max) {.range_min = min, \ + .range_max = max, \ + } + +/** + * @brief Install temperature sensor driver + * + * @param tsens_config Pointer to config structure. + * @param ret_tsens Return the pointer of temperature sensor handle. + * @return + * - ESP_OK if succeed + */ +esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens); + +/** + * @brief Uninstall the temperature sensor driver + * + * @param tsens The handle created by `temperature_sensor_install()`. + * @return + * - ESP_OK if succeed. + */ +esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens); + +/** + * @brief Start temperature measurement. + * + * @param tsens The handle created by `temperature_sensor_install()`. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE if temperature sensor is started already. + */ +esp_err_t temperature_sensor_start(temperature_sensor_handle_t tsens); + +/** + * @brief Stop temperature sensor measure. + * + * @param tsens The handle created by `temperature_sensor_install()`. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE if temperature sensor is stopped already. + */ +esp_err_t temperature_sensor_stop(temperature_sensor_handle_t tsens); + +/** + * @brief Read temperature sensor data that is converted to degrees Celsius. + * @note Should not be called from interrupt. + * + * @param tsens The handle created by `temperature_sensor_install()`. + * @param out_celsius The measure output value. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG ARG is NULL. + * - ESP_ERR_INVALID_STATE The ambient temperature is out of range. + */ +esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/temperature_sensor.c b/components/driver/temperature_sensor.c new file mode 100644 index 0000000000..dad90224c1 --- /dev/null +++ b/components/driver/temperature_sensor.c @@ -0,0 +1,200 @@ +/* + * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for this source file +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif + +#include +#include +#include +#include "esp_log.h" +#include "sys/lock.h" +#include "soc/rtc.h" +#include "esp_check.h" +#include "esp_types.h" +#include "esp_heap_caps.h" +#include "clk_ctrl_os.h" +#include "freertos/FreeRTOS.h" +#include "driver/temperature_sensor.h" +#include "esp_efuse_rtc_calib.h" +#include "esp_private/periph_ctrl.h" +#include "hal/temperature_sensor_types.h" +#include "hal/temperature_sensor_ll.h" + +static const char *TAG = "temperature_sensor"; + +extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. +#define TEMPERATURE_SENSOR_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) +#define TEMPERATURE_SENSOR_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) + +typedef enum { + TSENS_HW_STATE_UNCONFIGURED, + TSENS_HW_STATE_CONFIGURED, + TSENS_HW_STATE_STARTED, +} temp_sensor_state_t; + +static float s_deltaT = NAN; // unused number + +typedef struct temperature_sensor_obj_t temperature_sensor_obj_t; + +struct temperature_sensor_obj_t { + const temp_sensor_ll_attribute_t *tsens_attribute; + temp_sensor_state_t tsens_hw_state; + temperature_sensor_clk_src_t clk_src; +}; + +static temp_sensor_ll_attribute_t *s_tsens_attribute_copy; + +static int inline accuracy_compare(const void *p1, const void *p2) +{ + return ((*(temp_sensor_ll_attribute_t*)p1).error_max < (*(temp_sensor_ll_attribute_t*)p2).error_max) ? -1 : 1; +} + +static esp_err_t temperature_sensor_attribute_table_sort(void) +{ + s_tsens_attribute_copy = (temp_sensor_ll_attribute_t*)heap_caps_malloc(sizeof(temp_sensor_ll_attributes), MALLOC_CAP_DEFAULT); + ESP_RETURN_ON_FALSE(s_tsens_attribute_copy != NULL, ESP_ERR_NO_MEM, TAG, "No space for s_tsens_attribute_copy"); + for (int i = 0 ; i < TEMPERATURE_SENSOR_LL_RANGE_NUM; i++) { + s_tsens_attribute_copy[i] = temp_sensor_ll_attributes[i]; + } + // Sort from small to large by error_max. + qsort(s_tsens_attribute_copy, TEMPERATURE_SENSOR_LL_RANGE_NUM, sizeof(s_tsens_attribute_copy[0]), accuracy_compare); + return ESP_OK; +} + +static esp_err_t temperature_sensor_choose_best_range(temperature_sensor_handle_t tsens, const temperature_sensor_config_t *tsens_config) +{ + for (int i = 0 ; i < TEMPERATURE_SENSOR_LL_RANGE_NUM; i++) { + if ((tsens_config->range_min >= s_tsens_attribute_copy[i].range_min) && (tsens_config->range_max <= s_tsens_attribute_copy[i].range_max)) { + tsens->tsens_attribute = &s_tsens_attribute_copy[i]; + break; + } + } + ESP_RETURN_ON_FALSE(tsens->tsens_attribute != NULL, ESP_ERR_INVALID_ARG, TAG, "Out of testing range"); + return ESP_OK; +} + +esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens) +{ + esp_err_t ret = ESP_OK; +#if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG + esp_log_level_set(TAG, ESP_LOG_DEBUG); +#endif + ESP_RETURN_ON_FALSE((tsens_config && ret_tsens), ESP_ERR_INVALID_ARG, TAG, "Invalid argument"); + ESP_RETURN_ON_FALSE((s_tsens_attribute_copy == NULL), ESP_ERR_INVALID_STATE, TAG, "Already installed"); + temperature_sensor_handle_t tsens; + tsens = (temperature_sensor_obj_t*) heap_caps_calloc(1, sizeof(temperature_sensor_obj_t), MALLOC_CAP_DEFAULT); + ESP_GOTO_ON_FALSE(tsens != NULL, ESP_ERR_NO_MEM, err, TAG, "install fail..."); + tsens->clk_src = tsens_config->clk_src; + + periph_module_enable(PERIPH_TEMPSENSOR_MODULE); + periph_module_reset(PERIPH_TEMPSENSOR_MODULE); + ESP_GOTO_ON_ERROR(temperature_sensor_attribute_table_sort(), err, TAG, "Table sort failed"); + ESP_GOTO_ON_ERROR(temperature_sensor_choose_best_range(tsens, tsens_config), err, TAG, "Cannot select the correct range"); + + ESP_LOGI(TAG, "Range [%d°C ~ %d°C], error < %d°C", + tsens->tsens_attribute->range_min, + tsens->tsens_attribute->range_max, + tsens->tsens_attribute->error_max); + TEMPERATURE_SENSOR_ENTER_CRITICAL(); + temperature_sensor_ll_set_range(tsens->tsens_attribute->reg_val); + TEMPERATURE_SENSOR_EXIT_CRITICAL(); + tsens->tsens_hw_state = TSENS_HW_STATE_CONFIGURED; + *ret_tsens = tsens; + return ESP_OK; +err: + temperature_sensor_uninstall(tsens); + return ret; +} + +esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens) +{ + ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has already been uninstalled"); + ESP_RETURN_ON_FALSE(tsens->tsens_hw_state != TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_STATE, TAG, "Has not been stopped"); + if (s_tsens_attribute_copy) { + free(s_tsens_attribute_copy); + } + s_tsens_attribute_copy = NULL; + tsens->tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED; + heap_caps_free(tsens); + tsens = NULL; + return ESP_OK; +} + +esp_err_t temperature_sensor_start(temperature_sensor_handle_t tsens) +{ + ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has not been installed"); + ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_CONFIGURED, ESP_ERR_INVALID_STATE, TAG, "Is already running or has not been configured"); +#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_FAST_RC) { + periph_rtc_dig_clk8m_enable(); + } +#endif + temperature_sensor_ll_clk_enable(true); + temperature_sensor_ll_clk_sel(tsens->clk_src); + temperature_sensor_ll_enable(true); + tsens->tsens_hw_state = TSENS_HW_STATE_STARTED; + return ESP_OK; +} + +esp_err_t temperature_sensor_stop(temperature_sensor_handle_t tsens) +{ + ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_STATE, TAG, "Has not been started"); + temperature_sensor_ll_enable(false); +#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_FAST_RC) { + periph_rtc_dig_clk8m_disable(); + } +#endif + periph_module_disable(PERIPH_TEMPSENSOR_MODULE); + tsens->tsens_hw_state = TSENS_HW_STATE_CONFIGURED; + return ESP_OK; +} + +static esp_err_t temp_sensor_read_raw(uint32_t *tsens_out) +{ + ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "No tsens_out specified"); + *tsens_out = temperature_sensor_ll_get_raw_value(); + return ESP_OK; +} + +static esp_err_t read_delta_t_from_efuse(void) +{ + if (esp_efuse_rtc_calib_get_tsens_val(&s_deltaT) != ESP_OK) { + ESP_LOGW(TAG, "Calibration failed"); + } + ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT); + return ESP_OK; +} + +static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset) +{ + if (isnan(s_deltaT)) { //suggests that the value is not initialized + read_delta_t_from_efuse(); + } + float result = (TEMPERATURE_SENSOR_LL_ADC_FACTOR * (float)tsens_raw - TEMPERATURE_SENSOR_LL_DAC_FACTOR * dac_offset - TEMPERATURE_SENSOR_LL_OFFSET_FACTOR) - s_deltaT / 10.0; + return result; +} + +esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius) +{ + ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Has not been installed"); + ESP_RETURN_ON_FALSE(out_celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "Celsius points to nothing"); + ESP_RETURN_ON_FALSE(tsens->tsens_hw_state == TSENS_HW_STATE_STARTED, ESP_ERR_INVALID_ARG, TAG, "Has not been started"); + uint32_t tsens_out = 0; + temp_sensor_read_raw(&tsens_out); + ESP_LOGV(TAG, "tsens_out %d", tsens_out); + *out_celsius = parse_temp_sensor_raw_value(tsens_out, tsens->tsens_attribute->offset); + if (*out_celsius < tsens->tsens_attribute->range_min || *out_celsius > tsens->tsens_attribute->range_max) { + ESP_LOGW(TAG, "Temperature range exceeded!"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} diff --git a/components/driver/test_apps/temperature_sensor/CMakeLists.txt b/components/driver/test_apps/temperature_sensor/CMakeLists.txt new file mode 100644 index 0000000000..bc01ce7841 --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/CMakeLists.txt @@ -0,0 +1,5 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(test_app_include_temperature_sensor) diff --git a/components/driver/test_apps/temperature_sensor/README.md b/components/driver/test_apps/temperature_sensor/README.md new file mode 100644 index 0000000000..0dfa474720 --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/temperature_sensor/main/CMakeLists.txt b/components/driver/test_apps/temperature_sensor/main/CMakeLists.txt new file mode 100644 index 0000000000..2bffac2c61 --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(srcs "test_app_main.c" + "test_temperature_sensor.c") + +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES driver unity) + +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_temperature_sensor") diff --git a/components/driver/test_apps/temperature_sensor/main/test_app_main.c b/components/driver/test_apps/temperature_sensor/main/test_app_main.c new file mode 100644 index 0000000000..183a88ae3c --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/main/test_app_main.c @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" + +#define TEST_MEMORY_LEAK_THRESHOLD (-600) + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/driver/test_apps/temperature_sensor/main/test_temperature_sensor.c b/components/driver/test_apps/temperature_sensor/main/test_temperature_sensor.c new file mode 100644 index 0000000000..49aae23336 --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/main/test_temperature_sensor.c @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_log.h" +#include "unity.h" +#include "driver/temperature_sensor.h" + +void test_app_include_temperature_sensor(void) +{ +} + +TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]") +{ + printf("Initializing Temperature sensor\n"); + float tsens_out; + temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_start(temp_handle)); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temperature_sensor_stop(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); + // Reconfig the temperature sensor. + temp_sensor.range_min = -20; + temp_sensor.range_max = 45; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_start(temp_handle)); + printf("Temperature sensor started again\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temperature_sensor_stop(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} + +TEST_CASE("Double install error cause test", "[temperature_sensor]") +{ + printf("Initializing Temperature sensor\n"); + temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} + +TEST_CASE("Double start error cause test", "[temperatere_sensor]") +{ + printf("Initializing Temperature sensor\n"); + temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_start(temp_handle)); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temperature_sensor_start(temp_handle)); + TEST_ESP_OK(temperature_sensor_stop(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} + +TEST_CASE("Double Start-Stop test", "[temperature_sensor]") +{ + printf("Initializing Temperature sensor\n"); + float tsens_out; + temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_start(temp_handle)); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temperature_sensor_stop(temp_handle)); + TEST_ESP_OK(temperature_sensor_start(temp_handle)); + printf("Temperature sensor started again\n"); + TEST_ESP_OK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temperature_sensor_stop(temp_handle)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); +} diff --git a/components/driver/test_apps/temperature_sensor/pytest_temperature_sensor.py b/components/driver/test_apps/temperature_sensor/pytest_temperature_sensor.py new file mode 100644 index 0000000000..9ad33be12f --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/pytest_temperature_sensor.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize('config', [ + 'release', +], indirect=True) +def test_temperature_sensor_driver(dut: Dut) -> None: + dut.expect('Press ENTER to see the list of tests') + dut.write('*') + dut.expect_unity_test_output(timeout=120) diff --git a/components/driver/test_apps/temperature_sensor/sdkconfig.ci.release b/components/driver/test_apps/temperature_sensor/sdkconfig.ci.release new file mode 100644 index 0000000000..91d93f163e --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/sdkconfig.ci.release @@ -0,0 +1,5 @@ +CONFIG_PM_ENABLE=y +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/driver/test_apps/temperature_sensor/sdkconfig.defaults b/components/driver/test_apps/temperature_sensor/sdkconfig.defaults new file mode 100644 index 0000000000..a1f2ef6f8b --- /dev/null +++ b/components/driver/test_apps/temperature_sensor/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_TASK_WDT=n diff --git a/components/efuse/esp32c3/esp_efuse_rtc_calib.c b/components/efuse/esp32c3/esp_efuse_rtc_calib.c index dc02072e4e..b6db18ad06 100644 --- a/components/efuse/esp32c3/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32c3/esp_efuse_rtc_calib.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -73,9 +73,13 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* return ESP_OK; } -float esp_efuse_rtc_calib_get_cal_temp(int version) +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal) { - assert(version == 1); + uint32_t version = esp_efuse_rtc_calib_get_ver(); + if (version != 1) { + *tsens_cal = 0.0; + return ESP_ERR_NOT_SUPPORTED; + } const esp_efuse_desc_t** cal_temp_efuse; cal_temp_efuse = ESP_EFUSE_TEMP_CALIB; int cal_temp_size = esp_efuse_get_field_size(cal_temp_efuse); @@ -86,5 +90,6 @@ float esp_efuse_rtc_calib_get_cal_temp(int version) assert(err == ESP_OK); (void)err; // BIT(8) stands for sign: 1: negtive, 0: positive - return ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp; + *tsens_cal = ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp; + return ESP_OK; } diff --git a/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h index d7bb47f644..40e7ad0330 100644 --- a/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h +++ b/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,11 +47,12 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* /** * @brief Get the temperature sensor calibration number delta_T stored in the efuse. * - * @param version Version of the stored efuse + * @param tsens_cal Pointer of the specification of temperature sensor calibration number in efuse. * - * @return The specification of temperature sensor calibration number in efuse. + * @return ESP_OK if get the calibration value successfully. + * ESP_ERR_INVALID_ARG if can't get the calibration value. */ -float esp_efuse_rtc_calib_get_cal_temp(int version); +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal); #ifdef __cplusplus } diff --git a/components/efuse/esp32h2/esp_efuse_rtc_calib.c b/components/efuse/esp32h2/esp_efuse_rtc_calib.c index 52e4167363..5bfd20b019 100644 --- a/components/efuse/esp32h2/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32h2/esp_efuse_rtc_calib.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -72,9 +72,13 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* return ESP_OK; } -float esp_efuse_rtc_calib_get_cal_temp(int version) +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal) { - assert(version == 1); + uint32_t version = esp_efuse_rtc_calib_get_ver(); + if (version != 1) { + *tsens_cal = 0.0; + return ESP_ERR_NOT_SUPPORTED; + } const esp_efuse_desc_t** cal_temp_efuse; cal_temp_efuse = ESP_EFUSE_TEMP_CALIB; int cal_temp_size = esp_efuse_get_field_size(cal_temp_efuse); @@ -85,5 +89,6 @@ float esp_efuse_rtc_calib_get_cal_temp(int version) assert(err == ESP_OK); (void)err; // BIT(8) stands for sign: 1: negtive, 0: positive - return ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp; + *tsens_cal = ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp; + return ESP_OK; } diff --git a/components/efuse/esp32h2/include/esp_efuse_rtc_calib.h b/components/efuse/esp32h2/include/esp_efuse_rtc_calib.h index 0e059c4f3f..e495669710 100644 --- a/components/efuse/esp32h2/include/esp_efuse_rtc_calib.h +++ b/components/efuse/esp32h2/include/esp_efuse_rtc_calib.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,11 +43,12 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* /** * @brief Get the temperature sensor calibration number delta_T stored in the efuse. * - * @param version Version of the stored efuse + * @param tsens_cal Pointer of the specification of temperature sensor calibration number in efuse. * - * @return The specification of temperature sensor calibration number in efuse. + * @return ESP_OK if get the calibration value successfully. + * ESP_ERR_INVALID_ARG if can't get the calibration value. */ -float esp_efuse_rtc_calib_get_cal_temp(int version); +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal); #ifdef __cplusplus } diff --git a/components/efuse/esp32s2/esp_efuse_rtc_calib.c b/components/efuse/esp32s2/esp_efuse_rtc_calib.c new file mode 100644 index 0000000000..40202ecfba --- /dev/null +++ b/components/efuse/esp32s2/esp_efuse_rtc_calib.c @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_bit_defs.h" +#include "esp_efuse.h" +#include "esp_efuse_rtc_table.h" + +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal) +{ + uint32_t version = esp_efuse_rtc_table_read_calib_version(); + if ((version != 1) && (version != 2)) { + *tsens_cal = 0.0; + return ESP_ERR_NOT_SUPPORTED; + } + *tsens_cal = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false); + + return ESP_OK; +} diff --git a/components/efuse/esp32s2/include/esp_efuse_rtc_calib.h b/components/efuse/esp32s2/include/esp_efuse_rtc_calib.h new file mode 100644 index 0000000000..c6393e5959 --- /dev/null +++ b/components/efuse/esp32s2/include/esp_efuse_rtc_calib.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_types.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Get the temperature sensor calibration number delta_T stored in the efuse. + * + * @param tsens_cal Pointer of the specification of temperature sensor calibration number in efuse. + * + * @return ESP_OK if get the calibration value successfully. + * ESP_ERR_INVALID_ARG if can't get the calibration value. + */ +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal); + +#ifdef __cplusplus +} +#endif diff --git a/components/efuse/esp32s2/sources.cmake b/components/efuse/esp32s2/sources.cmake index a498623c4f..cd0ea6f9a6 100644 --- a/components/efuse/esp32s2/sources.cmake +++ b/components/efuse/esp32s2/sources.cmake @@ -1,4 +1,5 @@ set(EFUSE_SOC_SRCS "esp_efuse_table.c" "esp_efuse_fields.c" "esp_efuse_rtc_table.c" + "esp_efuse_rtc_calib.c" "esp_efuse_utility.c") diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index f7382650d5..20377e24d4 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -80,6 +72,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return SYSTEM_BT_BASEBAND_EN; case PERIPH_BT_LC_MODULE: return SYSTEM_BT_LC_EN; + case PERIPH_TEMPSENSOR_MODULE: + return SYSTEM_TSENS_CLK_EN; default: return 0; } @@ -123,6 +117,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return SYSTEM_TWAI_RST; case PERIPH_HMAC_MODULE: return SYSTEM_CRYPTO_HMAC_RST; + case PERIPH_TEMPSENSOR_MODULE: + return SYSTEM_TSENS_RST; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset also. @@ -171,6 +167,7 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) case PERIPH_RSA_MODULE: case PERIPH_SHA_MODULE: case PERIPH_GDMA_MODULE: + case PERIPH_TEMPSENSOR_MODULE: return SYSTEM_PERIP_CLK_EN1_REG; default: return SYSTEM_PERIP_CLK_EN0_REG; @@ -194,6 +191,7 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_RSA_MODULE: case PERIPH_SHA_MODULE: case PERIPH_GDMA_MODULE: + case PERIPH_TEMPSENSOR_MODULE: return SYSTEM_PERIP_RST_EN1_REG; default: return SYSTEM_PERIP_RST_EN0_REG; diff --git a/components/hal/esp32c3/include/hal/temperature_sensor_ll.h b/components/hal/esp32c3/include/hal/temperature_sensor_ll.h new file mode 100644 index 0000000000..3d21f05557 --- /dev/null +++ b/components/hal/esp32c3/include/hal/temperature_sensor_ll.h @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in component/hal/readme.md + ******************************************************************************/ + +// The LL for temperature sensor + +#pragma once + +#include +#include +#include "regi2c_ctrl.h" +#include "soc/apb_saradc_struct.h" +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "hal/temperature_sensor_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define TEMPERATURE_SENSOR_LL_ADC_FACTOR (0.4386) +#define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88) +#define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52) + +#define TEMPERATURE_SENSOR_LL_RANGE_NUM (5) + +typedef struct { + int offset; + int reg_val; + int range_min; + int range_max; + int error_max; +} temp_sensor_ll_attribute_t; + +static const temp_sensor_ll_attribute_t temp_sensor_ll_attributes[TEMPERATURE_SENSOR_LL_RANGE_NUM] = { + /*Offset, reg_val, min, max, error */ + { -2, 5, 50, 125, 3}, + { -1, 7, 20, 100, 2}, + { 0, 15, -10, 80, 1}, + { 1, 11, -30, 50, 2}, + { 2, 10, -40, 20, 3}, +}; + +/** + * @brief Enable the temperature sensor power. + * + * @param enable true: enable the power. + */ +static inline void temperature_sensor_ll_enable(bool enable) +{ + APB_SARADC.apb_tsens_ctrl.tsens_pu = enable; +} + +/** + * @brief Enable the clock + */ +static inline void temperature_sensor_ll_clk_enable(bool enable) +{ + // No need to enable the temperature clock on esp32c3 +} + +/** + * @brief Select the clock source for temperature sensor. On ESP32-C3, temperautre sensor + * can use XTAL or FOSC. To make it convenience, suggest using XTAL all the time. + * + * @param clk_src refer to ``temperature_sensor_clk_src_t`` + */ +static inline void temperature_sensor_ll_clk_sel(temperature_sensor_clk_src_t clk_src) +{ + uint8_t clk_sel = 0; + switch (clk_src) { + case TEMPERATURE_SENSOR_CLK_SRC_DEFAULT: + case TEMPERATURE_SENSOR_CLK_SRC_XTAL: + clk_sel = 1; + break; + case TEMPERATURE_SENSOR_CLK_SRC_FAST_RC: + clk_sel = 0; + break; + default: + abort(); + break; + } + APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = clk_sel; +} + +/** + * @brief Set the hardware range, you can refer to the table ``temp_sensor_ll_attributes`` + * + * @param tsens_dac ``reg_val`` in table ``temp_sensor_ll_attributes`` + */ +static inline void temperature_sensor_ll_set_range(uint32_t range) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); + REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, range); +} + +/** + * @brief Get the raw value of temperature sensor. + * + * @return uint32_t raw_value + */ +static inline uint32_t temperature_sensor_ll_get_raw_value(void) +{ + return APB_SARADC.apb_tsens_ctrl.tsens_out; +} + +/** + * @brief Get the offset value of temperature sensor. + * + * @note This function is only used in legacy driver + * + * @return uint32_t offset value + */ +static inline uint32_t temperature_sensor_ll_get_offset(void) +{ + return REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); +} + +/** + * @brief Get the clock division factor value. + * + * @note This function is only used in legacy driver + * + * @return uint32_t clock division factor + */ +static inline uint32_t temperature_sensor_ll_get_clk_div(void) +{ + return APB_SARADC.apb_tsens_ctrl.tsens_clk_div; +} + +/** + * @brief Set the clock division factor value, actually this has no impact on temperature sensor. + * Suggest just keep it as default value 6. + * + * @note This function is only used in legacy driver + * + * @param clk_div clock division factor, range from 1-10 + */ +static inline void temperature_sensor_ll_set_clk_div(uint8_t clk_div) +{ + APB_SARADC.apb_tsens_ctrl.tsens_clk_div = clk_div; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index adfa13261d..e9255bc9b9 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -68,6 +60,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return SYSTEM_CRYPTO_HMAC_CLK_EN; case PERIPH_DS_MODULE: return SYSTEM_CRYPTO_DS_CLK_EN; + case PERIPH_TEMPSENSOR_MODULE: + return SYSTEM_TSENS_CLK_EN; default: return 0; } @@ -111,6 +105,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return SYSTEM_TWAI_RST; case PERIPH_HMAC_MODULE: return SYSTEM_CRYPTO_HMAC_RST; + case PERIPH_TEMPSENSOR_MODULE: + return SYSTEM_TSENS_RST; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset also. @@ -151,6 +147,7 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) case PERIPH_RSA_MODULE: case PERIPH_SHA_MODULE: case PERIPH_GDMA_MODULE: + case PERIPH_TEMPSENSOR_MODULE: return SYSTEM_PERIP_CLK_EN1_REG; default: return SYSTEM_PERIP_CLK_EN0_REG; @@ -166,6 +163,7 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_RSA_MODULE: case PERIPH_SHA_MODULE: case PERIPH_GDMA_MODULE: + case PERIPH_TEMPSENSOR_MODULE: return SYSTEM_PERIP_RST_EN1_REG; default: return SYSTEM_PERIP_RST_EN0_REG; diff --git a/components/hal/esp32h2/include/hal/temperature_sensor_ll.h b/components/hal/esp32h2/include/hal/temperature_sensor_ll.h new file mode 100644 index 0000000000..64061adced --- /dev/null +++ b/components/hal/esp32h2/include/hal/temperature_sensor_ll.h @@ -0,0 +1,155 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in component/hal/readme.md + ******************************************************************************/ + +// The LL for temperature sensor + +#pragma once + +#include +#include +#include "regi2c_ctrl.h" +#include "soc/apb_saradc_struct.h" +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "hal/temperature_sensor_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TEMPERATURE_SENSOR_LL_ADC_FACTOR (0.4386) +#define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88) +#define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52) + +#define TEMPERATURE_SENSOR_LL_RANGE_NUM (5) + +typedef struct { + int offset; + int reg_val; + int range_min; + int range_max; + int error_max; +} temp_sensor_ll_attribute_t; + +static const temp_sensor_ll_attribute_t temp_sensor_ll_attributes[TEMPERATURE_SENSOR_LL_RANGE_NUM] = { + /*Offset, reg_val, min, max, error */ + { -2, 5, 50, 125, 3}, + { -1, 7, 20, 100, 2}, + { 0, 15, -10, 80, 1}, + { 1, 11, -30, 50, 2}, + { 2, 10, -40, 20, 3}, +}; + +/** + * @brief Enable the temperature sensor power. + * + * @param enable true: enable the power. + */ +static inline void temperature_sensor_ll_enable(bool enable) +{ + APB_SARADC.apb_tsens_ctrl.tsens_pu = enable; +} + +/** + * @brief Enable the clock + */ +static inline void temperature_sensor_ll_clk_enable(bool enable) +{ + // No need to enable the temperature clock on esp32h2 +} + +/** + * @brief Select the clock source for temperature sensor. On ESP32-H2, temperature sensor + * can use XTAL or FOSC. To make it convenience, suggest using XTAL all the time. + * + * @param clk_src refer to ``temperature_sensor_clk_src_t`` + */ +static inline void temperature_sensor_ll_clk_sel(temperature_sensor_clk_src_t clk_src) +{ + uint8_t clk_sel = 0; + switch (clk_src) { + case TEMPERATURE_SENSOR_CLK_SRC_DEFAULT: + case TEMPERATURE_SENSOR_CLK_SRC_XTAL: + clk_sel = 1; + break; + case TEMPERATURE_SENSOR_CLK_SRC_FAST_RC: + clk_sel = 0; + break; + default: + abort(); + break; + } + APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = clk_sel; +} + +/** + * @brief Set the hardware range, you can refer to the table ``temp_sensor_ll_attributes`` + * + * @param tsens_dac ``reg_val`` in table ``temp_sensor_ll_attributes`` + */ +static inline void temperature_sensor_ll_set_range(uint32_t range) +{ + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU); + REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, range); +} + +/** + * @brief Get the raw value of temperature sensor. + * + * @return uint32_t raw_value + */ +static inline uint32_t temperature_sensor_ll_get_raw_value(void) +{ + return APB_SARADC.apb_tsens_ctrl.tsens_out; +} + +/** + * @brief Get the offset value of temperature sensor. + * + * @note This function is only used in legacy driver + * + * @return uint32_t offset value + */ +static inline uint32_t temperature_sensor_ll_get_offset(void) +{ + return REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); +} + +/** + * @brief Get the clock division factor value. + * + * @note This function is only used in legacy driver + * + * @return uint32_t clock division factor + */ +static inline uint32_t temperature_sensor_ll_get_clk_div(void) +{ + return APB_SARADC.apb_tsens_ctrl.tsens_clk_div; +} + +/** + * @brief Set the clock division factor value, actually this has no impact on temperature sensor. + * Suggest just keep it as default value 6. + * + * @note This function is only used in legacy driver + * + * @param clk_div clock division factor, range from 1-10 + */ +static inline void temperature_sensor_ll_set_clk_div(uint8_t clk_div) +{ + APB_SARADC.apb_tsens_ctrl.tsens_clk_div = clk_div; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/temperature_sensor_ll.h b/components/hal/esp32s2/include/hal/temperature_sensor_ll.h new file mode 100644 index 0000000000..223bdc4bde --- /dev/null +++ b/components/hal/esp32s2/include/hal/temperature_sensor_ll.h @@ -0,0 +1,147 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in component/hal/readme.md + ******************************************************************************/ + +// The LL for temperature sensor + +#pragma once + +#include +#include "regi2c_ctrl.h" +#include "soc/apb_saradc_struct.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_struct.h" +#include "hal/temperature_sensor_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TEMPERATURE_SENSOR_LL_ADC_FACTOR (0.4386) +#define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88) +#define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52) + +#define TEMPERATURE_SENSOR_LL_RANGE_NUM (5) + +typedef struct { + int offset; + int reg_val; + int range_min; + int range_max; + int error_max; +} temp_sensor_ll_attribute_t; + +static const temp_sensor_ll_attribute_t temp_sensor_ll_attributes[TEMPERATURE_SENSOR_LL_RANGE_NUM] = { + /*Offset, reg_val, min, max, error */ + { -2, 5, 50, 125, 3}, + { -1, 7, 20, 100, 2}, + { 0, 15, -10, 80, 1}, + { 1, 11, -30, 50, 2}, + { 2, 10, -40, 20, 3}, +}; + +/** + * @brief Enable the temperature sensor power. + * + * @param enable true: enable the power. + */ +static inline void temperature_sensor_ll_enable(bool enable) +{ + SENS.sar_tctrl.tsens_power_up_force = enable; + SENS.sar_tctrl2.tsens_xpd_force = enable; + SENS.sar_tctrl.tsens_power_up = enable; +} + +/** + * @brief Enable the clock + */ +static inline void temperature_sensor_ll_clk_enable(bool enable) +{ + SENS.sar_tctrl2.tsens_clkgate_en = enable; +} + +/** + * @brief Choose the clock. No need to choose the clock source on ESP32-S2. ESP32-S2 + * can use RTC clock. + */ +static inline void temperature_sensor_ll_clk_sel(temperature_sensor_clk_src_t clk_src) +{ + // No need to select the temperature sensor clock on esp32s2. +} + +/** + * @brief Set the hardware range, you can refer to the table ``temp_sensor_ll_attributes`` + * + * @param tsens_dac ``reg_val`` in table ``temp_sensor_ll_attributes`` + */ +static inline void temperature_sensor_ll_set_range(uint32_t tsens_dac) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M); + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); + REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, tsens_dac); +} + +/** + * @brief Get the raw value of temperature sensor. + * + * @return uint32_t raw_value + */ +static inline uint32_t temperature_sensor_ll_get_raw_value(void) +{ + SENS.sar_tctrl.tsens_dump_out = 1; + while (!SENS.sar_tctrl.tsens_ready) { + } + SENS.sar_tctrl.tsens_dump_out = 0; + return SENS.sar_tctrl.tsens_out; +} + +/** + * @brief Get the offset value of temperature sensor. + * + * @note This function is only used in legacy driver + * + * @return uint32_t offset value + */ +static inline uint32_t temperature_sensor_ll_get_offset(void) +{ + return REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC); +} + +/** + * @brief Get the clock division factor value. + * + * @note This function is only used in legacy driver + * + * @return uint32_t clock division factor + */ +static inline uint32_t temperature_sensor_ll_get_clk_div(void) +{ + return SENS.sar_tctrl.tsens_clk_div; +} + +/** + * @brief Set the clock division factor value, actually this has no impact on temperature sensor. + * Suggest just keep it as default value 6. + * + * @note This function is only used in legacy driver + * + * @param clk_div clock division factor, range from 1-10 + */ +static inline void temperature_sensor_ll_set_clk_div(uint8_t clk_div) +{ + SENS.sar_tctrl.tsens_clk_div = clk_div; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/temperature_sensor_types.h b/components/hal/include/hal/temperature_sensor_types.h new file mode 100644 index 0000000000..6c8b8e1f3d --- /dev/null +++ b/components/hal/include/hal/temperature_sensor_types.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief temperature sensor clock source + * @note User should select the clock source based on the real requirement: + * @verbatim embed:rst:leading-asterisk + * +------------------------------------+-------------------------+----------------------------+ + * | temperature sensor clock source | Features | Power Management | + * +====================================+=========================+============================+ + * | TEMPERATURE_SENSOR_CLK_SRC_XTAL | external clock source | no lock | + * +------------------------------------+-------------------------+----------------------------+ + * | TEMPERATURE_SENSOR_CLK_SRC_FAST_RC | On board clock source | no lock | + * +------------------------------------+-------------------------+----------------------------+ + * @endverbatim + */ +typedef enum { + TEMPERATURE_SENSOR_CLK_SRC_DEFAULT = 0, +#if SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL + TEMPERATURE_SENSOR_CLK_SRC_XTAL = 1, /*!< Select XTAL as the source clock */ +#endif +#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + TEMPERATURE_SENSOR_CLK_SRC_FAST_RC = 2, /*!< Select FOSC as the source clock */ +#endif +} temperature_sensor_clk_src_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index e393a511b7..dfb4c59720 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -646,3 +646,11 @@ config SOC_PM_SUPPORT_WIFI_PD config SOC_PM_SUPPORT_BT_PD bool default y + +config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + bool + default y + +config SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL + bool + default y diff --git a/components/soc/esp32c3/include/soc/periph_defs.h b/components/soc/esp32c3/include/soc/periph_defs.h index 5fa1af8bf8..df5d4fbc07 100644 --- a/components/soc/esp32c3/include/soc/periph_defs.h +++ b/components/soc/esp32c3/include/soc/periph_defs.h @@ -38,6 +38,7 @@ typedef enum { PERIPH_GDMA_MODULE, PERIPH_SYSTIMER_MODULE, PERIPH_SARADC_MODULE, + PERIPH_TEMPSENSOR_MODULE, PERIPH_MODULE_MAX } periph_module_t; diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 7f42c8cda4..8eb55e2645 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -320,3 +320,7 @@ #define SOC_PM_SUPPORT_WIFI_PD (1) #define SOC_PM_SUPPORT_BT_PD (1) + +/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ +#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 20bb3eb969..096465994d 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -606,3 +606,11 @@ config SOC_PM_SUPPORT_CPU_PD config SOC_PM_SUPPORT_BT_PD bool default y + +config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + bool + default y + +config SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL + bool + default y diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 7d9ffd0203..f475efb3a6 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -38,6 +38,7 @@ typedef enum { PERIPH_GDMA_MODULE, PERIPH_SYSTIMER_MODULE, PERIPH_SARADC_MODULE, + PERIPH_TEMPSENSOR_MODULE, PERIPH_MODULE_MAX } periph_module_t; diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 4c5862d2bf..ea40d0e79b 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -303,3 +303,7 @@ #define SOC_PM_SUPPORT_CPU_PD (1) #define SOC_PM_SUPPORT_BT_PD (1) + +/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ +#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) +#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 94c1929055..38d8675fc0 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -730,3 +730,7 @@ config SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP config SOC_COEX_HW_PTI bool default y + +config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + bool + default y diff --git a/components/soc/esp32s2/include/soc/periph_defs.h b/components/soc/esp32s2/include/soc/periph_defs.h index 8d85bd0ab5..f0532bdbef 100644 --- a/components/soc/esp32s2/include/soc/periph_defs.h +++ b/components/soc/esp32s2/include/soc/periph_defs.h @@ -42,6 +42,7 @@ typedef enum { PERIPH_SHA_DMA_MODULE, PERIPH_DEDIC_GPIO_MODULE, PERIPH_SARADC_MODULE, + PERIPH_TEMPSENSOR_MODULE, PERIPH_MODULE_MAX } periph_module_t; diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 9411514d28..338643de57 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -359,3 +359,6 @@ #define SOC_COEX_HW_PTI (1) /* ---------------------------- Compatibility ------------------------------- */ // No contents + +/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ +#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) diff --git a/examples/peripherals/temp_sensor/README.md b/examples/peripherals/temp_sensor/README.md index 611c2dc700..45f9d25c1e 100644 --- a/examples/peripherals/temp_sensor/README.md +++ b/examples/peripherals/temp_sensor/README.md @@ -1,9 +1,9 @@ -| Supported Targets | ESP32-S2 | ESP32-C3 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-S2 | ESP32-C3 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | # Temperature Sensor Example -The ESP32-S2 and ESP32-C3 has a built-in temperature sensor. The temperature sensor module contains an 8-bit Sigma-Delta ADC and a temperature offset DAC. +The ESP32-S2/C3/S3 has a built-in temperature sensor. The temperature sensor module contains an 8-bit Sigma-Delta ADC and a temperature offset DAC. The conversion relationship is the first two columns of the table below. Among them, `offset = 0`(default) is the main measurement option, and other values are extended measurement options. @@ -21,7 +21,7 @@ Before project configuration and build, be sure to set the correct chip target u ### Hardware Required -* A development board with ESP32-S2 or ESP32-C3 SoC (e.g., ESP32-S2-Saola-1, ESP32-S2-DevKitM-1, ESP32-C3-DevKitM-1, etc.) +* A development board with ESP32-S2/C3/S3 SoC (e.g., ESP32-S2-Saola-1, ESP32-S2-DevKitM-1, ESP32-C3-DevKitM-1, ESP32-S3-WROOM-1, etc.) * A USB cable for power supply and programming ### Build and Flash @@ -37,15 +37,19 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l ## Example Output ``` -I (243) TempSensor: Initializing Temperature sensor -I (243) TempSensor: default dac 2, clk_div 6 -I (243) TempSensor: Config temperature range [-10°C ~ 80°C], error < 1°C -I (253) TempSensor: Temperature sensor started -I (1253) TempSensor: Temperature out celsius 27.287399°C -I (2253) TempSensor: Temperature out celsius 26.848801°C -I (3253) TempSensor: Temperature out celsius 26.848801°C -I (4253) TempSensor: Temperature out celsius 27.287399°C -I (5253) TempSensor: Temperature out celsius 27.287399°C +I (276) example: Initializing Temperature sensor +I (276) temperature_sensor: temperature range [-10°C ~ 80°C], error < 1°C +I (286) example: Temperature sensor started +I (1286) example: Temperature out celsius 21.64 +I (2286) example: Temperature out celsius 21.64 +I (3286) example: Temperature out celsius 21.64 +I (4286) example: Temperature out celsius 22.08 +I (5286) example: Temperature out celsius 22.08 +I (6286) example: Temperature out celsius 22.08 +I (7286) example: Temperature out celsius 22.08 +I (8286) example: Temperature out celsius 22.08 +I (9286) example: Temperature out celsius 22.08 + ``` ## Troubleshooting diff --git a/examples/peripherals/temp_sensor/main/temp_sensor_main.c b/examples/peripherals/temp_sensor/main/temp_sensor_main.c index 85e796f2dc..3439634773 100644 --- a/examples/peripherals/temp_sensor/main/temp_sensor_main.c +++ b/examples/peripherals/temp_sensor/main/temp_sensor_main.c @@ -1,54 +1,37 @@ -/* Temperature Sensor Example +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include #include "esp_log.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "driver/temperature_sensor.h" -/* Note: ESP32 don't support temperature sensor */ +static const char *TAG = "example"; -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 -#include "driver/temp_sensor.h" - -static const char *TAG = "TempSensor"; - -void tempsensor_example(void *arg) +void tempsensor_example(void) { // Initialize touch pad peripheral, it will start a timer to run a filter ESP_LOGI(TAG, "Initializing Temperature sensor"); float tsens_out; - temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); - temp_sensor_get_config(&temp_sensor); - ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div); - temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. - temp_sensor_set_config(temp_sensor); - temp_sensor_start(); + temperature_sensor_config_t temp_sensor = TEMPERAUTRE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor, &temp_handle)); + ESP_ERROR_CHECK(temperature_sensor_start(temp_handle)); ESP_LOGI(TAG, "Temperature sensor started"); - while (1) { + int cnt = 20; //read value for 20 times + while (cnt) { vTaskDelay(1000 / portTICK_PERIOD_MS); - temp_sensor_read_celsius(&tsens_out); - ESP_LOGI(TAG, "Temperature out celsius %f°C", tsens_out); + ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + ESP_LOGI(TAG, "Temperature out celsius %.02f", tsens_out); + cnt--; } - vTaskDelete(NULL); } void app_main(void) { - xTaskCreate(tempsensor_example, "temp", 2048, NULL, 5, NULL); + tempsensor_example(); } - -#elif CONFIG_IDF_TARGET_ESP32 - -void app_main(void) -{ - printf("ESP32 don't support temperature sensor\n"); -} - -#endif diff --git a/examples/peripherals/temp_sensor/pytest_temp_sensor_example.py b/examples/peripherals/temp_sensor/pytest_temp_sensor_example.py new file mode 100644 index 0000000000..63e22af035 --- /dev/null +++ b/examples/peripherals/temp_sensor/pytest_temp_sensor_example.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded.dut import Dut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s3 +@pytest.mark.generic +def test_temp_sensor_example(dut: Dut) -> None: + dut.expect_exact('Initializing Temperature sensor') + dut.expect_exact('Temperature sensor started') + temp_value = dut.expect(r'Temperature out celsius (\d+\.\d+)', timeout=30) + # Because the example test only run in the normal temperature environment. So this assert range is meaningful + assert 0 < float(temp_value.group(1)) < 45 diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index a881acd0bc..8beb5c27f3 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -838,7 +838,6 @@ components/hal/esp32c3/brownout_hal.c components/hal/esp32c3/hmac_hal.c components/hal/esp32c3/include/hal/adc_hal_conf.h components/hal/esp32c3/include/hal/aes_ll.h -components/hal/esp32c3/include/hal/clk_gate_ll.h components/hal/esp32c3/include/hal/ds_ll.h components/hal/esp32c3/include/hal/gpspi_flash_ll.h components/hal/esp32c3/include/hal/hmac_hal.h @@ -862,7 +861,6 @@ components/hal/esp32h2/brownout_hal.c components/hal/esp32h2/hmac_hal.c components/hal/esp32h2/include/hal/adc_hal_conf.h components/hal/esp32h2/include/hal/aes_ll.h -components/hal/esp32h2/include/hal/clk_gate_ll.h components/hal/esp32h2/include/hal/ds_ll.h components/hal/esp32h2/include/hal/gpspi_flash_ll.h components/hal/esp32h2/include/hal/hmac_hal.h @@ -2236,7 +2234,6 @@ examples/peripherals/spi_slave_hd/append_mode/master/main/app_main.c examples/peripherals/spi_slave_hd/append_mode/slave/main/app_main.c examples/peripherals/spi_slave_hd/segment_mode/seg_master/main/app_main.c examples/peripherals/spi_slave_hd/segment_mode/seg_slave/main/app_main.c -examples/peripherals/temp_sensor/main/temp_sensor_main.c examples/peripherals/touch_element/touch_button/main/touch_button_example_main.c examples/peripherals/touch_element/touch_element_waterproof/main/waterproof_example_main.c examples/peripherals/touch_element/touch_elements_combination/main/touch_elements_example_main.c