From 1703a0a5e9d5bde8fb69fba737196fea8396aea8 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 23 May 2023 14:02:42 +0800 Subject: [PATCH] doc: explain why RMT encoder may result in more data transmitting Closes https://github.com/espressif/esp-idf/issues/11468 --- .../test_apps/rmt/main/test_rmt_common.c | 2 +- .../driver/test_apps/rmt/main/test_rmt_iram.c | 21 ++-- .../driver/test_apps/rmt/main/test_rmt_rx.c | 10 +- .../driver/test_apps/rmt/main/test_rmt_tx.c | 116 ++++++++++++------ docs/en/api-reference/peripherals/rmt.rst | 11 ++ 5 files changed, 98 insertions(+), 62 deletions(-) diff --git a/components/driver/test_apps/rmt/main/test_rmt_common.c b/components/driver/test_apps/rmt/main/test_rmt_common.c index aa04597d62..8944a545ff 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_common.c +++ b/components/driver/test_apps/rmt/main/test_rmt_common.c @@ -13,7 +13,7 @@ #include "driver/rmt_rx.h" #include "soc/soc_caps.h" -TEST_CASE("rmt_channel_install_uninstall", "[rmt]") +TEST_CASE("rmt channel install & uninstall", "[rmt]") { rmt_tx_channel_config_t tx_channel_cfg = { .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, diff --git a/components/driver/test_apps/rmt/main/test_rmt_iram.c b/components/driver/test_apps/rmt/main/test_rmt_iram.c index 2efd2103ee..755e360bfa 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_iram.c +++ b/components/driver/test_apps/rmt/main/test_rmt_iram.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -78,17 +78,14 @@ static void test_rmt_tx_iram_safe(size_t mem_block_symbols, bool with_dma) TEST_ESP_OK(rmt_del_encoder(led_strip_encoder)); } -TEST_CASE("rmt_tx_iram_safe_no_dma", "[rmt]") +TEST_CASE("rmt tx iram safe", "[rmt]") { test_rmt_tx_iram_safe(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); +#if SOC_RMT_SUPPORT_DMA + test_rmt_tx_iram_safe(1024, true); +#endif } -#if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_tx_iram_safe_with_dma", "[rmt]") -{ - test_rmt_tx_iram_safe(1024, true); -} -#endif static void IRAM_ATTR test_simulate_input_post_cache_disable(void *args) @@ -169,14 +166,10 @@ static void test_rmt_rx_iram_safe(size_t mem_block_symbols, bool with_dma, rmt_c TEST_ESP_OK(rmt_del_channel(rx_channel)); } -TEST_CASE("rmt_rx_iram_safe_no_dma", "[rmt]") +TEST_CASE("rmt rx iram safe", "[rmt]") { test_rmt_rx_iram_safe(SOC_RMT_MEM_WORDS_PER_CHANNEL, false, RMT_CLK_SRC_DEFAULT); -} - #if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_rx_iram_safe_with_dma", "[rmt]") -{ test_rmt_rx_iram_safe(128, true, RMT_CLK_SRC_DEFAULT); -} #endif +} diff --git a/components/driver/test_apps/rmt/main/test_rmt_rx.c b/components/driver/test_apps/rmt/main/test_rmt_rx.c index dfbcdac378..fe081c7f67 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_rx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_rx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -185,18 +185,14 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ESP_OK(rmt_del_encoder(nec_encoder)); } -TEST_CASE("rmt_rx_nec_carrier_no_dma", "[rmt]") +TEST_CASE("rmt rx nec with carrier", "[rmt]") { // test width different clock sources rmt_clock_source_t clk_srcs[] = SOC_RMT_CLKS; for (size_t i = 0; i < sizeof(clk_srcs) / sizeof(clk_srcs[0]); i++) { test_rmt_rx_nec_carrier(SOC_RMT_MEM_WORDS_PER_CHANNEL, false, clk_srcs[i]); } -} - #if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_rx_nec_carrier_with_dma", "[rmt]") -{ test_rmt_rx_nec_carrier(128, true, RMT_CLK_SRC_DEFAULT); -} #endif +} diff --git a/components/driver/test_apps/rmt/main/test_rmt_tx.c b/components/driver/test_apps/rmt/main/test_rmt_tx.c index 8696aaa8f4..28242f6455 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_tx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_tx.c @@ -20,6 +20,63 @@ #define TEST_RMT_CALLBACK_ATTR #endif +TEST_CASE("rmt bytes encoder", "[rmt]") +{ + rmt_tx_channel_config_t tx_channel_cfg = { + .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 1000000, // 1MHz, 1 tick = 1us + .trans_queue_depth = 4, + .gpio_num = 0, + }; + printf("install tx channel\r\n"); + rmt_channel_handle_t tx_channel = NULL; + TEST_ESP_OK(rmt_new_tx_channel(&tx_channel_cfg, &tx_channel)); + printf("install bytes encoder\r\n"); + rmt_encoder_handle_t bytes_encoder = NULL; + rmt_bytes_encoder_config_t bytes_enc_config = { + .bit0 = { + .level0 = 1, + .duration0 = 3, // 3us + .level1 = 0, + .duration1 = 9, // 9us + }, + .bit1 = { + .level0 = 1, + .duration0 = 9, // 9us + .level1 = 0, + .duration1 = 3, // 3us + }, + }; + TEST_ESP_OK(rmt_new_bytes_encoder(&bytes_enc_config, &bytes_encoder)); + printf("enable tx channel\r\n"); + TEST_ESP_OK(rmt_enable(tx_channel)); + + printf("start transaction\r\n"); + rmt_transmit_config_t transmit_config = { + .loop_count = 0, // no loop + }; + TEST_ESP_OK(rmt_transmit(tx_channel, bytes_encoder, (uint8_t[]) { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + }, 6, &transmit_config)); + // adding extra delay here for visualizing + vTaskDelay(pdMS_TO_TICKS(500)); + TEST_ESP_OK(rmt_transmit(tx_channel, bytes_encoder, (uint8_t[]) { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }, 7, &transmit_config)); + vTaskDelay(pdMS_TO_TICKS(500)); + TEST_ESP_OK(rmt_transmit(tx_channel, bytes_encoder, (uint8_t[]) { + 0x00, 0x01, 0x02, 0x03, 0x04 + }, 5, &transmit_config)); + vTaskDelay(pdMS_TO_TICKS(500)); + + printf("disable tx channel\r\n"); + TEST_ESP_OK(rmt_disable(tx_channel)); + printf("remove tx channel and encoder\r\n"); + TEST_ESP_OK(rmt_del_channel(tx_channel)); + TEST_ESP_OK(rmt_del_encoder(bytes_encoder)); +} + static void test_rmt_channel_single_trans(size_t mem_block_symbols, bool with_dma) { rmt_tx_channel_config_t tx_channel_cfg = { @@ -66,17 +123,13 @@ static void test_rmt_channel_single_trans(size_t mem_block_symbols, bool with_dm TEST_ESP_OK(rmt_del_encoder(led_strip_encoder)); } -TEST_CASE("rmt_single_trans_no_dma", "[rmt]") +TEST_CASE("rmt single transaction", "[rmt]") { test_rmt_channel_single_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); -} - #if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_single_trans_with_dma", "[rmt]") -{ test_rmt_channel_single_trans(512, true); -} #endif +} static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) { @@ -147,17 +200,14 @@ static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) #undef TEST_LED_NUM } -TEST_CASE("rmt_ping_pong_trans_no_dma", "[rmt]") +TEST_CASE("rmt ping-pong transaction", "[rmt]") { test_rmt_ping_pong_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); +#if SOC_RMT_SUPPORT_DMA + test_rmt_ping_pong_trans(1024, true); +#endif } -#if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_ping_pong_trans_with_dma", "[rmt]") -{ - test_rmt_ping_pong_trans(1024, true); -} -#endif TEST_RMT_CALLBACK_ATTR static bool test_rmt_tx_done_cb_check_event_data(rmt_channel_handle_t channel, const rmt_tx_done_event_data_t *edata, void *user_data) @@ -222,17 +272,13 @@ static void test_rmt_trans_done_event(size_t mem_block_symbols, bool with_dma) #undef TEST_LED_NUM } -TEST_CASE("rmt_trans_done_event_callback_no_dma", "[rmt]") +TEST_CASE("rmt trans_done event callback", "[rmt]") { test_rmt_trans_done_event(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); -} - #if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_trans_done_event_callback_with_dma", "[rmt]") -{ test_rmt_trans_done_event(332, true); -} #endif +} #if SOC_RMT_SUPPORT_TX_LOOP_COUNT @@ -294,20 +340,17 @@ static void test_rmt_loop_trans(size_t mem_block_symbols, bool with_dma) #undef TEST_LED_NUM } -TEST_CASE("rmt_loop_trans_no_dma", "[rmt]") +TEST_CASE("rmt finite loop transaction", "[rmt]") { test_rmt_loop_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL * 2, false); +#if SOC_RMT_SUPPORT_DMA + test_rmt_loop_trans(128, true); +#endif } -#if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_loop_trans_with_dma", "[rmt]") -{ - test_rmt_loop_trans(128, true); -} -#endif // SOC_RMT_SUPPORT_DMA #endif // SOC_RMT_SUPPORT_TX_LOOP_COUNT -TEST_CASE("rmt_infinite_loop_trans", "[rmt]") +TEST_CASE("rmt infinite loop transaction", "[rmt]") { rmt_tx_channel_config_t tx_channel_cfg = { .clk_src = RMT_CLK_SRC_DEFAULT, @@ -441,17 +484,14 @@ static void test_rmt_tx_nec_carrier(size_t mem_block_symbols, bool with_dma) TEST_ESP_OK(rmt_del_encoder(nec_encoder)); } -TEST_CASE("rmt_tx_nec_carrier_no_dma", "[rmt]") +TEST_CASE("rmt tx nec with carrier", "[rmt]") { test_rmt_tx_nec_carrier(SOC_RMT_MEM_WORDS_PER_CHANNEL, false); +#if SOC_RMT_SUPPORT_DMA + test_rmt_tx_nec_carrier(128, true); +#endif } -#if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_tx_nec_carrier_with_dma", "[rmt]") -{ - test_rmt_tx_nec_carrier(128, true); -} -#endif TEST_RMT_CALLBACK_ATTR static bool test_rmt_tx_done_cb_record_time(rmt_channel_handle_t channel, const rmt_tx_done_event_data_t *edata, void *user_data) @@ -596,14 +636,10 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz #undef TEST_RMT_CHANS } -TEST_CASE("rmt_multi_channels_trans_no_dma", "[rmt]") +TEST_CASE("rmt multiple channels transaction", "[rmt]") { test_rmt_multi_channels_trans(SOC_RMT_MEM_WORDS_PER_CHANNEL, SOC_RMT_MEM_WORDS_PER_CHANNEL, false, false); -} - #if SOC_RMT_SUPPORT_DMA -TEST_CASE("rmt_multi_channels_trans_with_dma", "[rmt]") -{ test_rmt_multi_channels_trans(1024, SOC_RMT_MEM_WORDS_PER_CHANNEL, true, false); -} #endif +} diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 7fbf730342..8a4bb679a8 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -520,6 +520,17 @@ Application Examples * RMT infinite loop for driving DShot ESC: :example:`peripherals/rmt/dshot_esc` * RMT simulate 1-wire protocol (take DS18B20 as example): :example:`peripherals/rmt/onewire` +FAQ +--- + +* Why the RMT encoder results in more data than expected? + +The RMT encoding takes place in the ISR context. If your RMT encoding session takes a long time (e.g. by logging debug information) or the encoding session is deferred somehow because of interrupt latency, then it's possible the transmitting becomes **faster** than the encoding. Which in result, the encoder can't prepare the next data in time, leading to the transmitter sending the previous data again. There's no way to ask the transmitter to stop and wait. You can mitigate the issue by combining the following ways: + + - increase the :cpp:member:`rmt_tx_channel_config_t::mem_block_symbols`, in steps of {IDF_TARGET_SOC_RMT_MEM_WORDS_PER_CHANNEL} + - place the encoding function in the IRAM + - Enables the :cpp:member:`rmt_tx_channel_config_t::with_dma` if it's available for your chip + API Reference -------------