From 4e03f8df0ffcf44dbe89d6a3e09fb50e0c43a32c Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Wed, 6 Aug 2025 14:39:14 +0800 Subject: [PATCH 1/2] fix(rmt): correct the condition for warnings in loop mode --- components/esp_driver_rmt/src/rmt_tx.c | 10 ++++++---- docs/en/api-reference/peripherals/rmt.rst | 2 +- docs/zh_CN/api-reference/peripherals/rmt.rst | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index e6006fa788..6e8649d2c6 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.c @@ -648,20 +648,22 @@ size_t rmt_encode_check_result(rmt_tx_channel_t *tx_chan, rmt_tx_trans_desc_t *t rmt_encode_state_t encode_state = RMT_ENCODING_RESET; rmt_encoder_handle_t encoder = t->encoder; size_t encoded_symbols = encoder->encode(encoder, &tx_chan->base, t->payload, t->payload_bytes, &encode_state); + bool is_mem_full = encode_state & RMT_ENCODING_MEM_FULL; + bool need_eof_mark = (encode_state & RMT_ENCODING_WITH_EOF) == 0; if (encode_state & RMT_ENCODING_COMPLETE) { - bool need_eof_mark = (encode_state & RMT_ENCODING_WITH_EOF) == 0; // inserting EOF symbol if there's extra space - if (!(encode_state & RMT_ENCODING_MEM_FULL)) { + if (!is_mem_full) { encoded_symbols += rmt_tx_mark_eof(tx_chan, need_eof_mark); } t->flags.encoding_done = true; t->flags.need_eof_mark = need_eof_mark; } - // for loop transaction, the memory block should accommodate all encoded RMT symbols + // for loop transaction, the memory block should accommodate all encoded RMT symbols and an extra EOF symbol if (t->loop_count != 0) { - if (unlikely(encoded_symbols > tx_chan->base.mem_block_num * SOC_RMT_MEM_WORDS_PER_CHANNEL)) { + size_t limit_symbols = tx_chan->base.mem_block_num * SOC_RMT_MEM_WORDS_PER_CHANNEL; + if (unlikely(encoded_symbols > limit_symbols || (encoded_symbols == limit_symbols && is_mem_full && need_eof_mark))) { ESP_DRAM_LOGE(TAG, "encoding artifacts can't exceed hw memory block for loop transmission"); } } diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 7d8777a471..47c5460594 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -256,7 +256,7 @@ Once you created an encoder, you can initiate a TX transaction by calling :cpp:f .. note:: - There is a limitation in the transmission size if the :cpp:member:`rmt_transmit_config_t::loop_count` is set to non-zero, i.e., to enable the loop feature. The encoded RMT symbols should not exceed the capacity of the RMT hardware memory block size, or you might see an error message like ``encoding artifacts can't exceed hw memory block for loop transmission``. If you have to start a large transaction by loop, you can try either of the following methods. + There is a limitation in the transmission size if the :cpp:member:`rmt_transmit_config_t::loop_count` is set to non-zero, i.e., to enable the loop feature. The total amount of symbols returned by the encoder should not exceed the capacity of :c:macro:`SOC_RMT_MEM_WORDS_PER_CHANNEL`, or you might see an error message like ``encoding artifacts can't exceed hw memory block for loop transmission``. If you have to start a large transaction by loop, you can try either of the following methods. - Increase the :cpp:member:`rmt_tx_channel_config_t::mem_block_symbols`. This approach does not work if the DMA backend is also enabled. - Customize an encoder and construct an infinite loop in the encoding function. See also :ref:`rmt-rmt-encoder`. diff --git a/docs/zh_CN/api-reference/peripherals/rmt.rst b/docs/zh_CN/api-reference/peripherals/rmt.rst index 652d18063e..bed0d1bafc 100644 --- a/docs/zh_CN/api-reference/peripherals/rmt.rst +++ b/docs/zh_CN/api-reference/peripherals/rmt.rst @@ -256,7 +256,7 @@ RMT 是一种特殊的通信外设,无法像 SPI 和 I2C 那样发送原始字 .. note:: - 如果将 :cpp:member:`rmt_transmit_config_t::loop_count` 设置为非零值,即启用循环功能,则传输的大小将受到限制。编码的 RMT 符号不应超过 RMT 硬件内存块容量,否则会出现类似 ``encoding artifacts can't exceed hw memory block for loop transmission`` 的报错信息。如需通过循环启动大型事务,请尝试以下任一方法: + 如果将 :cpp:member:`rmt_transmit_config_t::loop_count` 设置为非零值,即启用循环功能,则传输的大小将受到限制。编码器返回的符号总量不能超过 :c:macro:`SOC_RMT_MEM_WORDS_PER_CHANNEL`,否则会出现类似 ``encoding artifacts can't exceed hw memory block for loop transmission`` 的报错信息。如需通过循环启动大型事务,请尝试以下任一方法: - 增加 :cpp:member:`rmt_tx_channel_config_t::mem_block_symbols`。若此时启用了 DMA 后端,该方法将失效。 - 自定义编码器,并在编码函数中构造一个无限循环,详情请参阅 :ref:`rmt-rmt-encoder`。 From 6c3d275342d8d4717d9373a43f481d5b120b0b92 Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Thu, 7 Aug 2025 13:09:00 +0800 Subject: [PATCH 2/2] fix(rmt): treat loop once as no loop --- components/esp_driver_rmt/src/rmt_tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index 6e8649d2c6..5e432ad079 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.c @@ -521,7 +521,7 @@ esp_err_t rmt_transmit(rmt_channel_handle_t channel, rmt_encoder_t *encoder, con ESP_RETURN_ON_FALSE(channel && encoder && payload && payload_bytes && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(channel->direction == RMT_CHANNEL_DIRECTION_TX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction"); #if !SOC_RMT_SUPPORT_TX_LOOP_COUNT - ESP_RETURN_ON_FALSE(config->loop_count <= 0, ESP_ERR_NOT_SUPPORTED, TAG, "loop count is not supported"); + ESP_RETURN_ON_FALSE(config->loop_count <= 1, ESP_ERR_NOT_SUPPORTED, TAG, "loop count is not supported"); #endif // !SOC_RMT_SUPPORT_TX_LOOP_COUNT #if CONFIG_RMT_TX_ISR_CACHE_SAFE // payload is retrieved by the encoder, we should make sure it's still accessible even when the cache is disabled @@ -546,7 +546,8 @@ esp_err_t rmt_transmit(rmt_channel_handle_t channel, rmt_encoder_t *encoder, con t->encoder = encoder; t->payload = payload; t->payload_bytes = payload_bytes; - t->loop_count = config->loop_count; + // treat loop_count == 1 as no loop + t->loop_count = config->loop_count == 1 ? 0 : config->loop_count; t->remain_loop_count = t->loop_count; t->flags.eot_level = config->flags.eot_level;