diff --git a/components/esp_driver_tsens/include/driver/temperature_sensor.h b/components/esp_driver_tsens/include/driver/temperature_sensor.h index f918597f3de..802d7f90fc2 100644 --- a/components/esp_driver_tsens/include/driver/temperature_sensor.h +++ b/components/esp_driver_tsens/include/driver/temperature_sensor.h @@ -30,6 +30,8 @@ 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. */ + int intr_priority; /**< Temperature sensor interrupt priority, + if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */ struct { uint32_t allow_pd; /**< If set, the driver will backup/restore the temperature sensor registers before/after entering/exist sleep mode. By this approach, the system can power off temperature sensor's power domain. @@ -46,6 +48,7 @@ typedef struct { .range_min = min, \ .range_max = max, \ .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, \ + .intr_priority = 0, \ .flags = { \ .allow_pd = 0, \ }, \ diff --git a/components/esp_driver_tsens/src/temperature_sensor.c b/components/esp_driver_tsens/src/temperature_sensor.c index 38378095c36..afaadda39b3 100644 --- a/components/esp_driver_tsens/src/temperature_sensor.c +++ b/components/esp_driver_tsens/src/temperature_sensor.c @@ -133,6 +133,11 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co esp_err_t ret = ESP_OK; 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"); + if (tsens_config->intr_priority) { + ESP_RETURN_ON_FALSE(tsens_config->intr_priority > 0 && + ((1 << tsens_config->intr_priority) & TEMPERATURE_SENSOR_ALLOW_INTR_PRIORITY_MASK), + ESP_ERR_INVALID_ARG, TAG, "invalid interrupt priority:%d", tsens_config->intr_priority); + } temperature_sensor_handle_t tsens = NULL; tsens = (temperature_sensor_obj_t *) heap_caps_calloc(1, sizeof(temperature_sensor_obj_t), MALLOC_CAP_DEFAULT); ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_NO_MEM, TAG, "no mem for temp sensor"); @@ -141,6 +146,9 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co } else { tsens->clk_src = tsens_config->clk_src; } +#if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + tsens->intr_priority = tsens_config->intr_priority; +#endif #if !SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION ESP_RETURN_ON_FALSE(tsens_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep"); @@ -362,7 +370,8 @@ esp_err_t temperature_sensor_register_callbacks(temperature_sensor_handle_t tsen } #endif - int isr_flags = TEMPERATURE_SENSOR_INTR_ALLOC_FLAGS; + int isr_flags = TEMPERATURE_SENSOR_INTR_ALLOC_FLAGS | + (tsens->intr_priority ? (1 << tsens->intr_priority) : TEMPERATURE_SENSOR_ALLOW_INTR_PRIORITY_MASK); #if SOC_ADC_TEMPERATURE_SHARE_INTR isr_flags |= ESP_INTR_FLAG_SHARED; #endif diff --git a/components/esp_driver_tsens/src/temperature_sensor_private.h b/components/esp_driver_tsens/src/temperature_sensor_private.h index 81210b45a4d..48d854d06b7 100644 --- a/components/esp_driver_tsens/src/temperature_sensor_private.h +++ b/components/esp_driver_tsens/src/temperature_sensor_private.h @@ -28,12 +28,13 @@ typedef enum { } 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_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED) #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_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED) #define TEMPERATURE_SENSOR_MEM_ALLOC_CAPS (MALLOC_CAP_DEFAULT) #endif +#define TEMPERATURE_SENSOR_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED // Use retention link only when the target supports sleep retention and PM is enabled #define TEMPERATURE_SENSOR_USE_RETENTION_LINK (SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN) @@ -57,6 +58,7 @@ struct temperature_sensor_obj_t { temp_sensor_fsm_t fsm; temperature_sensor_clk_src_t clk_src; #if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT + int intr_priority; intr_handle_t temp_sensor_isr_handle; temperature_thres_cb_t threshold_cbs; void *cb_user_arg; diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp index e52b4b3b533..c4dc0fbde02 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/main/test_temperature_sensor.cpp @@ -101,6 +101,29 @@ IRAM_ATTR static bool temp_sensor_cbs_test(temperature_sensor_handle_t tsens, co return false; } +TEST_CASE("Temperature sensor interrupt priority test", "[temperature_sensor]") +{ + temperature_sensor_config_t temp_sensor = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50); + temperature_sensor_handle_t temp_handle = NULL; + temperature_sensor_event_callbacks_t cbs = { + .on_threshold = temp_sensor_cbs_test, + }; + uint8_t temperature_alarm = 0; + + TEST_ASSERT_EQUAL(0, temp_sensor.intr_priority); + temp_sensor.intr_priority = -1; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, temperature_sensor_install(&temp_sensor, &temp_handle)); + temp_sensor.intr_priority = 4; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, temperature_sensor_install(&temp_sensor, &temp_handle)); + + for (int priority = 1; priority <= 3; priority++) { + temp_sensor.intr_priority = priority; + TEST_ESP_OK(temperature_sensor_install(&temp_sensor, &temp_handle)); + TEST_ESP_OK(temperature_sensor_register_callbacks(temp_handle, &cbs, &temperature_alarm)); + TEST_ESP_OK(temperature_sensor_uninstall(temp_handle)); + } +} + #if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE static void IRAM_ATTR test_delay_post_cache_disable(void *args) { @@ -127,7 +150,7 @@ TEST_CASE("Temperature sensor callback test", "[temperature_sensor]") 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_register_callbacks(temp_handle, &cbs, &temperature_alarm)); TEST_ESP_OK(temperature_sensor_enable(temp_handle)); #if CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE @@ -162,6 +185,7 @@ static void test_temperature_sensor_sleep_retention(bool allow_pd) .range_min = 10, .range_max = 50, .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, + .intr_priority = 0, .flags = { .allow_pd = allow_pd, }, diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index 1c2ca965c5e..52b5a640a85 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -39,6 +39,7 @@ In order to install a built-in temperature sensor instance, the first thing is t - :cpp:member:`range_min`: The minimum value of the testing range you have evaluated. - :cpp:member:`range_max`: The maximum value of the testing range you have evaluated. +- :cpp:member:`temperature_sensor_config_t::intr_priority` sets the interrupt priority. If it is set to ``0``, the driver will allocate an interrupt with a default low or medium priority (1, 2, or 3). Otherwise, use the priority number 1, 2, or 3, not the bitmask. - :cpp:member:`allow_pd` configures if the driver allows the system to power down the peripheral in light sleep mode. Before entering sleep, the system will backup the temperature sensor register context, which will be restored later when the system exit the sleep mode. Powering down the peripheral can save more power, but at the cost of more memory consumed to save the register context. It's a tradeoff between power consumption and memory consumption. This configuration option relies on specific hardware feature, if you enable it on an unsupported chip, you will see error message like ``not able to power down in light sleep``. After the ranges are set, the structure could be passed to :cpp:func:`temperature_sensor_install`, which will instantiate the temperature sensor instance and return a handle. diff --git a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst index 912e0c48d15..b650e222fa8 100644 --- a/docs/zh_CN/api-reference/peripherals/temp_sensor.rst +++ b/docs/zh_CN/api-reference/peripherals/temp_sensor.rst @@ -39,6 +39,7 @@ - :cpp:member:`range_min`:所测量温度范围的最小值。 - :cpp:member:`range_max`:所测量温度范围的最大值。 +- :cpp:member:`temperature_sensor_config_t::intr_priority`:设置中断优先级。设置为 ``0`` 时,驱动程序将分配默认的低或中优先级中断(优先级 1、2 或 3)。如需指定优先级,请使用数值 1、2 或 3,而不是位掩码。 - :cpp:member:`allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前,系统将备份温度传感器寄存器上下文,当系统退出睡眠模式时,这些上下文将被恢复。关闭外设可以节省更多功耗,但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能,如果在不支持的芯片上启用它,你将看到类似 ``not able to power down in light sleep`` 的错误消息。 设置好温度范围后,将配置结构体传递给 :cpp:func:`temperature_sensor_install`,该函数将创建温度传感器模块并返回句柄。