From 441900caa2cc1faf4875945ba57d7a474ea71361 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 4 Mar 2022 17:59:07 +0800 Subject: [PATCH 1/4] Temperature_sensor: keep legacy drivers --- components/driver/Kconfig | 20 +++ .../driver/deprecated/driver/temp_sensor.h | 76 +++++++++ .../driver/temp_sensor_types_legacy.h | 40 +++++ components/driver/rtc_temperature_legacy.c | 152 ++++++++++++++++++ .../legacy_rtc_temp_driver/CMakeLists.txt | 5 + .../legacy_rtc_temp_driver/README.md | 2 + .../main/CMakeLists.txt | 7 + .../main/test_app_main.c | 40 +++++ .../main/test_rtc_temp_driver.c | 68 ++++++++ .../pytest_legacy_temp_sensor_driver.py | 18 +++ .../sdkconfig.ci.release | 5 + .../legacy_rtc_temp_driver/sdkconfig.defaults | 2 + 12 files changed, 435 insertions(+) create mode 100644 components/driver/deprecated/driver/temp_sensor.h create mode 100644 components/driver/deprecated/driver/temp_sensor_types_legacy.h create mode 100644 components/driver/rtc_temperature_legacy.c create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/CMakeLists.txt create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/README.md create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/main/CMakeLists.txt create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/main/test_app_main.c create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/main/test_rtc_temp_driver.c create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/sdkconfig.ci.release create mode 100644 components/driver/test_apps/legacy_rtc_temp_driver/sdkconfig.defaults diff --git a/components/driver/Kconfig b/components/driver/Kconfig index d0f0f8542b..0f98cdb998 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -145,6 +145,26 @@ menu "Driver configurations" endmenu # TWAI Configuration + menu "Temperature sensor Configuration" + visible if SOC_TEMP_SENSOR_SUPPORTED + + config TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN + bool "Suppress legacy driver deprecated warning" + default n + help + Wether to suppress the deprecation warnings when using legacy temperature sensor driver + (driver/temp_sensor.h). If you want to continue using the legacy driver, + and don't want to see related deprecation warnings, you can enable this option. + + config TEMP_SENSOR_ENABLE_DEBUG_LOG + bool "Enable debug log" + default n + help + Wether to enable the debug log message for temperature sensor driver. + Note that, this option only controls the temperature sensor driver log, won't affect other drivers. + + endmenu # TEMP_SENSOR Configuration + menu "UART configuration" config UART_ISR_IN_IRAM diff --git a/components/driver/deprecated/driver/temp_sensor.h b/components/driver/deprecated/driver/temp_sensor.h new file mode 100644 index 0000000000..c5a28600df --- /dev/null +++ b/components/driver/deprecated/driver/temp_sensor.h @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/temp_sensor_types_legacy.h" + +#if !CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN +#warning "legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @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/deprecated/driver/temp_sensor_types_legacy.h b/components/driver/deprecated/driver/temp_sensor_types_legacy.h new file mode 100644 index 0000000000..61f5ab7919 --- /dev/null +++ b/components/driver/deprecated/driver/temp_sensor_types_legacy.h @@ -0,0 +1,40 @@ +/* + * 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} + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/rtc_temperature_legacy.c b/components/driver/rtc_temperature_legacy.c new file mode 100644 index 0000000000..a3f9f33443 --- /dev/null +++ b/components/driver/rtc_temperature_legacy.c @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "esp_types.h" +#include "esp_log.h" +#include "esp_check.h" +#include "soc/rtc_cntl_reg.h" +#include "regi2c_ctrl.h" +#include "esp_log.h" +#include "esp_efuse_rtc_calib.h" +#include "hal/temperature_sensor_ll.h" +#include "driver/temp_sensor_types_legacy.h" +#include "esp_private/periph_ctrl.h" +#include "sdkconfig.h" + +static const char *TAG = "tsens"; + +#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 reg_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) +{ + 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; + } + temperature_sensor_ll_set_clk_div(tsens.clk_div); + temperature_sensor_ll_set_range(dac_offset[tsens.dac_offset].reg_val); + temperature_sensor_ll_enable(true); + ESP_LOGI(TAG, "Config 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"); + tsens->dac_offset = temperature_sensor_ll_get_offset(); + for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) { + if ((int)tsens->dac_offset == dac_offset[i].reg_val) { + tsens->dac_offset = dac_offset[i].index; + break; + } + } + tsens->clk_div = temperature_sensor_ll_get_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, "Is already running or not be configured"); + err = ESP_ERR_INVALID_STATE; + } + periph_module_enable(PERIPH_TEMPSENSOR_MODULE); + temperature_sensor_ll_enable(true); + temperature_sensor_ll_clk_enable(true); + temperature_sensor_ll_clk_sel(TEMPERATURE_SENSOR_CLK_SRC_DEFAULT); + tsens_hw_state = TSENS_HW_STATE_STARTED; + return err; +} + +esp_err_t temp_sensor_stop(void) +{ + temperature_sensor_ll_enable(false); + tsens_hw_state = TSENS_HW_STATE_CONFIGURED; + 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 = temperature_sensor_ll_get_raw_value(); + return ESP_OK; +} + +static esp_err_t read_delta_t_from_efuse(void) +{ + ESP_RETURN_ON_ERROR(esp_efuse_rtc_calib_get_tsens_val(&s_deltaT), TAG, "Calibration error"); + 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 temp_sensor_read_celsius(float *celsius) +{ + ESP_RETURN_ON_FALSE(celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "celsius points to nothing"); + if (tsens_hw_state != TSENS_HW_STATE_STARTED) { + ESP_LOGE(TAG, "Has not been started"); + return ESP_ERR_INVALID_STATE; + } + temp_sensor_config_t tsens; + uint32_t tsens_out = 0; + temp_sensor_get_config(&tsens); + temp_sensor_read_raw(&tsens_out); + ESP_LOGV(TAG, "tsens_out %d", tsens_out); + 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!"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/CMakeLists.txt b/components/driver/test_apps/legacy_rtc_temp_driver/CMakeLists.txt new file mode 100644 index 0000000000..761e56ea88 --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/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(legacy_rtc_temp_driver_test) diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/README.md b/components/driver/test_apps/legacy_rtc_temp_driver/README.md new file mode 100644 index 0000000000..0dfa474720 --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/main/CMakeLists.txt b/components/driver/test_apps/legacy_rtc_temp_driver/main/CMakeLists.txt new file mode 100644 index 0000000000..483019a963 --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(srcs "test_app_main.c" + "test_rtc_temp_driver.c") + +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES driver unity) + +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_rtc_temp_driver") diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/main/test_app_main.c b/components/driver/test_apps/legacy_rtc_temp_driver/main/test_app_main.c new file mode 100644 index 0000000000..183a88ae3c --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/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/legacy_rtc_temp_driver/main/test_rtc_temp_driver.c b/components/driver/test_apps/legacy_rtc_temp_driver/main/test_rtc_temp_driver.c new file mode 100644 index 0000000000..5ffdb8aaaf --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/main/test_rtc_temp_driver.c @@ -0,0 +1,68 @@ +/* + * 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/temp_sensor.h" + +void test_app_include_rtc_temp_driver(void) +{ +} + +TEST_CASE("Temperature_lagecy_workflow_test", "[hw_timer]") +{ + printf("Initializing Temperature sensor\n"); + float tsens_out; + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); + TEST_ESP_OK(temp_sensor_get_config(&temp_sensor)); + printf("default dac %d, clk_div %d\n", temp_sensor.dac_offset, temp_sensor.clk_div); + temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. + TEST_ESP_OK(temp_sensor_set_config(temp_sensor)); + TEST_ESP_OK(temp_sensor_start()); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temp_sensor_read_celsius(&tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temp_sensor_stop()); + temp_sensor.dac_offset = TSENS_DAC_L3; + TEST_ESP_OK(temp_sensor_set_config(temp_sensor)); + TEST_ESP_OK(temp_sensor_start()); + printf("Temperature sensor started again\n"); + TEST_ESP_OK(temp_sensor_read_celsius(&tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temp_sensor_stop()); +} + +TEST_CASE("Double start error cause test", "[temperatere_sensor]") +{ + printf("Initializing Temperature sensor\n"); + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); + TEST_ESP_OK(temp_sensor_set_config(temp_sensor)); + TEST_ESP_OK(temp_sensor_start()); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, temp_sensor_start()); + TEST_ESP_OK(temp_sensor_stop()); +} + +TEST_CASE("Double Start-Stop test", "[temperature_sensor]") +{ + printf("Initializing Temperature sensor\n"); + float tsens_out; + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); + TEST_ESP_OK(temp_sensor_get_config(&temp_sensor)); + printf("default dac %d, clk_div %d\n", temp_sensor.dac_offset, temp_sensor.clk_div); + temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. + TEST_ESP_OK(temp_sensor_set_config(temp_sensor)); + TEST_ESP_OK(temp_sensor_start()); + printf("Temperature sensor started\n"); + TEST_ESP_OK(temp_sensor_read_celsius(&tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temp_sensor_stop()); + TEST_ESP_OK(temp_sensor_start()); + printf("Temperature sensor started again\n"); + TEST_ESP_OK(temp_sensor_read_celsius(&tsens_out)); + printf("Temperature out celsius %f°C\n", tsens_out); + TEST_ESP_OK(temp_sensor_stop()); +} diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py new file mode 100644 index 0000000000..e885e9efc7 --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.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_legacy_temp_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/legacy_rtc_temp_driver/sdkconfig.ci.release b/components/driver/test_apps/legacy_rtc_temp_driver/sdkconfig.ci.release new file mode 100644 index 0000000000..91d93f163e --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/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/legacy_rtc_temp_driver/sdkconfig.defaults b/components/driver/test_apps/legacy_rtc_temp_driver/sdkconfig.defaults new file mode 100644 index 0000000000..4335b5386b --- /dev/null +++ b/components/driver/test_apps/legacy_rtc_temp_driver/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_ESP_TASK_WDT=n +CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN=y From 214e206111d98682f0bce5c2d1c0db01334d945d Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 4 Mar 2022 18:02:38 +0800 Subject: [PATCH 2/4] Temperature_sensor: Add temperature support for ESP32-S3 --- .../esp32s3/include/driver/temp_sensor.h | 97 ------------ .../efuse/esp32s3/esp_efuse_rtc_calib.c | 23 ++- .../esp32s3/include/esp_efuse_rtc_calib.h | 9 +- .../include/hal/temperature_sensor_ll.h | 146 ++++++++++++++++++ .../esp32s3/include/soc/Kconfig.soc_caps.in | 16 +- .../soc/esp32s3/include/soc/periph_defs.h | 3 +- components/soc/esp32s3/include/soc/soc_caps.h | 4 + 7 files changed, 187 insertions(+), 111 deletions(-) delete mode 100644 components/driver/esp32s3/include/driver/temp_sensor.h create mode 100644 components/hal/esp32s3/include/hal/temperature_sensor_ll.h diff --git a/components/driver/esp32s3/include/driver/temp_sensor.h b/components/driver/esp32s3/include/driver/temp_sensor.h deleted file mode 100644 index c3a87068b6..0000000000 --- a/components/driver/esp32s3/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/efuse/esp32s3/esp_efuse_rtc_calib.c b/components/efuse/esp32s3/esp_efuse_rtc_calib.c index 272549986b..06deef540b 100644 --- a/components/efuse/esp32s3/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32s3/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 */ @@ -96,3 +96,24 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, in return ESP_OK; } + +esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal) +{ + 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); + assert(cal_temp_size == 9); + + uint32_t cal_temp = 0; + esp_err_t err = esp_efuse_read_field_blob(cal_temp_efuse, &cal_temp, cal_temp_size); + assert(err == ESP_OK); + (void)err; + // BIT(8) stands for sign: 1: negtive, 0: positive + *tsens_cal = ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp; + return ESP_OK; +} diff --git a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h index e2f5b54329..0f0f37938d 100644 --- a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h +++ b/components/efuse/esp32s3/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 */ @@ -48,11 +48,12 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, in /** * @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/hal/esp32s3/include/hal/temperature_sensor_ll.h b/components/hal/esp32s3/include/hal/temperature_sensor_ll.h new file mode 100644 index 0000000000..f38ff685b1 --- /dev/null +++ b/components/hal/esp32s3/include/hal/temperature_sensor_ll.h @@ -0,0 +1,146 @@ +/* + * 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_peri_clk_gate_conf.tsens_clk_en = enable; +} + +/** + * @brief Choose the clock. No need to choose the clock source on ESP32-S3. ESP32-S3 + * 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 esp32s3. +} + +/** + * @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) +{ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU); + 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/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 9826a817cf..554aff0f41 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -83,14 +83,6 @@ config SOC_MPU_REGION_WO_SUPPORTED bool default n -config SOC_PCNT_PORT_NUM - bool - default y - -config SOC_PCNT_UNIT_NUM - int - default 4 - config SOC_RTCIO_PIN_COUNT int default 22 @@ -243,6 +235,10 @@ config SOC_SIGMADELTA_SUPPORTED bool default y +config SOC_TEMP_SENSOR_SUPPORTED + bool + default y + config SOC_APPCPU_HAS_CLOCK_GATING_BUG bool default y @@ -863,6 +859,10 @@ config SOC_SDMMC_SUPPORT_XTAL_CLOCK bool default y +config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC + bool + default y + config SOC_TWAI_BRP_MIN int default 2 diff --git a/components/soc/esp32s3/include/soc/periph_defs.h b/components/soc/esp32s3/include/soc/periph_defs.h index c2bb13a80c..78510ca83f 100644 --- a/components/soc/esp32s3/include/soc/periph_defs.h +++ b/components/soc/esp32s3/include/soc/periph_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,6 +51,7 @@ typedef enum { PERIPH_GDMA_MODULE, PERIPH_DEDIC_GPIO_MODULE, PERIPH_SARADC_MODULE, + PERIPH_TEMPSENSOR_MODULE, PERIPH_MODULE_MAX } periph_module_t; diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 324a33746c..8e489084f1 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -59,6 +59,7 @@ #define SOC_I2S_SUPPORTED 1 #define SOC_RMT_SUPPORTED 1 #define SOC_SIGMADELTA_SUPPORTED 1 +#define SOC_TEMP_SENSOR_SUPPORTED 1 /*-------------------------- SOC CAPS ----------------------------------------*/ #define SOC_APPCPU_HAS_CLOCK_GATING_BUG (1) @@ -369,3 +370,6 @@ #define SOC_SDMMC_NUM_SLOTS 2 /* Indicates that there is an option to use XTAL clock instead of PLL for SDMMC */ #define SOC_SDMMC_SUPPORT_XTAL_CLOCK 1 + +/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ +#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) From d25feba1bf77437f811dbcac5efb58b62f80f1a3 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 4 Mar 2022 18:03:39 +0800 Subject: [PATCH 3/4] Temperature_sensor: update temperature sensor documents --- docs/doxygen/Doxyfile_esp32c2 | 2 +- docs/doxygen/Doxyfile_esp32c3 | 2 +- docs/doxygen/Doxyfile_esp32h2 | 2 +- docs/doxygen/Doxyfile_esp32s2 | 2 +- docs/doxygen/Doxyfile_esp32s3 | 1 + .../api-reference/peripherals/temp_sensor.rst | 160 ++++++++++++------ .../api-reference/system/power_management.rst | 1 + docs/en/migration-guides/peripherals.rst | 10 ++ 8 files changed, 126 insertions(+), 54 deletions(-) diff --git a/docs/doxygen/Doxyfile_esp32c2 b/docs/doxygen/Doxyfile_esp32c2 index 2f3bda1516..8225dce1f1 100644 --- a/docs/doxygen/Doxyfile_esp32c2 +++ b/docs/doxygen/Doxyfile_esp32c2 @@ -1,2 +1,2 @@ INPUT += \ - $(PROJECT_PATH)/components/driver/esp32c3/include/driver/temp_sensor.h + $(PROJECT_PATH)/components/driver/include/driver/temperature_sensor.h \ diff --git a/docs/doxygen/Doxyfile_esp32c3 b/docs/doxygen/Doxyfile_esp32c3 index 4afae97962..be9b6e7590 100644 --- a/docs/doxygen/Doxyfile_esp32c3 +++ b/docs/doxygen/Doxyfile_esp32c3 @@ -1,4 +1,4 @@ INPUT += \ - $(PROJECT_PATH)/components/driver/esp32c3/include/driver/temp_sensor.h \ + $(PROJECT_PATH)/components/driver/include/driver/temperature_sensor.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h diff --git a/docs/doxygen/Doxyfile_esp32h2 b/docs/doxygen/Doxyfile_esp32h2 index 77e8851191..4bd6cd90c3 100644 --- a/docs/doxygen/Doxyfile_esp32h2 +++ b/docs/doxygen/Doxyfile_esp32h2 @@ -1,4 +1,4 @@ INPUT += \ - $(PROJECT_PATH)/components/driver/esp32h2/include/driver/temp_sensor.h \ + $(PROJECT_PATH)/components/driver/include/driver/temperature_sensor.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h diff --git a/docs/doxygen/Doxyfile_esp32s2 b/docs/doxygen/Doxyfile_esp32s2 index cfc54153fc..0bbfad6d80 100644 --- a/docs/doxygen/Doxyfile_esp32s2 +++ b/docs/doxygen/Doxyfile_esp32s2 @@ -4,7 +4,7 @@ INPUT += \ $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ $(PROJECT_PATH)/components/driver/include/driver/pulse_cnt.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ - $(PROJECT_PATH)/components/driver/esp32s2/include/driver/temp_sensor.h \ + $(PROJECT_PATH)/components/driver/include/driver/temperature_sensor.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \ diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index ac6025713e..1be3ccd5f9 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -5,6 +5,7 @@ INPUT += \ $(PROJECT_PATH)/components/driver/include/driver/mcpwm.h \ $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ $(PROJECT_PATH)/components/driver/include/driver/pulse_cnt.h \ + $(PROJECT_PATH)/components/driver/include/driver/temperature_sensor.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ $(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \ diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index 31ab51f324..d91e0d94ae 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -1,67 +1,127 @@ Temperature Sensor -=================== +================== -.. only:: esp32s3 - - .. warning:: - - This feature is not supported in v4.4 - -Overview --------- - -The {IDF_TARGET_NAME} has a built-in temperature sensor used to measure the chip's internal temperature, and hard to measure the environmental temperature accurately. Being built-in means that the temperature sensor should work on any {IDF_TARGET_NAME} regardless of what board the chip is embedded in. The temperature sensor module contains an 8-bit Sigma-Delta ADC and a temperature offset DAC. - -The conversion relationship is the first columns of the table below. Among them, offset = 0 is the main measurement option, and other values are extended measurement options. - -+--------+------------------------+------------------------+ -| offset | measure range(Celsius) | measure error(Celsius) | -+========+========================+========================+ -| -2 | 50 ~ 125 | < 3 | -+--------+------------------------+------------------------+ -| -1 | 20 ~ 100 | < 2 | -+--------+------------------------+------------------------+ -| 0 | -10 ~ 80 | < 1 | -+--------+------------------------+------------------------+ -| 1 | -30 ~ 50 | < 2 | -+--------+------------------------+------------------------+ -| 2 | -40 ~ 20 | < 3 | -+--------+------------------------+------------------------+ - -Driver Usage +Introduction ------------ -1. Initialize the temperature sensor by calling the function :cpp:func:`temp_sensor_set_config` and pass to it a :cpp:type:`temp_sensor_config_t` structure. The :cpp:type:`temp_sensor_config_t` structure should contain all the required parameters. See the example below. +The {IDF_TARGET_NAME} has a built-in sensor used to measure the chip's internal temperature. The temperature sensor module contains an 8-bit Sigma-Delta ADC and a DAC to compensate for the temperature offset. -.. code-block:: c +Due to restrictions of hardware, the sensor has predefined measurement ranges with specific measurement errors. See the table below for details. - temp_sensor_config_t temp_sensor = { - .dac_offset = TSENS_DAC_L2, - .clk_div = 6, - }; - temp_sensor_set_config(temp_sensor); - -2. Start the temp_sensor by calling :cpp:func:'temp_sensor_start'. The temperature sensor will now measure the temperature. - -3. To get the current temperature, take the example below as a reference, the value you get is in Celsius. - -.. code-block:: c - - float tsens_out; - temp_sensor_read_celsius(&tsens_out); - -4. To stop the temperature sensor, please call :cpp:func:'temp_sensor_stop'. ++------------------------+------------------------+ +| predefined range (°C) | error (°C) | ++========================+========================+ +| 50 ~ 125 | < 3 | ++------------------------+------------------------+ +| 20 ~ 100 | < 2 | ++------------------------+------------------------+ +| -10 ~ 80 | < 1 | ++------------------------+------------------------+ +| -30 ~ 50 | < 2 | ++------------------------+------------------------+ +| -40 ~ 20 | < 3 | ++------------------------+------------------------+ .. note:: - If you want dynamic reconfiguration, you need to stop the sensor first (temp_sensor_stop), set the new configuration (temp_sensor_set_config), then start the sensor again (temp_sensor_start). + The temperature sensor is designed primarily to measure the temperature changes inside the chip. The temperature value depends on factors like microcontroller clock frequency or I/O load. Generally, the chip's internal temperature might be higher than the ambient temperature. + +Functional Overview +------------------- + +- `Resource Allocation <#resource-allocation>`__ - covers which parameters should be set up to get a temperature sensor handle and how to recycle the resources when temperature sensor finishes working. + +- `Start and Stop Temperature <#start-and-stop-temperature>`__ - covers how to start or stop the temperature sensor. + +- `Get Temperature Value <#get-temperature-value>`__ - covers how to get the real-time temperature value. + +- `Power Management <#power-management>`__ - covers how temperature sensor is affected when changing power mode (i.e. light sleep). + +- `Thread Safety <#thread-safety>`__ - covers how to make the driver to be thread safe. + +Resource Allocation +^^^^^^^^^^^^^^^^^^^ + +The {IDF_TARGET_NAME} has just one built-in temperature sensor hardware. The temperature sensor instance is represented by :cpp:type:`temperature_sensor_handle_t`, which is also the bond of the context. It would always be the parameter of the temperature APIs with the information of hardware and configurations, so user can just create a pointer of type :cpp:type:`temperature_sensor_handle_t` and passing to APIs as needed. + +In order to install a built-in temperature sensor instance, the first thing is to evaluate the temperature range in your detection environment (For example: if the testing environment is in a room, the range you evaluate might be 10 °C ~ 30 °C; if the testing in a lamp bulb, the range you evaluate might be 60 °C ~ 110 °C). Based on that, the following configuration structure should be defined in advance: +:cpp:type:`temperature_sensor_config_t`: + +- :cpp:member:`range_min`. The minimum value of testing range you have evaluated. + +- :cpp:member:`range_max`. The maximum value of testing range you have evaluated. + +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. + +As mentioned above, different measure ranges have different measurement errors. The user doesn't need to care about the measurement error because we have an internal mechanism to choose the minimum error according to the given range. + +If the temperature sensor is no longer needed, you need to call :cpp:func:`temperature_sensor_uninstall` to free the temperature sensor resource. + +Creating a Temperature Sensor Handle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Step1: Evaluate the testing range. In this example, the range is 20 °C ~ 50 °C. + +* Step2: Configure the range and obtain a handle + +.. code:: c + + temperature_sensor_handle_t temp_handle = NULL; + temperature_sensor_config_t temp_sensor = { + .range_min = 20, + .range_max = 50, + }; + ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor, &temp_handle)); + +Start and Stop Temperature +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Start the temperature sensor by calling :cpp:func:`temperature_sensor_start`. The temperature sensor will now measure the temperature. + +2. To stop the temperature sensor, please call :cpp:func:`temperature_sensor_stop`. + +Get Temperature Value +^^^^^^^^^^^^^^^^^^^^^ + +After the temperature sensor has been installed, you can get the temperature value by following the steps below. + +1. To get the current temperature, please call :cpp:func:`temperature_sensor_get_celsius`. + +.. code:: c + + ESP_ERROR_CHECK(temperature_sensor_start(temp_handle)); + printf("Temperature sensor started\n"); + float tsens_out; + ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_handle, &tsens_out)); + printf("Temperature in %f °C\n", tsens_out); + ESP_ERROR_CHECK(temperature_sensor_stop(temp_handle)); + +Power Management +^^^^^^^^^^^^^^^^ + +When power management is enabled (i.e. ``CONFIG_PM_ENABLE`` is on), temperature sensor will still keep working because it uses XTAL clock (on ESP32-C3) or RTC clock (on ESP32-S2/S3). + +Thread Safety +^^^^^^^^^^^^^ + +In temperature sensor we don't add any protection to keep the thread safe. Because from the common usage, temperature sensor should only be called in one task. If you must use this driver in different tasks, please add extra locks to protect it. + +Unexpected Behaviors +-------------------- + +1. The value user gets from the chip is usually different from the ambient temperature. It is because the temperature sensor is built inside the chip. To some extent, it measures the temperature of the chip. + +2. When installing the temperature sensor, the driver gives a 'the boundary you gave cannot meet the range of internal temperature sensor' error feedback. It is because the built-in temperature sensor has testing limit. The error due to setting :cpp:type:`temperature_sensor_config_t`: + + (1) Totally out of range, like 200 °C ~ 300 °C. + (2) Cross the boundary of each predefined measurement. like 40 °C ~ 110 °C. Application Example ------------------- Temperature sensor reading example: :example:`peripherals/temp_sensor`. -API Reference - Normal Temp Sensor +API Reference ---------------------------------- -.. include-build-file:: inc/temp_sensor.inc +.. include-build-file:: inc/temperature_sensor.inc diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index fc26109c6f..16815dc3fd 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -104,6 +104,7 @@ The following peripherals work normally even when the APB frequency is changing: - **LEDC**: if REF_TICK is used as a clock source. See :cpp:func:`ledc_timer_config` function. - **RMT**: if REF_TICK or XTAL is used as a clock source. See `flags` member of :cpp:class:`rmt_config_t` and macro `RMT_CHANNEL_FLAGS_AWARE_DFS`. - **GPTimer**: if APB is used as the clock source. See :c:member:`clk_src` member of :c:type:`gptimer_config_t`. +- **TSENS**: XTAL or RTC_8M is used as a clock source. So, APB frequency changing will not influence it. Currently, the following peripheral drivers are aware of DFS and will use the ``ESP_PM_APB_FREQ_MAX`` lock for the duration of the transaction: diff --git a/docs/en/migration-guides/peripherals.rst b/docs/en/migration-guides/peripherals.rst index 96c94fcc00..711ef8bd75 100644 --- a/docs/en/migration-guides/peripherals.rst +++ b/docs/en/migration-guides/peripherals.rst @@ -96,3 +96,13 @@ I2C - ``pcnt_filter_enable``, ``pcnt_filter_disable``, and ``pcnt_set_filter_value`` are replaced by :cpp:func:`pcnt_unit_set_glitch_filter`. Meanwhile, ``pcnt_get_filter_value`` has been removed. - ``pcnt_set_mode`` is replaced by :cpp:func:`pcnt_channel_set_edge_action` and :cpp:func:`pcnt_channel_set_level_action`. - ``pcnt_isr_service_install``, ``pcnt_isr_service_uninstall``, ``pcnt_isr_handler_add`` and ``pcnt_isr_handler_remove`` are replaced by :cpp:func:`pcnt_unit_register_event_callbacks`. The default ISR handler is lazy installed in the new driver. + +.. only:: SOC_TEMP_SENSOR_SUPPORTED + + Temperature Sensor Driver + ------------------------- + + 1. Old API header ``temp_sensor.h`` has been redesigned as ``temperature_sensor.h``, it is recommended to use the new driver and the old driver is not allowed to be used at the same time. + 2. Although it's recommended to use the new driver APIs, the legacy driver is still available in the previous include path ``driver/temp_sensor.h``. However, by default, including ``driver/temp_sensor.h`` will bring a build warning like "legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h". The warning can be suppressed by enabling the menuconfig option :ref:`CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN`. + 3. Configuration contents has been changed. In old version, user need to configure the ``clk_div`` and ``dac_offset``. While in new version, user only need to choose ``tsens_range`` + 4. The process of using temperature sensor has been changed. In old version, user can use ``config->start->read_celsius`` to get value. In the new version, user must install the temperature sensor driver firstly, by ``temperature_sensor_install`` and uninstall it when finished. For more information, you can refer to :doc:`Temperature Sensor <../api-reference/peripherals/temp_sensor>` . From b248046bcb3e5eba8af688f3c42fabb634c63d91 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 4 Mar 2022 18:04:20 +0800 Subject: [PATCH 4/4] 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