refactor(touch): eliminate global variable g_touch

This commit is contained in:
Hu Rui
2026-03-18 15:09:06 +08:00
parent 594679aa73
commit 9db885c49d
5 changed files with 71 additions and 83 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -37,7 +37,7 @@
static const char *TAG = "touch";
touch_sensor_handle_t g_touch = NULL;
static touch_sensor_handle_t s_sens_handle = NULL; /* Only used to enforce the controller singleton */
static void touch_channel_pin_init(int id)
{
@@ -68,8 +68,8 @@ static void s_touch_free_resource(touch_sensor_handle_t sens_handle)
vSemaphoreDeleteWithCaps(sens_handle->mutex);
sens_handle->mutex = NULL;
}
free(g_touch);
g_touch = NULL;
free(sens_handle);
s_sens_handle = NULL;
}
esp_err_t touch_sensor_new_controller(const touch_sensor_config_t *sens_cfg, touch_sensor_handle_t *ret_sens_handle)
@@ -80,38 +80,38 @@ esp_err_t touch_sensor_new_controller(const touch_sensor_config_t *sens_cfg, tou
esp_err_t ret = ESP_OK;
TOUCH_NULL_POINTER_CHECK(sens_cfg);
TOUCH_NULL_POINTER_CHECK(ret_sens_handle);
ESP_RETURN_ON_FALSE(!g_touch, ESP_ERR_INVALID_STATE, TAG, "Touch sensor has been allocated");
ESP_RETURN_ON_FALSE(!s_sens_handle, ESP_ERR_INVALID_STATE, TAG, "Touch sensor has been allocated");
g_touch = (touch_sensor_handle_t)heap_caps_calloc(1, sizeof(struct touch_sensor_s), TOUCH_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(g_touch, ESP_ERR_NO_MEM, TAG, "No memory for touch sensor struct");
s_sens_handle = (touch_sensor_handle_t)heap_caps_calloc(1, sizeof(struct touch_sensor_s), TOUCH_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(s_sens_handle, ESP_ERR_NO_MEM, TAG, "No memory for touch sensor struct");
g_touch->mutex = xSemaphoreCreateRecursiveMutexWithCaps(TOUCH_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(g_touch->mutex, ESP_ERR_NO_MEM, err, TAG, "No memory for mutex semaphore");
s_sens_handle->mutex = xSemaphoreCreateRecursiveMutexWithCaps(TOUCH_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(s_sens_handle->mutex, ESP_ERR_NO_MEM, err, TAG, "No memory for mutex semaphore");
touch_priv_enable_module(true);
#if SOC_TOUCH_SENSOR_VERSION >= 2
touch_ll_reset_module();
#endif
ESP_GOTO_ON_ERROR(touch_priv_config_controller(g_touch, sens_cfg), err, TAG, "Failed to configure the touch controller");
ESP_GOTO_ON_ERROR(touch_priv_config_controller(s_sens_handle, sens_cfg), err, TAG, "Failed to configure the touch controller");
#if SOC_TOUCH_SENSOR_VERSION <= 2
ESP_GOTO_ON_ERROR(rtc_isr_register(touch_priv_default_intr_handler, NULL, TOUCH_LL_INTR_MASK_ALL, 0), err, TAG, "Failed to register interrupt handler");
ESP_GOTO_ON_ERROR(rtc_isr_register(touch_priv_default_intr_handler, s_sens_handle, TOUCH_LL_INTR_MASK_ALL, 0), err, TAG, "Failed to register interrupt handler");
#else
ESP_GOTO_ON_ERROR(esp_intr_alloc(TOUCH_LL_INTR_SOURCE, TOUCH_INTR_ALLOC_FLAGS, touch_priv_default_intr_handler, NULL, &(g_touch->intr_handle)),
ESP_GOTO_ON_ERROR(esp_intr_alloc(TOUCH_LL_INTR_SOURCE, TOUCH_INTR_ALLOC_FLAGS, touch_priv_default_intr_handler, s_sens_handle, &(s_sens_handle->intr_handle)),
err, TAG, "Failed to register interrupt handler");
#endif
*ret_sens_handle = g_touch;
*ret_sens_handle = s_sens_handle;
return ret;
err:
touch_priv_enable_module(false);
s_touch_free_resource(g_touch);
s_touch_free_resource(s_sens_handle);
return ret;
}
esp_err_t touch_sensor_del_controller(touch_sensor_handle_t sens_handle)
{
TOUCH_NULL_POINTER_CHECK(sens_handle);
ESP_RETURN_ON_FALSE(g_touch == sens_handle, ESP_ERR_INVALID_ARG, TAG, "The input touch sensor handle is unmatched");
ESP_RETURN_ON_FALSE(s_sens_handle == sens_handle, ESP_ERR_INVALID_ARG, TAG, "The input touch sensor handle is unmatched");
esp_err_t ret = ESP_OK;
// Take the semaphore to make sure the touch has stopped
@@ -123,7 +123,7 @@ esp_err_t touch_sensor_del_controller(touch_sensor_handle_t sens_handle)
ESP_GOTO_ON_ERROR(touch_priv_deinit_controller(sens_handle), err, TAG, "Failed to deinitialize the controller");
#if SOC_TOUCH_SENSOR_VERSION <= 2
ESP_GOTO_ON_ERROR(rtc_isr_deregister(touch_priv_default_intr_handler, NULL), err, TAG, "Failed to deregister the interrupt handler");
ESP_GOTO_ON_ERROR(rtc_isr_deregister(touch_priv_default_intr_handler, sens_handle), err, TAG, "Failed to deregister the interrupt handler");
#else
ESP_GOTO_ON_ERROR(esp_intr_free(sens_handle->intr_handle), err, TAG, "Failed to deregister the interrupt handler");
#endif
@@ -134,10 +134,9 @@ esp_err_t touch_sensor_del_controller(touch_sensor_handle_t sens_handle)
touch_priv_enable_module(false);
s_touch_free_resource(sens_handle);
return ret;
err:
if (g_touch && g_touch->mutex) {
xSemaphoreGiveRecursive(g_touch->mutex);
}
xSemaphoreGiveRecursive(sens_handle->mutex);
return ret;
}
@@ -151,7 +150,7 @@ esp_err_t touch_sensor_new_channel(touch_sensor_handle_t sens_handle, int chan_i
TOUCH_CHANNEL_CHECK(chan_id);
uint32_t ch_offset = chan_id - TOUCH_MIN_CHAN_ID;
ESP_RETURN_ON_FALSE(g_touch == sens_handle, ESP_ERR_INVALID_ARG, TAG, "The input touch sensor handle is unmatched");
ESP_RETURN_ON_FALSE(s_sens_handle == sens_handle, ESP_ERR_INVALID_ARG, TAG, "The input touch sensor handle is unmatched");
esp_err_t ret = ESP_OK;
xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY);
@@ -226,8 +225,8 @@ esp_err_t touch_sensor_del_channel(touch_channel_handle_t chan_handle)
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
touch_channel_pin_deinit(chan_handle->id);
free(g_touch->ch[ch_offset]);
g_touch->ch[ch_offset] = NULL;
free(sens_handle->ch[ch_offset]);
sens_handle->ch[ch_offset] = NULL;
err:
xSemaphoreGiveRecursive(sens_handle->mutex);
return ret;
@@ -397,8 +396,8 @@ esp_err_t touch_sensor_trigger_oneshot_scanning(touch_sensor_handle_t sens_handl
TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK);
while (!touch_ll_is_measure_done()) {
#if SOC_TOUCH_SENSOR_VERSION >= 2
if (g_touch->is_meas_timeout) {
g_touch->is_meas_timeout = false;
if (sens_handle->is_meas_timeout) {
sens_handle->is_meas_timeout = false;
ESP_LOGW(TAG, "The measurement time on channel %d exceed the limitation", i);
break;
}
@@ -152,8 +152,6 @@ struct touch_channel_s {
#endif
};
extern touch_sensor_handle_t g_touch; /*!< Global touch sensor controller handle for `esp_driver_touch_sens` use only */
/**
* @brief Touch sensor module enable interface
* @note This is a private interface of `esp_driver_touch_sens`
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -124,10 +124,7 @@ void touch_priv_enable_module(bool enable)
void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
{
/* If the touch controller object has not been allocated, return directly */
if (!g_touch) {
return;
}
touch_sensor_handle_t sens_handle = (touch_sensor_handle_t)arg;
bool need_yield = false;
touch_hw_active_event_data_t data;
// Only one `on_active` interrupt source, clear directly
@@ -135,8 +132,8 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
touch_ll_get_active_channel_mask(&(data.active_mask));
touch_ll_clear_active_channel_status();
// Get the activated channels
if (g_touch->cbs.on_hw_active) {
need_yield |= g_touch->cbs.on_hw_active(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_hw_active) {
need_yield |= sens_handle->cbs.on_hw_active(sens_handle, &data, sens_handle->user_ctx);
}
if (need_yield) {
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -53,13 +53,10 @@ void touch_priv_enable_module(bool enable)
void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
{
/* If the touch controller object has not been allocated, return directly */
if (!g_touch) {
return;
}
touch_sensor_handle_t sens_handle = (touch_sensor_handle_t)arg;
bool need_yield = false;
uint32_t status = touch_ll_get_intr_status_mask();
g_touch->is_meas_timeout = false;
sens_handle->is_meas_timeout = false;
touch_ll_interrupt_clear(status);
touch_base_event_data_t data;
touch_ll_get_active_channel_mask(&data.status_mask);
@@ -69,7 +66,7 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
}
/* It actually won't be out of range in the real environment, but limit the range to pass the coverity check */
uint32_t curr_chan_offset = (curr_chan >= TOUCH_LL_GET(CHAN_NUM) ? TOUCH_LL_GET(CHAN_NUM) - 1 : curr_chan) - TOUCH_MIN_CHAN_ID;
data.chan = g_touch->ch[curr_chan_offset];
data.chan = sens_handle->ch[curr_chan_offset];
/* If the channel is not registered, return directly */
if (!data.chan) {
return;
@@ -86,8 +83,8 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
status |= TOUCH_LL_INTR_MASK_PROX_DONE;
}
#endif
if (g_touch->cbs.on_measure_done) {
need_yield |= g_touch->cbs.on_measure_done(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_measure_done) {
need_yield |= sens_handle->cbs.on_measure_done(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_SCAN_DONE) {
@@ -96,13 +93,13 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
(Only happens when both channel 13 and 14 are enabled)
The scan done interrupt will be triggered twice for channel 13 and 14,
but we only hope it be triggered after channel 14 measurement done. */
bool fake_scan_done = data.chan_id == 13 && (g_touch->chan_mask >> 13 == 0x03);
if (g_touch->cbs.on_scan_done && !fake_scan_done)
bool fake_scan_done = data.chan_id == 13 && (sens_handle->chan_mask >> 13 == 0x03);
if (sens_handle->cbs.on_scan_done && !fake_scan_done)
#else
if (g_touch->cbs.on_scan_done)
if (sens_handle->cbs.on_scan_done)
#endif
{
need_yield |= g_touch->cbs.on_scan_done(g_touch, &data, g_touch->user_ctx);
need_yield |= sens_handle->cbs.on_scan_done(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_PROX_DONE) {
@@ -110,37 +107,37 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
Read it out to latch the last proximity sensing data. */
touch_ll_read_chan_data(data.chan_id, TOUCH_LL_READ_BENCHMARK, &data.chan->prox_val[0]);
// TODO: support to judge by software if the proximity channel triggered
if (g_touch->cbs.on_proximity_meas_done) {
need_yield |= g_touch->cbs.on_proximity_meas_done(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_proximity_meas_done) {
need_yield |= sens_handle->cbs.on_proximity_meas_done(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_ACTIVE) {
/* When the guard ring activated, disable the scanning of other channels to avoid fake touch */
TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->waterproof_en && data.chan == g_touch->guard_chan) {
if (sens_handle->waterproof_en && data.chan == sens_handle->guard_chan) {
touch_ll_enable_scan_mask(~BIT(data.chan->id), false);
}
TOUCH_EXIT_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->cbs.on_active) {
need_yield |= g_touch->cbs.on_active(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_active) {
need_yield |= sens_handle->cbs.on_active(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_INACTIVE) {
/* When the guard ring inactivated, enable the scanning of other channels again */
TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->waterproof_en && data.chan == g_touch->guard_chan) {
touch_ll_enable_scan_mask(g_touch->chan_mask & (~BIT(g_touch->shield_chan->id)), true);
if (sens_handle->waterproof_en && data.chan == sens_handle->guard_chan) {
touch_ll_enable_scan_mask(sens_handle->chan_mask & (~BIT(sens_handle->shield_chan->id)), true);
}
TOUCH_EXIT_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->cbs.on_inactive) {
need_yield |= g_touch->cbs.on_inactive(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_inactive) {
need_yield |= sens_handle->cbs.on_inactive(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_TIMEOUT) {
g_touch->is_meas_timeout = true;
sens_handle->is_meas_timeout = true;
touch_ll_force_done_curr_measurement();
if ((g_touch->cbs.on_timeout)) {
need_yield |= g_touch->cbs.on_timeout(g_touch, &data, g_touch->user_ctx);
if ((sens_handle->cbs.on_timeout)) {
need_yield |= sens_handle->cbs.on_timeout(sens_handle, &data, sens_handle->user_ctx);
}
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -52,13 +52,10 @@ void touch_priv_enable_module(bool enable)
void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
{
/* If the touch controller object has not been allocated, return directly */
if (!g_touch) {
return;
}
touch_sensor_handle_t sens_handle = (touch_sensor_handle_t)arg;
bool need_yield = false;
uint32_t status = touch_ll_get_intr_status_mask();
g_touch->is_meas_timeout = false;
sens_handle->is_meas_timeout = false;
touch_ll_interrupt_clear(status);
touch_base_event_data_t data;
touch_ll_get_active_channel_mask(&data.status_mask);
@@ -67,7 +64,7 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
/* Not a valid channel */
return;
}
data.chan = g_touch->ch[ch_offset];
data.chan = sens_handle->ch[ch_offset];
/* If the channel is not registered, return directly */
if (!data.chan) {
return;
@@ -75,55 +72,55 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
data.chan_id = data.chan->id;
if (status & TOUCH_LL_INTR_MASK_DONE) {
if (g_touch->cbs.on_measure_done) {
need_yield |= g_touch->cbs.on_measure_done(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_measure_done) {
need_yield |= sens_handle->cbs.on_measure_done(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_SCAN_DONE) {
if (g_touch->cbs.on_scan_done) {
need_yield |= g_touch->cbs.on_scan_done(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_scan_done) {
need_yield |= sens_handle->cbs.on_scan_done(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_PROX_DONE) {
data.chan->prox_cnt++;
/* The proximity sensing result only accurate when the scanning times equal to the sample_cfg_num */
if (data.chan->prox_cnt == g_touch->sample_cfg_num) {
if (data.chan->prox_cnt == sens_handle->sample_cfg_num) {
data.chan->prox_cnt = 0;
for (uint32_t i = 0; i < g_touch->sample_cfg_num; i++) {
for (uint32_t i = 0; i < sens_handle->sample_cfg_num; i++) {
touch_ll_read_chan_data(data.chan_id, i, TOUCH_LL_READ_BENCHMARK, &data.chan->prox_val[i]);
}
if (g_touch->cbs.on_proximity_meas_done) {
need_yield |= g_touch->cbs.on_proximity_meas_done(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_proximity_meas_done) {
need_yield |= sens_handle->cbs.on_proximity_meas_done(sens_handle, &data, sens_handle->user_ctx);
}
}
}
if (status & TOUCH_LL_INTR_MASK_ACTIVE) {
/* When the guard ring activated, disable the scanning of other channels to avoid fake touch */
TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->immersion_proof && data.chan == g_touch->guard_chan) {
if (sens_handle->immersion_proof && data.chan == sens_handle->guard_chan) {
touch_ll_enable_scan_mask(~BIT(data.chan->id), false);
}
TOUCH_EXIT_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->cbs.on_active) {
need_yield |= g_touch->cbs.on_active(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_active) {
need_yield |= sens_handle->cbs.on_active(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_INACTIVE) {
/* When the guard ring inactivated, enable the scanning of other channels again */
TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->immersion_proof && data.chan == g_touch->guard_chan) {
touch_ll_enable_scan_mask(g_touch->chan_mask & (~BIT(g_touch->shield_chan->id)), true);
if (sens_handle->immersion_proof && data.chan == sens_handle->guard_chan) {
touch_ll_enable_scan_mask(sens_handle->chan_mask & (~BIT(sens_handle->shield_chan->id)), true);
}
TOUCH_EXIT_CRITICAL_SAFE(TOUCH_PERIPH_LOCK);
if (g_touch->cbs.on_inactive) {
need_yield |= g_touch->cbs.on_inactive(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_inactive) {
need_yield |= sens_handle->cbs.on_inactive(sens_handle, &data, sens_handle->user_ctx);
}
}
if (status & TOUCH_LL_INTR_MASK_TIMEOUT) {
g_touch->is_meas_timeout = true;
sens_handle->is_meas_timeout = true;
touch_ll_force_done_curr_measurement();
if (g_touch->cbs.on_timeout) {
need_yield |= g_touch->cbs.on_timeout(g_touch, &data, g_touch->user_ctx);
if (sens_handle->cbs.on_timeout) {
need_yield |= sens_handle->cbs.on_timeout(sens_handle, &data, sens_handle->user_ctx);
}
}