mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-27 10:24:04 +00:00
fix(legacy_touch): fixed touch read API can't be called in ISR context
Closes https://github.com/espressif/esp-idf/issues/17045
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -301,6 +301,11 @@ static bool s_pad_activated[TOUCH_PAD_MAX];
|
|||||||
static void test_touch_intr_cb(void *arg)
|
static void test_touch_intr_cb(void *arg)
|
||||||
{
|
{
|
||||||
uint32_t pad_intr = touch_pad_get_status();
|
uint32_t pad_intr = touch_pad_get_status();
|
||||||
|
uint16_t touch_value;
|
||||||
|
// Should be able to read touch value in ISR
|
||||||
|
touch_pad_read_filtered(touch_list[0], &touch_value);
|
||||||
|
touch_pad_read_raw_data(touch_list[0], &touch_value);
|
||||||
|
|
||||||
//clear interrupt
|
//clear interrupt
|
||||||
touch_pad_clear_status();
|
touch_pad_clear_status();
|
||||||
for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) {
|
for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) {
|
||||||
|
@@ -52,13 +52,17 @@ static SemaphoreHandle_t rtc_touch_mux = NULL;
|
|||||||
static __attribute__((unused)) const char *TOUCH_TAG = "TOUCH_SENSOR";
|
static __attribute__((unused)) const char *TOUCH_TAG = "TOUCH_SENSOR";
|
||||||
|
|
||||||
#define TOUCH_CHANNEL_CHECK(channel) ESP_RETURN_ON_FALSE(channel < SOC_TOUCH_SENSOR_NUM, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch channel error");
|
#define TOUCH_CHANNEL_CHECK(channel) ESP_RETURN_ON_FALSE(channel < SOC_TOUCH_SENSOR_NUM, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch channel error");
|
||||||
|
#define TOUCH_CHANNEL_CHECK_ISR(channel) ESP_RETURN_ON_FALSE_ISR(channel < SOC_TOUCH_SENSOR_NUM, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch channel error");
|
||||||
#define TOUCH_NULL_POINTER_CHECK(p, name) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, TOUCH_TAG, "input param '"name"' is NULL")
|
#define TOUCH_NULL_POINTER_CHECK(p, name) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, TOUCH_TAG, "input param '"name"' is NULL")
|
||||||
|
#define TOUCH_NULL_POINTER_CHECK_ISR(p, name) ESP_RETURN_ON_FALSE_ISR((p), ESP_ERR_INVALID_ARG, TOUCH_TAG, "input param '"name"' is NULL")
|
||||||
#define TOUCH_PARAM_CHECK_STR(s) ""s" parameter error"
|
#define TOUCH_PARAM_CHECK_STR(s) ""s" parameter error"
|
||||||
|
|
||||||
static portMUX_TYPE s_filter_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE s_filter_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||||
#define TOUCH_ENTER_CRITICAL(spinlock) portENTER_CRITICAL(spinlock)
|
#define TOUCH_ENTER_CRITICAL(spinlock) portENTER_CRITICAL(spinlock)
|
||||||
#define TOUCH_EXIT_CRITICAL(spinlock) portEXIT_CRITICAL(spinlock)
|
#define TOUCH_EXIT_CRITICAL(spinlock) portEXIT_CRITICAL(spinlock)
|
||||||
|
#define TOUCH_ENTER_CRITICAL_SAFE(spinlock) portENTER_CRITICAL_SAFE(spinlock)
|
||||||
|
#define TOUCH_EXIT_CRITICAL_SAFE(spinlock) portEXIT_CRITICAL_SAFE(spinlock)
|
||||||
|
|
||||||
/*---------------------------------------------------------------
|
/*---------------------------------------------------------------
|
||||||
Touch Pad
|
Touch Pad
|
||||||
@@ -67,6 +71,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
|||||||
#define BITSWAP(data, n, m) (((data >> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <<n) | (0x1 << m))))
|
#define BITSWAP(data, n, m) (((data >> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <<n) | (0x1 << m))))
|
||||||
#define TOUCH_BITS_SWAP(v) BITSWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
|
#define TOUCH_BITS_SWAP(v) BITSWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
|
||||||
static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode);
|
static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode);
|
||||||
|
static esp_err_t s_touch_pad_filter_create(void);
|
||||||
|
|
||||||
esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
|
esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
|
||||||
{
|
{
|
||||||
@@ -339,25 +344,15 @@ esp_err_t touch_pad_init(void)
|
|||||||
TOUCH_ENTER_CRITICAL(&rtc_spinlock);
|
TOUCH_ENTER_CRITICAL(&rtc_spinlock);
|
||||||
touch_hal_init();
|
touch_hal_init();
|
||||||
TOUCH_EXIT_CRITICAL(&rtc_spinlock);
|
TOUCH_EXIT_CRITICAL(&rtc_spinlock);
|
||||||
|
ESP_RETURN_ON_ERROR(s_touch_pad_filter_create(), TOUCH_TAG, "failed to create the filter");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t touch_pad_deinit(void)
|
esp_err_t touch_pad_deinit(void)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
||||||
esp_err_t ret = ESP_OK;
|
ESP_RETURN_ON_ERROR(touch_pad_filter_delete(), TOUCH_TAG, "failed to delete the filter");
|
||||||
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
||||||
if (s_touch_pad_filter) {
|
|
||||||
if (s_touch_pad_filter->timer) {
|
|
||||||
ESP_GOTO_ON_ERROR(esp_timer_stop(s_touch_pad_filter->timer), err, TOUCH_TAG, "failed to stop the timer");
|
|
||||||
ESP_GOTO_ON_ERROR(esp_timer_delete(s_touch_pad_filter->timer), err, TOUCH_TAG, "failed to delete the timer");
|
|
||||||
s_touch_pad_filter->timer = NULL;
|
|
||||||
}
|
|
||||||
free(s_touch_pad_filter);
|
|
||||||
TOUCH_ENTER_CRITICAL(&s_filter_spinlock);
|
|
||||||
s_touch_pad_filter = NULL;
|
|
||||||
TOUCH_EXIT_CRITICAL(&s_filter_spinlock);
|
|
||||||
}
|
|
||||||
s_touch_pad_init_bit = 0x0000;
|
s_touch_pad_init_bit = 0x0000;
|
||||||
TOUCH_ENTER_CRITICAL(&rtc_spinlock);
|
TOUCH_ENTER_CRITICAL(&rtc_spinlock);
|
||||||
touch_hal_deinit();
|
touch_hal_deinit();
|
||||||
@@ -366,9 +361,6 @@ esp_err_t touch_pad_deinit(void)
|
|||||||
vSemaphoreDelete(rtc_touch_mux);
|
vSemaphoreDelete(rtc_touch_mux);
|
||||||
rtc_touch_mux = NULL;
|
rtc_touch_mux = NULL;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
err:
|
|
||||||
xSemaphoreGive(rtc_touch_mux);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode)
|
static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode)
|
||||||
@@ -414,38 +406,34 @@ esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value)
|
|||||||
IRAM_ATTR esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value)
|
IRAM_ATTR esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
ESP_RETURN_ON_FALSE_ISR(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
||||||
TOUCH_CHANNEL_CHECK(touch_num);
|
TOUCH_CHANNEL_CHECK_ISR(touch_num);
|
||||||
TOUCH_NULL_POINTER_CHECK(touch_value, "touch_value");
|
TOUCH_NULL_POINTER_CHECK_ISR(touch_value, "touch_value");
|
||||||
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
ESP_GOTO_ON_FALSE_ISR(s_touch_pad_filter, ESP_FAIL, err, TOUCH_TAG, "Touch pad filter not initialized");
|
||||||
ESP_GOTO_ON_FALSE(s_touch_pad_filter, ESP_FAIL, err, TOUCH_TAG, "Touch pad filter not initialized");
|
TOUCH_ENTER_CRITICAL_SAFE(&s_filter_spinlock);
|
||||||
TOUCH_ENTER_CRITICAL(&s_filter_spinlock);
|
|
||||||
*touch_value = s_touch_pad_filter->raw_val[touch_num];
|
*touch_value = s_touch_pad_filter->raw_val[touch_num];
|
||||||
TOUCH_EXIT_CRITICAL(&s_filter_spinlock);
|
TOUCH_EXIT_CRITICAL_SAFE(&s_filter_spinlock);
|
||||||
if (*touch_value == 0) {
|
if (*touch_value == 0) {
|
||||||
ret = ESP_ERR_INVALID_STATE;
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
xSemaphoreGive(rtc_touch_mux);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value)
|
IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
ESP_RETURN_ON_FALSE_ISR(rtc_touch_mux, ESP_FAIL, TOUCH_TAG, "Touch pad not initialized");
|
||||||
TOUCH_CHANNEL_CHECK(touch_num);
|
TOUCH_CHANNEL_CHECK_ISR(touch_num);
|
||||||
TOUCH_NULL_POINTER_CHECK(touch_value, "touch_value");
|
TOUCH_NULL_POINTER_CHECK_ISR(touch_value, "touch_value");
|
||||||
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
ESP_GOTO_ON_FALSE_ISR(s_touch_pad_filter, ESP_FAIL, err, TOUCH_TAG, "Touch pad filter not initialized");
|
||||||
ESP_GOTO_ON_FALSE(s_touch_pad_filter, ESP_FAIL, err, TOUCH_TAG, "Touch pad filter not initialized");
|
TOUCH_ENTER_CRITICAL_SAFE(&s_filter_spinlock);
|
||||||
TOUCH_ENTER_CRITICAL(&s_filter_spinlock);
|
|
||||||
*touch_value = (s_touch_pad_filter->filtered_val[touch_num]);
|
*touch_value = (s_touch_pad_filter->filtered_val[touch_num]);
|
||||||
TOUCH_EXIT_CRITICAL(&s_filter_spinlock);
|
TOUCH_EXIT_CRITICAL_SAFE(&s_filter_spinlock);
|
||||||
if (*touch_value == 0) {
|
if (*touch_value == 0) {
|
||||||
ret = ESP_ERR_INVALID_STATE;
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
xSemaphoreGive(rtc_touch_mux);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,37 +478,12 @@ esp_err_t touch_pad_filter_start(uint32_t filter_period_ms)
|
|||||||
|
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
||||||
if (s_touch_pad_filter == NULL) {
|
ESP_GOTO_ON_FALSE(s_touch_pad_filter && s_touch_pad_filter->timer, ESP_ERR_INVALID_STATE, err, TOUCH_TAG, "Touch pad filter not initialized");
|
||||||
s_touch_pad_filter = (touch_pad_filter_t *) calloc(1, sizeof(touch_pad_filter_t));
|
|
||||||
ESP_GOTO_ON_FALSE(s_touch_pad_filter, ESP_ERR_NO_MEM, err_no_mem, TOUCH_TAG, "no memory for filter");
|
|
||||||
}
|
|
||||||
if (s_touch_pad_filter->timer == NULL) {
|
|
||||||
esp_timer_create_args_t timer_cfg = {
|
|
||||||
.callback = touch_pad_filter_cb,
|
|
||||||
.arg = NULL,
|
|
||||||
.dispatch_method = ESP_TIMER_TASK,
|
|
||||||
.name = "touch filter timer",
|
|
||||||
.skip_unhandled_events = true,
|
|
||||||
};
|
|
||||||
ESP_GOTO_ON_ERROR(esp_timer_create(&timer_cfg, &(s_touch_pad_filter->timer)),
|
|
||||||
err_timer_create, TOUCH_TAG, "failed to create the filter timer");
|
|
||||||
s_touch_pad_filter->period = filter_period_ms;
|
s_touch_pad_filter->period = filter_period_ms;
|
||||||
touch_pad_filter_cb(NULL); // Trigger once immediately to get the initial raw value
|
touch_pad_filter_cb(NULL); // Trigger once immediately to get the initial raw value
|
||||||
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(s_touch_pad_filter->timer, filter_period_ms * 1000),
|
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(s_touch_pad_filter->timer, filter_period_ms * 1000),
|
||||||
err_timer_start, TOUCH_TAG, "failed to start the filter timer");
|
err, TOUCH_TAG, "failed to start the filter timer");
|
||||||
}
|
err:
|
||||||
|
|
||||||
xSemaphoreGive(rtc_touch_mux);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
err_timer_start:
|
|
||||||
esp_timer_delete(s_touch_pad_filter->timer);
|
|
||||||
err_timer_create:
|
|
||||||
free(s_touch_pad_filter);
|
|
||||||
TOUCH_ENTER_CRITICAL(&s_filter_spinlock);
|
|
||||||
s_touch_pad_filter = NULL;
|
|
||||||
TOUCH_EXIT_CRITICAL(&s_filter_spinlock);
|
|
||||||
err_no_mem:
|
|
||||||
xSemaphoreGive(rtc_touch_mux);
|
xSemaphoreGive(rtc_touch_mux);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -538,6 +501,31 @@ esp_err_t touch_pad_filter_stop(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t s_touch_pad_filter_create(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
||||||
|
if (s_touch_pad_filter == NULL) {
|
||||||
|
s_touch_pad_filter = (touch_pad_filter_t *) calloc(1, sizeof(touch_pad_filter_t));
|
||||||
|
ESP_GOTO_ON_FALSE(s_touch_pad_filter, ESP_ERR_NO_MEM, err, TOUCH_TAG, "no memory for filter");
|
||||||
|
}
|
||||||
|
if (s_touch_pad_filter->timer == NULL) {
|
||||||
|
esp_timer_create_args_t timer_cfg = {
|
||||||
|
.callback = touch_pad_filter_cb,
|
||||||
|
.arg = NULL,
|
||||||
|
.dispatch_method = ESP_TIMER_TASK,
|
||||||
|
.name = "touch filter timer",
|
||||||
|
.skip_unhandled_events = true,
|
||||||
|
};
|
||||||
|
ESP_GOTO_ON_ERROR(esp_timer_create(&timer_cfg, &(s_touch_pad_filter->timer)),
|
||||||
|
err, TOUCH_TAG, "failed to create the filter timer");
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
xSemaphoreGive(rtc_touch_mux);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t touch_pad_filter_delete(void)
|
esp_err_t touch_pad_filter_delete(void)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG, "Touch pad filter not initialized");
|
ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG, "Touch pad filter not initialized");
|
||||||
|
Reference in New Issue
Block a user