From 7d0d7c52dbb4a9573306dbe54a91dbd5b98eee62 Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Thu, 22 May 2025 14:28:15 +0800 Subject: [PATCH] fix(rmt): deal with spurious RX done interrupts on ESP32 Closes https://github.com/espressif/esp-idf/issues/15948 --- components/driver/deprecated/rmt_legacy.c | 2 +- components/esp_driver_rmt/src/rmt_rx.c | 10 ++++++++++ components/esp_driver_rmt/src/rmt_tx.c | 4 ++-- components/soc/esp32c3/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 2 +- components/soc/esp32c5/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c5/include/soc/soc_caps.h | 2 +- components/soc/esp32c6/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c6/include/soc/soc_caps.h | 2 +- components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32h2/include/soc/soc_caps.h | 2 +- .../soc/esp32h21/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32h21/include/soc/soc_caps.h | 2 +- components/soc/esp32h4/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32h4/include/soc/soc_caps.h | 2 +- components/soc/esp32p4/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32p4/include/soc/soc_caps.h | 2 +- components/soc/esp32s2/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32s2/include/soc/soc_caps.h | 2 +- components/soc/esp32s3/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32s3/include/soc/soc_caps.h | 2 +- 21 files changed, 31 insertions(+), 21 deletions(-) diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index de84d121af..a88898e685 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/components/driver/deprecated/rmt_legacy.c @@ -302,7 +302,7 @@ esp_err_t rmt_tx_stop(rmt_channel_t channel) { ESP_RETURN_ON_FALSE(RMT_IS_TX_CHANNEL(channel), ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); RMT_ENTER_CRITICAL(); -#if SOC_RMT_SUPPORT_TX_ASYNC_STOP +#if SOC_RMT_SUPPORT_ASYNC_STOP rmt_ll_tx_stop(rmt_contex.hal.regs, channel); #else // write ending marker to stop the TX channel diff --git a/components/esp_driver_rmt/src/rmt_rx.c b/components/esp_driver_rmt/src/rmt_rx.c index fa3425ae46..f8c3ff0c97 100644 --- a/components/esp_driver_rmt/src/rmt_rx.c +++ b/components/esp_driver_rmt/src/rmt_rx.c @@ -575,6 +575,16 @@ bool rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan) rmt_ll_rx_enable(hal->regs, channel_id, false); portEXIT_CRITICAL_ISR(&channel->spinlock); +#if !SOC_RMT_SUPPORT_ASYNC_STOP + // This is a workaround for ESP32. + // The RX engine can not be disabled once it is enabled in ESP32 + // If the state isn't RMT_FSM_RUN, it means the RX engine was disabled + // and we shouldn't process the data. + if (atomic_load(&channel->fsm) != RMT_FSM_RUN) { + return false; + } +#endif + uint32_t offset = rmt_ll_rx_get_memory_writer_offset(hal->regs, channel_id); // Start from C6, the actual pulse count is the number of input pulses N - 1. diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index c5ac5d89d9..c696e2095f 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.c @@ -821,14 +821,14 @@ static esp_err_t rmt_tx_disable(rmt_channel_handle_t channel) // disable the hardware portENTER_CRITICAL(&channel->spinlock); rmt_ll_tx_enable_loop(hal->regs, channel->channel_id, false); -#if SOC_RMT_SUPPORT_TX_ASYNC_STOP +#if SOC_RMT_SUPPORT_ASYNC_STOP rmt_ll_tx_stop(hal->regs, channel->channel_id); #endif portEXIT_CRITICAL(&channel->spinlock); portENTER_CRITICAL(&group->spinlock); rmt_ll_enable_interrupt(hal->regs, RMT_LL_EVENT_TX_MASK(channel_id), false); -#if !SOC_RMT_SUPPORT_TX_ASYNC_STOP +#if !SOC_RMT_SUPPORT_ASYNC_STOP // we do a trick to stop the undergoing transmission // stop interrupt, insert EOF marker to the RMT memory, polling the trans_done event channel->hw_mem_base[0].val = 0; diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 1d5fbd4d16..33b43e514f 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -619,7 +619,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 5f56f39f7c..1dbbdac467 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -258,7 +258,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index ccd3b55333..bcadb4b8de 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -899,7 +899,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index e42a62ab5a..c811aba83f 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -357,7 +357,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index ebd805c524..ce90aace50 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -831,7 +831,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index be26d94f1f..398f1738b7 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -329,7 +329,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 1c58c53324..6cba6e6b22 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -827,7 +827,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 203f450bf1..55e5ea3385 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -343,7 +343,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 191165ce27..83ce91f7eb 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -527,7 +527,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 5ad8faaa89..1a3f9ab620 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -319,7 +319,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index b80a9c9d0c..acf9e3d51a 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -519,7 +519,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 383a99c7e4..ce020cf6e9 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -335,7 +335,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 07b508925f..8bd9d21db7 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1203,7 +1203,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a49e4ae9d2..8de4a4f440 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -436,7 +436,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index fdf69ab06d..1ac2efd10d 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -623,7 +623,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 8ccc41b362..fe8cf33945 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -270,7 +270,7 @@ #define SOC_RMT_CHANNELS_PER_GROUP 4 /*!< Total 4 channels */ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 64 /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmitting specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 735104e4ff..c1427cac5b 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -747,7 +747,7 @@ config SOC_RMT_SUPPORT_RX_DEMODULATION bool default y -config SOC_RMT_SUPPORT_TX_ASYNC_STOP +config SOC_RMT_SUPPORT_ASYNC_STOP bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index b455d19e3f..ee16efb66e 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -294,7 +294,7 @@ #define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ #define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */ #define SOC_RMT_SUPPORT_RX_DEMODULATION 1 /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ +#define SOC_RMT_SUPPORT_ASYNC_STOP 1 /*!< Support stop transmission asynchronously */ #define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */ #define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */