Skip to content

Commit 54d7bec

Browse files
committed
Merge branch 'fix/rmt_lim_thres_incorrect' into 'master'
fix(rmt): fix the received symbols issue See merge request espressif/esp-idf!37706
2 parents 4608cc0 + fac2d9e commit 54d7bec

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

components/esp_driver_rmt/src/rmt_rx.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,20 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan)
597597
portEXIT_CRITICAL_ISR(&channel->spinlock);
598598

599599
uint32_t offset = rmt_ll_rx_get_memory_writer_offset(hal->regs, channel_id);
600-
// sanity check
601-
assert(offset >= rx_chan->mem_off);
602-
size_t mem_want = (offset - rx_chan->mem_off) * sizeof(rmt_symbol_word_t);
600+
601+
// Start from C6, the actual pulse count is the number of input pulses N - 1.
602+
// Resulting in the last threshold interrupts may not be triggered correctly when the number of received symbols is a multiple of the memory block size.
603+
// As shown in the figure below, So we special handle the offset
604+
605+
// mem_off (should be updated here in the last threshold interrupt, but interrupt lost)
606+
// |
607+
// V
608+
// |________|________|
609+
// | |
610+
// offset mem_off(actually here now)
611+
612+
size_t mem_want = (offset >= rx_chan->mem_off ? offset - rx_chan->mem_off : rx_chan->mem_off - offset);
613+
mem_want *= sizeof(rmt_symbol_word_t);
603614
size_t mem_have = trans_desc->buffer_size - trans_desc->copy_dest_off;
604615
size_t copy_size = mem_want;
605616
if (mem_want > mem_have) {

components/esp_driver_rmt/test_apps/rmt/main/test_rmt_rx.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -208,9 +208,9 @@ TEST_CASE("rmt rx nec with carrier", "[rmt]")
208208
#if SOC_RMT_SUPPORT_RX_PINGPONG
209209
#define TEST_RMT_SYMBOLS 10000 // a very long frame, contains 10000 symbols
210210

211-
static void pwm_bit_bang(int gpio_num)
211+
static void pwm_bit_bang(int gpio_num, int count)
212212
{
213-
for (int i = 0; i < TEST_RMT_SYMBOLS; i++) {
213+
for (int i = 0; i < count; i++) {
214214
gpio_set_level(gpio_num, 1);
215215
esp_rom_delay_us(50);
216216
gpio_set_level(gpio_num, 0);
@@ -231,7 +231,7 @@ static bool test_rmt_partial_receive_done(rmt_channel_handle_t channel, const rm
231231
return high_task_wakeup == pdTRUE;
232232
}
233233

234-
static void test_rmt_partial_receive(size_t mem_block_symbols, bool with_dma, rmt_clock_source_t clk_src)
234+
static void test_rmt_partial_receive(size_t mem_block_symbols, int test_symbols_num, bool with_dma, rmt_clock_source_t clk_src)
235235
{
236236
uint32_t const test_rx_buffer_symbols = 128; // the user buffer is small, it can't hold all the received symbols
237237
rmt_symbol_word_t *receive_user_buf = heap_caps_aligned_calloc(64, test_rx_buffer_symbols, sizeof(rmt_symbol_word_t),
@@ -280,11 +280,11 @@ static void test_rmt_partial_receive(size_t mem_block_symbols, bool with_dma, rm
280280
TEST_ESP_OK(rmt_receive(rx_channel, receive_user_buf, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &rx_config));
281281

282282
// simulate input signal by GPIO
283-
pwm_bit_bang(TEST_RMT_GPIO_NUM_A);
283+
pwm_bit_bang(TEST_RMT_GPIO_NUM_A, test_symbols_num);
284284

285285
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(2000)));
286286
printf("received %zu symbols\r\n", test_user_data.received_symbol_num);
287-
TEST_ASSERT_EQUAL(TEST_RMT_SYMBOLS, test_user_data.received_symbol_num);
287+
TEST_ASSERT_EQUAL(test_symbols_num, test_user_data.received_symbol_num);
288288
// verify the received data
289289
for (int i = 0; i < 10; i++) {
290290
printf("{%d:%d},{%d:%d}\r\n", receive_user_buf[i].level0, receive_user_buf[i].duration0, receive_user_buf[i].level1, receive_user_buf[i].duration1);
@@ -303,11 +303,19 @@ static void test_rmt_partial_receive(size_t mem_block_symbols, bool with_dma, rm
303303

304304
TEST_CASE("rmt rx long frame partially", "[rmt]")
305305
{
306-
test_rmt_partial_receive(SOC_RMT_MEM_WORDS_PER_CHANNEL, false, RMT_CLK_SRC_DEFAULT);
306+
test_rmt_partial_receive(SOC_RMT_MEM_WORDS_PER_CHANNEL, TEST_RMT_SYMBOLS, false, RMT_CLK_SRC_DEFAULT);
307307
#if SOC_RMT_SUPPORT_DMA
308-
test_rmt_partial_receive(256, true, RMT_CLK_SRC_DEFAULT);
308+
test_rmt_partial_receive(256, TEST_RMT_SYMBOLS, true, RMT_CLK_SRC_DEFAULT);
309309
#endif
310310
}
311+
312+
TEST_CASE("rmt rx boundary conditions", "[rmt]")
313+
{
314+
test_rmt_partial_receive(SOC_RMT_MEM_WORDS_PER_CHANNEL, SOC_RMT_MEM_WORDS_PER_CHANNEL - 1, false, RMT_CLK_SRC_DEFAULT);
315+
test_rmt_partial_receive(SOC_RMT_MEM_WORDS_PER_CHANNEL, SOC_RMT_MEM_WORDS_PER_CHANNEL, false, RMT_CLK_SRC_DEFAULT);
316+
test_rmt_partial_receive(SOC_RMT_MEM_WORDS_PER_CHANNEL, SOC_RMT_MEM_WORDS_PER_CHANNEL + 1, false, RMT_CLK_SRC_DEFAULT);
317+
}
318+
311319
#endif // SOC_RMT_SUPPORT_RX_PINGPONG
312320

313321
TEST_RMT_CALLBACK_ATTR

0 commit comments

Comments
 (0)