Temperature_sensor: Create new temperature sensor API

This commit is contained in:
Cao Sen Miao 2022-03-04 18:04:20 +08:00
parent d25feba1bf
commit b248046bcb
44 changed files with 1143 additions and 987 deletions

View File

@ -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")

View File

@ -1,92 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@ -1,92 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@ -1,164 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#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;
}

View File

@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@ -1,164 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#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;
}

View File

@ -1,97 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@ -1,187 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#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;
}

View File

@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#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

View File

@ -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 <stdlib.h>
#include <math.h>
#include <string.h>
#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;
}

View File

@ -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)

View File

@ -0,0 +1,2 @@
| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-C3 |
| ----------------- | -------- | -------- | -------- |

View File

@ -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")

View File

@ -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();
}

View File

@ -0,0 +1,81 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#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));
}

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1 @@
CONFIG_ESP_TASK_WDT=n

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#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;
}

View File

@ -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

View File

@ -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")

View File

@ -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;

View File

@ -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 <stdbool.h>
#include <stdlib.h>
#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

View File

@ -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;

View File

@ -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 <stdbool.h>
#include <stdlib.h>
#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

View File

@ -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 <stdbool.h>
#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

View File

@ -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

View File

@ -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

View File

@ -38,6 +38,7 @@ typedef enum {
PERIPH_GDMA_MODULE,
PERIPH_SYSTIMER_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_TEMPSENSOR_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;

View File

@ -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)

View File

@ -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

View File

@ -38,6 +38,7 @@ typedef enum {
PERIPH_GDMA_MODULE,
PERIPH_SYSTIMER_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_TEMPSENSOR_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -359,3 +359,6 @@
#define SOC_COEX_HW_PTI (1)
/* ---------------------------- Compatibility ------------------------------- */
// No contents
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/
#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1)

View File

@ -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

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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

View File

@ -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

View File

@ -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