temperature_sensor: Implement temperature monitor interrupt feature on ESP32H2/ESP32C6

This commit is contained in:
Cao Sen Miao 2023-03-03 10:38:40 +08:00
parent 2f6a362be9
commit 840ff4f865
15 changed files with 497 additions and 65 deletions

View File

@ -208,6 +208,14 @@ menu "Driver Configurations"
Wether to enable the debug log message for temperature sensor driver. 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. Note that, this option only controls the temperature sensor driver log, won't affect other drivers.
config TEMP_SENSOR_ISR_IRAM_SAFE
depends on SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
bool "Temperature sensor ISR IRAM-Safe"
default n
help
Ensure the Temperature Sensor interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).
endmenu # TEMP_SENSOR Configuration endmenu # TEMP_SENSOR Configuration
menu "UART Configuration" menu "UART Configuration"

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,6 +7,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "esp_err.h" #include "esp_err.h"
#include "hal/temperature_sensor_types.h" #include "hal/temperature_sensor_types.h"
@ -94,6 +95,92 @@ esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens);
*/ */
esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius); esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius);
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
/**
* @brief Temperature sensor event data
*/
typedef struct {
int celsius_value; /**< Celsius value in interrupt callback. */
} temperature_sensor_threshold_event_data_t;
/**
* @brief Callback for temperature sensor threshold interrupt.
*
* @param[in] tsens The handle created by `temperature_sensor_install()`.
* @param[in] edata temperature sensor event data, fed by driver.
* @param[in] user_data User data, set in `temperature_sensor_register_callbacks()`.
* @return Whether a high priority task has been waken up by this function.
*/
typedef bool (*temperature_thres_cb_t)(temperature_sensor_handle_t tsens, const temperature_sensor_threshold_event_data_t *edata, void *user_data);
/**
* @brief Group of temperature sensor callback functions, all of them will be run in ISR.
*/
typedef struct {
temperature_thres_cb_t on_threshold; /**< Temperature value interrupt callback */
} temperature_sensor_event_callbacks_t;
/**
* @brief Config options for temperature value absolute interrupt.
*/
typedef struct {
float high_threshold; /**< High threshold value(Celsius). Interrupt will be triggered if temperature value is higher than this value */
float low_threshold; /**< Low threshold value(Celsius). Interrupt will be triggered if temperature value is lower than this value */
} temperature_sensor_abs_threshold_config_t;
/**
* @brief Set temperature sensor absolute mode automatic monitor.
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @param abs_cfg Configuration of temperature sensor absolute mode interrupt, see `temperature_sensor_abs_threshold_config_t`.
* @note This function should not be called with `temperature_sensor_set_delta_threshold`.
*
* @return
* - ESP_OK: Set absolute threshold successfully.
* - ESP_ERR_INVALID_STATE: Set absolute threshold failed because of wrong state.
* - ESP_ERR_INVALID_ARG: Set absolute threshold failed because of invalid argument.
*/
esp_err_t temperature_sensor_set_absolute_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_abs_threshold_config_t *abs_cfg);
/**
* @brief Config options for temperature value delta interrupt.
*/
typedef struct {
float increase_delta; /**< Interrupt will be triggered if the temperature increment of two consecutive samplings if larger than `increase_delta` */
float decrease_delta; /**< Interrupt will be triggered if the temperature decrement of two consecutive samplings if smaller than `decrease_delta` */
} temperature_sensor_delta_threshold_config_t;
/**
* @brief Set temperature sensor differential mode automatic monitor.
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @param delta_cfg Configuration of temperature sensor delta mode interrupt, see `temperature_sensor_delta_threshold_config_t`.
* @note This function should not be called with `temperature_sensor_set_absolute_threshold`
*
* @return
* - ESP_OK: Set differential value threshold successfully.
* - ESP_ERR_INVALID_STATE: Set absolute threshold failed because of wrong state.
* - ESP_ERR_INVALID_ARG: Set differential value threshold failed because of invalid argument.
*/
esp_err_t temperature_sensor_set_delta_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_delta_threshold_config_t *delta_cfg);
/**
* @brief Install temperature sensor interrupt callback. Temperature sensor interrupt will be enabled at same time
*
* @param tsens The handle created by `temperature_sensor_install()`.
* @param cbs Pointer to the group of temperature sensor interrupt callbacks.
* @param user_arg Callback argument.
*
* @return
* - ESP_OK: Set event callbacks successfully
* - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument
* - ESP_FAIL: Set event callbacks failed because of other error
*/
esp_err_t temperature_sensor_register_callbacks(temperature_sensor_handle_t tsens, const temperature_sensor_event_callbacks_t *cbs, void *user_arg);
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -24,25 +24,18 @@
#include "driver/temperature_sensor.h" #include "driver/temperature_sensor.h"
#include "esp_efuse_rtc_calib.h" #include "esp_efuse_rtc_calib.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#include "temperature_sensor_private.h"
#include "hal/temperature_sensor_ll.h" #include "hal/temperature_sensor_ll.h"
#include "soc/temperature_sensor_periph.h" #include "soc/temperature_sensor_periph.h"
#include "esp_memory_utils.h"
static const char *TAG = "temperature_sensor"; static const char *TAG = "temperature_sensor";
typedef enum {
TEMP_SENSOR_FSM_INIT,
TEMP_SENSOR_FSM_ENABLE,
} temp_sensor_fsm_t;
static float s_deltaT = NAN; // unused number static float s_deltaT = NAN; // unused number
typedef struct temperature_sensor_obj_t temperature_sensor_obj_t; #if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
static int8_t s_temperature_regval_2_celsius(temperature_sensor_handle_t tsens, uint8_t regval);
struct temperature_sensor_obj_t { #endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
const temperature_sensor_attribute_t *tsens_attribute;
temp_sensor_fsm_t fsm;
temperature_sensor_clk_src_t clk_src;
};
static temperature_sensor_attribute_t *s_tsens_attribute_copy; static temperature_sensor_attribute_t *s_tsens_attribute_copy;
@ -53,7 +46,7 @@ static int inline accuracy_compare(const void *p1, const void *p2)
static esp_err_t temperature_sensor_attribute_table_sort(void) static esp_err_t temperature_sensor_attribute_table_sort(void)
{ {
s_tsens_attribute_copy = (temperature_sensor_attribute_t *)heap_caps_malloc(sizeof(temperature_sensor_attributes), MALLOC_CAP_DEFAULT); s_tsens_attribute_copy = (temperature_sensor_attribute_t *)heap_caps_malloc(sizeof(temperature_sensor_attributes), TEMPERATURE_SENSOR_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(s_tsens_attribute_copy != NULL, ESP_ERR_NO_MEM, TAG, "No space for s_tsens_attribute_copy"); 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_ATTR_RANGE_NUM; i++) { for (int i = 0 ; i < TEMPERATURE_SENSOR_ATTR_RANGE_NUM; i++) {
s_tsens_attribute_copy[i] = temperature_sensor_attributes[i]; s_tsens_attribute_copy[i] = temperature_sensor_attributes[i];
@ -75,6 +68,27 @@ static esp_err_t temperature_sensor_choose_best_range(temperature_sensor_handle_
return ESP_OK; return ESP_OK;
} }
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
static void IRAM_ATTR temperature_sensor_isr(void *arg)
{
temperature_sensor_ll_clear_intr();
bool cbs_yield = false;
temperature_sensor_handle_t tsens = (temperature_sensor_handle_t) arg;
temperature_sensor_threshold_event_data_t data = {
.celsius_value = s_temperature_regval_2_celsius(tsens, temperature_sensor_ll_get_raw_value()),
};
if (tsens->threshold_cbs) {
if (tsens->threshold_cbs(tsens, &data, tsens->cb_user_arg)) {
cbs_yield = true;
}
}
if (cbs_yield) {
portYIELD_FROM_ISR();
}
}
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens) esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens)
{ {
#if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG #if CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG
@ -121,6 +135,13 @@ esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens)
s_tsens_attribute_copy = NULL; s_tsens_attribute_copy = NULL;
regi2c_saradc_disable(); regi2c_saradc_disable();
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
temperature_sensor_ll_enable_intr(false);
if (tsens->temp_sensor_isr_handle) {
ESP_RETURN_ON_ERROR(esp_intr_free(tsens->temp_sensor_isr_handle), TAG, "uninstall interrupt service failed");
}
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
periph_module_disable(PERIPH_TEMPSENSOR_MODULE); periph_module_disable(PERIPH_TEMPSENSOR_MODULE);
free(tsens); free(tsens);
return ESP_OK; return ESP_OK;
@ -137,6 +158,11 @@ esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens)
} }
#endif #endif
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
temperature_sensor_ll_wakeup_enable(true);
temperature_sensor_ll_sample_enable(true);
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
temperature_sensor_ll_clk_enable(true); temperature_sensor_ll_clk_enable(true);
temperature_sensor_ll_clk_sel(tsens->clk_src); temperature_sensor_ll_clk_sel(tsens->clk_src);
temperature_sensor_ll_enable(true); temperature_sensor_ll_enable(true);
@ -149,6 +175,11 @@ esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens)
ESP_RETURN_ON_FALSE(tsens, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(tsens, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet"); ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet");
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
temperature_sensor_ll_wakeup_enable(false);
temperature_sensor_ll_sample_enable(false);
#endif
temperature_sensor_ll_enable(false); temperature_sensor_ll_enable(false);
#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC #if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) { if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) {
@ -185,7 +216,7 @@ esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, floa
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet"); ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "tsens not enabled yet");
uint32_t tsens_out = temperature_sensor_ll_get_raw_value(); uint32_t tsens_out = temperature_sensor_ll_get_raw_value();
ESP_LOGV(TAG, "tsens_out %"PRIu32, tsens_out); ESP_LOGD(TAG, "tsens_out %"PRIu32, tsens_out);
*out_celsius = parse_temp_sensor_raw_value(tsens_out, tsens->tsens_attribute->offset); *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) { if (*out_celsius < tsens->tsens_attribute->range_min || *out_celsius > tsens->tsens_attribute->range_max) {
@ -194,3 +225,86 @@ esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, floa
} }
return ESP_OK; return ESP_OK;
} }
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
static uint8_t s_temperature_celsius_2_regval(temperature_sensor_handle_t tsens, int8_t celsius)
{
return (uint8_t)((celsius + TEMPERATURE_SENSOR_LL_OFFSET_FACTOR + TEMPERATURE_SENSOR_LL_DAC_FACTOR * tsens->tsens_attribute->offset)/TEMPERATURE_SENSOR_LL_ADC_FACTOR);
}
IRAM_ATTR static int8_t s_temperature_regval_2_celsius(temperature_sensor_handle_t tsens, uint8_t regval)
{
return TEMPERATURE_SENSOR_LL_ADC_FACTOR * regval - TEMPERATURE_SENSOR_LL_DAC_FACTOR * tsens->tsens_attribute->offset - TEMPERATURE_SENSOR_LL_OFFSET_FACTOR;
}
esp_err_t temperature_sensor_set_absolute_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_abs_threshold_config_t *abs_cfg)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Temperature sensor has not been installed");
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "temperature sensor is not in init state");
ESP_RETURN_ON_FALSE(abs_cfg, ESP_ERR_INVALID_ARG, TAG, "Invalid callback configuration");
temperature_sensor_ll_set_sample_rate(0xffff);
temperature_sensor_ll_wakeup_mode(TEMPERATURE_SENSOR_LL_WAKE_ABSOLUTE);
temperature_sensor_ll_set_th_high_val(s_temperature_celsius_2_regval(tsens, abs_cfg->high_threshold));
temperature_sensor_ll_set_th_low_val(s_temperature_celsius_2_regval(tsens, abs_cfg->low_threshold));
return ret;
}
esp_err_t temperature_sensor_set_delta_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_delta_threshold_config_t *delta_cfg)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Temperature sensor has not been installed");
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "temperature sensor is not in init state");
ESP_RETURN_ON_FALSE(delta_cfg, ESP_ERR_INVALID_ARG, TAG, "Invalid callback configuration");
temperature_sensor_ll_set_sample_rate(0xffff);
temperature_sensor_ll_wakeup_mode(TEMPERATURE_SENSOR_LL_WAKE_DELTA);
temperature_sensor_ll_set_th_high_val((uint8_t)(delta_cfg->increase_delta / TEMPERATURE_SENSOR_LL_ADC_FACTOR));
temperature_sensor_ll_set_th_low_val((uint8_t)(delta_cfg->decrease_delta / TEMPERATURE_SENSOR_LL_ADC_FACTOR));
return ret;
}
esp_err_t temperature_sensor_register_callbacks(temperature_sensor_handle_t tsens, const temperature_sensor_event_callbacks_t *cbs, void *user_arg)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "Temperature sensor has not been installed");
ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "temperature sensor is not in init state");
ESP_RETURN_ON_FALSE(cbs, ESP_ERR_INVALID_ARG, TAG, "callback group pointer is invalid");
#if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE
if (cbs->on_threshold) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_threshold), ESP_ERR_INVALID_ARG, TAG, "threshold callback not in IRAM");
}
if (user_arg) {
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_arg), ESP_ERR_INVALID_ARG, TAG, "user argument not in internal RAM");
}
#endif
int isr_flags = TEMPERATURE_SENSOR_INTR_ALLOC_FLAGS;
#if SOC_ADC_TEMPERATURE_SHARE_INTR
isr_flags |= ESP_INTR_FLAG_SHARED;
#endif
// lazy install interrupt service.
if (!tsens->temp_sensor_isr_handle) {
ret = esp_intr_alloc_intrstatus(ETS_APB_ADC_INTR_SOURCE, isr_flags,
(uint32_t)temperature_sensor_ll_get_intr_status(),
TEMPERATURE_SENSOR_LL_INTR_MASK, temperature_sensor_isr, tsens, &tsens->temp_sensor_isr_handle);
}
if (cbs->on_threshold != NULL) {
temperature_sensor_ll_enable_intr(true);
temperature_sensor_ll_clear_intr();
tsens->threshold_cbs = cbs->on_threshold;
tsens->cb_user_arg = user_arg;
} else {
temperature_sensor_ll_enable_intr(false);
}
return ret;
}
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT

View File

@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdlib.h>
#include "soc/temperature_sensor_periph.h"
#include "hal/temperature_sensor_types.h"
#include "driver/temperature_sensor.h"
#include "esp_intr_alloc.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
TEMP_SENSOR_FSM_INIT,
TEMP_SENSOR_FSM_ENABLE,
} temp_sensor_fsm_t;
#if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE
#define TEMPERATURE_SENSOR_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
#define TEMPERATURE_SENSOR_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define TEMPERATURE_SENSOR_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
#define TEMPERATURE_SENSOR_MEM_ALLOC_CAPS (MALLOC_CAP_DEFAULT)
#endif
typedef struct temperature_sensor_obj_t temperature_sensor_obj_t;
struct temperature_sensor_obj_t {
const temperature_sensor_attribute_t *tsens_attribute;
temp_sensor_fsm_t fsm;
temperature_sensor_clk_src_t clk_src;
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
intr_handle_t temp_sensor_isr_handle;
temperature_thres_cb_t threshold_cbs;
void *cb_user_arg;
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
};
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -8,6 +8,11 @@
#include "esp_log.h" #include "esp_log.h"
#include "unity.h" #include "unity.h"
#include "driver/temperature_sensor.h" #include "driver/temperature_sensor.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "unity_test_utils_cache.h"
TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]") TEST_CASE("Temperature_sensor_driver_workflow_test", "[temperature_sensor]")
{ {
@ -79,3 +84,64 @@ TEST_CASE("Double Start-Stop test", "[temperature_sensor]")
TEST_ESP_OK(temperature_sensor_disable(temp_handle)); TEST_ESP_OK(temperature_sensor_disable(temp_handle));
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
} }
#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
IRAM_ATTR static bool temp_sensor_cbs_test(temperature_sensor_handle_t tsens, const temperature_sensor_threshold_event_data_t *edata, void *user_data)
{
uint8_t *times = (uint8_t*)user_data;
ESP_DRAM_LOGI("tsens", "Temperature value is higher or lower than threshold, restart...\n\n");
(*times)++;
return false;
}
#if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE
static void IRAM_ATTR test_delay_post_cache_disable(void *args)
{
esp_rom_delay_us(1000);
}
#endif
TEST_CASE("Temperature sensor callback test", "[temperature_sensor]")
{
printf("Initializing Temperature sensor\n");
float tsens_out;
temperature_sensor_config_t temp_sensor = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50);
temperature_sensor_handle_t temp_handle = NULL;
TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle));
temperature_sensor_event_callbacks_t cbs = {
.on_threshold = temp_sensor_cbs_test,
};
temperature_sensor_abs_threshold_config_t threshold_cfg = {
.high_threshold = 50,
.low_threshold = -10,
};
uint8_t temperature_alarm = 0;
uint8_t cnt = 10;
TEST_ESP_OK(temperature_sensor_set_absolute_threshold(temp_handle, &threshold_cfg));
temperature_sensor_register_callbacks(temp_handle, &cbs, &temperature_alarm);
TEST_ESP_OK(temperature_sensor_enable(temp_handle));
#if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE
printf("disable flash cache and check if we can still get temperature intr\r\n");
for (int i = 0; i < 100; i++) {
unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL);
}
#endif
while (cnt--) {
ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
printf("Temperature out celsius %f°C\n", tsens_out);
vTaskDelay(pdMS_TO_TICKS(1000));
}
TEST_ESP_OK(temperature_sensor_disable(temp_handle));
TEST_ESP_OK(temperature_sensor_uninstall(temp_handle));
printf("temperature alarm is %d\n", temperature_alarm);
// Note that on CI runner there is no way to heat the board to trigger such an interrupt.
// But locally test should be notice that alarm must be larger than 0.
TEST_ASSERT_GREATER_OR_EQUAL(0, temperature_alarm);
}
#endif // SOC_TEMPERATURE_SENSOR_INTR_SUPPORT

View File

@ -16,6 +16,14 @@ from pytest_embedded import Dut
'release', 'release',
], indirect=True) ], indirect=True)
def test_temperature_sensor_driver(dut: Dut) -> None: def test_temperature_sensor_driver(dut: Dut) -> None:
dut.expect('Press ENTER to see the list of tests') dut.run_all_single_board_cases()
dut.write('*')
dut.expect_unity_test_output(timeout=120)
@pytest.mark.esp32c6
@pytest.mark.esp32h2
@pytest.mark.generic
@pytest.mark.parametrize('config', [
'iram_safe',
], indirect=True)
def test_temperature_sensor_cbs(dut: Dut) -> None:
dut.run_all_single_board_cases()

View File

@ -0,0 +1,7 @@
CONFIG_COMPILER_DUMP_RTL_FILES=y
CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE=y
CONFIG_COMPILER_OPTIMIZATION_NONE=y
# silent the error check, as the error string are stored in rodata, causing RTL check failure
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
# place non-ISR FreeRTOS functions in Flash
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y

View File

@ -19,6 +19,7 @@
#include "hal/regi2c_ctrl.h" #include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h" #include "soc/regi2c_saradc.h"
#include "soc/apb_saradc_struct.h" #include "soc/apb_saradc_struct.h"
#include "soc/apb_saradc_reg.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
@ -34,6 +35,13 @@ extern "C" {
#define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88) #define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88)
#define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52) #define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52)
#define TEMPERATURE_SENSOR_LL_INTR_MASK APB_SARADC_APB_SARADC_TSENS_INT_ST
typedef enum {
TEMPERATURE_SENSOR_LL_WAKE_ABSOLUTE = 0,
TEMPERATURE_SENSOR_LL_WAKE_DELTA = 1,
} temperature_sensor_ll_wakeup_mode_t;
/** /**
* @brief Enable the temperature sensor power. * @brief Enable the temperature sensor power.
* *
@ -90,6 +98,7 @@ static inline void temperature_sensor_ll_set_range(uint32_t range)
* *
* @return uint32_t raw_value * @return uint32_t raw_value
*/ */
__attribute__((always_inline))
static inline uint32_t temperature_sensor_ll_get_raw_value(void) static inline uint32_t temperature_sensor_ll_get_raw_value(void)
{ {
return APB_SARADC.saradc_apb_tsens_ctrl.saradc_tsens_out; return APB_SARADC.saradc_apb_tsens_ctrl.saradc_tsens_out;
@ -187,6 +196,7 @@ static inline void temperature_sensor_ll_enable_intr(bool enable)
/** /**
* @brief Clear temperature sensor interrupt * @brief Clear temperature sensor interrupt
*/ */
__attribute__((always_inline))
static inline void temperature_sensor_ll_clear_intr(void) static inline void temperature_sensor_ll_clear_intr(void)
{ {
APB_SARADC.saradc_int_clr.saradc_apb_saradc_tsens_int_clr = 1; APB_SARADC.saradc_int_clr.saradc_apb_saradc_tsens_int_clr = 1;
@ -194,12 +204,10 @@ static inline void temperature_sensor_ll_clear_intr(void)
/** /**
* @brief Get temperature sensor interrupt status. * @brief Get temperature sensor interrupt status.
*
* @param[out] int_status interrupt status.
*/ */
static inline void temperature_sensor_ll_get_intr_status(uint8_t *int_status) static inline volatile void *temperature_sensor_ll_get_intr_status(void)
{ {
*int_status = APB_SARADC.saradc_int_st.saradc_apb_saradc_tsens_int_st; return &APB_SARADC.saradc_int_st;
} }
/** /**

View File

@ -19,6 +19,7 @@
#include "hal/regi2c_ctrl.h" #include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h" #include "soc/regi2c_saradc.h"
#include "soc/apb_saradc_struct.h" #include "soc/apb_saradc_struct.h"
#include "soc/apb_saradc_reg.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "soc/pcr_struct.h" #include "soc/pcr_struct.h"
@ -34,6 +35,13 @@ extern "C" {
#define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88) #define TEMPERATURE_SENSOR_LL_DAC_FACTOR (27.88)
#define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52) #define TEMPERATURE_SENSOR_LL_OFFSET_FACTOR (20.52)
#define TEMPERATURE_SENSOR_LL_INTR_MASK APB_SARADC_APB_SARADC_TSENS_INT_ST
typedef enum {
TEMPERATURE_SENSOR_LL_WAKE_ABSOLUTE = 0,
TEMPERATURE_SENSOR_LL_WAKE_DELTA = 1,
} temperature_sensor_ll_wakeup_mode_t;
/** /**
* @brief Enable the temperature sensor power. * @brief Enable the temperature sensor power.
* *
@ -90,6 +98,7 @@ static inline void temperature_sensor_ll_set_range(uint32_t range)
* *
* @return uint32_t raw_value * @return uint32_t raw_value
*/ */
__attribute__((always_inline))
static inline uint32_t temperature_sensor_ll_get_raw_value(void) static inline uint32_t temperature_sensor_ll_get_raw_value(void)
{ {
return APB_SARADC.saradc_apb_tsens_ctrl.saradc_tsens_out; return APB_SARADC.saradc_apb_tsens_ctrl.saradc_tsens_out;
@ -187,6 +196,7 @@ static inline void temperature_sensor_ll_enable_intr(bool enable)
/** /**
* @brief Clear temperature sensor interrupt * @brief Clear temperature sensor interrupt
*/ */
__attribute__((always_inline))
static inline void temperature_sensor_ll_clear_intr(void) static inline void temperature_sensor_ll_clear_intr(void)
{ {
APB_SARADC.saradc_int_clr.saradc_apb_saradc_tsens_int_clr = 1; APB_SARADC.saradc_int_clr.saradc_apb_saradc_tsens_int_clr = 1;
@ -194,12 +204,10 @@ static inline void temperature_sensor_ll_clear_intr(void)
/** /**
* @brief Get temperature sensor interrupt status. * @brief Get temperature sensor interrupt status.
*
* @param[out] int_status interrupt status.
*/ */
static inline void temperature_sensor_ll_get_intr_status(uint8_t *int_status) static inline volatile void *temperature_sensor_ll_get_intr_status(void)
{ {
*int_status = APB_SARADC.saradc_int_st.saradc_apb_saradc_tsens_int_st; return &APB_SARADC.saradc_int_st;
} }
/** /**

View File

@ -271,6 +271,10 @@ config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool bool
default n default n
config SOC_ADC_TEMPERATURE_SHARE_INTR
bool
default y
config SOC_APB_BACKUP_DMA config SOC_APB_BACKUP_DMA
bool bool
default n default n
@ -1099,6 +1103,10 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL
bool bool
default y default y
config SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
bool
default y
config SOC_WIFI_HW_TSF config SOC_WIFI_HW_TSF
bool bool
default y default y

View File

@ -113,6 +113,9 @@
/*!< Calibration */ /*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (0) /*!< support HW offset calibration version 1*/ #define SOC_ADC_CALIBRATION_V1_SUPPORTED (0) /*!< support HW offset calibration version 1*/
/*!< Interrupt */
#define SOC_ADC_TEMPERATURE_SHARE_INTR (1)
// ESP32C6-TODO: Copy from esp32c6, need check // ESP32C6-TODO: Copy from esp32c6, need check
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/ /*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (0) #define SOC_APB_BACKUP_DMA (0)
@ -460,7 +463,8 @@
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/
#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1)
#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1)
#define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1)
/*------------------------------------ WI-FI CAPS ------------------------------------*/ /*------------------------------------ WI-FI CAPS ------------------------------------*/
#define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ #define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */

View File

@ -235,6 +235,10 @@ config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool bool
default n default n
config SOC_ADC_TEMPERATURE_SHARE_INTR
bool
default y
config SOC_APB_BACKUP_DMA config SOC_APB_BACKUP_DMA
bool bool
default n default n
@ -1035,6 +1039,10 @@ config SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL
bool bool
default y default y
config SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
bool
default y
config SOC_BLE_SUPPORTED config SOC_BLE_SUPPORTED
bool bool
default y default y

View File

@ -1,5 +1,5 @@
/** /**
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -14,7 +14,7 @@ extern "C" {
/** APB_SARADC_CTRL_REG register /** APB_SARADC_CTRL_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_CTRL_REG (DR_REG_APB_BASE + 0x0) #define APB_SARADC_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x0)
/** APB_SARADC_SARADC_START_FORCE : R/W; bitpos: [0]; default: 0; /** APB_SARADC_SARADC_START_FORCE : R/W; bitpos: [0]; default: 0;
* select software enable saradc sample * select software enable saradc sample
*/ */
@ -82,7 +82,7 @@ extern "C" {
/** APB_SARADC_CTRL2_REG register /** APB_SARADC_CTRL2_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_CTRL2_REG (DR_REG_APB_BASE + 0x4) #define APB_SARADC_CTRL2_REG (DR_REG_APB_SARADC_BASE + 0x4)
/** APB_SARADC_SARADC_MEAS_NUM_LIMIT : R/W; bitpos: [0]; default: 0; /** APB_SARADC_SARADC_MEAS_NUM_LIMIT : R/W; bitpos: [0]; default: 0;
* enable max meas num * enable max meas num
*/ */
@ -129,7 +129,7 @@ extern "C" {
/** APB_SARADC_FILTER_CTRL1_REG register /** APB_SARADC_FILTER_CTRL1_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_FILTER_CTRL1_REG (DR_REG_APB_BASE + 0x8) #define APB_SARADC_FILTER_CTRL1_REG (DR_REG_APB_SARADC_BASE + 0x8)
/** APB_SARADC_APB_SARADC_FILTER_FACTOR1 : R/W; bitpos: [28:26]; default: 0; /** APB_SARADC_APB_SARADC_FILTER_FACTOR1 : R/W; bitpos: [28:26]; default: 0;
* Factor of saradc filter1 * Factor of saradc filter1
*/ */
@ -148,7 +148,7 @@ extern "C" {
/** APB_SARADC_FSM_WAIT_REG register /** APB_SARADC_FSM_WAIT_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_FSM_WAIT_REG (DR_REG_APB_BASE + 0xc) #define APB_SARADC_FSM_WAIT_REG (DR_REG_APB_SARADC_BASE + 0xc)
/** APB_SARADC_SARADC_XPD_WAIT : R/W; bitpos: [7:0]; default: 8; /** APB_SARADC_SARADC_XPD_WAIT : R/W; bitpos: [7:0]; default: 8;
* saradc_xpd_wait * saradc_xpd_wait
*/ */
@ -174,7 +174,7 @@ extern "C" {
/** APB_SARADC_SAR1_STATUS_REG register /** APB_SARADC_SAR1_STATUS_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR1_STATUS_REG (DR_REG_APB_BASE + 0x10) #define APB_SARADC_SAR1_STATUS_REG (DR_REG_APB_SARADC_BASE + 0x10)
/** APB_SARADC_SARADC_SAR1_STATUS : RO; bitpos: [31:0]; default: 536870912; /** APB_SARADC_SARADC_SAR1_STATUS : RO; bitpos: [31:0]; default: 536870912;
* saradc1 status about data and channel * saradc1 status about data and channel
*/ */
@ -186,7 +186,7 @@ extern "C" {
/** APB_SARADC_SAR2_STATUS_REG register /** APB_SARADC_SAR2_STATUS_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR2_STATUS_REG (DR_REG_APB_BASE + 0x14) #define APB_SARADC_SAR2_STATUS_REG (DR_REG_APB_SARADC_BASE + 0x14)
/** APB_SARADC_SARADC_SAR2_STATUS : RO; bitpos: [31:0]; default: 536870912; /** APB_SARADC_SARADC_SAR2_STATUS : RO; bitpos: [31:0]; default: 536870912;
* saradc2 status about data and channel * saradc2 status about data and channel
*/ */
@ -198,7 +198,7 @@ extern "C" {
/** APB_SARADC_SAR_PATT_TAB1_REG register /** APB_SARADC_SAR_PATT_TAB1_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR_PATT_TAB1_REG (DR_REG_APB_BASE + 0x18) #define APB_SARADC_SAR_PATT_TAB1_REG (DR_REG_APB_SARADC_BASE + 0x18)
/** APB_SARADC_SARADC_SAR_PATT_TAB1 : R/W; bitpos: [23:0]; default: 16777215; /** APB_SARADC_SARADC_SAR_PATT_TAB1 : R/W; bitpos: [23:0]; default: 16777215;
* item 0 ~ 3 for pattern table 1 (each item one byte) * item 0 ~ 3 for pattern table 1 (each item one byte)
*/ */
@ -210,7 +210,7 @@ extern "C" {
/** APB_SARADC_SAR_PATT_TAB2_REG register /** APB_SARADC_SAR_PATT_TAB2_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR_PATT_TAB2_REG (DR_REG_APB_BASE + 0x1c) #define APB_SARADC_SAR_PATT_TAB2_REG (DR_REG_APB_SARADC_BASE + 0x1c)
/** APB_SARADC_SARADC_SAR_PATT_TAB2 : R/W; bitpos: [23:0]; default: 16777215; /** APB_SARADC_SARADC_SAR_PATT_TAB2 : R/W; bitpos: [23:0]; default: 16777215;
* Item 4 ~ 7 for pattern table 1 (each item one byte) * Item 4 ~ 7 for pattern table 1 (each item one byte)
*/ */
@ -222,7 +222,7 @@ extern "C" {
/** APB_SARADC_ONETIME_SAMPLE_REG register /** APB_SARADC_ONETIME_SAMPLE_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_ONETIME_SAMPLE_REG (DR_REG_APB_BASE + 0x20) #define APB_SARADC_ONETIME_SAMPLE_REG (DR_REG_APB_SARADC_BASE + 0x20)
/** APB_SARADC_SARADC_ONETIME_ATTEN : R/W; bitpos: [24:23]; default: 0; /** APB_SARADC_SARADC_ONETIME_ATTEN : R/W; bitpos: [24:23]; default: 0;
* configure onetime atten * configure onetime atten
*/ */
@ -262,7 +262,7 @@ extern "C" {
/** APB_SARADC_ARB_CTRL_REG register /** APB_SARADC_ARB_CTRL_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_ARB_CTRL_REG (DR_REG_APB_BASE + 0x24) #define APB_SARADC_ARB_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x24)
/** APB_SARADC_ADC_ARB_APB_FORCE : R/W; bitpos: [2]; default: 0; /** APB_SARADC_ADC_ARB_APB_FORCE : R/W; bitpos: [2]; default: 0;
* adc2 arbiter force to enableapb controller * adc2 arbiter force to enableapb controller
*/ */
@ -323,7 +323,7 @@ extern "C" {
/** APB_SARADC_FILTER_CTRL0_REG register /** APB_SARADC_FILTER_CTRL0_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_FILTER_CTRL0_REG (DR_REG_APB_BASE + 0x28) #define APB_SARADC_FILTER_CTRL0_REG (DR_REG_APB_SARADC_BASE + 0x28)
/** APB_SARADC_APB_SARADC_FILTER_CHANNEL1 : R/W; bitpos: [21:18]; default: 13; /** APB_SARADC_APB_SARADC_FILTER_CHANNEL1 : R/W; bitpos: [21:18]; default: 13;
* configure filter1 to adc channel * configure filter1 to adc channel
*/ */
@ -349,7 +349,7 @@ extern "C" {
/** APB_SARADC_SAR1DATA_STATUS_REG register /** APB_SARADC_SAR1DATA_STATUS_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR1DATA_STATUS_REG (DR_REG_APB_BASE + 0x2c) #define APB_SARADC_SAR1DATA_STATUS_REG (DR_REG_APB_SARADC_BASE + 0x2c)
/** APB_SARADC_APB_SARADC1_DATA : RO; bitpos: [16:0]; default: 0; /** APB_SARADC_APB_SARADC1_DATA : RO; bitpos: [16:0]; default: 0;
* saradc1 data * saradc1 data
*/ */
@ -361,7 +361,7 @@ extern "C" {
/** APB_SARADC_SAR2DATA_STATUS_REG register /** APB_SARADC_SAR2DATA_STATUS_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_SAR2DATA_STATUS_REG (DR_REG_APB_BASE + 0x30) #define APB_SARADC_SAR2DATA_STATUS_REG (DR_REG_APB_SARADC_BASE + 0x30)
/** APB_SARADC_APB_SARADC2_DATA : RO; bitpos: [16:0]; default: 0; /** APB_SARADC_APB_SARADC2_DATA : RO; bitpos: [16:0]; default: 0;
* saradc2 data * saradc2 data
*/ */
@ -373,7 +373,7 @@ extern "C" {
/** APB_SARADC_THRES0_CTRL_REG register /** APB_SARADC_THRES0_CTRL_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_THRES0_CTRL_REG (DR_REG_APB_BASE + 0x34) #define APB_SARADC_THRES0_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x34)
/** APB_SARADC_APB_SARADC_THRES0_CHANNEL : R/W; bitpos: [3:0]; default: 13; /** APB_SARADC_APB_SARADC_THRES0_CHANNEL : R/W; bitpos: [3:0]; default: 13;
* configure thres0 to adc channel * configure thres0 to adc channel
*/ */
@ -399,7 +399,7 @@ extern "C" {
/** APB_SARADC_THRES1_CTRL_REG register /** APB_SARADC_THRES1_CTRL_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_THRES1_CTRL_REG (DR_REG_APB_BASE + 0x38) #define APB_SARADC_THRES1_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x38)
/** APB_SARADC_APB_SARADC_THRES1_CHANNEL : R/W; bitpos: [3:0]; default: 13; /** APB_SARADC_APB_SARADC_THRES1_CHANNEL : R/W; bitpos: [3:0]; default: 13;
* configure thres1 to adc channel * configure thres1 to adc channel
*/ */
@ -425,7 +425,7 @@ extern "C" {
/** APB_SARADC_THRES_CTRL_REG register /** APB_SARADC_THRES_CTRL_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_THRES_CTRL_REG (DR_REG_APB_BASE + 0x3c) #define APB_SARADC_THRES_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x3c)
/** APB_SARADC_APB_SARADC_THRES_ALL_EN : R/W; bitpos: [27]; default: 0; /** APB_SARADC_APB_SARADC_THRES_ALL_EN : R/W; bitpos: [27]; default: 0;
* enable thres to all channel * enable thres to all channel
*/ */
@ -451,7 +451,7 @@ extern "C" {
/** APB_SARADC_INT_ENA_REG register /** APB_SARADC_INT_ENA_REG register
* digital saradc int register * digital saradc int register
*/ */
#define APB_SARADC_INT_ENA_REG (DR_REG_APB_BASE + 0x40) #define APB_SARADC_INT_ENA_REG (DR_REG_APB_SARADC_BASE + 0x40)
/** APB_SARADC_APB_SARADC_TSENS_INT_ENA : R/W; bitpos: [25]; default: 0; /** APB_SARADC_APB_SARADC_TSENS_INT_ENA : R/W; bitpos: [25]; default: 0;
* tsens low interrupt enable * tsens low interrupt enable
*/ */
@ -505,7 +505,7 @@ extern "C" {
/** APB_SARADC_INT_RAW_REG register /** APB_SARADC_INT_RAW_REG register
* digital saradc int register * digital saradc int register
*/ */
#define APB_SARADC_INT_RAW_REG (DR_REG_APB_BASE + 0x44) #define APB_SARADC_INT_RAW_REG (DR_REG_APB_SARADC_BASE + 0x44)
/** APB_SARADC_APB_SARADC_TSENS_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0; /** APB_SARADC_APB_SARADC_TSENS_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0;
* saradc tsens interrupt raw * saradc tsens interrupt raw
*/ */
@ -559,7 +559,7 @@ extern "C" {
/** APB_SARADC_INT_ST_REG register /** APB_SARADC_INT_ST_REG register
* digital saradc int register * digital saradc int register
*/ */
#define APB_SARADC_INT_ST_REG (DR_REG_APB_BASE + 0x48) #define APB_SARADC_INT_ST_REG (DR_REG_APB_SARADC_BASE + 0x48)
/** APB_SARADC_APB_SARADC_TSENS_INT_ST : RO; bitpos: [25]; default: 0; /** APB_SARADC_APB_SARADC_TSENS_INT_ST : RO; bitpos: [25]; default: 0;
* saradc tsens interrupt state * saradc tsens interrupt state
*/ */
@ -613,7 +613,7 @@ extern "C" {
/** APB_SARADC_INT_CLR_REG register /** APB_SARADC_INT_CLR_REG register
* digital saradc int register * digital saradc int register
*/ */
#define APB_SARADC_INT_CLR_REG (DR_REG_APB_BASE + 0x4c) #define APB_SARADC_INT_CLR_REG (DR_REG_APB_SARADC_BASE + 0x4c)
/** APB_SARADC_APB_SARADC_TSENS_INT_CLR : WT; bitpos: [25]; default: 0; /** APB_SARADC_APB_SARADC_TSENS_INT_CLR : WT; bitpos: [25]; default: 0;
* saradc tsens interrupt clear * saradc tsens interrupt clear
*/ */
@ -667,7 +667,7 @@ extern "C" {
/** APB_SARADC_DMA_CONF_REG register /** APB_SARADC_DMA_CONF_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_DMA_CONF_REG (DR_REG_APB_BASE + 0x50) #define APB_SARADC_DMA_CONF_REG (DR_REG_APB_SARADC_BASE + 0x50)
/** APB_SARADC_APB_ADC_EOF_NUM : R/W; bitpos: [15:0]; default: 255; /** APB_SARADC_APB_ADC_EOF_NUM : R/W; bitpos: [15:0]; default: 255;
* the dma_in_suc_eof gen when sample cnt = spi_eof_num * the dma_in_suc_eof gen when sample cnt = spi_eof_num
*/ */
@ -693,7 +693,7 @@ extern "C" {
/** APB_SARADC_CLKM_CONF_REG register /** APB_SARADC_CLKM_CONF_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_CLKM_CONF_REG (DR_REG_APB_BASE + 0x54) #define APB_SARADC_CLKM_CONF_REG (DR_REG_APB_SARADC_BASE + 0x54)
/** APB_SARADC_CLKM_DIV_NUM : R/W; bitpos: [7:0]; default: 4; /** APB_SARADC_CLKM_DIV_NUM : R/W; bitpos: [7:0]; default: 4;
* Integral I2S clock divider value * Integral I2S clock divider value
*/ */
@ -733,7 +733,7 @@ extern "C" {
/** APB_SARADC_APB_TSENS_CTRL_REG register /** APB_SARADC_APB_TSENS_CTRL_REG register
* digital tsens configure register * digital tsens configure register
*/ */
#define APB_SARADC_APB_TSENS_CTRL_REG (DR_REG_APB_BASE + 0x58) #define APB_SARADC_APB_TSENS_CTRL_REG (DR_REG_APB_SARADC_BASE + 0x58)
/** APB_SARADC_TSENS_OUT : RO; bitpos: [7:0]; default: 128; /** APB_SARADC_TSENS_OUT : RO; bitpos: [7:0]; default: 128;
* temperature sensor data out * temperature sensor data out
*/ */
@ -766,7 +766,7 @@ extern "C" {
/** APB_SARADC_TSENS_CTRL2_REG register /** APB_SARADC_TSENS_CTRL2_REG register
* digital tsens configure register * digital tsens configure register
*/ */
#define APB_SARADC_TSENS_CTRL2_REG (DR_REG_APB_BASE + 0x5c) #define APB_SARADC_TSENS_CTRL2_REG (DR_REG_APB_SARADC_BASE + 0x5c)
/** APB_SARADC_TSENS_XPD_WAIT : R/W; bitpos: [11:0]; default: 2; /** APB_SARADC_TSENS_XPD_WAIT : R/W; bitpos: [11:0]; default: 2;
* the time that power up tsens need wait * the time that power up tsens need wait
*/ */
@ -799,7 +799,7 @@ extern "C" {
/** APB_SARADC_CALI_REG register /** APB_SARADC_CALI_REG register
* digital saradc configure register * digital saradc configure register
*/ */
#define APB_SARADC_CALI_REG (DR_REG_APB_BASE + 0x60) #define APB_SARADC_CALI_REG (DR_REG_APB_SARADC_BASE + 0x60)
/** APB_SARADC_APB_SARADC_CALI_CFG : R/W; bitpos: [16:0]; default: 32768; /** APB_SARADC_APB_SARADC_CALI_CFG : R/W; bitpos: [16:0]; default: 32768;
* saradc cali factor * saradc cali factor
*/ */
@ -811,7 +811,7 @@ extern "C" {
/** APB_TSENS_WAKE_REG register /** APB_TSENS_WAKE_REG register
* digital tsens configure register * digital tsens configure register
*/ */
#define APB_TSENS_WAKE_REG (DR_REG_APB_BASE + 0x64) #define APB_TSENS_WAKE_REG (DR_REG_APB_SARADC_BASE + 0x64)
/** APB_SARADC_WAKEUP_TH_LOW : R/W; bitpos: [7:0]; default: 0; /** APB_SARADC_WAKEUP_TH_LOW : R/W; bitpos: [7:0]; default: 0;
* reg_wakeup_th_low * reg_wakeup_th_low
*/ */
@ -851,7 +851,7 @@ extern "C" {
/** APB_TSENS_SAMPLE_REG register /** APB_TSENS_SAMPLE_REG register
* digital tsens configure register * digital tsens configure register
*/ */
#define APB_TSENS_SAMPLE_REG (DR_REG_APB_BASE + 0x68) #define APB_TSENS_SAMPLE_REG (DR_REG_APB_SARADC_BASE + 0x68)
/** APB_SARADC_TSENS_SAMPLE_RATE : R/W; bitpos: [15:0]; default: 20; /** APB_SARADC_TSENS_SAMPLE_RATE : R/W; bitpos: [15:0]; default: 20;
* HW sample rate * HW sample rate
*/ */
@ -870,7 +870,7 @@ extern "C" {
/** APB_SARADC_CTRL_DATE_REG register /** APB_SARADC_CTRL_DATE_REG register
* version * version
*/ */
#define APB_SARADC_CTRL_DATE_REG (DR_REG_APB_BASE + 0x3fc) #define APB_SARADC_CTRL_DATE_REG (DR_REG_APB_SARADC_BASE + 0x3fc)
/** APB_SARADC_DATE : R/W; bitpos: [31:0]; default: 35676736; /** APB_SARADC_DATE : R/W; bitpos: [31:0]; default: 35676736;
* version * version
*/ */

View File

@ -109,6 +109,9 @@
/*!< Calibration */ /*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (0) /*!< support HW offset calibration version 1*/ #define SOC_ADC_CALIBRATION_V1_SUPPORTED (0) /*!< support HW offset calibration version 1*/
/*!< Interrupt */
#define SOC_ADC_TEMPERATURE_SHARE_INTR (1)
// ESP32H2-TODO: Copy from esp32c6, need check // ESP32H2-TODO: Copy from esp32c6, need check
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/ /*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (0) #define SOC_APB_BACKUP_DMA (0)
@ -454,10 +457,10 @@
#define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */ #define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */
// TODO: IDF-6229 (Copy from esp32c6, need check)
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/
#define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1)
#define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1)
#define SOC_TEMPERATURE_SENSOR_INTR_SUPPORT (1)
/*---------------------------------- Bluetooth CAPS ----------------------------------*/ /*---------------------------------- Bluetooth CAPS ----------------------------------*/
#define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */

View File

@ -29,11 +29,15 @@ Due to restrictions of hardware, the sensor has predefined measurement ranges wi
Functional Overview 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. .. list::
- `Enable and Disable Temperature Sensor <#enable-and-disable-temperature-sensor>`__ - covers how to enable and disable the temperature sensor.
- `Get Temperature Value <#get-temperature-value>`__ - covers how to get the real-time temperature value. - `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.
- `Power Management <#power-management>`__ - covers how temperature sensor is affected when changing power mode (i.e. light sleep). - `Enable and Disable Temperature Sensor <#enable-and-disable-temperature-sensor>`__ - covers how to enable and disable the temperature sensor.
- `Thread Safety <#thread-safety>`__ - covers how to make the driver to be thread safe. - `Get Temperature Value <#get-temperature-value>`__ - covers how to get the real-time temperature value.
:SOC_TEMPERATURE_SENSOR_INTR_SUPPORT: - `Temperature Threshold Interrupt <#install-temperature-threshold-callback>`__ - describes how to register a temperature threshold callback.
- `Power Management <#power-management>`__ - covers how temperature sensor is affected when changing power mode (i.e. light sleep).
:SOC_TEMPERATURE_SENSOR_INTR_SUPPORT: - `IRAM Safe <#iram-safe>`__ - describes tips on how to make the temperature sensor interrupt work better along with a disabled cache.
- `Thread Safety <#thread-safety>`__ - covers how to make the driver to be thread safe.
Resource Allocation Resource Allocation
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
@ -89,11 +93,58 @@ After the temperature sensor is enabled by :cpp:func:`temperature_sensor_enable`
// Disable the temperature sensor if it's not needed and save the power // Disable the temperature sensor if it's not needed and save the power
ESP_ERROR_CHECK(temperature_sensor_disable(temp_handle)); ESP_ERROR_CHECK(temperature_sensor_disable(temp_handle));
.. only:: SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
Install Temperature Threshold Callback
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{IDF_TARGET_NAME} supports automatically triggering to monitor the temperature value continuously. When temperature value reaches a given threshold, an interrupt will happen. Thus users can install their own interrupt callback functions to do what they want. (e.g. alarm, restart, etc.). Following information indicates how to prepare a threshold callback.
- :cpp:member:`temperature_sensor_event_callbacks_t::on_threshold`. As this function is called within the ISR context, you must ensure that the function does not attempt to block (e.g., by making sure that only FreeRTOS APIs with ``ISR`` suffix are called from within the function, etc.). The function prototype is declared in :cpp:type:`temperature_thres_cb_t`.
You can save your own context to :cpp:func:`temperature_sensor_register_callbacks` as well, via the parameter ``user_arg``. The user data will be directly passed to the callback function.
.. code:: c
IRAM_ATTR static bool temp_sensor_monitor_cbs(temperature_sensor_handle_t tsens, const temperature_sensor_threshold_event_data_t *edata, void *user_data)
{
ESP_DRAM_LOGI("tsens", "Temperature value is higher or lower than threshold, value is %d\n...\n\n", edata->celsius_value);
return false;
}
// Callback configurations
temperature_sensor_abs_threshold_config_t threshold_cfg = {
.high_threshold = 50,
.low_threshold = -10,
};
// Set absolute value monitor threshold.
temperature_sensor_set_absolute_threshold(temp_sensor, &threshold_cfg);
// Register interrupt callback
temperature_sensor_event_callbacks_t cbs = {
.on_threshold = temp_sensor_monitor_cbs,
};
// Install temperature callback.
temperature_sensor_register_callbacks(temp_sensor, &cbs, NULL);
Power Management 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). 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).
.. only:: SOC_TEMPERATURE_SENSOR_INTR_SUPPORT
IRAM Safe
^^^^^^^^^
By default, the temperature sensor interrupt will be deferred when the Cache is disabled for reasons like writing/erasing Flash. Thus the event callback functions will not get executed in time, which is not expected in a real-time application.
There's a Kconfig option :ref:`CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE` that will:
1. Enable the interrupt being serviced even when cache is disabled.
2. Place all functions that used by the ISR into IRAM.
This will allow the interrupt to run while the cache is disabled but will come at the cost of increased IRAM consumption.
Thread Safety Thread Safety
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -112,7 +163,10 @@ Unexpected Behaviors
Application Example Application Example
------------------- -------------------
* Temperature sensor reading example: :example:`peripherals/temp_sensor`. .. list::
* Temperature sensor reading example: :example:`peripherals/temperature_sensor/temp_sensor`.
:SOC_TEMPERATURE_SENSOR_INTR_SUPPORT: * Temperature sensor value monitor example: :example:`peripherals/temperature_sensor/temp_sensor`.
API Reference API Reference
---------------------------------- ----------------------------------