From 6bb05cccdd59355cfc85e9495138823c75a971aa Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 1 Aug 2023 17:32:26 +0800 Subject: [PATCH] feat(rmt): add driver support for esp32p4 including DMA feature --- components/driver/Kconfig | 27 +- components/driver/deprecated/rmt_legacy.c | 44 +- components/driver/deprecated/timer_legacy.c | 2 +- components/driver/gptimer/gptimer.c | 2 +- components/driver/rmt/Kconfig.rmt | 26 + components/driver/rmt/rmt_common.c | 46 +- components/driver/rmt/rmt_encoder.c | 44 +- components/driver/rmt/rmt_private.h | 32 +- components/driver/rmt/rmt_rx.c | 69 +- components/driver/rmt/rmt_tx.c | 99 +- .../test_apps/legacy_rmt_driver/README.md | 4 +- .../legacy_rmt_driver/main/test_legacy_rmt.c | 12 +- components/driver/test_apps/rmt/README.md | 4 +- .../driver/test_apps/rmt/main/test_board.h | 9 + .../test_apps/rmt/main/test_rmt_common.c | 62 +- .../driver/test_apps/rmt/main/test_rmt_iram.c | 7 +- .../driver/test_apps/rmt/main/test_rmt_rx.c | 64 +- .../driver/test_apps/rmt/main/test_rmt_tx.c | 54 +- .../rmt/main/test_util_rmt_encoders.c | 11 +- .../esp_hw_support/dma/async_memcpy_gdma.c | 6 +- components/hal/esp32/include/hal/rmt_ll.h | 38 +- components/hal/esp32c3/include/hal/rmt_ll.h | 35 +- components/hal/esp32c6/include/hal/rmt_ll.h | 24 + components/hal/esp32h2/include/hal/rmt_ll.h | 24 + .../hal/esp32p4/include/hal/clk_gate_ll.h | 6 - components/hal/esp32p4/include/hal/rmt_ll.h | 923 ++++++++++++++++++ components/hal/esp32s2/include/hal/rmt_ll.h | 39 +- components/hal/esp32s3/include/hal/rmt_ll.h | 33 + components/hal/rmt_hal.c | 2 - .../esp32p4/include/soc/Kconfig.soc_caps.in | 20 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 36 + .../soc/esp32p4/include/soc/rmt_struct.h | 586 +++++------ components/soc/esp32p4/include/soc/soc_caps.h | 15 +- .../soc/esp32p4/ld/esp32p4.peripherals.ld | 4 +- components/soc/esp32p4/rmt_periph.c | 41 +- docs/docs_not_updated/esp32p4.txt | 1 - examples/peripherals/rmt/dshot_esc/README.md | 4 +- .../rmt/ir_nec_transceiver/README.md | 4 +- examples/peripherals/rmt/led_strip/README.md | 4 +- .../peripherals/rmt/musical_buzzer/README.md | 4 +- examples/peripherals/rmt/onewire/README.md | 4 +- .../peripherals/rmt/stepper_motor/README.md | 4 +- 42 files changed, 1882 insertions(+), 593 deletions(-) create mode 100644 components/driver/rmt/Kconfig.rmt create mode 100644 components/driver/test_apps/rmt/main/test_board.h create mode 100644 components/hal/esp32p4/include/hal/rmt_ll.h diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 46f2d0b979..65f29bd8e7 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -299,32 +299,7 @@ menu "Driver Configurations" orsource "./pcnt/Kconfig.pcnt" - menu "RMT Configuration" - depends on SOC_RMT_SUPPORTED - config RMT_ISR_IRAM_SAFE - bool "RMT ISR IRAM-Safe" - default n - select GDMA_ISR_IRAM_SAFE if SOC_RMT_SUPPORT_DMA # RMT basic functionality relies on GDMA callback - select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to restart the GDMA in the interrupt - help - Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be - executable when the cache is disabled (e.g. SPI Flash write). - - config RMT_SUPPRESS_DEPRECATE_WARN - bool "Suppress legacy driver deprecated warning" - default n - help - Wether to suppress the deprecation warnings when using legacy rmt driver (driver/rmt.h). - If you want to continue using the legacy driver, and don't want to see related deprecation warnings, - you can enable this option. - - config RMT_ENABLE_DEBUG_LOG - bool "Enable debug log" - default n - help - Wether to enable the debug log message for RMT driver. - Note that, this option only controls the RMT driver log, won't affect other drivers. - endmenu # RMT Configuration + orsource "./rmt/Kconfig.rmt" orsource "./mcpwm/Kconfig.mcpwm" diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index 66950f7b60..e485420a7b 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/components/driver/deprecated/rmt_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -58,6 +58,18 @@ static const char *TAG = "rmt(legacy)"; #define RMT_DECODE_RX_CHANNEL(encode_chan) ((encode_chan - RMT_RX_CHANNEL_ENCODING_START)) #define RMT_ENCODE_RX_CHANNEL(decode_chan) ((decode_chan + RMT_RX_CHANNEL_ENCODING_START)) +#if SOC_PERIPH_CLK_CTRL_SHARED +#define RMT_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RMT_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define RMT_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RMT_RCC_ATOMIC() +#endif + typedef struct { rmt_hal_context_t hal; _lock_t rmt_driver_isr_lock; @@ -125,8 +137,10 @@ static void rmt_module_enable(void) { RMT_ENTER_CRITICAL(); if (rmt_contex.rmt_module_enabled == false) { - periph_module_reset(rmt_periph_signals.groups[0].module); - periph_module_enable(rmt_periph_signals.groups[0].module); + RMT_RCC_ATOMIC() { + rmt_ll_enable_bus_clock(0, true); + rmt_ll_reset_register(0); + } rmt_contex.rmt_module_enabled = true; } RMT_EXIT_CRITICAL(); @@ -137,7 +151,9 @@ static void rmt_module_disable(void) { RMT_ENTER_CRITICAL(); if (rmt_contex.rmt_module_enabled == true) { - periph_module_disable(rmt_periph_signals.groups[0].module); + RMT_RCC_ATOMIC() { + rmt_ll_enable_bus_clock(0, false); + } rmt_contex.rmt_module_enabled = false; } RMT_EXIT_CRITICAL(); @@ -415,7 +431,9 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk) ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); RMT_ENTER_CRITICAL(); // `rmt_clock_source_t` and `rmt_source_clk_t` are binary compatible, as the underlying enum entries come from the same `soc_module_clk_t` - rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0); + RMT_CLOCK_SRC_ATOMIC() { + rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -552,6 +570,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par uint32_t carrier_freq_hz = rmt_param->tx_config.carrier_freq_hz; bool carrier_en = rmt_param->tx_config.carrier_en; uint32_t rmt_source_clk_hz; + rmt_clock_source_t clk_src = RMT_BASECLK_DEFAULT; ESP_RETURN_ON_FALSE(rmt_is_channel_number_valid(channel, mode), ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); ESP_RETURN_ON_FALSE(mem_cnt + channel <= SOC_RMT_CHANNELS_PER_GROUP && mem_cnt > 0, ESP_ERR_INVALID_ARG, TAG, RMT_MEM_CNT_ERROR_STR); @@ -567,19 +586,18 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par if (rmt_param->flags & RMT_CHANNEL_FLAGS_AWARE_DFS) { #if SOC_RMT_SUPPORT_XTAL // clock src: XTAL_CLK - esp_clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); - rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_XTAL, 1, 0, 0); + clk_src = RMT_BASECLK_XTAL; #elif SOC_RMT_SUPPORT_REF_TICK // clock src: REF_CLK - esp_clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_REF, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); - rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_REF, 1, 0, 0); + clk_src = RMT_BASECLK_REF; #else #error "No clock source is aware of DFS" #endif - } else { - // fallback to use default clock source - esp_clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); - rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_DEFAULT, 1, 0, 0); + } + esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); + RMT_CLOCK_SRC_ATOMIC() { + rmt_ll_set_group_clock_src(dev, channel, clk_src, 1, 0, 0); + rmt_ll_enable_group_clock(dev, true); } RMT_EXIT_CRITICAL(); diff --git a/components/driver/deprecated/timer_legacy.c b/components/driver/deprecated/timer_legacy.c index 43f42336d0..7df292bdf3 100644 --- a/components/driver/deprecated/timer_legacy.c +++ b/components/driver/deprecated/timer_legacy.c @@ -34,7 +34,7 @@ static const char *TIMER_TAG = "timer_group"; #define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL_SAFE(mux); #define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL_SAFE(mux); -#if CONFIG_IDF_TARGET_ESP32P4 +#if SOC_PERIPH_CLK_CTRL_SHARED #define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define GPTIMER_CLOCK_SRC_ATOMIC() diff --git a/components/driver/gptimer/gptimer.c b/components/driver/gptimer/gptimer.c index cf1b2ec797..61978935b1 100644 --- a/components/driver/gptimer/gptimer.c +++ b/components/driver/gptimer/gptimer.c @@ -32,7 +32,7 @@ static const char *TAG = "gptimer"; -#if CONFIG_IDF_TARGET_ESP32P4 +#if SOC_PERIPH_CLK_CTRL_SHARED #define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() #else #define GPTIMER_CLOCK_SRC_ATOMIC() diff --git a/components/driver/rmt/Kconfig.rmt b/components/driver/rmt/Kconfig.rmt new file mode 100644 index 0000000000..76605b7575 --- /dev/null +++ b/components/driver/rmt/Kconfig.rmt @@ -0,0 +1,26 @@ +menu "RMT Configuration" + depends on SOC_RMT_SUPPORTED + config RMT_ISR_IRAM_SAFE + bool "RMT ISR IRAM-Safe" + default n + select GDMA_ISR_IRAM_SAFE if SOC_RMT_SUPPORT_DMA # RMT basic functionality relies on GDMA callback + select GDMA_CTRL_FUNC_IN_IRAM if SOC_RMT_SUPPORT_DMA # RMT needs to restart the GDMA in the interrupt + help + Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be + executable when the cache is disabled (e.g. SPI Flash write). + + config RMT_SUPPRESS_DEPRECATE_WARN + bool "Suppress legacy driver deprecated warning" + default n + help + Wether to suppress the deprecation warnings when using legacy rmt driver (driver/rmt.h). + If you want to continue using the legacy driver, and don't want to see related deprecation warnings, + you can enable this option. + + config RMT_ENABLE_DEBUG_LOG + bool "Enable debug log" + default n + help + Wether to enable the debug log message for RMT driver. + Note that, this option only controls the RMT driver log, won't affect other drivers. +endmenu # RMT Configuration diff --git a/components/driver/rmt/rmt_common.c b/components/driver/rmt/rmt_common.c index 2a95f4b61f..0cb834d959 100644 --- a/components/driver/rmt/rmt_common.c +++ b/components/driver/rmt/rmt_common.c @@ -24,6 +24,18 @@ static const char *TAG = "rmt"; +#if SOC_PERIPH_CLK_CTRL_SHARED +#define RMT_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RMT_CLOCK_SRC_ATOMIC() +#endif + +#if !SOC_RCC_IS_INDEPENDENT +#define RMT_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define RMT_RCC_ATOMIC() +#endif + typedef struct rmt_platform_t { _lock_t mutex; // platform level mutex lock rmt_group_t *groups[SOC_RMT_GROUPS]; // array of RMT group instances @@ -50,11 +62,13 @@ rmt_group_t *rmt_acquire_group_handle(int group_id) group->occupy_mask = UINT32_MAX & ~((1 << SOC_RMT_CHANNELS_PER_GROUP) - 1); // group clock won't be configured at this stage, it will be set when allocate the first channel group->clk_src = 0; - // enable APB access RMT registers - periph_module_enable(rmt_periph_signals.groups[group_id].module); - periph_module_reset(rmt_periph_signals.groups[group_id].module); - // "uninitialize" group intr_priority, read comments in `rmt_new_tx_channel()` for detail - group->intr_priority = RMT_GROUP_INTR_PRIORITY_UNINITALIZED; + // group interrupt priority is shared between all channels, it will be set when allocate the first channel + group->intr_priority = RMT_GROUP_INTR_PRIORITY_UNINITIALIZED; + // enable the bus clock for the RMT peripheral + RMT_RCC_ATOMIC() { + rmt_ll_enable_bus_clock(group_id, true); + rmt_ll_reset_register(group_id); + } // hal layer initialize rmt_hal_init(&group->hal); } @@ -78,15 +92,23 @@ void rmt_release_group_handle(rmt_group_t *group) int group_id = group->group_id; rmt_clock_source_t clk_src = group->clk_src; bool do_deinitialize = false; + rmt_hal_context_t *hal = &group->hal; _lock_acquire(&s_platform.mutex); s_platform.group_ref_counts[group_id]--; if (s_platform.group_ref_counts[group_id] == 0) { do_deinitialize = true; s_platform.groups[group_id] = NULL; + // disable core clock + RMT_CLOCK_SRC_ATOMIC() { + rmt_ll_enable_group_clock(hal->regs, false); + } // hal layer deinitialize - rmt_hal_deinit(&group->hal); - periph_module_disable(rmt_periph_signals.groups[group_id].module); + rmt_hal_deinit(hal); + // disable bus clock + RMT_RCC_ATOMIC() { + rmt_ll_enable_bus_clock(group_id, false); + } free(group); } _lock_release(&s_platform.mutex); @@ -165,7 +187,10 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t #endif // CONFIG_PM_ENABLE // no division for group clock source, to achieve highest resolution - rmt_ll_set_group_clock_src(group->hal.regs, channel_id, clk_src, 1, 1, 0); + RMT_CLOCK_SRC_ATOMIC() { + rmt_ll_set_group_clock_src(group->hal.regs, channel_id, clk_src, 1, 1, 0); + rmt_ll_enable_group_clock(group->hal.regs, true); + } group->resolution_hz = periph_src_clk_hz; ESP_LOGD(TAG, "group clock resolution:%"PRIu32, group->resolution_hz); return ret; @@ -211,7 +236,7 @@ bool rmt_set_intr_priority_to_group(rmt_group_t *group, int intr_priority) { bool priority_conflict = false; portENTER_CRITICAL(&group->spinlock); - if (group->intr_priority == RMT_GROUP_INTR_PRIORITY_UNINITALIZED) { + if (group->intr_priority == RMT_GROUP_INTR_PRIORITY_UNINITIALIZED) { // intr_priority never allocated, accept user's value unconditionally // intr_priority could only be set once here group->intr_priority = intr_priority; @@ -240,7 +265,8 @@ bool rmt_set_intr_priority_to_group(rmt_group_t *group, int intr_priority) return priority_conflict; } -int rmt_get_isr_flags(rmt_group_t *group) { +int rmt_get_isr_flags(rmt_group_t *group) +{ int isr_flags = RMT_INTR_ALLOC_FLAG; if (group->intr_priority) { // Use user-specified priority bit diff --git a/components/driver/rmt/rmt_encoder.c b/components/driver/rmt/rmt_encoder.c index f6c5939b74..f261862878 100644 --- a/components/driver/rmt/rmt_encoder.c +++ b/components/driver/rmt/rmt_encoder.c @@ -62,8 +62,8 @@ static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_han rmt_tx_channel_t *tx_chan = __containerof(channel, rmt_tx_channel_t, base); const uint8_t *nd = (const uint8_t *)primary_data; rmt_encode_state_t state = RMT_ENCODING_RESET; - dma_descriptor_t *desc0 = NULL; - dma_descriptor_t *desc1 = NULL; + rmt_dma_descriptor_t *desc0 = NULL; + rmt_dma_descriptor_t *desc1 = NULL; size_t byte_index = bytes_encoder->last_byte_index; size_t bit_index = bytes_encoder->last_bit_index; @@ -72,7 +72,12 @@ static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_han // how many symbols we can save for this round size_t mem_have = tx_chan->mem_end - tx_chan->mem_off; // where to put the encoded symbols? DMA buffer or RMT HW memory - rmt_symbol_word_t *mem_to = channel->dma_chan ? channel->dma_mem_base : channel->hw_mem_base; + rmt_symbol_word_t *mem_to_nc = NULL; + if (channel->dma_chan) { + mem_to_nc = (rmt_symbol_word_t *)RMT_GET_NON_CACHE_ADDR(channel->dma_mem_base); + } else { + mem_to_nc = channel->hw_mem_base; + } // how many symbols will be encoded in this round size_t encode_len = MIN(mem_want, mem_have); bool encoding_truncated = mem_have < mem_want; @@ -81,9 +86,9 @@ static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_han if (channel->dma_chan) { // mark the start descriptor if (tx_chan->mem_off < tx_chan->ping_pong_symbols) { - desc0 = &tx_chan->dma_nodes[0]; + desc0 = &tx_chan->dma_nodes_nc[0]; } else { - desc0 = &tx_chan->dma_nodes[1]; + desc0 = &tx_chan->dma_nodes_nc[1]; } } @@ -97,9 +102,9 @@ static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_han } while ((len > 0) && (bit_index < 8)) { if (cur_byte & (1 << bit_index)) { - mem_to[tx_chan->mem_off++] = bytes_encoder->bit1; + mem_to_nc[tx_chan->mem_off++] = bytes_encoder->bit1; } else { - mem_to[tx_chan->mem_off++] = bytes_encoder->bit0; + mem_to_nc[tx_chan->mem_off++] = bytes_encoder->bit0; } len--; bit_index++; @@ -113,9 +118,9 @@ static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_han if (channel->dma_chan) { // mark the end descriptor if (tx_chan->mem_off < tx_chan->ping_pong_symbols) { - desc1 = &tx_chan->dma_nodes[0]; + desc1 = &tx_chan->dma_nodes_nc[0]; } else { - desc1 = &tx_chan->dma_nodes[1]; + desc1 = &tx_chan->dma_nodes_nc[1]; } // cross line, means desc0 has prepared with sufficient data buffer @@ -168,8 +173,8 @@ static size_t IRAM_ATTR rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_hand rmt_tx_channel_t *tx_chan = __containerof(channel, rmt_tx_channel_t, base); rmt_symbol_word_t *symbols = (rmt_symbol_word_t *)primary_data; rmt_encode_state_t state = RMT_ENCODING_RESET; - dma_descriptor_t *desc0 = NULL; - dma_descriptor_t *desc1 = NULL; + rmt_dma_descriptor_t *desc0 = NULL; + rmt_dma_descriptor_t *desc1 = NULL; size_t symbol_index = copy_encoder->last_symbol_index; // how many symbols will be copied by the encoder @@ -177,7 +182,12 @@ static size_t IRAM_ATTR rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_hand // how many symbols we can save for this round size_t mem_have = tx_chan->mem_end - tx_chan->mem_off; // where to put the encoded symbols? DMA buffer or RMT HW memory - rmt_symbol_word_t *mem_to = channel->dma_chan ? channel->dma_mem_base : channel->hw_mem_base; + rmt_symbol_word_t *mem_to_nc = NULL; + if (channel->dma_chan) { + mem_to_nc = (rmt_symbol_word_t *)RMT_GET_NON_CACHE_ADDR(channel->dma_mem_base); + } else { + mem_to_nc = channel->hw_mem_base; + } // how many symbols will be encoded in this round size_t encode_len = MIN(mem_want, mem_have); bool encoding_truncated = mem_have < mem_want; @@ -186,24 +196,24 @@ static size_t IRAM_ATTR rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_hand if (channel->dma_chan) { // mark the start descriptor if (tx_chan->mem_off < tx_chan->ping_pong_symbols) { - desc0 = &tx_chan->dma_nodes[0]; + desc0 = &tx_chan->dma_nodes_nc[0]; } else { - desc0 = &tx_chan->dma_nodes[1]; + desc0 = &tx_chan->dma_nodes_nc[1]; } } size_t len = encode_len; while (len > 0) { - mem_to[tx_chan->mem_off++] = symbols[symbol_index++]; + mem_to_nc[tx_chan->mem_off++] = symbols[symbol_index++]; len--; } if (channel->dma_chan) { // mark the end descriptor if (tx_chan->mem_off < tx_chan->ping_pong_symbols) { - desc1 = &tx_chan->dma_nodes[0]; + desc1 = &tx_chan->dma_nodes_nc[0]; } else { - desc1 = &tx_chan->dma_nodes[1]; + desc1 = &tx_chan->dma_nodes_nc[1]; } // cross line, means desc0 has prepared with sufficient data buffer diff --git a/components/driver/rmt/rmt_private.h b/components/driver/rmt/rmt_private.h index 4fb4406a89..c68d67cfcf 100644 --- a/components/driver/rmt/rmt_private.h +++ b/components/driver/rmt/rmt_private.h @@ -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 */ @@ -13,9 +13,11 @@ #include "freertos/idf_additions.h" #include "esp_err.h" #include "soc/soc_caps.h" +#include "soc/gdma_channel.h" #include "hal/rmt_types.h" #include "hal/rmt_hal.h" #include "hal/dma_types.h" +#include "hal/cache_ll.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" #include "esp_pm.h" @@ -44,16 +46,27 @@ extern "C" { #define RMT_TX_CHANNEL_OFFSET_IN_GROUP 0 #define RMT_RX_CHANNEL_OFFSET_IN_GROUP (SOC_RMT_CHANNELS_PER_GROUP - SOC_RMT_TX_CANDIDATES_PER_GROUP) - #define RMT_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED // DMA buffer size must align to `rmt_symbol_word_t` #define RMT_DMA_DESC_BUF_MAX_SIZE (DMA_DESCRIPTOR_BUFFER_MAX_SIZE & ~(sizeof(rmt_symbol_word_t) - 1)) -#define RMT_DMA_NODES_PING_PONG 2 // two nodes ping-pong -#define RMT_PM_LOCK_NAME_LEN_MAX 16 +#define RMT_DMA_NODES_PING_PONG 2 // two nodes ping-pong +#define RMT_PM_LOCK_NAME_LEN_MAX 16 +#define RMT_GROUP_INTR_PRIORITY_UNINITIALIZED (-1) -#define RMT_GROUP_INTR_PRIORITY_UNINITALIZED (-1) +#if SOC_GDMA_TRIG_PERIPH_RMT0_BUS == SOC_GDMA_BUS_AHB +#define RMT_DMA_DESC_ALIGN 32 +typedef dma_descriptor_align4_t rmt_dma_descriptor_t; +#else +#error "Unsupported RMT DMA bus" +#endif + +#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR +#define RMT_GET_NON_CACHE_ADDR(addr) ((addr) ? CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) : 0) +#else +#define RMT_GET_NON_CACHE_ADDR(addr) (addr) +#endif typedef struct { struct { @@ -151,7 +164,8 @@ struct rmt_tx_channel_t { rmt_tx_trans_desc_t *cur_trans; // points to current transaction void *user_data; // user context rmt_tx_done_callback_t on_trans_done; // callback, invoked on trans done - dma_descriptor_t dma_nodes[RMT_DMA_NODES_PING_PONG]; // DMA descriptor nodes, make up a circular link list + rmt_dma_descriptor_t *dma_nodes; // DMA descriptor nodes + rmt_dma_descriptor_t *dma_nodes_nc; // DMA descriptor nodes accessed in non-cached way rmt_tx_trans_desc_t trans_desc_pool[]; // transfer descriptor pool }; @@ -164,13 +178,14 @@ typedef struct { struct rmt_rx_channel_t { rmt_channel_t base; // channel base class - size_t mem_off; // starting offset to fetch the symbols in RMTMEM + size_t mem_off; // starting offset to fetch the symbols in RMT-MEM size_t ping_pong_symbols; // ping-pong size (half of the RMT channel memory) rmt_rx_done_callback_t on_recv_done; // callback, invoked on receive done void *user_data; // user context rmt_rx_trans_desc_t trans_desc; // transaction description size_t num_dma_nodes; // number of DMA nodes, determined by how big the memory block that user configures - dma_descriptor_t dma_nodes[]; // DMA link nodes + rmt_dma_descriptor_t *dma_nodes; // DMA link nodes + rmt_dma_descriptor_t *dma_nodes_nc; // DMA descriptor nodes accessed in non-cached way }; /** @@ -201,7 +216,6 @@ void rmt_release_group_handle(rmt_group_t *group); */ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clk_src); - /** * @brief Set interrupt priority to RMT group * @param group RMT group to set interrupt priority to diff --git a/components/driver/rmt/rmt_rx.c b/components/driver/rmt/rmt_rx.c index 03c3d1de5b..9ee7d1ad16 100644 --- a/components/driver/rmt/rmt_rx.c +++ b/components/driver/rmt/rmt_rx.c @@ -21,10 +21,12 @@ #include "soc/rmt_periph.h" #include "soc/rtc.h" #include "hal/rmt_ll.h" +#include "hal/cache_hal.h" #include "hal/gpio_hal.h" #include "driver/gpio.h" #include "driver/rmt_rx.h" #include "rmt_private.h" +#include "rom/cache.h" #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) @@ -39,26 +41,26 @@ static void rmt_rx_default_isr(void *args); #if SOC_RMT_SUPPORT_DMA static bool rmt_dma_rx_eof_cb(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data); -static void rmt_rx_mount_dma_buffer(dma_descriptor_t *desc_array, size_t array_size, const void *buffer, size_t buffer_size) +static void rmt_rx_mount_dma_buffer(rmt_dma_descriptor_t *desc_array, rmt_dma_descriptor_t *desc_array_nc, size_t array_size, const void *buffer, size_t buffer_size) { size_t prepared_length = 0; uint8_t *data = (uint8_t *)buffer; int dma_node_i = 0; - dma_descriptor_t *desc = NULL; + rmt_dma_descriptor_t *desc = NULL; while (buffer_size > RMT_DMA_DESC_BUF_MAX_SIZE) { - desc = &desc_array[dma_node_i]; + desc = &desc_array_nc[dma_node_i]; desc->dw0.suc_eof = 0; desc->dw0.size = RMT_DMA_DESC_BUF_MAX_SIZE; desc->dw0.length = 0; desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; desc->buffer = &data[prepared_length]; - desc->next = &desc_array[dma_node_i + 1]; + desc->next = &desc_array[dma_node_i + 1]; // note, we must use the cache address for the "next" pointer prepared_length += RMT_DMA_DESC_BUF_MAX_SIZE; buffer_size -= RMT_DMA_DESC_BUF_MAX_SIZE; dma_node_i++; } if (buffer_size) { - desc = &desc_array[dma_node_i]; + desc = &desc_array_nc[dma_node_i]; desc->dw0.suc_eof = 0; desc->dw0.size = buffer_size; desc->dw0.length = 0; @@ -77,11 +79,6 @@ static esp_err_t rmt_rx_init_dma_link(rmt_rx_channel_t *rx_channel, const rmt_rx #if SOC_GDMA_TRIG_PERIPH_RMT0_BUS == SOC_GDMA_BUS_AHB ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &rx_channel->base.dma_chan), TAG, "allocate RX DMA channel failed"); #endif - gdma_strategy_config_t gdma_strategy_conf = { - .auto_update_desc = true, - .owner_check = true, - }; - gdma_apply_strategy(rx_channel->base.dma_chan, &gdma_strategy_conf); gdma_rx_event_callbacks_t cbs = { .on_recv_eof = rmt_dma_rx_eof_cb, }; @@ -173,6 +170,9 @@ static esp_err_t rmt_rx_destroy(rmt_rx_channel_t *rx_channel) // de-register channel from RMT group rmt_rx_unregister_from_group(&rx_channel->base, rx_channel->base.group); } + if (rx_channel->dma_nodes) { + free(rx_channel->dma_nodes); + } free(rx_channel); return ESP_OK; } @@ -197,18 +197,21 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_ ESP_GOTO_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, err, TAG, "DMA not supported"); #endif // SOC_RMT_SUPPORT_DMA - size_t num_dma_nodes = 0; - if (config->flags.with_dma) { - num_dma_nodes = config->mem_block_symbols * sizeof(rmt_symbol_word_t) / RMT_DMA_DESC_BUF_MAX_SIZE + 1; - } // malloc channel memory uint32_t mem_caps = RMT_MEM_ALLOC_CAPS; - if (config->flags.with_dma) { - // DMA descriptors must be placed in internal SRAM - mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; - } - rx_channel = heap_caps_calloc(1, sizeof(rmt_rx_channel_t) + num_dma_nodes * sizeof(dma_descriptor_t), mem_caps); + rx_channel = heap_caps_calloc(1, sizeof(rmt_rx_channel_t), mem_caps); ESP_GOTO_ON_FALSE(rx_channel, ESP_ERR_NO_MEM, err, TAG, "no mem for rx channel"); + // create DMA descriptor + size_t num_dma_nodes = 0; + if (config->flags.with_dma) { + mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; + num_dma_nodes = config->mem_block_symbols * sizeof(rmt_symbol_word_t) / RMT_DMA_DESC_BUF_MAX_SIZE + 1; + // DMA descriptors must be placed in internal SRAM + rx_channel->dma_nodes = heap_caps_aligned_calloc(RMT_DMA_DESC_ALIGN, num_dma_nodes, sizeof(rmt_dma_descriptor_t), mem_caps); + ESP_GOTO_ON_FALSE(rx_channel->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no mem for rx channel DMA nodes"); + // we will use the non-cached address to manipulate the DMA descriptor, for simplicity + rx_channel->dma_nodes_nc = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(rx_channel->dma_nodes); + } rx_channel->num_dma_nodes = num_dma_nodes; // register the channel to group ESP_GOTO_ON_ERROR(rmt_rx_register_to_group(rx_channel, config), err, TAG, "register channel failed"); @@ -348,6 +351,12 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_ if (channel->dma_chan) { ESP_RETURN_ON_FALSE(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "buffer must locate in internal RAM for DMA use"); + +#if CONFIG_IDF_TARGET_ESP32P4 + uint32_t data_cache_line_mask = cache_hal_get_cache_line_size(CACHE_TYPE_DATA) - 1; + ESP_RETURN_ON_FALSE(((uintptr_t)buffer & data_cache_line_mask) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer must be aligned to cache line size"); + ESP_RETURN_ON_FALSE((buffer_size & data_cache_line_mask) == 0, ESP_ERR_INVALID_ARG, TAG, "buffer size must be aligned to cache line size"); +#endif } if (channel->dma_chan) { ESP_RETURN_ON_FALSE(buffer_size <= rx_chan->num_dma_nodes * RMT_DMA_DESC_BUF_MAX_SIZE, @@ -371,9 +380,9 @@ esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_ if (channel->dma_chan) { #if SOC_RMT_SUPPORT_DMA - rmt_rx_mount_dma_buffer(rx_chan->dma_nodes, rx_chan->num_dma_nodes, buffer, buffer_size); + rmt_rx_mount_dma_buffer(rx_chan->dma_nodes, rx_chan->dma_nodes_nc, rx_chan->num_dma_nodes, buffer, buffer_size); gdma_reset(channel->dma_chan); - gdma_start(channel->dma_chan, (intptr_t)rx_chan->dma_nodes); + gdma_start(channel->dma_chan, (intptr_t)rx_chan->dma_nodes); // note, we must use the cached descriptor address to start the DMA #endif } @@ -624,12 +633,12 @@ static void IRAM_ATTR rmt_rx_default_isr(void *args) } #if SOC_RMT_SUPPORT_DMA -static size_t IRAM_ATTR rmt_rx_get_received_symbol_num_from_dma(dma_descriptor_t *desc) +static size_t IRAM_ATTR rmt_rx_get_received_symbol_num_from_dma(rmt_dma_descriptor_t *desc_nc) { size_t received_bytes = 0; - while (desc) { - received_bytes += desc->dw0.length; - desc = desc->next; + while (desc_nc) { + received_bytes += desc_nc->dw0.length; + desc_nc = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(desc_nc->next); } received_bytes = ALIGN_UP(received_bytes, sizeof(rmt_symbol_word_t)); return received_bytes / sizeof(rmt_symbol_word_t); @@ -650,10 +659,18 @@ static bool IRAM_ATTR rmt_dma_rx_eof_cb(gdma_channel_handle_t dma_chan, gdma_eve rmt_ll_rx_enable(hal->regs, channel_id, false); portEXIT_CRITICAL_ISR(&channel->spinlock); +#if CONFIG_IDF_TARGET_ESP32P4 + int invalidate_map = CACHE_MAP_L1_DCACHE; + if (esp_ptr_external_ram((const void *)trans_desc->buffer)) { + invalidate_map |= CACHE_MAP_L2_CACHE; + } + Cache_Invalidate_Addr(invalidate_map, (uint32_t)trans_desc->buffer, trans_desc->buffer_size); +#endif + if (rx_chan->on_recv_done) { rmt_rx_done_event_data_t edata = { .received_symbols = trans_desc->buffer, - .num_symbols = rmt_rx_get_received_symbol_num_from_dma(rx_chan->dma_nodes), + .num_symbols = rmt_rx_get_received_symbol_num_from_dma(rx_chan->dma_nodes_nc), }; if (rx_chan->on_recv_done(channel, &edata, rx_chan->user_data)) { need_yield = true; diff --git a/components/driver/rmt/rmt_tx.c b/components/driver/rmt/rmt_tx.c index 1c0c1c21d1..31a53bec3f 100644 --- a/components/driver/rmt/rmt_tx.c +++ b/components/driver/rmt/rmt_tx.c @@ -46,29 +46,26 @@ static bool rmt_dma_tx_eof_cb(gdma_channel_handle_t dma_chan, gdma_event_data_t static esp_err_t rmt_tx_init_dma_link(rmt_tx_channel_t *tx_channel, const rmt_tx_channel_config_t *config) { - rmt_symbol_word_t *dma_mem_base = heap_caps_calloc(1, sizeof(rmt_symbol_word_t) * config->mem_block_symbols, RMT_MEM_ALLOC_CAPS | MALLOC_CAP_DMA); + rmt_symbol_word_t *dma_mem_base = heap_caps_calloc(1, sizeof(rmt_symbol_word_t) * config->mem_block_symbols, + RMT_MEM_ALLOC_CAPS | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); ESP_RETURN_ON_FALSE(dma_mem_base, ESP_ERR_NO_MEM, TAG, "no mem for tx DMA buffer"); tx_channel->base.dma_mem_base = dma_mem_base; for (int i = 0; i < RMT_DMA_NODES_PING_PONG; i++) { // each descriptor shares half of the DMA buffer - tx_channel->dma_nodes[i].buffer = dma_mem_base + tx_channel->ping_pong_symbols * i; - tx_channel->dma_nodes[i].dw0.size = tx_channel->ping_pong_symbols * sizeof(rmt_symbol_word_t); + tx_channel->dma_nodes_nc[i].buffer = dma_mem_base + tx_channel->ping_pong_symbols * i; + tx_channel->dma_nodes_nc[i].dw0.size = tx_channel->ping_pong_symbols * sizeof(rmt_symbol_word_t); // the ownership will be switched to DMA in `rmt_tx_do_transaction()` - tx_channel->dma_nodes[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; + tx_channel->dma_nodes_nc[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; // each node can generate the DMA eof interrupt, and the driver will do a ping-pong trick in the eof callback - tx_channel->dma_nodes[i].dw0.suc_eof = 1; + tx_channel->dma_nodes_nc[i].dw0.suc_eof = 1; } + gdma_channel_alloc_config_t dma_chan_config = { .direction = GDMA_CHANNEL_DIRECTION_TX, }; #if SOC_GDMA_TRIG_PERIPH_RMT0_BUS == SOC_GDMA_BUS_AHB ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_chan_config, &tx_channel->base.dma_chan), TAG, "allocate TX DMA channel failed"); #endif - gdma_strategy_config_t gdma_strategy_conf = { - .auto_update_desc = true, - .owner_check = true, - }; - gdma_apply_strategy(tx_channel->base.dma_chan, &gdma_strategy_conf); gdma_tx_event_callbacks_t cbs = { .on_trans_eof = rmt_dma_tx_eof_cb, }; @@ -199,6 +196,9 @@ static esp_err_t rmt_tx_destroy(rmt_tx_channel_t *tx_channel) // de-register channel from RMT group rmt_tx_unregister_from_group(&tx_channel->base, tx_channel->base.group); } + if (tx_channel->dma_nodes) { + free(tx_channel->dma_nodes); + } free(tx_channel); return ESP_OK; } @@ -231,12 +231,17 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ // malloc channel memory uint32_t mem_caps = RMT_MEM_ALLOC_CAPS; + tx_channel = heap_caps_calloc(1, sizeof(rmt_tx_channel_t) + sizeof(rmt_tx_trans_desc_t) * config->trans_queue_depth, mem_caps); + ESP_GOTO_ON_FALSE(tx_channel, ESP_ERR_NO_MEM, err, TAG, "no mem for tx channel"); + // create DMA descriptors if (config->flags.with_dma) { // DMA descriptors must be placed in internal SRAM mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; + tx_channel->dma_nodes = heap_caps_aligned_calloc(RMT_DMA_DESC_ALIGN, RMT_DMA_NODES_PING_PONG, sizeof(rmt_dma_descriptor_t), mem_caps); + ESP_GOTO_ON_FALSE(tx_channel->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no mem for tx DMA nodes"); + // we will use the non-cached address to manipulate the DMA descriptor, for simplicity + tx_channel->dma_nodes_nc = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(tx_channel->dma_nodes); } - tx_channel = heap_caps_calloc(1, sizeof(rmt_tx_channel_t) + sizeof(rmt_tx_trans_desc_t) * config->trans_queue_depth, mem_caps); - ESP_GOTO_ON_FALSE(tx_channel, ESP_ERR_NO_MEM, err, TAG, "no mem for tx channel"); // create transaction queues ESP_GOTO_ON_ERROR(rmt_tx_create_trans_queue(tx_channel, config), err, TAG, "install trans queues failed"); // register the channel to group @@ -318,9 +323,9 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ tx_channel->base.disable = rmt_tx_disable; // return general channel handle *ret_chan = &tx_channel->base; - ESP_LOGD(TAG, "new tx channel(%d,%d) at %p, gpio=%d, res=%"PRIu32"Hz, hw_mem_base=%p, dma_mem_base=%p, ping_pong_size=%zu, queue_depth=%zu", + ESP_LOGD(TAG, "new tx channel(%d,%d) at %p, gpio=%d, res=%"PRIu32"Hz, hw_mem_base=%p, dma_mem_base=%p, dma_nodes_nc=%p,ping_pong_size=%zu, queue_depth=%zu", group_id, channel_id, tx_channel, config->gpio_num, tx_channel->base.resolution_hz, - tx_channel->base.hw_mem_base, tx_channel->base.dma_mem_base, tx_channel->ping_pong_symbols, tx_channel->queue_size); + tx_channel->base.hw_mem_base, tx_channel->base.dma_mem_base, tx_channel->dma_nodes_nc, tx_channel->ping_pong_symbols, tx_channel->queue_size); return ESP_OK; err: @@ -548,12 +553,17 @@ static void IRAM_ATTR rmt_tx_mark_eof(rmt_tx_channel_t *tx_chan) rmt_channel_t *channel = &tx_chan->base; rmt_group_t *group = channel->group; int channel_id = channel->channel_id; - rmt_symbol_word_t *mem_to = channel->dma_chan ? channel->dma_mem_base : channel->hw_mem_base; + rmt_symbol_word_t *mem_to_nc = NULL; rmt_tx_trans_desc_t *cur_trans = tx_chan->cur_trans; - dma_descriptor_t *desc = NULL; + rmt_dma_descriptor_t *desc_nc = NULL; + if (channel->dma_chan) { + mem_to_nc = (rmt_symbol_word_t *)RMT_GET_NON_CACHE_ADDR(channel->dma_mem_base); + } else { + mem_to_nc = channel->hw_mem_base; + } // a RMT word whose duration is zero means a "stop" pattern - mem_to[tx_chan->mem_off++] = (rmt_symbol_word_t) { + mem_to_nc[tx_chan->mem_off++] = (rmt_symbol_word_t) { .duration0 = 0, .level0 = cur_trans->flags.eot_level, .duration1 = 0, @@ -563,16 +573,16 @@ static void IRAM_ATTR rmt_tx_mark_eof(rmt_tx_channel_t *tx_chan) size_t off = 0; if (channel->dma_chan) { if (tx_chan->mem_off <= tx_chan->ping_pong_symbols) { - desc = &tx_chan->dma_nodes[0]; + desc_nc = &tx_chan->dma_nodes_nc[0]; off = tx_chan->mem_off; } else { - desc = &tx_chan->dma_nodes[1]; + desc_nc = &tx_chan->dma_nodes_nc[1]; off = tx_chan->mem_off - tx_chan->ping_pong_symbols; } - desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - desc->dw0.length = off * sizeof(rmt_symbol_word_t); + desc_nc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + desc_nc->dw0.length = off * sizeof(rmt_symbol_word_t); // break down the DMA descriptor link - desc->next = NULL; + desc_nc->next = NULL; } else { portENTER_CRITICAL_ISR(&group->spinlock); // This is the end of a sequence of encoding sessions, disable the threshold interrupt as no more data will be put into RMT memory block @@ -586,6 +596,7 @@ static size_t IRAM_ATTR rmt_encode_check_result(rmt_tx_channel_t *tx_chan, rmt_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); + if (encode_state & RMT_ENCODING_COMPLETE) { t->flags.encoding_done = true; // inserting EOF symbol if there's extra space @@ -615,12 +626,12 @@ static void IRAM_ATTR rmt_tx_do_transaction(rmt_tx_channel_t *tx_chan, rmt_tx_tr #if SOC_RMT_SUPPORT_DMA if (channel->dma_chan) { gdma_reset(channel->dma_chan); - // chain the descritpros into a ring, and will break it in `rmt_encode_eof()` + // chain the descriptors into a ring, and will break it in `rmt_encode_eof()` for (int i = 0; i < RMT_DMA_NODES_PING_PONG; i++) { - tx_chan->dma_nodes[i].next = &tx_chan->dma_nodes[i + 1]; - tx_chan->dma_nodes[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; + tx_chan->dma_nodes_nc[i].next = &tx_chan->dma_nodes[i + 1]; // note, we must use the cache address for the next pointer + tx_chan->dma_nodes_nc[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; } - tx_chan->dma_nodes[1].next = &tx_chan->dma_nodes[0]; + tx_chan->dma_nodes_nc[1].next = &tx_chan->dma_nodes[0]; } #endif // SOC_RMT_SUPPORT_DMA @@ -672,7 +683,7 @@ static void IRAM_ATTR rmt_tx_do_transaction(rmt_tx_channel_t *tx_chan, rmt_tx_tr #if SOC_RMT_SUPPORT_DMA if (channel->dma_chan) { - gdma_start(channel->dma_chan, (intptr_t)tx_chan->dma_nodes); + gdma_start(channel->dma_chan, (intptr_t)tx_chan->dma_nodes); // note, we must use the cached descriptor address to start the DMA // delay a while, wait for DMA data going to RMT memory block esp_rom_delay_us(1); } @@ -1040,22 +1051,26 @@ static void IRAM_ATTR rmt_tx_default_isr(void *args) static bool IRAM_ATTR rmt_dma_tx_eof_cb(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { rmt_tx_channel_t *tx_chan = (rmt_tx_channel_t *)user_data; - dma_descriptor_t *eof_desc = (dma_descriptor_t *)event_data->tx_eof_desc_addr; - // if the DMA descriptor link is still a ring (i.e. hasn't broken down by `rmt_tx_mark_eof()`), then we treat it as a valid ping-pong event - if (eof_desc->next && eof_desc->next->next) { - // continue pingpong transmission - rmt_tx_trans_desc_t *t = tx_chan->cur_trans; - size_t encoded_symbols = t->transmitted_symbol_num; - if (t->flags.encoding_done) { - rmt_tx_mark_eof(tx_chan); - encoded_symbols += 1; - } else { - encoded_symbols += rmt_encode_check_result(tx_chan, t); + rmt_dma_descriptor_t *eof_desc_nc = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(event_data->tx_eof_desc_addr); + rmt_dma_descriptor_t *n = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(eof_desc_nc->next); // next points to a cache address, needs to convert it to a non-cached one + if (n) { + rmt_dma_descriptor_t *nn = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(n->next); + // if the DMA descriptor link is still a ring (i.e. hasn't broken down by `rmt_tx_mark_eof()`), then we treat it as a valid ping-pong event + if (nn) { + // continue ping-pong transmission + rmt_tx_trans_desc_t *t = tx_chan->cur_trans; + size_t encoded_symbols = t->transmitted_symbol_num; + if (t->flags.encoding_done) { + rmt_tx_mark_eof(tx_chan); + encoded_symbols += 1; + } else { + encoded_symbols += rmt_encode_check_result(tx_chan, t); + } + t->transmitted_symbol_num = encoded_symbols; + tx_chan->mem_end = tx_chan->ping_pong_symbols * 3 - tx_chan->mem_end; // mem_end equals to either ping_pong_symbols or ping_pong_symbols*2 + // tell DMA that we have a new descriptor attached + gdma_append(dma_chan); } - t->transmitted_symbol_num = encoded_symbols; - tx_chan->mem_end = tx_chan->ping_pong_symbols * 3 - tx_chan->mem_end; // mem_end equals to either ping_pong_symbols or ping_pong_symbols*2 - // tell DMA that we have a new descriptor attached - gdma_append(dma_chan); } return false; } diff --git a/components/driver/test_apps/legacy_rmt_driver/README.md b/components/driver/test_apps/legacy_rmt_driver/README.md index 19f1d19a54..a79fcf4c5e 100644 --- a/components/driver/test_apps/legacy_rmt_driver/README.md +++ b/components/driver/test_apps/legacy_rmt_driver/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c b/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c index b73d40ec64..39027ce8bb 100644 --- a/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c +++ b/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include "esp_rom_gpio.h" #include "ir_tools.h" #include "driver/rmt.h" +#include "soc/rmt_periph.h" #define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_PER_GROUP-SOC_RMT_TX_CANDIDATES_PER_GROUP) #define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CANDIDATES_PER_GROUP-1) @@ -72,8 +73,12 @@ static void rmt_setup_testbench(int tx_channel, int rx_channel, uint32_t flags) // Routing internal signals by IO Matrix (bind rmt tx and rx signal on the same GPIO) gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[RMT_DATA_IO], PIN_FUNC_GPIO); TEST_ESP_OK(gpio_set_direction(RMT_DATA_IO, GPIO_MODE_INPUT_OUTPUT)); - esp_rom_gpio_connect_out_signal(RMT_DATA_IO, RMT_SIG_OUT0_IDX + tx_channel, 0, 0); - esp_rom_gpio_connect_in_signal(RMT_DATA_IO, RMT_SIG_IN0_IDX + rx_channel, 0); + if (tx_channel >= 0) { + esp_rom_gpio_connect_out_signal(RMT_DATA_IO, rmt_periph_signals.groups[0].channels[tx_channel].tx_sig, 0, 0); + } + if (rx_channel >= 0) { + esp_rom_gpio_connect_in_signal(RMT_DATA_IO, rmt_periph_signals.groups[0].channels[rx_channel].rx_sig, 0); + } // install driver if (tx_channel >= 0) { @@ -161,7 +166,6 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]") TEST_ASSERT_EQUAL_INT(RMT_BASECLK_XTAL, src_clk); #endif - TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 10, 10, 1)); TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0)); diff --git a/components/driver/test_apps/rmt/README.md b/components/driver/test_apps/rmt/README.md index 19f1d19a54..a79fcf4c5e 100644 --- a/components/driver/test_apps/rmt/README.md +++ b/components/driver/test_apps/rmt/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/rmt/main/test_board.h b/components/driver/test_apps/rmt/main/test_board.h new file mode 100644 index 0000000000..2dca5205af --- /dev/null +++ b/components/driver/test_apps/rmt/main/test_board.h @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#define TEST_RMT_GPIO_NUM_A 0 +#define TEST_RMT_GPIO_NUM_B 2 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 8944a545ff..9f80e0e29f 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_common.c +++ b/components/driver/test_apps/rmt/main/test_rmt_common.c @@ -12,12 +12,13 @@ #include "driver/rmt_tx.h" #include "driver/rmt_rx.h" #include "soc/soc_caps.h" +#include "test_board.h" TEST_CASE("rmt channel install & uninstall", "[rmt]") { rmt_tx_channel_config_t tx_channel_cfg = { .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 1000000, .trans_queue_depth = 1, @@ -25,7 +26,7 @@ TEST_CASE("rmt channel install & uninstall", "[rmt]") rmt_channel_handle_t tx_channels[SOC_RMT_TX_CANDIDATES_PER_GROUP] = {}; rmt_rx_channel_config_t rx_channel_cfg = { .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, - .gpio_num = 2, + .gpio_num = TEST_RMT_GPIO_NUM_B, .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 1000000, }; @@ -98,3 +99,60 @@ TEST_CASE("rmt channel install & uninstall", "[rmt]") } #endif // SOC_RMT_SUPPORT_DMA } + +TEST_CASE("RMT interrupt priority", "[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, + .intr_priority = 3 + }; + // --- Check if specifying interrupt priority works + 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)); + + rmt_channel_handle_t another_tx_channel = NULL; + rmt_tx_channel_config_t another_tx_channel_cfg = tx_channel_cfg; + // --- Check if rmt interrupt priority valid check works + another_tx_channel_cfg.intr_priority = 4; + TEST_ESP_ERR(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel), ESP_ERR_INVALID_ARG); + // --- Check if rmt interrupt priority conflict check works + another_tx_channel_cfg.intr_priority = 1; ///< Specifying a conflict intr_priority + TEST_ESP_ERR(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel), ESP_ERR_INVALID_ARG); + another_tx_channel_cfg.intr_priority = 0; ///< Do not specify an intr_priority, should not conflict + TEST_ESP_OK(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel)); + + rmt_rx_channel_config_t rx_channel_cfg = { + .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 1000000, // 1MHz, 1 tick = 1us + .gpio_num = 0, + .flags.with_dma = false, // Interrupt will only be allocated when dma disabled + .flags.io_loop_back = true, // the GPIO will act like a loopback + .intr_priority = 3, + }; + // --- Check if specifying interrupt priority works + printf("install rx channel\r\n"); + rmt_channel_handle_t rx_channel = NULL; + TEST_ESP_OK(rmt_new_rx_channel(&rx_channel_cfg, &rx_channel)); + + rmt_channel_handle_t another_rx_channel = NULL; + rmt_rx_channel_config_t another_rx_channel_cfg = rx_channel_cfg; + // --- Check if rmt interrupt priority valid check works + another_rx_channel_cfg.intr_priority = 4; ///< Specifying a invalid intr_priority + TEST_ESP_ERR(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel), ESP_ERR_INVALID_ARG); + // --- Check if rmt interrupt priority conflict check works + another_rx_channel_cfg.intr_priority = 1; ///< Specifying a conflict intr_priority + TEST_ESP_ERR(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel), ESP_ERR_INVALID_ARG); + another_rx_channel_cfg.intr_priority = 0; ///< Do not specify an intr_priority, should not conflict + TEST_ESP_OK(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel)); + + TEST_ESP_OK(rmt_del_channel(tx_channel)); + TEST_ESP_OK(rmt_del_channel(another_tx_channel)); + TEST_ESP_OK(rmt_del_channel(rx_channel)); + TEST_ESP_OK(rmt_del_channel(another_rx_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 755e360bfa..f772de8beb 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_iram.c +++ b/components/driver/test_apps/rmt/main/test_rmt_iram.c @@ -16,6 +16,7 @@ #include "esp_timer.h" #include "soc/soc_caps.h" #include "test_util_rmt_encoders.h" +#include "test_board.h" static void IRAM_ATTR test_delay_post_cache_disable(void *args) { @@ -29,7 +30,7 @@ static void test_rmt_tx_iram_safe(size_t mem_block_symbols, bool with_dma) .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, }; printf("install tx channel\r\n"); @@ -86,8 +87,6 @@ TEST_CASE("rmt tx iram safe", "[rmt]") #endif } - - static void IRAM_ATTR test_simulate_input_post_cache_disable(void *args) { int gpio_num = (int)args; @@ -121,7 +120,7 @@ static void test_rmt_rx_iram_safe(size_t mem_block_symbols, bool with_dma, rmt_c .clk_src = clk_src, .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .mem_block_symbols = mem_block_symbols, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .flags.io_loop_back = true, // the GPIO will act like a loopback }; 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 562731c66d..22958a3c71 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_rx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_rx.c @@ -13,6 +13,7 @@ #include "driver/rmt_rx.h" #include "soc/soc_caps.h" #include "test_util_rmt_encoders.h" +#include "test_board.h" #if CONFIG_RMT_ISR_IRAM_SAFE #define TEST_RMT_CALLBACK_ATTR IRAM_ATTR @@ -42,11 +43,16 @@ static bool test_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt_clock_source_t clk_src) { + uint32_t const test_rx_buffer_symbols = 128; + rmt_symbol_word_t *remote_codes = heap_caps_aligned_calloc(64, test_rx_buffer_symbols, sizeof(rmt_symbol_word_t), + MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + TEST_ASSERT_NOT_NULL(remote_codes); + rmt_rx_channel_config_t rx_channel_cfg = { .clk_src = clk_src, .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .mem_block_symbols = mem_block_symbols, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .flags.io_loop_back = true, // the GPIO will act like a loopback }; @@ -67,7 +73,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.io_loop_back = true, // TX channel and RX channel will bounded to the same GPIO }; printf("install tx channel\r\n"); @@ -86,15 +92,13 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt printf("enable rx channel\r\n"); TEST_ESP_OK(rmt_enable(rx_channel)); - rmt_symbol_word_t remote_codes[128]; - rmt_receive_config_t receive_config = { .signal_range_min_ns = 1250, .signal_range_max_ns = 12000000, }; // ready to receive - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send NEC frame without carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0x0440, 0x3003 // address, command @@ -102,7 +106,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000))); TEST_ASSERT_EQUAL(34, test_user_data.received_symbol_num); - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send NEC frame without carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0x0440, 0x3003 // address, command @@ -112,7 +116,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt #if SOC_RMT_SUPPORT_RX_PINGPONG // ready to receive - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send customized NEC frame without carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0xFF00, 0xFF00, 0xFF00, 0xFF00 @@ -121,7 +125,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ASSERT_EQUAL(66, test_user_data.received_symbol_num); #else // ready to receive - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send customized NEC frame without carrier\r\n"); // the maximum symbols can receive is its memory block capacity TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { @@ -144,7 +148,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt carrier_cfg.frequency_hz = 25000; TEST_ESP_OK(rmt_apply_carrier(rx_channel, &carrier_cfg)); - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send NEC frame with carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0x0440, 0x3003 // address, command @@ -153,7 +157,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ASSERT_EQUAL(34, test_user_data.received_symbol_num); #if SOC_RMT_SUPPORT_RX_PINGPONG - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send customized frame with carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0xFF00, 0xFF00, 0xFF00, 0xFF00 @@ -167,7 +171,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ESP_OK(rmt_apply_carrier(rx_channel, NULL)); #endif // SOC_RMT_SUPPORT_RX_DEMODULATION - TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, sizeof(remote_codes), &receive_config)); + TEST_ESP_OK(rmt_receive(rx_channel, remote_codes, test_rx_buffer_symbols * sizeof(rmt_symbol_word_t), &receive_config)); printf("send NEC frame without carrier\r\n"); TEST_ESP_OK(rmt_transmit(tx_channel, nec_encoder, (uint16_t[]) { 0x0440, 0x3003 // address, command @@ -183,6 +187,7 @@ static void test_rmt_rx_nec_carrier(size_t mem_block_symbols, bool with_dma, rmt TEST_ESP_OK(rmt_del_channel(rx_channel)); TEST_ESP_OK(rmt_del_channel(tx_channel)); TEST_ESP_OK(rmt_del_encoder(nec_encoder)); + free(remote_codes); } TEST_CASE("rmt rx nec with carrier", "[rmt]") @@ -196,40 +201,3 @@ TEST_CASE("rmt rx nec with carrier", "[rmt]") test_rmt_rx_nec_carrier(128, true, RMT_CLK_SRC_DEFAULT); #endif } - -TEST_CASE("RMT RX test specifying interrupt priority", "[rmt]") -{ - rmt_clock_source_t clk_srcs[] = SOC_RMT_CLKS; - rmt_rx_channel_config_t rx_channel_cfg = { - .clk_src = clk_srcs[0], - .resolution_hz = 1000000, // 1MHz, 1 tick = 1us - .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, - .gpio_num = 0, - .flags.with_dma = false, // Interrupt will only be allocated when dma disabled - .flags.io_loop_back = true, // the GPIO will act like a loopback - .intr_priority = 3, - }; - // --- Check if specifying interrupt priority works - printf("install rx channel\r\n"); - rmt_channel_handle_t rx_channel = NULL; - TEST_ESP_OK(rmt_new_rx_channel(&rx_channel_cfg, &rx_channel)); - - rmt_channel_handle_t another_rx_channel = NULL; - rmt_rx_channel_config_t another_rx_channel_cfg = rx_channel_cfg; - // --- Check if rmt interrupt priority valid check works - another_rx_channel_cfg.intr_priority = 4; ///< Specifying a invalid intr_priority - TEST_ESP_ERR(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel), ESP_ERR_INVALID_ARG); - // --- Check if rmt interrupt priority conflict check works - another_rx_channel_cfg.intr_priority = 1; ///< Specifying a conflict intr_priority - TEST_ESP_ERR(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel), ESP_ERR_INVALID_ARG); - another_rx_channel_cfg.intr_priority = 0; ///< Do not specify an intr_priority, should not conflict - TEST_ESP_OK(rmt_new_rx_channel(&another_rx_channel_cfg, &another_rx_channel)); - // --- Check if channel works - TEST_ESP_OK(rmt_enable(rx_channel)); - TEST_ESP_OK(rmt_enable(another_rx_channel)); - // --- Post-test - TEST_ESP_OK(rmt_disable(rx_channel)); - TEST_ESP_OK(rmt_disable(another_rx_channel)); - TEST_ESP_OK(rmt_del_channel(rx_channel)); - TEST_ESP_OK(rmt_del_channel(another_rx_channel)); -} 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 03ede412af..8da964f1c3 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_tx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_tx.c @@ -13,6 +13,7 @@ #include "esp_timer.h" #include "soc/soc_caps.h" #include "test_util_rmt_encoders.h" +#include "test_board.h" #if CONFIG_RMT_ISR_IRAM_SAFE #define TEST_RMT_CALLBACK_ATTR IRAM_ATTR @@ -27,7 +28,7 @@ TEST_CASE("rmt bytes encoder", "[rmt]") .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .intr_priority = 3 }; printf("install tx channel\r\n"); @@ -89,7 +90,7 @@ static void test_rmt_channel_single_trans(size_t mem_block_symbols, bool with_dm .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .intr_priority = 2 }; @@ -144,7 +145,7 @@ static void test_rmt_ping_pong_trans(size_t mem_block_symbols, bool with_dma) .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .intr_priority = 1 }; @@ -215,7 +216,6 @@ TEST_CASE("rmt ping-pong transaction", "[rmt]") #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) { @@ -231,7 +231,7 @@ static void test_rmt_trans_done_event(size_t mem_block_symbols, bool with_dma) .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) .trans_queue_depth = 1, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .intr_priority = 3 }; @@ -305,7 +305,7 @@ static void test_rmt_loop_trans(size_t mem_block_symbols, bool with_dma) .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) .trans_queue_depth = 4, - .gpio_num = 0, + .gpio_num = TEST_RMT_GPIO_NUM_A, .flags.with_dma = with_dma, .intr_priority = 2 }; @@ -365,7 +365,7 @@ TEST_CASE("rmt infinite loop transaction", "[rmt]") .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, - .gpio_num = 2, + .gpio_num = TEST_RMT_GPIO_NUM_B, .trans_queue_depth = 3, .intr_priority = 1 }; @@ -444,7 +444,7 @@ static void test_rmt_tx_nec_carrier(size_t mem_block_symbols, bool with_dma) .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 1000000, // 1MHz, 1 tick = 1us .mem_block_symbols = mem_block_symbols, - .gpio_num = 2, + .gpio_num = TEST_RMT_GPIO_NUM_B, .trans_queue_depth = 4, .flags.with_dma = with_dma, .intr_priority = 3 @@ -503,7 +503,6 @@ TEST_CASE("rmt tx nec with carrier", "[rmt]") #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) { @@ -526,7 +525,7 @@ static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, siz }; printf("install tx channels\r\n"); rmt_channel_handle_t tx_channels[TEST_RMT_CHANS] = {NULL}; - int gpio_nums[TEST_RMT_CHANS] = {0, 2}; + int gpio_nums[TEST_RMT_CHANS] = {TEST_RMT_GPIO_NUM_A, TEST_RMT_GPIO_NUM_B}; size_t mem_blk_syms[TEST_RMT_CHANS] = {channel0_mem_block_symbols, channel1_mem_block_symbols}; bool dma_flags[TEST_RMT_CHANS] = {channel0_with_dma, channel1_with_dma}; for (int i = 0; i < TEST_RMT_CHANS; i++) { @@ -655,38 +654,3 @@ TEST_CASE("rmt multiple channels transaction", "[rmt]") test_rmt_multi_channels_trans(1024, SOC_RMT_MEM_WORDS_PER_CHANNEL, true, false); #endif } - -TEST_CASE("RMT TX test specifying interrupt priority", "[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, - .intr_priority = 3 - }; - // --- Check if specifying interrupt priority works - 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)); - - rmt_channel_handle_t another_tx_channel = NULL; - rmt_tx_channel_config_t another_tx_channel_cfg = tx_channel_cfg; - // --- Check if rmt interrupt priority valid check works - another_tx_channel_cfg.intr_priority = 4; - TEST_ESP_ERR(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel), ESP_ERR_INVALID_ARG); - // --- Check if rmt interrupt priority conflict check works - another_tx_channel_cfg.intr_priority = 1; ///< Specifying a conflict intr_priority - TEST_ESP_ERR(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel), ESP_ERR_INVALID_ARG); - another_tx_channel_cfg.intr_priority = 0; ///< Do not specify an intr_priority, should not conflict - TEST_ESP_OK(rmt_new_tx_channel(&another_tx_channel_cfg, &another_tx_channel)); - // --- Check if channel works - TEST_ESP_OK(rmt_enable(tx_channel)); - TEST_ESP_OK(rmt_enable(another_tx_channel)); - // --- Post-test - TEST_ESP_OK(rmt_disable(tx_channel)); - TEST_ESP_OK(rmt_disable(another_tx_channel)); - TEST_ESP_OK(rmt_del_channel(tx_channel)); - TEST_ESP_OK(rmt_del_channel(another_tx_channel)); -} diff --git a/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c b/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c index 5cfadd4097..6c95e5d631 100644 --- a/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c +++ b/components/driver/test_apps/rmt/main/test_util_rmt_encoders.c @@ -11,12 +11,6 @@ #include "driver/rmt_encoder.h" #include "esp_attr.h" -#if CONFIG_RMT_ISR_IRAM_SAFE -#define TEST_RMT_ENCODER_ATTR IRAM_ATTR -#else -#define TEST_RMT_ENCODER_ATTR -#endif - typedef struct { rmt_encoder_t base; rmt_encoder_t *bytes_encoder; @@ -25,8 +19,7 @@ typedef struct { rmt_symbol_word_t reset_code; } rmt_led_strip_encoder_t; -TEST_RMT_ENCODER_ATTR -static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) +IRAM_ATTR static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) { rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); rmt_encode_state_t session_state = RMT_ENCODING_RESET; @@ -119,7 +112,7 @@ typedef struct { int state; } rmt_nec_protocol_encoder_t; -static size_t rmt_encode_nec_protocol(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) +IRAM_ATTR static size_t rmt_encode_nec_protocol(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) { rmt_nec_protocol_encoder_t *nec_encoder = __containerof(encoder, rmt_nec_protocol_encoder_t, base); rmt_encode_state_t session_state = RMT_ENCODING_RESET; diff --git a/components/esp_hw_support/dma/async_memcpy_gdma.c b/components/esp_hw_support/dma/async_memcpy_gdma.c index 2538ece16c..a19f61cefb 100644 --- a/components/esp_hw_support/dma/async_memcpy_gdma.c +++ b/components/esp_hw_support/dma/async_memcpy_gdma.c @@ -447,11 +447,11 @@ static bool mcp_gdma_rx_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_ if (atomic_compare_exchange_strong(&mcp_gdma->fsm, &expected_fsm, MCP_FSM_IDLE_WAIT)) { // if the data is in the cache, invalidate, then CPU can see the latest data #if MCP_NEEDS_INVALIDATE_DST_CACHE - int write_back_map = CACHE_MAP_L1_DCACHE; + int invalidate_map = CACHE_MAP_L1_DCACHE; if (esp_ptr_external_ram((const void *)trans->memcpy_dst_addr)) { - write_back_map |= CACHE_MAP_L2_CACHE; + invalidate_map |= CACHE_MAP_L2_CACHE; } - Cache_Invalidate_Addr(write_back_map, (uint32_t)trans->memcpy_dst_addr, trans->memcpy_size); + Cache_Invalidate_Addr(invalidate_map, (uint32_t)trans->memcpy_dst_addr, trans->memcpy_size); #endif // invoked callback registered by user diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index 68de11d8d1..c410ffc16f 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "hal/misc.h" #include "hal/assert.h" #include "soc/rmt_struct.h" +#include "soc/dport_reg.h" #include "hal/rmt_types.h" #ifdef __cplusplus @@ -40,6 +41,41 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG); + reg_val &= ~DPORT_RMT_CLK_EN; + reg_val |= enable << 9; + DPORT_WRITE_PERI_REG(DPORT_PERIP_CLK_EN_REG, reg_val); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST); + DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, 0); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_reset_register(__VA_ARGS__) + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index 1c3c4c907f..e70a0bf435 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "hal/misc.h" #include "hal/assert.h" #include "soc/rmt_struct.h" +#include "soc/system_struct.h" #include "hal/rmt_types.h" #ifdef __cplusplus @@ -41,6 +42,38 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + SYSTEM.perip_clk_en0.reg_rmt_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + SYSTEM.perip_rst_en0.reg_rmt_rst = 1; + SYSTEM.perip_rst_en0.reg_rmt_rst = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_reset_register(__VA_ARGS__) + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/esp32c6/include/hal/rmt_ll.h b/components/hal/esp32c6/include/hal/rmt_ll.h index 7f7f24f9be..9db5a5109c 100644 --- a/components/hal/esp32c6/include/hal/rmt_ll.h +++ b/components/hal/esp32c6/include/hal/rmt_ll.h @@ -42,6 +42,30 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.rmt_conf.rmt_clk_en = enable; +} + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.rmt_conf.rmt_rst_en = 1; + PCR.rmt_conf.rmt_rst_en = 0; +} + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index d290163f59..bc7b29ed40 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -42,6 +42,30 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + PCR.rmt_conf.rmt_clk_en = enable; +} + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + PCR.rmt_conf.rmt_rst_en = 1; + PCR.rmt_conf.rmt_rst_en = 0; +} + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index b33031bedb..566a112b40 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -76,8 +76,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return HP_SYS_CLKRST_REG_SYSTIMER_CLK_EN; case PERIPH_LEDC_MODULE: return HP_SYS_CLKRST_REG_LEDC_CLK_EN; - case PERIPH_RMT_MODULE: - return HP_SYS_CLKRST_REG_RMT_CLK_EN; case PERIPH_SARADC_MODULE: return HP_SYS_CLKRST_REG_ADC_CLK_EN; case PERIPH_PVT_MODULE: @@ -147,8 +145,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return HP_SYS_CLKRST_REG_RST_EN_I2C0; case PERIPH_I2C1_MODULE: return HP_SYS_CLKRST_REG_RST_EN_I2C1; - case PERIPH_RMT_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_RMT; case PERIPH_TWAI0_MODULE: return HP_SYS_CLKRST_REG_RST_EN_CAN0; case PERIPH_TWAI1_MODULE: @@ -253,7 +249,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return HP_SYS_CLKRST_PERI_CLK_CTRL119_REG; case PERIPH_SYSTIMER_MODULE: case PERIPH_LEDC_MODULE: - case PERIPH_RMT_MODULE: return HP_SYS_CLKRST_PERI_CLK_CTRL21_REG; case PERIPH_SARADC_MODULE: return HP_SYS_CLKRST_PERI_CLK_CTRL22_REG; @@ -299,7 +294,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) case PERIPH_I2C0_MODULE: case PERIPH_I2C1_MODULE: return HP_SYS_CLKRST_HP_RST_EN1_REG; - case PERIPH_RMT_MODULE: case PERIPH_TWAI0_MODULE: case PERIPH_TWAI1_MODULE: case PERIPH_TWAI2_MODULE: diff --git a/components/hal/esp32p4/include/hal/rmt_ll.h b/components/hal/esp32p4/include/hal/rmt_ll.h new file mode 100644 index 0000000000..46667223f9 --- /dev/null +++ b/components/hal/esp32p4/include/hal/rmt_ll.h @@ -0,0 +1,923 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @note TX and RX channels are index from 0 in the LL driver, i.e. tx_channel = [0,3], rx_channel = [0,3] + */ + +#pragma once + +#include +#include +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "hal/rmt_types.h" +#include "soc/rmt_struct.h" +#include "soc/hp_sys_clkrst_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RMT_LL_EVENT_TX_DONE(channel) (1 << (channel)) +#define RMT_LL_EVENT_TX_THRES(channel) (1 << ((channel) + 8)) +#define RMT_LL_EVENT_TX_LOOP_END(channel) (1 << ((channel) + 12)) +#define RMT_LL_EVENT_TX_ERROR(channel) (1 << ((channel) + 4)) +#define RMT_LL_EVENT_RX_DONE(channel) (1 << ((channel) + 16)) +#define RMT_LL_EVENT_RX_THRES(channel) (1 << ((channel) + 24)) +#define RMT_LL_EVENT_RX_ERROR(channel) (1 << ((channel) + 20)) +#define RMT_LL_EVENT_TX_MASK(channel) (RMT_LL_EVENT_TX_DONE(channel) | RMT_LL_EVENT_TX_THRES(channel) | RMT_LL_EVENT_TX_LOOP_END(channel)) +#define RMT_LL_EVENT_RX_MASK(channel) (RMT_LL_EVENT_RX_DONE(channel) | RMT_LL_EVENT_RX_THRES(channel)) + +#define RMT_LL_MAX_LOOP_COUNT_PER_BATCH 1023 +#define RMT_LL_MAX_FILTER_VALUE 255 +#define RMT_LL_MAX_IDLE_VALUE 32767 + +typedef enum { + RMT_LL_MEM_OWNER_SW = 0, + RMT_LL_MEM_OWNER_HW = 1, +} rmt_ll_mem_owner_t; + +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_rmt_sys_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_rmt = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_rmt = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_reset_register(__VA_ARGS__) + +/** + * @brief Set clock source and divider for RMT channel group + * + * @param dev Peripheral instance address + * @param channel not used as clock source is set for all channels + * @param src Clock source + * @param divider_integral Integral part of the divider + * @param divider_denominator Denominator part of the divider + * @param divider_numerator Numerator part of the divider + */ +static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, rmt_clock_source_t src, + uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator) +{ + (void)dev; + // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) + (void)channel; // the source clock is set for all channels + HAL_ASSERT(divider_integral >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl22, reg_rmt_clk_div_num, divider_integral - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl22, reg_rmt_clk_div_numerator, divider_numerator); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl22, reg_rmt_clk_div_denominator, divider_denominator); + switch (src) { + case RMT_CLK_SRC_PLL_F80M: + HP_SYS_CLKRST.peri_clk_ctrl22.reg_rmt_clk_src_sel = 2; + break; + case RMT_CLK_SRC_RC_FAST: + HP_SYS_CLKRST.peri_clk_ctrl22.reg_rmt_clk_src_sel = 1; + break; + case RMT_CLK_SRC_XTAL: + HP_SYS_CLKRST.peri_clk_ctrl22.reg_rmt_clk_src_sel = 0; + break; + default: + HAL_ASSERT(false && "unsupported RMT clock source"); + break; + } +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_set_group_clock_src(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_set_group_clock_src(__VA_ARGS__) + +/** + * @brief Enable RMT peripheral source clock + * + * @param dev Peripheral instance address + * @param en True to enable, False to disable + */ +static inline void rmt_ll_enable_group_clock(rmt_dev_t *dev, bool en) +{ + (void)dev; + HP_SYS_CLKRST.peri_clk_ctrl22.reg_rmt_clk_en = en; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_group_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_group_clock(__VA_ARGS__) + +/** + * @brief Enable clock gate for register and memory + * + * @param dev Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_enable_periph_clock(rmt_dev_t *dev, bool enable) +{ + dev->sys_conf.clk_en = enable; // register clock gating + dev->sys_conf.mem_clk_force_on = enable; // memory clock gating +} + +/** + * @brief Power down memory + * + * @param dev Peripheral instance address + * @param enable True to power down, False to power up + */ +static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) +{ + dev->sys_conf.mem_force_pu = !enable; + dev->sys_conf.mem_force_pd = enable; +} + +/** + * @brief Enable APB accessing RMT memory in nonfifo mode + * + * @param dev Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_enable_mem_access_nonfifo(rmt_dev_t *dev, bool enable) +{ + dev->sys_conf.apb_fifo_mask = enable; +} + +////////////////////////////////////////TX Channel Specific///////////////////////////////////////////////////////////// + +/** + * @brief Reset clock divider for TX channels by mask + * + * @param dev Peripheral instance address + * @param channel_mask Mask of TX channels + */ +static inline void rmt_ll_tx_reset_channels_clock_div(rmt_dev_t *dev, uint32_t channel_mask) +{ + // write 1 to reset + dev->ref_cnt_rst.val |= channel_mask & 0x0F; +} + +/** + * @brief Set TX channel clock divider + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param div Division value + */ +static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + HAL_ASSERT(div >= 1 && div <= 256 && "divider out of range"); + // limit the maximum divider to 256 + if (div >= 256) { + div = 0; // 0 means 256 division + } + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_chn, div); +} + +/** + * @brief Reset RMT reading pointer for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->chnconf0[channel].mem_rd_rst_chn = 1; + dev->chnconf0[channel].mem_rd_rst_chn = 0; + dev->chnconf0[channel].apb_mem_rst_chn = 1; + dev->chnconf0[channel].apb_mem_rst_chn = 0; +} + +/** + * @brief Enable DMA access for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_tx_enable_dma(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + HAL_ASSERT(channel == 3 && "only TX channel 3 has DMA ability"); + dev->chnconf0[channel].dma_access_en_chn = enable; +} + +/** + * @brief Start transmitting for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel) +{ + // update other configuration registers before start transmitting + dev->chnconf0[channel].conf_update_chn = 1; + dev->chnconf0[channel].tx_start_chn = 1; +} + +/** + * @brief Stop transmitting for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel) +{ + dev->chnconf0[channel].tx_stop_chn = 1; + // stop won't take place until configurations updated + dev->chnconf0[channel].conf_update_chn = 1; +} + +/** + * @brief Set memory block number for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param block_num memory block number + */ +static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->chnconf0[channel].mem_size_chn = block_num; +} + +/** + * @brief Enable TX wrap + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_tx_enable_wrap(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chnconf0[channel].mem_tx_wrap_en_chn = enable; +} + +/** + * @brief Enable transmitting in a loop + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chnconf0[channel].tx_conti_mode_chn = enable; +} + +/** + * @brief Set loop count for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param count TX loop count + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) +{ + HAL_ASSERT(count <= RMT_LL_MAX_LOOP_COUNT_PER_BATCH && "loop count out of range"); + dev->chn_tx_lim[channel].tx_loop_num_chn = count; +} + +/** + * @brief Reset loop count for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_reset_loop_count(rmt_dev_t *dev, uint32_t channel) +{ + dev->chn_tx_lim[channel].loop_count_reset_chn = 1; + dev->chn_tx_lim[channel].loop_count_reset_chn = 0; +} + +/** + * @brief Enable loop count for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chn_tx_lim[channel].tx_loop_cnt_en_chn = enable; +} + +/** + * @brief Enable loop stop at count value automatically + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_enable_loop_autostop(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chn_tx_lim[channel].loop_stop_en_chn = enable; +} + +/** + * @brief Enable transmit multiple channels synchronously + * + * @param dev Peripheral instance address + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable) +{ + dev->tx_sim.tx_sim_en = enable; +} + +/** + * @brief Clear the TX channels synchronous group + * + * @param dev Peripheral instance address + */ +static inline void rmt_ll_tx_clear_sync_group(rmt_dev_t *dev) +{ + dev->tx_sim.val &= ~(0x0F); +} + +/** + * @brief Add TX channels to the synchronous group + * + * @param dev Peripheral instance address + * @param channel_mask Mask of TX channels to be added to the synchronous group + */ +static inline void rmt_ll_tx_sync_group_add_channels(rmt_dev_t *dev, uint32_t channel_mask) +{ + dev->tx_sim.val |= (channel_mask & 0x0F); +} + +/** + * @brief Remove TX channels from the synchronous group + * + * @param dev Peripheral instance address + * @param channel_mask Mask of TX channels to be removed from the synchronous group + */ +static inline void rmt_ll_tx_sync_group_remove_channels(rmt_dev_t *dev, uint32_t channel_mask) +{ + dev->tx_sim.val &= ~channel_mask; +} + +/** + * @brief Fix the output level when TX channel is in IDLE state + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param level IDLE level (1 => high, 0 => low) + * @param enable True to fix the IDLE level, otherwise the IDLE level is determined by EOF encoder + */ +__attribute__((always_inline)) +static inline void rmt_ll_tx_fix_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level, bool enable) +{ + dev->chnconf0[channel].idle_out_en_chn = enable; + dev->chnconf0[channel].idle_out_lv_chn = level; +} + +/** + * @brief Set the amount of RMT symbols that can trigger the limitation interrupt + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param limit Specify the number of symbols + */ +static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +{ + dev->chn_tx_lim[channel].tx_lim_chn = limit; +} + +/** + * @brief Set high and low duration of carrier signal + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param high_ticks Duration of high level + * @param low_ticks Duration of low level + */ +static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +{ + HAL_ASSERT(high_ticks >= 1 && high_ticks <= 65536 && low_ticks >= 1 && low_ticks <= 65536 && "out of range high/low ticks"); + // ticks=0 means 65536 in hardware + if (high_ticks >= 65536) { + high_ticks = 0; + } + if (low_ticks >= 65536) { + low_ticks = 0; + } + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_high_chn, high_ticks); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_low_chn, low_ticks); +} + +/** + * @brief Enable modulating carrier signal to TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chnconf0[channel].carrier_en_chn = enable; +} + +/** + * @brief Set on high or low to modulate the carrier signal + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param level Which level to modulate on (0=>low level, 1=>high level) + */ +static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +{ + dev->chnconf0[channel].carrier_out_lv_chn = level; +} + +/** + * @brief Enable to always output carrier signal, regardless of a valid data transmission + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data + */ +static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chnconf0[channel].carrier_eff_en_chn = !enable; +} + +////////////////////////////////////////RX Channel Specific///////////////////////////////////////////////////////////// + +/** + * @brief Reset clock divider for RX channels by mask + * + * @param dev Peripheral instance address + * @param channel_mask Mask of RX channels + */ +static inline void rmt_ll_rx_reset_channels_clock_div(rmt_dev_t *dev, uint32_t channel_mask) +{ + dev->ref_cnt_rst.val |= ((channel_mask & 0x0F) << 4); +} + +/** + * @brief Set RX channel clock divider + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param div Division value + */ +static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + HAL_ASSERT(div >= 1 && div <= 256 && "divider out of range"); + // limit the maximum divider to 256 + if (div >= 256) { + div = 0; // 0 means 256 division + } + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_chm, div); +} + +/** + * @brief Reset RMT writing pointer for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + */ +static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->chmconf[channel].conf1.mem_wr_rst_chm = 1; + dev->chmconf[channel].conf1.mem_wr_rst_chm = 0; + dev->chmconf[channel].conf1.apb_mem_rst_chm = 1; + dev->chmconf[channel].conf1.apb_mem_rst_chm = 0; +} + +/** + * @brief Enable DMA access for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_rx_enable_dma(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + HAL_ASSERT(channel == 3 && "only RX channel 3 has DMA ability"); + dev->chmconf[channel].conf0.dma_access_en_chm = enable; +} + +/** + * @brief Enable receiving for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param enable True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chmconf[channel].conf1.rx_en_chm = enable; + // rx won't be enabled until configurations updated + dev->chmconf[channel].conf1.conf_update_chm = 1; +} + +/** + * @brief Set memory block number for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param block_num memory block number + */ +static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->chmconf[channel].conf0.mem_size_chm = block_num; +} + +/** + * @brief Set the time length for RX channel before going into IDLE state + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param thres Time length threshold + */ +static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->chmconf[channel].conf0.idle_thres_chm = thres; +} + +/** + * @brief Set RMT memory owner for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param owner Memory owner + */ +__attribute__((always_inline)) +static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt_ll_mem_owner_t owner) +{ + dev->chmconf[channel].conf1.mem_owner_chm = owner; +} + +/** + * @brief Enable filter for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX chanenl number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chmconf[channel].conf1.rx_filter_en_chm = enable; +} + +/** + * @brief Set RX channel filter threshold (i.e. the maximum width of one pulse signal that would be treated as a noise) + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param thres Filter threshold + */ +static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_chm, thres); +} + +/** + * @brief Get RMT memory write cursor offset + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return writer offset + */ +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_memory_writer_offset(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chmstatus[channel].mem_waddr_ex_chm - (channel + 4) * 48; +} + +/** + * @brief Set the amount of RMT symbols that can trigger the limitation interrupt + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param limit Specify the number of symbols + */ +static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +{ + dev->chm_rx_lim[channel].rx_lim_chm = limit; +} + +/** + * @brief Set high and low duration of carrier signal + * + * @param dev dev Peripheral instance address + * @param channel RMT TX channel number + * @param high_ticks Duration of high level + * @param low_ticks Duration of low level + */ +static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +{ + HAL_ASSERT(high_ticks >= 1 && high_ticks <= 65536 && low_ticks >= 1 && low_ticks <= 65536 && "out of range high/low ticks"); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_high_thres_chm, high_ticks - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_low_thres_chm, low_ticks - 1); +} + +/** + * @brief Enable demodulating the carrier on RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chmconf[channel].conf0.carrier_en_chm = enable; +} + +/** + * @brief Set on high or low to demodulate the carrier signal + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param level Which level to demodulate (0=>low level, 1=>high level) + */ +static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +{ + dev->chmconf[channel].conf0.carrier_out_lv_chm = level; +} + +/** + * @brief Enable RX wrap + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @param enable True to enable, False to disable + */ +static inline void rmt_ll_rx_enable_wrap(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chmconf[channel].conf1.mem_rx_wrap_en_chm = enable; +} + +//////////////////////////////////////////Interrupt Specific//////////////////////////////////////////////////////////// + +/** + * @brief Enable RMT interrupt for specific event mask + * + * @param dev Peripheral instance address + * @param mask Event mask + * @param enable True to enable, False to disable + */ +__attribute__((always_inline)) +static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool enable) +{ + if (enable) { + dev->int_ena.val |= mask; + } else { + dev->int_ena.val &= ~mask; + } +} + +/** + * @brief Clear RMT interrupt status by mask + * + * @param dev Peripheral instance address + * @param mask Interupt status mask + */ +__attribute__((always_inline)) +static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask) +{ + dev->int_clr.val = mask; +} + +/** + * @brief Get interrupt status register address + * + * @param dev Peripheral instance address + * @return Register address + */ +static inline volatile void *rmt_ll_get_interrupt_status_reg(rmt_dev_t *dev) +{ + return &dev->int_st; +} + +/** + * @brief Get interrupt status for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @return Interrupt status + */ +__attribute__((always_inline)) +static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_st.val & RMT_LL_EVENT_TX_MASK(channel); +} + +/** + * @brief Get interrupt raw status for TX channel + * + * @param dev Peripheral instance address + * @param channel RMT TX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel)); +} + +/** + * @brief Get interrupt raw status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt raw status + */ +static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel)); +} + +/** + * @brief Get interrupt status for RX channel + * + * @param dev Peripheral instance address + * @param channel RMT RX channel number + * @return Interrupt status + */ +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_interrupt_status(rmt_dev_t *dev, uint32_t channel) +{ + return dev->int_st.val & RMT_LL_EVENT_RX_MASK(channel); +} + +//////////////////////////////////////////Deprecated Functions////////////////////////////////////////////////////////// +/////////////////////////////The following functions are only used by the legacy driver///////////////////////////////// +/////////////////////////////They might be removed in the next major release (ESP-IDF 6.0)////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_tx_get_status_word(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chnstatus[channel].val; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_status_word(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chmstatus[channel].val; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_chn); + return div == 0 ? 256 : div; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_chm); + return div == 0 ? 256 : div; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chmconf[channel].conf0.idle_thres_chm; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chnconf0[channel].mem_size_chn; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chmconf[channel].conf0.mem_size_chm; +} + +__attribute__((always_inline)) +static inline bool rmt_ll_tx_is_loop_enabled(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chnconf0[channel].tx_conti_mode_chn; +} + +__attribute__((always_inline)) +static inline rmt_clock_source_t rmt_ll_get_group_clock_src(rmt_dev_t *dev, uint32_t channel) +{ + rmt_clock_source_t clk_src = RMT_CLK_SRC_PLL_F80M; + switch (HP_SYS_CLKRST.peri_clk_ctrl22.reg_rmt_clk_src_sel) { + case 0: + clk_src = RMT_CLK_SRC_XTAL; + break; + case 1: + clk_src = RMT_CLK_SRC_RC_FAST; + break; + case 2: + clk_src = RMT_CLK_SRC_PLL_F80M; + break; + } + return clk_src; +} + +__attribute__((always_inline)) +static inline bool rmt_ll_tx_is_idle_enabled(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chnconf0[channel].idle_out_en_chn; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chnconf0[channel].idle_out_lv_chn; +} + +static inline bool rmt_ll_is_mem_powered_down(rmt_dev_t *dev) +{ + // the RTC domain can also power down RMT memory + // so it's probably not enough to detect whether it's powered down or not + // mem_force_pd has higher priority than mem_force_pu + return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chmconf[channel].conf1.mem_owner_chm; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel) +{ + return dev->chm_rx_lim[channel].rx_lim_chm; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_tx_end_interrupt_status(rmt_dev_t *dev) +{ + return dev->int_st.val & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 16) & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 4) & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 20) & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 8) & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 24) & 0x0F; +} + +__attribute__((always_inline)) +static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev) +{ + return (dev->int_st.val >> 12) & 0x0F; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index fe8028802c..e20f6de957 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,13 +16,13 @@ #include "hal/misc.h" #include "hal/assert.h" #include "soc/rmt_struct.h" +#include "soc/system_reg.h" #include "hal/rmt_types.h" #ifdef __cplusplus extern "C" { #endif - #define RMT_LL_EVENT_TX_DONE(channel) (1 << ((channel) * 3)) #define RMT_LL_EVENT_TX_THRES(channel) (1 << ((channel) + 12)) #define RMT_LL_EVENT_TX_LOOP_END(channel) (1 << ((channel) + 16)) @@ -42,6 +42,41 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG); + reg_val &= ~DPORT_RMT_CLK_EN_M; + reg_val |= enable << DPORT_RMT_CLK_EN_S; + WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, DPORT_RMT_RST_M); + WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, 0); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_reset_register(__VA_ARGS__) + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index 70812539f0..223f24dc5e 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -16,6 +16,7 @@ #include "hal/misc.h" #include "hal/assert.h" #include "soc/rmt_struct.h" +#include "soc/system_struct.h" #include "hal/rmt_types.h" #ifdef __cplusplus @@ -41,6 +42,38 @@ typedef enum { RMT_LL_MEM_OWNER_HW = 1, } rmt_ll_mem_owner_t; +/** + * @brief Enable the bus clock for RMT module + * + * @param group_id Group ID + * @param enable true to enable, false to disable + */ +static inline void rmt_ll_enable_bus_clock(int group_id, bool enable) +{ + (void)group_id; + SYSTEM.perip_clk_en0.rmt_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the RMT module + * + * @param group_id Group ID + */ +static inline void rmt_ll_reset_register(int group_id) +{ + (void)group_id; + SYSTEM.perip_rst_en0.rmt_rst = 1; + SYSTEM.perip_rst_en0.rmt_rst = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define rmt_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; rmt_ll_reset_register(__VA_ARGS__) + /** * @brief Enable clock gate for register and memory * diff --git a/components/hal/rmt_hal.c b/components/hal/rmt_hal.c index c14c8501cc..d83e5952da 100644 --- a/components/hal/rmt_hal.c +++ b/components/hal/rmt_hal.c @@ -14,7 +14,6 @@ void rmt_hal_init(rmt_hal_context_t *hal) rmt_ll_enable_mem_access_nonfifo(hal->regs, true); // APB access the RMTMEM in nonfifo mode rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events - rmt_ll_enable_group_clock(hal->regs, true); // enable clock source #if SOC_RMT_SUPPORT_TX_SYNCHRO rmt_ll_tx_clear_sync_group(hal->regs); #endif // SOC_RMT_SUPPORT_TX_SYNCHRO @@ -25,7 +24,6 @@ void rmt_hal_deinit(rmt_hal_context_t *hal) rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events rmt_ll_power_down_mem(hal->regs, true); // turn off RMTMEM power domain - rmt_ll_enable_group_clock(hal->regs, false); // disable clock source hal->regs = NULL; } diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index f31edf192f..428c5f571c 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -55,6 +55,10 @@ config SOC_RTC_MEM_SUPPORTED bool default y +config SOC_RMT_SUPPORTED + bool + default y + config SOC_I2C_SUPPORTED bool default y @@ -489,15 +493,15 @@ config SOC_RMT_GROUPS config SOC_RMT_TX_CANDIDATES_PER_GROUP int - default 2 + default 4 config SOC_RMT_RX_CANDIDATES_PER_GROUP int - default 2 + default 4 config SOC_RMT_CHANNELS_PER_GROUP int - default 4 + default 8 config SOC_RMT_MEM_WORDS_PER_CHANNEL int @@ -515,6 +519,14 @@ config SOC_RMT_SUPPORT_TX_ASYNC_STOP bool default y +config SOC_RMT_SUPPORT_TX_LOOP_COUNT + bool + default y + +config SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP + bool + default y + config SOC_RMT_SUPPORT_TX_SYNCHRO bool default y @@ -527,7 +539,7 @@ config SOC_RMT_SUPPORT_XTAL bool default y -config SOC_RMT_SUPPORT_RC_FAST +config SOC_RMT_SUPPORT_DMA bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 25e71bf90e..8e3e34bc9c 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -213,6 +213,42 @@ typedef enum { //////////////////////////////////////////////////RMT/////////////////////////////////////////////////////////////////// +/** + * @brief Array initializer for all supported clock sources of RMT + */ +#if SOC_CLK_TREE_SUPPORTED +#define SOC_RMT_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} +#else +#define SOC_RMT_CLKS {SOC_MOD_CLK_XTAL} +#endif + +/** + * @brief Type of RMT clock source + */ +typedef enum { + RMT_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */ + RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ +#if SOC_CLK_TREE_SUPPORTED + RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default choice */ +#else + RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default choice */ +#endif +} soc_periph_rmt_clk_src_t; + +/** + * @brief Type of RMT clock source, reserved for the legacy RMT driver + */ +typedef enum { + RMT_BASECLK_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock is PLL_F80M */ + RMT_BASECLK_XTAL = SOC_MOD_CLK_XTAL, /*!< RMT source clock is XTAL */ +#if SOC_CLK_TREE_SUPPORTED + RMT_BASECLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock default choice is PLL_F80M */ +#else + RMT_BASECLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< RMT source clock default choice is XTAL */ +#endif +} soc_periph_rmt_clk_src_legacy_t; + //////////////////////////////////////////////////Temp Sensor/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/include/soc/rmt_struct.h b/components/soc/esp32p4/include/soc/rmt_struct.h index d64239ae58..efe4281c3b 100644 --- a/components/soc/esp32p4/include/soc/rmt_struct.h +++ b/components/soc/esp32p4/include/soc/rmt_struct.h @@ -1,11 +1,12 @@ /** * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include + #ifdef __cplusplus extern "C" { #endif @@ -16,10 +17,10 @@ extern "C" { */ typedef union { struct { - /** chndata : HRO; bitpos: [31:0]; default: 0; + /** chndata : RO; bitpos: [31:0]; default: 0; * Read and write data for channel n via APB FIFO. */ - uint32_t chndata:32; + uint32_t chndata: 32; }; uint32_t val; } rmt_chndata_reg_t; @@ -29,86 +30,93 @@ typedef union { */ typedef union { struct { - /** chmdata : HRO; bitpos: [31:0]; default: 0; + /** chmdata : RO; bitpos: [31:0]; default: 0; * Read and write data for channel $n via APB FIFO. */ - uint32_t chmdata:32; + uint32_t chmdata: 32; }; uint32_t val; } rmt_chmdata_reg_t; - /** Group: Configuration registers */ /** Type of chnconf0 register * Channel n configure register 0 */ typedef union { struct { - /** tx_start_ch0 : WT; bitpos: [0]; default: 0; + /** tx_start_chn : WT; bitpos: [0]; default: 0; * Set this bit to start sending data on CHANNELn. */ - uint32_t tx_start_ch0:1; - /** mem_rd_rst_ch0 : WT; bitpos: [1]; default: 0; + uint32_t tx_start_chn: 1; + /** mem_rd_rst_chn : WT; bitpos: [1]; default: 0; * Set this bit to reset read ram address for CHANNELn by accessing transmitter. */ - uint32_t mem_rd_rst_ch0:1; - /** apb_mem_rst_ch0 : WT; bitpos: [2]; default: 0; + uint32_t mem_rd_rst_chn: 1; + /** apb_mem_rst_chn : WT; bitpos: [2]; default: 0; * Set this bit to reset W/R ram address for CHANNELn by accessing apb fifo. */ - uint32_t apb_mem_rst_ch0:1; - /** tx_conti_mode_ch0 : R/W; bitpos: [3]; default: 0; + uint32_t apb_mem_rst_chn: 1; + /** tx_conti_mode_chn : R/W; bitpos: [3]; default: 0; * Set this bit to restart transmission from the first data to the last data in * CHANNELn. */ - uint32_t tx_conti_mode_ch0:1; - /** mem_tx_wrap_en_ch0 : R/W; bitpos: [4]; default: 0; + uint32_t tx_conti_mode_chn: 1; + /** mem_tx_wrap_en_chn : R/W; bitpos: [4]; default: 0; * This is the channel n enable bit for wraparound mode: it will resume sending at the * start when the data to be sent is more than its memory size. */ - uint32_t mem_tx_wrap_en_ch0:1; - /** idle_out_lv_ch0 : R/W; bitpos: [5]; default: 0; + uint32_t mem_tx_wrap_en_chn: 1; + /** idle_out_lv_chn : R/W; bitpos: [5]; default: 0; * This bit configures the level of output signal in CHANNELn when the latter is in * IDLE state. */ - uint32_t idle_out_lv_ch0:1; - /** idle_out_en_ch0 : R/W; bitpos: [6]; default: 0; + uint32_t idle_out_lv_chn: 1; + /** idle_out_en_chn : R/W; bitpos: [6]; default: 0; * This is the output enable-control bit for CHANNELn in IDLE state. */ - uint32_t idle_out_en_ch0:1; - /** tx_stop_ch0 : R/W/SC; bitpos: [7]; default: 0; + uint32_t idle_out_en_chn: 1; + /** tx_stop_chn : R/W/SC; bitpos: [7]; default: 0; * Set this bit to stop the transmitter of CHANNELn sending data out. */ - uint32_t tx_stop_ch0:1; - /** div_cnt_ch0 : R/W; bitpos: [15:8]; default: 2; + uint32_t tx_stop_chn: 1; + /** div_cnt_chn : R/W; bitpos: [15:8]; default: 2; * This register is used to configure the divider for clock of CHANNELn. */ - uint32_t div_cnt_ch0:8; - /** mem_size_ch0 : R/W; bitpos: [19:16]; default: 1; + uint32_t div_cnt_chn: 8; + /** mem_size_chn : R/W; bitpos: [19:16]; default: 1; * This register is used to configure the maximum size of memory allocated to CHANNELn. */ - uint32_t mem_size_ch0:4; - /** carrier_eff_en_ch0 : R/W; bitpos: [20]; default: 1; + uint32_t mem_size_chn: 4; + /** carrier_eff_en_chn : R/W; bitpos: [20]; default: 1; * 1: Add carrier modulation on the output signal only at the send data state for * CHANNELn. 0: Add carrier modulation on the output signal at all state for CHANNELn. * Only valid when RMT_CARRIER_EN_CHn is 1. */ - uint32_t carrier_eff_en_ch0:1; - /** carrier_en_ch0 : R/W; bitpos: [21]; default: 1; + uint32_t carrier_eff_en_chn: 1; + /** carrier_en_chn : R/W; bitpos: [21]; default: 1; * This is the carrier modulation enable-control bit for CHANNELn. 1: Add carrier * modulation in the output signal. 0: No carrier modulation in sig_out. */ - uint32_t carrier_en_ch0:1; - /** carrier_out_lv_ch0 : R/W; bitpos: [22]; default: 1; - * This bit is used to configure the position of carrier wave for CHANNELn.1'h0: add - * carrier wave on low level.1'h1: add carrier wave on high level. + uint32_t carrier_en_chn: 1; + /** carrier_out_lv_chn : R/W; bitpos: [22]; default: 1; + * This bit is used to configure the position of carrier wave for CHANNELn. + * 1'h0: add carrier wave on low level. + * 1'h1: add carrier wave on high level. */ - uint32_t carrier_out_lv_ch0:1; - uint32_t reserved_23:1; - /** conf_update_ch0 : WT; bitpos: [24]; default: 0; + uint32_t carrier_out_lv_chn: 1; + /** afifo_rst_chn : WT; bitpos: [23]; default: 0; + * Reserved + */ + uint32_t afifo_rst_chn: 1; + /** conf_update_chn : WT; bitpos: [24]; default: 0; * synchronization bit for CHANNELn */ - uint32_t conf_update_ch0:1; - uint32_t reserved_25:7; + uint32_t conf_update_chn: 1; + /** dma_access_en_chn : WT; bitpos: [25]; default: 0; + * DMA access control bit for CHANNELn (only CHANNEL3 has this control bit) + */ + uint32_t dma_access_en_chn: 1; + uint32_t reserved_26: 6; }; uint32_t val; } rmt_chnconf0_reg_t; @@ -118,31 +126,35 @@ typedef union { */ typedef union { struct { - /** div_cnt_ch4 : R/W; bitpos: [7:0]; default: 2; + /** div_cnt_chm : R/W; bitpos: [7:0]; default: 2; * This register is used to configure the divider for clock of CHANNELm. */ - uint32_t div_cnt_ch4:8; - /** idle_thres_ch4 : R/W; bitpos: [22:8]; default: 32767; + uint32_t div_cnt_chm: 8; + /** idle_thres_chm : R/W; bitpos: [22:8]; default: 32767; * When no edge is detected on the input signal and continuous clock cycles is longer * than this register value, received process is finished. */ - uint32_t idle_thres_ch4:15; - uint32_t reserved_23:1; - /** mem_size_ch4 : R/W; bitpos: [27:24]; default: 1; + uint32_t idle_thres_chm: 15; + /** dma_access_en_m : WT; bitpos: [23]; default: 0; + * DMA access control bit for CHANNELm (only channel7 has this control bit) + */ + uint32_t dma_access_en_chm: 1; + /** mem_size_chm : R/W; bitpos: [27:24]; default: 1; * This register is used to configure the maximum size of memory allocated to CHANNELm. */ - uint32_t mem_size_ch4:4; - /** carrier_en_ch4 : R/W; bitpos: [28]; default: 1; + uint32_t mem_size_chm: 4; + /** carrier_en_chm : R/W; bitpos: [28]; default: 1; * This is the carrier modulation enable-control bit for CHANNELm. 1: Add carrier * modulation in the output signal. 0: No carrier modulation in sig_out. */ - uint32_t carrier_en_ch4:1; - /** carrier_out_lv_ch4 : R/W; bitpos: [29]; default: 1; - * This bit is used to configure the position of carrier wave for CHANNELm.1'h0: add - * carrier wave on low level.1'h1: add carrier wave on high level. + uint32_t carrier_en_chm: 1; + /** carrier_out_lv_chm : R/W; bitpos: [29]; default: 1; + * This bit is used to configure the position of carrier wave for CHANNELm. + * 1'h0: add carrier wave on low level. + * 1'h1: add carrier wave on high level. */ - uint32_t carrier_out_lv_ch4:1; - uint32_t reserved_30:2; + uint32_t carrier_out_lv_chm: 1; + uint32_t reserved_30: 2; }; uint32_t val; } rmt_chmconf0_reg_t; @@ -152,43 +164,47 @@ typedef union { */ typedef union { struct { - /** rx_en_ch4 : R/W; bitpos: [0]; default: 0; + /** rx_en_chm : R/W; bitpos: [0]; default: 0; * Set this bit to enable receiver to receive data on CHANNELm. */ - uint32_t rx_en_ch4:1; - /** mem_wr_rst_ch4 : WT; bitpos: [1]; default: 0; + uint32_t rx_en_chm: 1; + /** mem_wr_rst_chm : WT; bitpos: [1]; default: 0; * Set this bit to reset write ram address for CHANNELm by accessing receiver. */ - uint32_t mem_wr_rst_ch4:1; - /** apb_mem_rst_ch4 : WT; bitpos: [2]; default: 0; + uint32_t mem_wr_rst_chm: 1; + /** apb_mem_rst_chm : WT; bitpos: [2]; default: 0; * Set this bit to reset W/R ram address for CHANNELm by accessing apb fifo. */ - uint32_t apb_mem_rst_ch4:1; - /** mem_owner_ch4 : R/W/SC; bitpos: [3]; default: 1; - * This register marks the ownership of CHANNELm's ram block.1'h1: Receiver is using - * the ram. 1'h0: APB bus is using the ram. + uint32_t apb_mem_rst_chm: 1; + /** mem_owner_chm : R/W/SC; bitpos: [3]; default: 1; + * This register marks the ownership of CHANNELm's ram block. + * 1'h1: Receiver is using the ram. + * 1'h0: APB bus is using the ram. */ - uint32_t mem_owner_ch4:1; - /** rx_filter_en_ch4 : R/W; bitpos: [4]; default: 0; + uint32_t mem_owner_chm: 1; + /** rx_filter_en_chm : R/W; bitpos: [4]; default: 0; * This is the receive filter's enable bit for CHANNELm. */ - uint32_t rx_filter_en_ch4:1; - /** rx_filter_thres_ch4 : R/W; bitpos: [12:5]; default: 15; + uint32_t rx_filter_en_chm: 1; + /** rx_filter_thres_chm : R/W; bitpos: [12:5]; default: 15; * Ignores the input pulse when its width is smaller than this register value in APB * clock periods (in receive mode). */ - uint32_t rx_filter_thres_ch4:8; - /** mem_rx_wrap_en_ch4 : R/W; bitpos: [13]; default: 0; + uint32_t rx_filter_thres_chm: 8; + /** mem_rx_wrap_en_chm : R/W; bitpos: [13]; default: 0; * This is the channel m enable bit for wraparound mode: it will resume receiving at * the start when the data to be received is more than its memory size. */ - uint32_t mem_rx_wrap_en_ch4:1; - uint32_t reserved_14:1; - /** conf_update_ch4 : WT; bitpos: [15]; default: 0; + uint32_t mem_rx_wrap_en_chm: 1; + /** afifo_rst_chm : WT; bitpos: [14]; default: 0; + * Reserved + */ + uint32_t afifo_rst_chm: 1; + /** conf_update_chm : WT; bitpos: [15]; default: 0; * synchronization bit for CHANNELm */ - uint32_t conf_update_ch4:1; - uint32_t reserved_16:16; + uint32_t conf_update_chm: 1; + uint32_t reserved_16: 16; }; uint32_t val; } rmt_chmconf1_reg_t; @@ -198,16 +214,16 @@ typedef union { */ typedef union { struct { - /** carrier_low_thres_ch4 : R/W; bitpos: [15:0]; default: 0; + /** carrier_low_thres_chm : R/W; bitpos: [15:0]; default: 0; * The low level period in a carrier modulation mode is * (REG_RMT_REG_CARRIER_LOW_THRES_CHm + 1) for channel m. */ - uint32_t carrier_low_thres_ch4:16; - /** carrier_high_thres_ch4 : R/W; bitpos: [31:16]; default: 0; + uint32_t carrier_low_thres_chm: 16; + /** carrier_high_thres_chm : R/W; bitpos: [31:16]; default: 0; * The high level period in a carrier modulation mode is * (REG_RMT_REG_CARRIER_HIGH_THRES_CHm + 1) for channel m. */ - uint32_t carrier_high_thres_ch4:16; + uint32_t carrier_high_thres_chm: 16; }; uint32_t val; } rmt_chm_rx_carrier_rm_reg_t; @@ -220,46 +236,46 @@ typedef union { /** apb_fifo_mask : R/W; bitpos: [0]; default: 0; * 1'h1: access memory directly. 1'h0: access memory by FIFO. */ - uint32_t apb_fifo_mask:1; + uint32_t apb_fifo_mask: 1; /** mem_clk_force_on : R/W; bitpos: [1]; default: 0; * Set this bit to enable the clock for RMT memory. */ - uint32_t mem_clk_force_on:1; + uint32_t mem_clk_force_on: 1; /** mem_force_pd : R/W; bitpos: [2]; default: 0; * Set this bit to power down RMT memory. */ - uint32_t mem_force_pd:1; + uint32_t mem_force_pd: 1; /** mem_force_pu : R/W; bitpos: [3]; default: 0; * 1: Disable RMT memory light sleep power down function. 0: Power down RMT memory * when RMT is in light sleep mode. */ - uint32_t mem_force_pu:1; + uint32_t mem_force_pu: 1; /** sclk_div_num : R/W; bitpos: [11:4]; default: 1; * the integral part of the fractional divisor */ - uint32_t sclk_div_num:8; + uint32_t sclk_div_num: 8; /** sclk_div_a : R/W; bitpos: [17:12]; default: 0; * the numerator of the fractional part of the fractional divisor */ - uint32_t sclk_div_a:6; + uint32_t sclk_div_a: 6; /** sclk_div_b : R/W; bitpos: [23:18]; default: 0; * the denominator of the fractional part of the fractional divisor */ - uint32_t sclk_div_b:6; + uint32_t sclk_div_b: 6; /** sclk_sel : R/W; bitpos: [25:24]; default: 1; * choose the clock source of rmt_sclk. 1:CLK_80Mhz.2:CLK_8MHz.3:XTAL */ - uint32_t sclk_sel:2; + uint32_t sclk_sel: 2; /** sclk_active : R/W; bitpos: [26]; default: 1; * rmt_sclk switch */ - uint32_t sclk_active:1; - uint32_t reserved_27:4; + uint32_t sclk_active: 1; + uint32_t reserved_27: 4; /** clk_en : R/W; bitpos: [31]; default: 0; * RMT register clock gate enable signal. 1: Power up the drive clock of registers. 0: * Power down the drive clock of registers */ - uint32_t clk_en:1; + uint32_t clk_en: 1; }; uint32_t val; } rmt_sys_conf_reg_t; @@ -272,73 +288,72 @@ typedef union { /** ref_cnt_rst_ch0 : WT; bitpos: [0]; default: 0; * This register is used to reset the clock divider of CHANNEL0. */ - uint32_t ref_cnt_rst_ch0:1; + uint32_t ref_cnt_rst_ch0: 1; /** ref_cnt_rst_ch1 : WT; bitpos: [1]; default: 0; * This register is used to reset the clock divider of CHANNEL1. */ - uint32_t ref_cnt_rst_ch1:1; + uint32_t ref_cnt_rst_ch1: 1; /** ref_cnt_rst_ch2 : WT; bitpos: [2]; default: 0; * This register is used to reset the clock divider of CHANNEL2. */ - uint32_t ref_cnt_rst_ch2:1; + uint32_t ref_cnt_rst_ch2: 1; /** ref_cnt_rst_ch3 : WT; bitpos: [3]; default: 0; * This register is used to reset the clock divider of CHANNEL3. */ - uint32_t ref_cnt_rst_ch3:1; + uint32_t ref_cnt_rst_ch3: 1; /** ref_cnt_rst_ch4 : WT; bitpos: [4]; default: 0; * This register is used to reset the clock divider of CHANNEL4. */ - uint32_t ref_cnt_rst_ch4:1; + uint32_t ref_cnt_rst_ch4: 1; /** ref_cnt_rst_ch5 : WT; bitpos: [5]; default: 0; * This register is used to reset the clock divider of CHANNEL5. */ - uint32_t ref_cnt_rst_ch5:1; + uint32_t ref_cnt_rst_ch5: 1; /** ref_cnt_rst_ch6 : WT; bitpos: [6]; default: 0; * This register is used to reset the clock divider of CHANNEL6. */ - uint32_t ref_cnt_rst_ch6:1; + uint32_t ref_cnt_rst_ch6: 1; /** ref_cnt_rst_ch7 : WT; bitpos: [7]; default: 0; * This register is used to reset the clock divider of CHANNEL7. */ - uint32_t ref_cnt_rst_ch7:1; - uint32_t reserved_8:24; + uint32_t ref_cnt_rst_ch7: 1; + uint32_t reserved_8: 24; }; uint32_t val; } rmt_ref_cnt_rst_reg_t; - /** Group: Status registers */ /** Type of chnstatus register * Channel n status register */ typedef union { struct { - /** mem_raddr_ex_ch0 : RO; bitpos: [9:0]; default: 0; + /** mem_raddr_ex_chn : RO; bitpos: [9:0]; default: 0; * This register records the memory address offset when transmitter of CHANNELn is * using the RAM. */ - uint32_t mem_raddr_ex_ch0:10; - uint32_t reserved_10:1; - /** apb_mem_waddr_ch0 : RO; bitpos: [20:11]; default: 0; + uint32_t mem_raddr_ex_chn: 10; + uint32_t reserved_10: 1; + /** apb_mem_waddr_chn : RO; bitpos: [20:11]; default: 0; * This register records the memory address offset when writes RAM over APB bus. */ - uint32_t apb_mem_waddr_ch0:10; - uint32_t reserved_21:1; - /** state_ch0 : RO; bitpos: [24:22]; default: 0; + uint32_t apb_mem_waddr_chn: 10; + uint32_t reserved_21: 1; + /** state_chn : RO; bitpos: [24:22]; default: 0; * This register records the FSM status of CHANNELn. */ - uint32_t state_ch0:3; - /** mem_empty_ch0 : RO; bitpos: [25]; default: 0; + uint32_t state_chn: 3; + /** mem_empty_chn : RO; bitpos: [25]; default: 0; * This status bit will be set when the data to be set is more than memory size and * the wraparound mode is disabled. */ - uint32_t mem_empty_ch0:1; - /** apb_mem_wr_err_ch0 : RO; bitpos: [26]; default: 0; + uint32_t mem_empty_chn: 1; + /** apb_mem_wr_err_chn : RO; bitpos: [26]; default: 0; * This status bit will be set if the offset address out of memory size when writes * via APB bus. */ - uint32_t apb_mem_wr_err_ch0:1; - uint32_t reserved_27:5; + uint32_t apb_mem_wr_err_chn: 1; + uint32_t reserved_27: 5; }; uint32_t val; } rmt_chnstatus_reg_t; @@ -348,40 +363,39 @@ typedef union { */ typedef union { struct { - /** mem_waddr_ex_ch4 : RO; bitpos: [9:0]; default: 192; + /** mem_waddr_ex_chm : RO; bitpos: [9:0]; default: 192; * This register records the memory address offset when receiver of CHANNELm is using * the RAM. */ - uint32_t mem_waddr_ex_ch4:10; - uint32_t reserved_10:1; - /** apb_mem_raddr_ch4 : RO; bitpos: [20:11]; default: 192; + uint32_t mem_waddr_ex_chm: 10; + uint32_t reserved_10: 1; + /** apb_mem_raddr_chm : RO; bitpos: [20:11]; default: 192; * This register records the memory address offset when reads RAM over APB bus. */ - uint32_t apb_mem_raddr_ch4:10; - uint32_t reserved_21:1; - /** state_ch4 : RO; bitpos: [24:22]; default: 0; + uint32_t apb_mem_raddr_chm: 10; + uint32_t reserved_21: 1; + /** state_chm : RO; bitpos: [24:22]; default: 0; * This register records the FSM status of CHANNELm. */ - uint32_t state_ch4:3; - /** mem_owner_err_ch4 : RO; bitpos: [25]; default: 0; + uint32_t state_chm: 3; + /** mem_owner_err_chm : RO; bitpos: [25]; default: 0; * This status bit will be set when the ownership of memory block is wrong. */ - uint32_t mem_owner_err_ch4:1; - /** mem_full_ch4 : RO; bitpos: [26]; default: 0; + uint32_t mem_owner_err_chm: 1; + /** mem_full_chm : RO; bitpos: [26]; default: 0; * This status bit will be set if the receiver receives more data than the memory size. */ - uint32_t mem_full_ch4:1; - /** apb_mem_rd_err_ch4 : RO; bitpos: [27]; default: 0; + uint32_t mem_full_chm: 1; + /** apb_mem_rd_err_chm : RO; bitpos: [27]; default: 0; * This status bit will be set if the offset address out of memory size when reads via * APB bus. */ - uint32_t apb_mem_rd_err_ch4:1; - uint32_t reserved_28:4; + uint32_t apb_mem_rd_err_chm: 1; + uint32_t reserved_28: 4; }; uint32_t val; } rmt_chmstatus_reg_t; - /** Group: Interrupt registers */ /** Type of int_raw register * Raw interrupt status @@ -391,136 +405,136 @@ typedef union { /** ch0_tx_end_int_raw : R/WTC/SS; bitpos: [0]; default: 0; * The interrupt raw bit for CHANNEL0. Triggered when transmission done. */ - uint32_t ch0_tx_end_int_raw:1; + uint32_t ch0_tx_end_int_raw: 1; /** ch1_tx_end_int_raw : R/WTC/SS; bitpos: [1]; default: 0; * The interrupt raw bit for CHANNEL1. Triggered when transmission done. */ - uint32_t ch1_tx_end_int_raw:1; + uint32_t ch1_tx_end_int_raw: 1; /** ch2_tx_end_int_raw : R/WTC/SS; bitpos: [2]; default: 0; * The interrupt raw bit for CHANNEL2. Triggered when transmission done. */ - uint32_t ch2_tx_end_int_raw:1; + uint32_t ch2_tx_end_int_raw: 1; /** ch3_tx_end_int_raw : R/WTC/SS; bitpos: [3]; default: 0; * The interrupt raw bit for CHANNEL3. Triggered when transmission done. */ - uint32_t ch3_tx_end_int_raw:1; + uint32_t ch3_tx_end_int_raw: 1; /** ch0_err_int_raw : R/WTC/SS; bitpos: [4]; default: 0; * The interrupt raw bit for CHANNEL0. Triggered when error occurs. */ - uint32_t ch0_err_int_raw:1; + uint32_t ch0_err_int_raw: 1; /** ch1_err_int_raw : R/WTC/SS; bitpos: [5]; default: 0; * The interrupt raw bit for CHANNEL1. Triggered when error occurs. */ - uint32_t ch1_err_int_raw:1; + uint32_t ch1_err_int_raw: 1; /** ch2_err_int_raw : R/WTC/SS; bitpos: [6]; default: 0; * The interrupt raw bit for CHANNEL2. Triggered when error occurs. */ - uint32_t ch2_err_int_raw:1; + uint32_t ch2_err_int_raw: 1; /** ch3_err_int_raw : R/WTC/SS; bitpos: [7]; default: 0; * The interrupt raw bit for CHANNEL3. Triggered when error occurs. */ - uint32_t ch3_err_int_raw:1; + uint32_t ch3_err_int_raw: 1; /** ch0_tx_thr_event_int_raw : R/WTC/SS; bitpos: [8]; default: 0; * The interrupt raw bit for CHANNEL0. Triggered when transmitter sent more data than * configured value. */ - uint32_t ch0_tx_thr_event_int_raw:1; + uint32_t ch0_tx_thr_event_int_raw: 1; /** ch1_tx_thr_event_int_raw : R/WTC/SS; bitpos: [9]; default: 0; * The interrupt raw bit for CHANNEL1. Triggered when transmitter sent more data than * configured value. */ - uint32_t ch1_tx_thr_event_int_raw:1; + uint32_t ch1_tx_thr_event_int_raw: 1; /** ch2_tx_thr_event_int_raw : R/WTC/SS; bitpos: [10]; default: 0; * The interrupt raw bit for CHANNEL2. Triggered when transmitter sent more data than * configured value. */ - uint32_t ch2_tx_thr_event_int_raw:1; + uint32_t ch2_tx_thr_event_int_raw: 1; /** ch3_tx_thr_event_int_raw : R/WTC/SS; bitpos: [11]; default: 0; * The interrupt raw bit for CHANNEL3. Triggered when transmitter sent more data than * configured value. */ - uint32_t ch3_tx_thr_event_int_raw:1; + uint32_t ch3_tx_thr_event_int_raw: 1; /** ch0_tx_loop_int_raw : R/WTC/SS; bitpos: [12]; default: 0; * The interrupt raw bit for CHANNEL0. Triggered when the loop count reaches the * configured threshold value. */ - uint32_t ch0_tx_loop_int_raw:1; + uint32_t ch0_tx_loop_int_raw: 1; /** ch1_tx_loop_int_raw : R/WTC/SS; bitpos: [13]; default: 0; * The interrupt raw bit for CHANNEL1. Triggered when the loop count reaches the * configured threshold value. */ - uint32_t ch1_tx_loop_int_raw:1; + uint32_t ch1_tx_loop_int_raw: 1; /** ch2_tx_loop_int_raw : R/WTC/SS; bitpos: [14]; default: 0; * The interrupt raw bit for CHANNEL2. Triggered when the loop count reaches the * configured threshold value. */ - uint32_t ch2_tx_loop_int_raw:1; + uint32_t ch2_tx_loop_int_raw: 1; /** ch3_tx_loop_int_raw : R/WTC/SS; bitpos: [15]; default: 0; * The interrupt raw bit for CHANNEL3. Triggered when the loop count reaches the * configured threshold value. */ - uint32_t ch3_tx_loop_int_raw:1; + uint32_t ch3_tx_loop_int_raw: 1; /** ch4_rx_end_int_raw : R/WTC/SS; bitpos: [16]; default: 0; * The interrupt raw bit for CHANNEL4. Triggered when reception done. */ - uint32_t ch4_rx_end_int_raw:1; + uint32_t ch4_rx_end_int_raw: 1; /** ch5_rx_end_int_raw : R/WTC/SS; bitpos: [17]; default: 0; * The interrupt raw bit for CHANNEL5. Triggered when reception done. */ - uint32_t ch5_rx_end_int_raw:1; + uint32_t ch5_rx_end_int_raw: 1; /** ch6_rx_end_int_raw : R/WTC/SS; bitpos: [18]; default: 0; * The interrupt raw bit for CHANNEL6. Triggered when reception done. */ - uint32_t ch6_rx_end_int_raw:1; + uint32_t ch6_rx_end_int_raw: 1; /** ch7_rx_end_int_raw : R/WTC/SS; bitpos: [19]; default: 0; * The interrupt raw bit for CHANNEL7. Triggered when reception done. */ - uint32_t ch7_rx_end_int_raw:1; + uint32_t ch7_rx_end_int_raw: 1; /** ch4_err_int_raw : R/WTC/SS; bitpos: [20]; default: 0; * The interrupt raw bit for CHANNEL4. Triggered when error occurs. */ - uint32_t ch4_err_int_raw:1; + uint32_t ch4_err_int_raw: 1; /** ch5_err_int_raw : R/WTC/SS; bitpos: [21]; default: 0; * The interrupt raw bit for CHANNEL5. Triggered when error occurs. */ - uint32_t ch5_err_int_raw:1; + uint32_t ch5_err_int_raw: 1; /** ch6_err_int_raw : R/WTC/SS; bitpos: [22]; default: 0; * The interrupt raw bit for CHANNEL6. Triggered when error occurs. */ - uint32_t ch6_err_int_raw:1; + uint32_t ch6_err_int_raw: 1; /** ch7_err_int_raw : R/WTC/SS; bitpos: [23]; default: 0; * The interrupt raw bit for CHANNEL7. Triggered when error occurs. */ - uint32_t ch7_err_int_raw:1; + uint32_t ch7_err_int_raw: 1; /** ch4_rx_thr_event_int_raw : R/WTC/SS; bitpos: [24]; default: 0; * The interrupt raw bit for CHANNEL4. Triggered when receiver receive more data than * configured value. */ - uint32_t ch4_rx_thr_event_int_raw:1; + uint32_t ch4_rx_thr_event_int_raw: 1; /** ch5_rx_thr_event_int_raw : R/WTC/SS; bitpos: [25]; default: 0; * The interrupt raw bit for CHANNEL5. Triggered when receiver receive more data than * configured value. */ - uint32_t ch5_rx_thr_event_int_raw:1; + uint32_t ch5_rx_thr_event_int_raw: 1; /** ch6_rx_thr_event_int_raw : R/WTC/SS; bitpos: [26]; default: 0; * The interrupt raw bit for CHANNEL6. Triggered when receiver receive more data than * configured value. */ - uint32_t ch6_rx_thr_event_int_raw:1; + uint32_t ch6_rx_thr_event_int_raw: 1; /** ch7_rx_thr_event_int_raw : R/WTC/SS; bitpos: [27]; default: 0; * The interrupt raw bit for CHANNEL7. Triggered when receiver receive more data than * configured value. */ - uint32_t ch7_rx_thr_event_int_raw:1; + uint32_t ch7_rx_thr_event_int_raw: 1; /** ch3_dma_access_fail_int_raw : R/WTC/SS; bitpos: [28]; default: 0; * The interrupt raw bit for CHANNEL3. Triggered when dma accessing CHANNEL3 fails. */ - uint32_t ch3_dma_access_fail_int_raw:1; + uint32_t ch3_dma_access_fail_int_raw: 1; /** ch7_dma_access_fail_int_raw : R/WTC/SS; bitpos: [29]; default: 0; * The interrupt raw bit for CHANNEL7. Triggered when dma accessing CHANNEL7 fails. */ - uint32_t ch7_dma_access_fail_int_raw:1; - uint32_t reserved_30:2; + uint32_t ch7_dma_access_fail_int_raw: 1; + uint32_t reserved_30: 2; }; uint32_t val; } rmt_int_raw_reg_t; @@ -533,124 +547,124 @@ typedef union { /** ch0_tx_end_int_st : RO; bitpos: [0]; default: 0; * The masked interrupt status bit for CH0_TX_END_INT. */ - uint32_t ch0_tx_end_int_st:1; + uint32_t ch0_tx_end_int_st: 1; /** ch1_tx_end_int_st : RO; bitpos: [1]; default: 0; * The masked interrupt status bit for CH1_TX_END_INT. */ - uint32_t ch1_tx_end_int_st:1; + uint32_t ch1_tx_end_int_st: 1; /** ch2_tx_end_int_st : RO; bitpos: [2]; default: 0; * The masked interrupt status bit for CH2_TX_END_INT. */ - uint32_t ch2_tx_end_int_st:1; + uint32_t ch2_tx_end_int_st: 1; /** ch3_tx_end_int_st : RO; bitpos: [3]; default: 0; * The masked interrupt status bit for CH3_TX_END_INT. */ - uint32_t ch3_tx_end_int_st:1; + uint32_t ch3_tx_end_int_st: 1; /** ch0_err_int_st : RO; bitpos: [4]; default: 0; * The masked interrupt status bit for CH0_ERR_INT. */ - uint32_t ch0_err_int_st:1; + uint32_t ch0_err_int_st: 1; /** ch1_err_int_st : RO; bitpos: [5]; default: 0; * The masked interrupt status bit for CH1_ERR_INT. */ - uint32_t ch1_err_int_st:1; + uint32_t ch1_err_int_st: 1; /** ch2_err_int_st : RO; bitpos: [6]; default: 0; * The masked interrupt status bit for CH2_ERR_INT. */ - uint32_t ch2_err_int_st:1; + uint32_t ch2_err_int_st: 1; /** ch3_err_int_st : RO; bitpos: [7]; default: 0; * The masked interrupt status bit for CH3_ERR_INT. */ - uint32_t ch3_err_int_st:1; + uint32_t ch3_err_int_st: 1; /** ch0_tx_thr_event_int_st : RO; bitpos: [8]; default: 0; * The masked interrupt status bit for CH0_TX_THR_EVENT_INT. */ - uint32_t ch0_tx_thr_event_int_st:1; + uint32_t ch0_tx_thr_event_int_st: 1; /** ch1_tx_thr_event_int_st : RO; bitpos: [9]; default: 0; * The masked interrupt status bit for CH1_TX_THR_EVENT_INT. */ - uint32_t ch1_tx_thr_event_int_st:1; + uint32_t ch1_tx_thr_event_int_st: 1; /** ch2_tx_thr_event_int_st : RO; bitpos: [10]; default: 0; * The masked interrupt status bit for CH2_TX_THR_EVENT_INT. */ - uint32_t ch2_tx_thr_event_int_st:1; + uint32_t ch2_tx_thr_event_int_st: 1; /** ch3_tx_thr_event_int_st : RO; bitpos: [11]; default: 0; * The masked interrupt status bit for CH3_TX_THR_EVENT_INT. */ - uint32_t ch3_tx_thr_event_int_st:1; + uint32_t ch3_tx_thr_event_int_st: 1; /** ch0_tx_loop_int_st : RO; bitpos: [12]; default: 0; * The masked interrupt status bit for CH0_TX_LOOP_INT. */ - uint32_t ch0_tx_loop_int_st:1; + uint32_t ch0_tx_loop_int_st: 1; /** ch1_tx_loop_int_st : RO; bitpos: [13]; default: 0; * The masked interrupt status bit for CH1_TX_LOOP_INT. */ - uint32_t ch1_tx_loop_int_st:1; + uint32_t ch1_tx_loop_int_st: 1; /** ch2_tx_loop_int_st : RO; bitpos: [14]; default: 0; * The masked interrupt status bit for CH2_TX_LOOP_INT. */ - uint32_t ch2_tx_loop_int_st:1; + uint32_t ch2_tx_loop_int_st: 1; /** ch3_tx_loop_int_st : RO; bitpos: [15]; default: 0; * The masked interrupt status bit for CH3_TX_LOOP_INT. */ - uint32_t ch3_tx_loop_int_st:1; + uint32_t ch3_tx_loop_int_st: 1; /** ch4_rx_end_int_st : RO; bitpos: [16]; default: 0; * The masked interrupt status bit for CH4_RX_END_INT. */ - uint32_t ch4_rx_end_int_st:1; + uint32_t ch4_rx_end_int_st: 1; /** ch5_rx_end_int_st : RO; bitpos: [17]; default: 0; * The masked interrupt status bit for CH5_RX_END_INT. */ - uint32_t ch5_rx_end_int_st:1; + uint32_t ch5_rx_end_int_st: 1; /** ch6_rx_end_int_st : RO; bitpos: [18]; default: 0; * The masked interrupt status bit for CH6_RX_END_INT. */ - uint32_t ch6_rx_end_int_st:1; + uint32_t ch6_rx_end_int_st: 1; /** ch7_rx_end_int_st : RO; bitpos: [19]; default: 0; * The masked interrupt status bit for CH7_RX_END_INT. */ - uint32_t ch7_rx_end_int_st:1; + uint32_t ch7_rx_end_int_st: 1; /** ch4_err_int_st : RO; bitpos: [20]; default: 0; * The masked interrupt status bit for CH4_ERR_INT. */ - uint32_t ch4_err_int_st:1; + uint32_t ch4_err_int_st: 1; /** ch5_err_int_st : RO; bitpos: [21]; default: 0; * The masked interrupt status bit for CH5_ERR_INT. */ - uint32_t ch5_err_int_st:1; + uint32_t ch5_err_int_st: 1; /** ch6_err_int_st : RO; bitpos: [22]; default: 0; * The masked interrupt status bit for CH6_ERR_INT. */ - uint32_t ch6_err_int_st:1; + uint32_t ch6_err_int_st: 1; /** ch7_err_int_st : RO; bitpos: [23]; default: 0; * The masked interrupt status bit for CH7_ERR_INT. */ - uint32_t ch7_err_int_st:1; + uint32_t ch7_err_int_st: 1; /** ch4_rx_thr_event_int_st : RO; bitpos: [24]; default: 0; * The masked interrupt status bit for CH4_RX_THR_EVENT_INT. */ - uint32_t ch4_rx_thr_event_int_st:1; + uint32_t ch4_rx_thr_event_int_st: 1; /** ch5_rx_thr_event_int_st : RO; bitpos: [25]; default: 0; * The masked interrupt status bit for CH5_RX_THR_EVENT_INT. */ - uint32_t ch5_rx_thr_event_int_st:1; + uint32_t ch5_rx_thr_event_int_st: 1; /** ch6_rx_thr_event_int_st : RO; bitpos: [26]; default: 0; * The masked interrupt status bit for CH6_RX_THR_EVENT_INT. */ - uint32_t ch6_rx_thr_event_int_st:1; + uint32_t ch6_rx_thr_event_int_st: 1; /** ch7_rx_thr_event_int_st : RO; bitpos: [27]; default: 0; * The masked interrupt status bit for CH7_RX_THR_EVENT_INT. */ - uint32_t ch7_rx_thr_event_int_st:1; + uint32_t ch7_rx_thr_event_int_st: 1; /** ch3_dma_access_fail_int_st : RO; bitpos: [28]; default: 0; * The masked interrupt status bit for CH3_DMA_ACCESS_FAIL_INT. */ - uint32_t ch3_dma_access_fail_int_st:1; + uint32_t ch3_dma_access_fail_int_st: 1; /** ch7_dma_access_fail_int_st : RO; bitpos: [29]; default: 0; * The masked interrupt status bit for CH7_DMA_ACCESS_FAIL_INT. */ - uint32_t ch7_dma_access_fail_int_st:1; - uint32_t reserved_30:2; + uint32_t ch7_dma_access_fail_int_st: 1; + uint32_t reserved_30: 2; }; uint32_t val; } rmt_int_st_reg_t; @@ -663,124 +677,124 @@ typedef union { /** ch0_tx_end_int_ena : R/W; bitpos: [0]; default: 0; * The interrupt enable bit for CH0_TX_END_INT. */ - uint32_t ch0_tx_end_int_ena:1; + uint32_t ch0_tx_end_int_ena: 1; /** ch1_tx_end_int_ena : R/W; bitpos: [1]; default: 0; * The interrupt enable bit for CH1_TX_END_INT. */ - uint32_t ch1_tx_end_int_ena:1; + uint32_t ch1_tx_end_int_ena: 1; /** ch2_tx_end_int_ena : R/W; bitpos: [2]; default: 0; * The interrupt enable bit for CH2_TX_END_INT. */ - uint32_t ch2_tx_end_int_ena:1; + uint32_t ch2_tx_end_int_ena: 1; /** ch3_tx_end_int_ena : R/W; bitpos: [3]; default: 0; * The interrupt enable bit for CH3_TX_END_INT. */ - uint32_t ch3_tx_end_int_ena:1; + uint32_t ch3_tx_end_int_ena: 1; /** ch0_err_int_ena : R/W; bitpos: [4]; default: 0; * The interrupt enable bit for CH0_ERR_INT. */ - uint32_t ch0_err_int_ena:1; + uint32_t ch0_err_int_ena: 1; /** ch1_err_int_ena : R/W; bitpos: [5]; default: 0; * The interrupt enable bit for CH1_ERR_INT. */ - uint32_t ch1_err_int_ena:1; + uint32_t ch1_err_int_ena: 1; /** ch2_err_int_ena : R/W; bitpos: [6]; default: 0; * The interrupt enable bit for CH2_ERR_INT. */ - uint32_t ch2_err_int_ena:1; + uint32_t ch2_err_int_ena: 1; /** ch3_err_int_ena : R/W; bitpos: [7]; default: 0; * The interrupt enable bit for CH3_ERR_INT. */ - uint32_t ch3_err_int_ena:1; + uint32_t ch3_err_int_ena: 1; /** ch0_tx_thr_event_int_ena : R/W; bitpos: [8]; default: 0; * The interrupt enable bit for CH0_TX_THR_EVENT_INT. */ - uint32_t ch0_tx_thr_event_int_ena:1; + uint32_t ch0_tx_thr_event_int_ena: 1; /** ch1_tx_thr_event_int_ena : R/W; bitpos: [9]; default: 0; * The interrupt enable bit for CH1_TX_THR_EVENT_INT. */ - uint32_t ch1_tx_thr_event_int_ena:1; + uint32_t ch1_tx_thr_event_int_ena: 1; /** ch2_tx_thr_event_int_ena : R/W; bitpos: [10]; default: 0; * The interrupt enable bit for CH2_TX_THR_EVENT_INT. */ - uint32_t ch2_tx_thr_event_int_ena:1; + uint32_t ch2_tx_thr_event_int_ena: 1; /** ch3_tx_thr_event_int_ena : R/W; bitpos: [11]; default: 0; * The interrupt enable bit for CH3_TX_THR_EVENT_INT. */ - uint32_t ch3_tx_thr_event_int_ena:1; + uint32_t ch3_tx_thr_event_int_ena: 1; /** ch0_tx_loop_int_ena : R/W; bitpos: [12]; default: 0; * The interrupt enable bit for CH0_TX_LOOP_INT. */ - uint32_t ch0_tx_loop_int_ena:1; + uint32_t ch0_tx_loop_int_ena: 1; /** ch1_tx_loop_int_ena : R/W; bitpos: [13]; default: 0; * The interrupt enable bit for CH1_TX_LOOP_INT. */ - uint32_t ch1_tx_loop_int_ena:1; + uint32_t ch1_tx_loop_int_ena: 1; /** ch2_tx_loop_int_ena : R/W; bitpos: [14]; default: 0; * The interrupt enable bit for CH2_TX_LOOP_INT. */ - uint32_t ch2_tx_loop_int_ena:1; + uint32_t ch2_tx_loop_int_ena: 1; /** ch3_tx_loop_int_ena : R/W; bitpos: [15]; default: 0; * The interrupt enable bit for CH3_TX_LOOP_INT. */ - uint32_t ch3_tx_loop_int_ena:1; + uint32_t ch3_tx_loop_int_ena: 1; /** ch4_rx_end_int_ena : R/W; bitpos: [16]; default: 0; * The interrupt enable bit for CH4_RX_END_INT. */ - uint32_t ch4_rx_end_int_ena:1; + uint32_t ch4_rx_end_int_ena: 1; /** ch5_rx_end_int_ena : R/W; bitpos: [17]; default: 0; * The interrupt enable bit for CH5_RX_END_INT. */ - uint32_t ch5_rx_end_int_ena:1; + uint32_t ch5_rx_end_int_ena: 1; /** ch6_rx_end_int_ena : R/W; bitpos: [18]; default: 0; * The interrupt enable bit for CH6_RX_END_INT. */ - uint32_t ch6_rx_end_int_ena:1; + uint32_t ch6_rx_end_int_ena: 1; /** ch7_rx_end_int_ena : R/W; bitpos: [19]; default: 0; * The interrupt enable bit for CH7_RX_END_INT. */ - uint32_t ch7_rx_end_int_ena:1; + uint32_t ch7_rx_end_int_ena: 1; /** ch4_err_int_ena : R/W; bitpos: [20]; default: 0; * The interrupt enable bit for CH4_ERR_INT. */ - uint32_t ch4_err_int_ena:1; + uint32_t ch4_err_int_ena: 1; /** ch5_err_int_ena : R/W; bitpos: [21]; default: 0; * The interrupt enable bit for CH5_ERR_INT. */ - uint32_t ch5_err_int_ena:1; + uint32_t ch5_err_int_ena: 1; /** ch6_err_int_ena : R/W; bitpos: [22]; default: 0; * The interrupt enable bit for CH6_ERR_INT. */ - uint32_t ch6_err_int_ena:1; + uint32_t ch6_err_int_ena: 1; /** ch7_err_int_ena : R/W; bitpos: [23]; default: 0; * The interrupt enable bit for CH7_ERR_INT. */ - uint32_t ch7_err_int_ena:1; + uint32_t ch7_err_int_ena: 1; /** ch4_rx_thr_event_int_ena : R/W; bitpos: [24]; default: 0; * The interrupt enable bit for CH4_RX_THR_EVENT_INT. */ - uint32_t ch4_rx_thr_event_int_ena:1; + uint32_t ch4_rx_thr_event_int_ena: 1; /** ch5_rx_thr_event_int_ena : R/W; bitpos: [25]; default: 0; * The interrupt enable bit for CH5_RX_THR_EVENT_INT. */ - uint32_t ch5_rx_thr_event_int_ena:1; + uint32_t ch5_rx_thr_event_int_ena: 1; /** ch6_rx_thr_event_int_ena : R/W; bitpos: [26]; default: 0; * The interrupt enable bit for CH6_RX_THR_EVENT_INT. */ - uint32_t ch6_rx_thr_event_int_ena:1; + uint32_t ch6_rx_thr_event_int_ena: 1; /** ch7_rx_thr_event_int_ena : R/W; bitpos: [27]; default: 0; * The interrupt enable bit for CH7_RX_THR_EVENT_INT. */ - uint32_t ch7_rx_thr_event_int_ena:1; + uint32_t ch7_rx_thr_event_int_ena: 1; /** ch3_dma_access_fail_int_ena : R/W; bitpos: [28]; default: 0; * The interrupt enable bit for CH3_DMA_ACCESS_FAIL_INT. */ - uint32_t ch3_dma_access_fail_int_ena:1; + uint32_t ch3_dma_access_fail_int_ena: 1; /** ch7_dma_access_fail_int_ena : R/W; bitpos: [29]; default: 0; * The interrupt enable bit for CH7_DMA_ACCESS_FAIL_INT. */ - uint32_t ch7_dma_access_fail_int_ena:1; - uint32_t reserved_30:2; + uint32_t ch7_dma_access_fail_int_ena: 1; + uint32_t reserved_30: 2; }; uint32_t val; } rmt_int_ena_reg_t; @@ -793,179 +807,177 @@ typedef union { /** ch0_tx_end_int_clr : WT; bitpos: [0]; default: 0; * Set this bit to clear theCH0_TX_END_INT interrupt. */ - uint32_t ch0_tx_end_int_clr:1; + uint32_t ch0_tx_end_int_clr: 1; /** ch1_tx_end_int_clr : WT; bitpos: [1]; default: 0; * Set this bit to clear theCH1_TX_END_INT interrupt. */ - uint32_t ch1_tx_end_int_clr:1; + uint32_t ch1_tx_end_int_clr: 1; /** ch2_tx_end_int_clr : WT; bitpos: [2]; default: 0; * Set this bit to clear theCH2_TX_END_INT interrupt. */ - uint32_t ch2_tx_end_int_clr:1; + uint32_t ch2_tx_end_int_clr: 1; /** ch3_tx_end_int_clr : WT; bitpos: [3]; default: 0; * Set this bit to clear theCH3_TX_END_INT interrupt. */ - uint32_t ch3_tx_end_int_clr:1; + uint32_t ch3_tx_end_int_clr: 1; /** ch0_err_int_clr : WT; bitpos: [4]; default: 0; * Set this bit to clear theCH0_ERR_INT interrupt. */ - uint32_t ch0_err_int_clr:1; + uint32_t ch0_err_int_clr: 1; /** ch1_err_int_clr : WT; bitpos: [5]; default: 0; * Set this bit to clear theCH1_ERR_INT interrupt. */ - uint32_t ch1_err_int_clr:1; + uint32_t ch1_err_int_clr: 1; /** ch2_err_int_clr : WT; bitpos: [6]; default: 0; * Set this bit to clear theCH2_ERR_INT interrupt. */ - uint32_t ch2_err_int_clr:1; + uint32_t ch2_err_int_clr: 1; /** ch3_err_int_clr : WT; bitpos: [7]; default: 0; * Set this bit to clear theCH3_ERR_INT interrupt. */ - uint32_t ch3_err_int_clr:1; + uint32_t ch3_err_int_clr: 1; /** ch0_tx_thr_event_int_clr : WT; bitpos: [8]; default: 0; * Set this bit to clear theCH0_TX_THR_EVENT_INT interrupt. */ - uint32_t ch0_tx_thr_event_int_clr:1; + uint32_t ch0_tx_thr_event_int_clr: 1; /** ch1_tx_thr_event_int_clr : WT; bitpos: [9]; default: 0; * Set this bit to clear theCH1_TX_THR_EVENT_INT interrupt. */ - uint32_t ch1_tx_thr_event_int_clr:1; + uint32_t ch1_tx_thr_event_int_clr: 1; /** ch2_tx_thr_event_int_clr : WT; bitpos: [10]; default: 0; * Set this bit to clear theCH2_TX_THR_EVENT_INT interrupt. */ - uint32_t ch2_tx_thr_event_int_clr:1; + uint32_t ch2_tx_thr_event_int_clr: 1; /** ch3_tx_thr_event_int_clr : WT; bitpos: [11]; default: 0; * Set this bit to clear theCH3_TX_THR_EVENT_INT interrupt. */ - uint32_t ch3_tx_thr_event_int_clr:1; + uint32_t ch3_tx_thr_event_int_clr: 1; /** ch0_tx_loop_int_clr : WT; bitpos: [12]; default: 0; * Set this bit to clear theCH0_TX_LOOP_INT interrupt. */ - uint32_t ch0_tx_loop_int_clr:1; + uint32_t ch0_tx_loop_int_clr: 1; /** ch1_tx_loop_int_clr : WT; bitpos: [13]; default: 0; * Set this bit to clear theCH1_TX_LOOP_INT interrupt. */ - uint32_t ch1_tx_loop_int_clr:1; + uint32_t ch1_tx_loop_int_clr: 1; /** ch2_tx_loop_int_clr : WT; bitpos: [14]; default: 0; * Set this bit to clear theCH2_TX_LOOP_INT interrupt. */ - uint32_t ch2_tx_loop_int_clr:1; + uint32_t ch2_tx_loop_int_clr: 1; /** ch3_tx_loop_int_clr : WT; bitpos: [15]; default: 0; * Set this bit to clear theCH3_TX_LOOP_INT interrupt. */ - uint32_t ch3_tx_loop_int_clr:1; + uint32_t ch3_tx_loop_int_clr: 1; /** ch4_rx_end_int_clr : WT; bitpos: [16]; default: 0; * Set this bit to clear theCH4_RX_END_INT interrupt. */ - uint32_t ch4_rx_end_int_clr:1; + uint32_t ch4_rx_end_int_clr: 1; /** ch5_rx_end_int_clr : WT; bitpos: [17]; default: 0; * Set this bit to clear theCH5_RX_END_INT interrupt. */ - uint32_t ch5_rx_end_int_clr:1; + uint32_t ch5_rx_end_int_clr: 1; /** ch6_rx_end_int_clr : WT; bitpos: [18]; default: 0; * Set this bit to clear theCH6_RX_END_INT interrupt. */ - uint32_t ch6_rx_end_int_clr:1; + uint32_t ch6_rx_end_int_clr: 1; /** ch7_rx_end_int_clr : WT; bitpos: [19]; default: 0; * Set this bit to clear theCH7_RX_END_INT interrupt. */ - uint32_t ch7_rx_end_int_clr:1; + uint32_t ch7_rx_end_int_clr: 1; /** ch4_err_int_clr : WT; bitpos: [20]; default: 0; * Set this bit to clear theCH4_ERR_INT interrupt. */ - uint32_t ch4_err_int_clr:1; + uint32_t ch4_err_int_clr: 1; /** ch5_err_int_clr : WT; bitpos: [21]; default: 0; * Set this bit to clear theCH5_ERR_INT interrupt. */ - uint32_t ch5_err_int_clr:1; + uint32_t ch5_err_int_clr: 1; /** ch6_err_int_clr : WT; bitpos: [22]; default: 0; * Set this bit to clear theCH6_ERR_INT interrupt. */ - uint32_t ch6_err_int_clr:1; + uint32_t ch6_err_int_clr: 1; /** ch7_err_int_clr : WT; bitpos: [23]; default: 0; * Set this bit to clear theCH7_ERR_INT interrupt. */ - uint32_t ch7_err_int_clr:1; + uint32_t ch7_err_int_clr: 1; /** ch4_rx_thr_event_int_clr : WT; bitpos: [24]; default: 0; * Set this bit to clear theCH4_RX_THR_EVENT_INT interrupt. */ - uint32_t ch4_rx_thr_event_int_clr:1; + uint32_t ch4_rx_thr_event_int_clr: 1; /** ch5_rx_thr_event_int_clr : WT; bitpos: [25]; default: 0; * Set this bit to clear theCH5_RX_THR_EVENT_INT interrupt. */ - uint32_t ch5_rx_thr_event_int_clr:1; + uint32_t ch5_rx_thr_event_int_clr: 1; /** ch6_rx_thr_event_int_clr : WT; bitpos: [26]; default: 0; * Set this bit to clear theCH6_RX_THR_EVENT_INT interrupt. */ - uint32_t ch6_rx_thr_event_int_clr:1; + uint32_t ch6_rx_thr_event_int_clr: 1; /** ch7_rx_thr_event_int_clr : WT; bitpos: [27]; default: 0; * Set this bit to clear theCH7_RX_THR_EVENT_INT interrupt. */ - uint32_t ch7_rx_thr_event_int_clr:1; + uint32_t ch7_rx_thr_event_int_clr: 1; /** ch3_dma_access_fail_int_clr : WT; bitpos: [28]; default: 0; * Set this bit to clear the CH3_DMA_ACCESS_FAIL_INT interrupt. */ - uint32_t ch3_dma_access_fail_int_clr:1; + uint32_t ch3_dma_access_fail_int_clr: 1; /** ch7_dma_access_fail_int_clr : WT; bitpos: [29]; default: 0; * Set this bit to clear the CH7_DMA_ACCESS_FAIL_INT interrupt. */ - uint32_t ch7_dma_access_fail_int_clr:1; - uint32_t reserved_30:2; + uint32_t ch7_dma_access_fail_int_clr: 1; + uint32_t reserved_30: 2; }; uint32_t val; } rmt_int_clr_reg_t; - /** Group: Carrier wave duty cycle registers */ /** Type of chncarrier_duty register * Channel n duty cycle configuration register */ typedef union { struct { - /** carrier_low_ch0 : R/W; bitpos: [15:0]; default: 64; + /** carrier_low_chn : R/W; bitpos: [15:0]; default: 64; * This register is used to configure carrier wave 's low level clock period for * CHANNELn. */ - uint32_t carrier_low_ch0:16; - /** carrier_high_ch0 : R/W; bitpos: [31:16]; default: 64; + uint32_t carrier_low_chn: 16; + /** carrier_high_chn : R/W; bitpos: [31:16]; default: 64; * This register is used to configure carrier wave 's high level clock period for * CHANNELn. */ - uint32_t carrier_high_ch0:16; + uint32_t carrier_high_chn: 16; }; uint32_t val; } rmt_chncarrier_duty_reg_t; - /** Group: Tx event configuration registers */ /** Type of chn_tx_lim register * Channel n Tx event configuration register */ typedef union { struct { - /** tx_lim_ch0 : R/W; bitpos: [8:0]; default: 128; + /** tx_lim_chn : R/W; bitpos: [8:0]; default: 128; * This register is used to configure the maximum entries that CHANNELn can send out. */ - uint32_t tx_lim_ch0:9; - /** tx_loop_num_ch0 : R/W; bitpos: [18:9]; default: 0; + uint32_t tx_lim_chn: 9; + /** tx_loop_num_chn : R/W; bitpos: [18:9]; default: 0; * This register is used to configure the maximum loop count when tx_conti_mode is * valid. */ - uint32_t tx_loop_num_ch0:10; - /** tx_loop_cnt_en_ch0 : R/W; bitpos: [19]; default: 0; + uint32_t tx_loop_num_chn: 10; + /** tx_loop_cnt_en_chn : R/W; bitpos: [19]; default: 0; * This register is the enabled bit for loop count. */ - uint32_t tx_loop_cnt_en_ch0:1; - /** loop_count_reset_ch0 : WT; bitpos: [20]; default: 0; + uint32_t tx_loop_cnt_en_chn: 1; + /** loop_count_reset_chn : WT; bitpos: [20]; default: 0; * This register is used to reset the loop count when tx_conti_mode is valid. */ - uint32_t loop_count_reset_ch0:1; - /** loop_stop_en_ch0 : R/W; bitpos: [21]; default: 0; + uint32_t loop_count_reset_chn: 1; + /** loop_stop_en_chn : R/W; bitpos: [21]; default: 0; * This bit is used to enable the loop send stop function after the loop counter * counts to loop number for CHANNELn. */ - uint32_t loop_stop_en_ch0:1; - uint32_t reserved_22:10; + uint32_t loop_stop_en_chn: 1; + uint32_t reserved_22: 10; }; uint32_t val; } rmt_chn_tx_lim_reg_t; @@ -979,49 +991,47 @@ typedef union { * Set this bit to enable CHANNEL0 to start sending data synchronously with other * enabled channels. */ - uint32_t tx_sim_ch0:1; + uint32_t tx_sim_ch0: 1; /** tx_sim_ch1 : R/W; bitpos: [1]; default: 0; * Set this bit to enable CHANNEL1 to start sending data synchronously with other * enabled channels. */ - uint32_t tx_sim_ch1:1; + uint32_t tx_sim_ch1: 1; /** tx_sim_ch2 : R/W; bitpos: [2]; default: 0; * Set this bit to enable CHANNEL2 to start sending data synchronously with other * enabled channels. */ - uint32_t tx_sim_ch2:1; + uint32_t tx_sim_ch2: 1; /** tx_sim_ch3 : R/W; bitpos: [3]; default: 0; * Set this bit to enable CHANNEL3 to start sending data synchronously with other * enabled channels. */ - uint32_t tx_sim_ch3:1; + uint32_t tx_sim_ch3: 1; /** tx_sim_en : R/W; bitpos: [4]; default: 0; * This register is used to enable multiple of channels to start sending data * synchronously. */ - uint32_t tx_sim_en:1; - uint32_t reserved_5:27; + uint32_t tx_sim_en: 1; + uint32_t reserved_5: 27; }; uint32_t val; } rmt_tx_sim_reg_t; - /** Group: Rx event configuration registers */ /** Type of chm_rx_lim register * Channel m Rx event configuration register */ typedef union { struct { - /** rx_lim_ch4 : R/W; bitpos: [8:0]; default: 128; + /** rx_lim_chm : R/W; bitpos: [8:0]; default: 128; * This register is used to configure the maximum entries that CHANNELm can receive. */ - uint32_t rx_lim_ch4:9; - uint32_t reserved_9:23; + uint32_t rx_lim_chm: 9; + uint32_t reserved_9: 23; }; uint32_t val; } rmt_chm_rx_lim_reg_t; - /** Group: Version register */ /** Type of date register * RMT version register @@ -1031,25 +1041,20 @@ typedef union { /** date : R/W; bitpos: [27:0]; default: 35655953; * This is the version register. */ - uint32_t date:28; - uint32_t reserved_28:4; + uint32_t date: 28; + uint32_t reserved_28: 4; }; uint32_t val; } rmt_date_reg_t; - -typedef struct { +typedef struct rmt_dev_t { volatile rmt_chndata_reg_t chndata[4]; volatile rmt_chmdata_reg_t chmdata[4]; volatile rmt_chnconf0_reg_t chnconf0[4]; - volatile rmt_chmconf0_reg_t ch4conf0; - volatile rmt_chmconf1_reg_t ch4conf1; - volatile rmt_chmconf0_reg_t ch5conf0; - volatile rmt_chmconf1_reg_t ch5conf1; - volatile rmt_chmconf0_reg_t ch6conf0; - volatile rmt_chmconf1_reg_t ch6conf1; - volatile rmt_chmconf0_reg_t ch7conf0; - volatile rmt_chmconf1_reg_t ch7conf1; + volatile struct { + rmt_chmconf0_reg_t conf0; + rmt_chmconf1_reg_t conf1; + } chmconf[4]; volatile rmt_chnstatus_reg_t chnstatus[4]; volatile rmt_chmstatus_reg_t chmstatus[4]; volatile rmt_int_raw_reg_t int_raw; @@ -1066,6 +1071,7 @@ typedef struct { volatile rmt_date_reg_t date; } rmt_dev_t; +extern rmt_dev_t RMT; #ifndef __cplusplus _Static_assert(sizeof(rmt_dev_t) == 0xd0, "Invalid size of rmt_dev_t structure"); diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 8c2ef769b8..aba4e39aa3 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -49,7 +49,7 @@ #define SOC_RTC_FAST_MEM_SUPPORTED 1 #define SOC_RTC_MEM_SUPPORTED 1 // #define SOC_I2S_SUPPORTED 1 //TODO: IDF-6508 -// #define SOC_RMT_SUPPORTED 1 //TODO: IDF-7476 +#define SOC_RMT_SUPPORTED 1 // #define SOC_SDM_SUPPORTED 1 //TODO: IDF-7551 // #define SOC_GPSPI_SUPPORTED 1 //TODO: IDF-7502, TODO: IDF-7503 // #define SOC_LEDC_SUPPORTED 1 //TODO: IDF-6510 @@ -271,19 +271,20 @@ /*--------------------------- RMT CAPS ---------------------------------------*/ #define SOC_RMT_GROUPS 1U /*!< One RMT group */ -#define SOC_RMT_TX_CANDIDATES_PER_GROUP 2 /*!< Number of channels that capable of Transmit */ -#define SOC_RMT_RX_CANDIDATES_PER_GROUP 2 /*!< Number of channels that capable of Receive */ -#define SOC_RMT_CHANNELS_PER_GROUP 4 /*!< Total 4 channels */ +#define SOC_RMT_TX_CANDIDATES_PER_GROUP 4 /*!< Number of channels that capable of Transmit in each group */ +#define SOC_RMT_RX_CANDIDATES_PER_GROUP 4 /*!< Number of channels that capable of Receive in each group */ +#define SOC_RMT_CHANNELS_PER_GROUP 8 /*!< Total 8 channels */ #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_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 */ //TODO: IDF-7476 +#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 */ #define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ -#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */ +// #define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST clock as the RMT clock source */ +#define SOC_RMT_SUPPORT_DMA 1 /*!< RMT peripheral can connect to DMA channel */ /*-------------------------- MCPWM CAPS --------------------------------------*/ #define SOC_MCPWM_GROUPS (2U) ///< 2 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals) diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index 4d395a30b6..4085a915e4 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -17,8 +17,8 @@ PROVIDE ( SPIMEM3 = 0x5008F000 ); PROVIDE ( I2C0 = 0x500C4000 ); PROVIDE ( I2C1 = 0x500C5000 ); PROVIDE ( UHCI0 = 0x500DF000 ); -PROVIDE ( RMT = 0x500D4000 ); -PROVIDE ( RMTMEM = 0x500D4800 ); +PROVIDE ( RMT = 0x500A2000 ); +PROVIDE ( RMTMEM = 0x500A2800 ); PROVIDE ( LEDC = 0x500D3000 ); PROVIDE ( TIMERG0 = 0x500C2000 ); PROVIDE ( TIMERG1 = 0x500C3000 ); diff --git a/components/soc/esp32p4/rmt_periph.c b/components/soc/esp32p4/rmt_periph.c index 650b4ddcf1..74d73690c9 100644 --- a/components/soc/esp32p4/rmt_periph.c +++ b/components/soc/esp32p4/rmt_periph.c @@ -8,5 +8,44 @@ #include "soc/gpio_sig_map.h" const rmt_signal_conn_t rmt_periph_signals = { - + .groups = { + [0] = { + .module = PERIPH_RMT_MODULE, + .irq = ETS_RMT_INTR_SOURCE, + .channels = { + [0] = { + .tx_sig = RMT_SIG_PAD_OUT0_IDX, + .rx_sig = -1 + }, + [1] = { + .tx_sig = RMT_SIG_PAD_OUT1_IDX, + .rx_sig = -1 + }, + [2] = { + .tx_sig = RMT_SIG_PAD_OUT2_IDX, + .rx_sig = -1 + }, + [3] = { + .tx_sig = RMT_SIG_PAD_OUT3_IDX, + .rx_sig = -1 + }, + [4] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_PAD_IN0_IDX + }, + [5] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_PAD_IN1_IDX + }, + [6] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_PAD_IN2_IDX + }, + [7] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_PAD_IN3_IDX + } + } + } + } }; diff --git a/docs/docs_not_updated/esp32p4.txt b/docs/docs_not_updated/esp32p4.txt index 16372cc25e..d5ceea9dbc 100644 --- a/docs/docs_not_updated/esp32p4.txt +++ b/docs/docs_not_updated/esp32p4.txt @@ -141,7 +141,6 @@ api-reference/peripherals/spi_master.rst api-reference/peripherals/index.rst api-reference/peripherals/sdmmc_host.rst api-reference/peripherals/uart.rst -api-reference/peripherals/rmt.rst api-reference/kconfig.rst api-reference/network/esp_openthread.rst api-reference/network/esp_eth.rst diff --git a/examples/peripherals/rmt/dshot_esc/README.md b/examples/peripherals/rmt/dshot_esc/README.md index defe814636..01d634c3d5 100644 --- a/examples/peripherals/rmt/dshot_esc/README.md +++ b/examples/peripherals/rmt/dshot_esc/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # RMT Infinite Loop Transmit Example -- Dshot ESC (Electronic Speed Controller) (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/peripherals/rmt/ir_nec_transceiver/README.md b/examples/peripherals/rmt/ir_nec_transceiver/README.md index 6f21c50abe..fee7164d27 100644 --- a/examples/peripherals/rmt/ir_nec_transceiver/README.md +++ b/examples/peripherals/rmt/ir_nec_transceiver/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # IR NEC Encoding and Decoding Example (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/peripherals/rmt/led_strip/README.md b/examples/peripherals/rmt/led_strip/README.md index 774838a81b..23e42f040d 100644 --- a/examples/peripherals/rmt/led_strip/README.md +++ b/examples/peripherals/rmt/led_strip/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # RMT Transmit Example -- LED Strip (See the README.md file in the upper level 'examples' directory for more information about examples.) diff --git a/examples/peripherals/rmt/musical_buzzer/README.md b/examples/peripherals/rmt/musical_buzzer/README.md index 7b16fd241d..a458a070b6 100644 --- a/examples/peripherals/rmt/musical_buzzer/README.md +++ b/examples/peripherals/rmt/musical_buzzer/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | # RMT Transmit Loop Count Example -- Musical Buzzer diff --git a/examples/peripherals/rmt/onewire/README.md b/examples/peripherals/rmt/onewire/README.md index f218e4689b..1cb065eafa 100644 --- a/examples/peripherals/rmt/onewire/README.md +++ b/examples/peripherals/rmt/onewire/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus diff --git a/examples/peripherals/rmt/stepper_motor/README.md b/examples/peripherals/rmt/stepper_motor/README.md index 772a888393..b1048c08cd 100644 --- a/examples/peripherals/rmt/stepper_motor/README.md +++ b/examples/peripherals/rmt/stepper_motor/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | # RMT Based Stepper Motor Smooth Controller