Merge branch 'feature/test_rmt_bytes_encoder' into 'master'

rmt: explained why encoder may results in more data being transmitted

Closes IDFGH-10201

See merge request espressif/esp-idf!23880
This commit is contained in:
morris 2023-05-31 10:20:13 +08:00
commit bdd0d1ddc8
5 changed files with 98 additions and 62 deletions

View File

@ -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,

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
-------------