From ff976867b3040d0acf7bfcb0878f5e0f7fcc3913 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 9 Oct 2020 16:41:41 +0800 Subject: [PATCH] rmt: split TX and RX in LL driver Split TX and RX function in LL driver. Channel number is encoded in driver layer. Added channel signal list in periph.c --- components/driver/include/driver/rmt.h | 63 ++- components/driver/rmt.c | 449 +++++++++++------- components/driver/test/test_rmt.c | 51 +- components/hal/esp32/include/hal/rmt_ll.h | 289 ++++++----- components/hal/esp32s2/include/hal/rmt_ll.h | 379 +++++++++------ components/hal/esp32s3/include/hal/rmt_ll.h | 439 +++++++++-------- components/hal/include/hal/rmt_hal.h | 47 +- components/hal/include/hal/rmt_types.h | 7 +- components/hal/rmt_hal.c | 57 +-- components/soc/esp32/CMakeLists.txt | 3 +- components/soc/esp32/include/soc/soc_caps.h | 9 +- components/soc/esp32/rmt_periph.c | 56 +++ components/soc/esp32s2/CMakeLists.txt | 1 + components/soc/esp32s2/include/soc/soc_caps.h | 17 +- components/soc/esp32s2/rmt_periph.c | 39 ++ components/soc/esp32s3/CMakeLists.txt | 1 + components/soc/esp32s3/include/soc/rmt_caps.h | 33 -- components/soc/esp32s3/include/soc/soc_caps.h | 18 +- components/soc/esp32s3/rmt_periph.c | 55 +++ components/soc/include/soc/rmt_periph.h | 28 +- .../components/test_utils/ref_clock.c | 30 +- 21 files changed, 1208 insertions(+), 863 deletions(-) create mode 100644 components/soc/esp32/rmt_periph.c create mode 100644 components/soc/esp32s2/rmt_periph.c delete mode 100644 components/soc/esp32s3/include/soc/rmt_caps.h create mode 100644 components/soc/esp32s3/rmt_periph.c diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index 4764a976e5..ef7f0f2323 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -28,7 +28,7 @@ extern "C" { #include "soc/rmt_struct.h" #include "hal/rmt_types.h" -#define RMT_CHANNEL_FLAGS_ALWAYS_ON (1 << 0) /*!< Channel can work when APB frequency is changing (RMT channel adopts REF_TICK as clock source) */ +#define RMT_CHANNEL_FLAGS_ALWAYS_ON (1 << 0) /*!< Channel can work during APB clock scaling */ /** * @brief Define memory space of each RMT channel (in words = 4 bytes) @@ -357,7 +357,7 @@ esp_err_t rmt_rx_start(rmt_channel_t channel, bool rx_idx_rst); esp_err_t rmt_rx_stop(rmt_channel_t channel); /** -* @brief Reset RMT TX/RX memory index. +* @brief Reset RMT TX memory * * @param channel RMT channel * @@ -365,7 +365,18 @@ esp_err_t rmt_rx_stop(rmt_channel_t channel); * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success */ -esp_err_t rmt_memory_rw_rst(rmt_channel_t channel); +esp_err_t rmt_tx_memory_reset(rmt_channel_t channel); + +/** +* @brief Reset RMT RX memory +* +* @param channel RMT channel +* +* @return +* - ESP_ERR_INVALID_ARG Parameter error +* - ESP_OK Success +*/ +esp_err_t rmt_rx_memory_reset(rmt_channel_t channel); /** * @brief Set RMT memory owner. @@ -504,22 +515,6 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool *idle_out_en, rmt_idle_ */ esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t *status); -/** -* @brief Set mask value to RMT interrupt enable register. -* -* @param mask Bit mask to set to the register -* -*/ -void rmt_set_intr_enable_mask(uint32_t mask); - -/** -* @brief Clear mask value to RMT interrupt enable register. -* -* @param mask Bit mask to clear the register -* -*/ -void rmt_clr_intr_enable_mask(uint32_t mask); - /** * @brief Set RMT RX interrupt enable * @@ -833,6 +828,36 @@ esp_err_t rmt_add_channel_to_group(rmt_channel_t channel); esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel); #endif +/** +* @brief Reset RMT TX/RX memory index. +* +* @param channel RMT channel +* +* @return +* - ESP_ERR_INVALID_ARG Parameter error +* - ESP_OK Success +*/ +esp_err_t rmt_memory_rw_rst(rmt_channel_t channel) +__attribute__((deprecated("use rmt_tx_memory_reset or rmt_rx_memory_reset instead"))); + +/** +* @brief Set mask value to RMT interrupt enable register. +* +* @param mask Bit mask to set to the register +* +*/ +void rmt_set_intr_enable_mask(uint32_t mask) +__attribute__((deprecated("interrupt should be handled by driver"))); + +/** +* @brief Clear mask value to RMT interrupt enable register. +* +* @param mask Bit mask to clear the register +* +*/ +void rmt_clr_intr_enable_mask(uint32_t mask) +__attribute__((deprecated("interrupt should be handled by driver"))); + #ifdef __cplusplus } #endif diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 7410b72fda..08f921bc59 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -14,6 +14,7 @@ #include #include #include +#include "esp_compiler.h" #include "esp_intr_alloc.h" #include "esp_log.h" #include "driver/gpio.h" @@ -24,6 +25,7 @@ #include "freertos/semphr.h" #include "freertos/ringbuf.h" #include "soc/soc_memory_layout.h" +#include "soc/rmt_periph.h" #include "soc/rtc.h" #include "hal/rmt_hal.h" #include "hal/rmt_ll.h" @@ -47,17 +49,24 @@ #define RMT_PARAM_ERR_STR "RMT param error" static const char *RMT_TAG = "rmt"; -#define RMT_CHECK(a, str, ret_val) \ - if (!(a)) \ - { \ - ESP_LOGE(RMT_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ +#define RMT_CHECK(a, str, ret_val, ...) \ + if (unlikely(!(a))) { \ + ESP_LOGE(RMT_TAG, "%s(%d): "str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return (ret_val); \ } // Spinlock for protecting concurrent register-level access only #define RMT_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock)) #define RMT_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock)) +#define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_NUM-SOC_RMT_TX_CHANNELS_NUM) +#define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1) + +#define RMT_IS_RX_CHANNEL(channel) ((channel) >= RMT_RX_CHANNEL_ENCODING_START) +#define RMT_IS_TX_CHANNEL(channel) ((channel) <= RMT_TX_CHANNEL_ENCODING_END) +#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)) + typedef struct { rmt_hal_context_t hal; _lock_t rmt_driver_isr_lock; @@ -108,13 +117,19 @@ static rmt_contex_t rmt_contex = { static rmt_obj_t *p_rmt_obj[RMT_CHANNEL_MAX] = {0}; +#if SOC_RMT_SOURCE_CLK_INDEPENDENT +static uint32_t s_rmt_source_clock_hz[RMT_CHANNEL_MAX]; +#else +static uint32_t s_rmt_source_clock_hz; +#endif + //Enable RMT module static void rmt_module_enable(void) { RMT_ENTER_CRITICAL(); if (rmt_contex.rmt_module_enabled == false) { - periph_module_reset(PERIPH_RMT_MODULE); - periph_module_enable(PERIPH_RMT_MODULE); + periph_module_reset(rmt_periph_signals.module); + periph_module_enable(rmt_periph_signals.module); rmt_contex.rmt_module_enabled = true; } RMT_EXIT_CRITICAL(); @@ -125,7 +140,7 @@ static void rmt_module_disable(void) { RMT_ENTER_CRITICAL(); if (rmt_contex.rmt_module_enabled == true) { - periph_module_disable(PERIPH_RMT_MODULE); + periph_module_disable(rmt_periph_signals.module); rmt_contex.rmt_module_enabled = false; } RMT_EXIT_CRITICAL(); @@ -135,7 +150,11 @@ esp_err_t rmt_set_clk_div(rmt_channel_t channel, uint8_t div_cnt) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_counter_clock_div(rmt_contex.hal.regs, channel, div_cnt); + if (RMT_IS_RX_CHANNEL(channel)) { + rmt_ll_rx_set_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), div_cnt); + } else { + rmt_ll_tx_set_counter_clock_div(rmt_contex.hal.regs, channel, div_cnt); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -145,26 +164,30 @@ esp_err_t rmt_get_clk_div(rmt_channel_t channel, uint8_t *div_cnt) RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(div_cnt != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - *div_cnt = (uint8_t)rmt_ll_get_counter_clock_div(rmt_contex.hal.regs, channel); + if (RMT_IS_RX_CHANNEL(channel)) { + *div_cnt = (uint8_t)rmt_ll_rx_get_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + } else { + *div_cnt = (uint8_t)rmt_ll_tx_get_counter_clock_div(rmt_contex.hal.regs, channel); + } RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_set_rx_idle_thresh(rmt_channel_t channel, uint16_t thresh) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_rx_idle_thres(rmt_contex.hal.regs, channel, thresh); + rmt_ll_rx_set_idle_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), thresh); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_get_rx_idle_thresh(rmt_channel_t channel, uint16_t *thresh) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(thresh != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - *thresh = (uint16_t)rmt_ll_get_rx_idle_thres(rmt_contex.hal.regs, channel); + *thresh = (uint16_t)rmt_ll_rx_get_idle_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -174,7 +197,11 @@ esp_err_t rmt_set_mem_block_num(rmt_channel_t channel, uint8_t rmt_mem_num) RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(rmt_mem_num <= RMT_CHANNEL_MAX - channel, RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_mem_blocks(rmt_contex.hal.regs, channel, rmt_mem_num); + if (RMT_IS_RX_CHANNEL(channel)) { + rmt_ll_rx_set_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), rmt_mem_num); + } else { + rmt_ll_tx_set_mem_blocks(rmt_contex.hal.regs, channel, rmt_mem_num); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -184,7 +211,11 @@ esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t *rmt_mem_num) RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(rmt_mem_num != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - *rmt_mem_num = (uint8_t)rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel); + if (RMT_IS_RX_CHANNEL(channel)) { + *rmt_mem_num = (uint8_t)rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + } else { + *rmt_mem_num = (uint8_t)rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -192,12 +223,12 @@ esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t *rmt_mem_num) esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t high_level, uint16_t low_level, rmt_carrier_level_t carrier_level) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(carrier_level < RMT_CARRIER_LEVEL_MAX, RMT_CARRIER_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_tx_carrier_high_low_ticks(rmt_contex.hal.regs, channel, high_level, low_level); - rmt_ll_set_carrier_on_level(rmt_contex.hal.regs, channel, carrier_level); - rmt_ll_enable_carrier(rmt_contex.hal.regs, channel, carrier_en); + rmt_ll_tx_set_carrier_high_low_ticks(rmt_contex.hal.regs, channel, high_level, low_level); + rmt_ll_tx_set_carrier_level(rmt_contex.hal.regs, channel, carrier_level); + rmt_ll_tx_enable_carrier_modulation(rmt_contex.hal.regs, channel, carrier_en); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -222,10 +253,10 @@ esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool *pd_en) esp_err_t rmt_tx_start(rmt_channel_t channel, bool tx_idx_rst) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); if (tx_idx_rst) { - rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); } rmt_ll_clear_tx_end_interrupt(rmt_contex.hal.regs, channel); // enable tx end interrupt in non-loop mode @@ -233,106 +264,114 @@ esp_err_t rmt_tx_start(rmt_channel_t channel, bool tx_idx_rst) rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, true); } else { #if SOC_RMT_SUPPORT_TX_LOOP_COUNT - rmt_ll_reset_tx_loop(rmt_contex.hal.regs, channel); - rmt_ll_enable_tx_loop_count(rmt_contex.hal.regs, channel, true); + rmt_ll_tx_reset_loop(rmt_contex.hal.regs, channel); + rmt_ll_tx_enable_loop_count(rmt_contex.hal.regs, channel, true); rmt_ll_clear_tx_loop_interrupt(rmt_contex.hal.regs, channel); rmt_ll_enable_tx_loop_interrupt(rmt_contex.hal.regs, channel, true); #endif } - rmt_ll_start_tx(rmt_contex.hal.regs, channel); + rmt_ll_tx_start(rmt_contex.hal.regs, channel); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_tx_stop(rmt_channel_t channel) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_stop_tx(rmt_contex.hal.regs, channel); - rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_tx_stop(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_rx_start(rmt_channel_t channel, bool rx_idx_rst) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false); + rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false); if (rx_idx_rst) { - rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); } - rmt_ll_clear_rx_end_interrupt(rmt_contex.hal.regs, channel); - rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, true); + rmt_ll_clear_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true); #if SOC_RMT_SUPPORT_RX_PINGPONG - const uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; + const uint32_t item_block_len = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)) * RMT_MEM_ITEM_NUM; p_rmt_obj[channel]->rx_item_start_idx = 0; p_rmt_obj[channel]->rx_item_len = 0; rmt_set_rx_thr_intr_en(channel, true, item_block_len / 2); #endif - rmt_ll_enable_rx(rmt_contex.hal.regs, channel, true); + rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_rx_stop(rmt_channel_t channel) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, false); - rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false); - rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false); + rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false); + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); #if SOC_RMT_SUPPORT_RX_PINGPONG - rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, false); + rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false); #endif RMT_EXIT_CRITICAL(); return ESP_OK; } -esp_err_t rmt_memory_rw_rst(rmt_channel_t channel) +esp_err_t rmt_tx_memory_reset(rmt_channel_t channel) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel); - rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); + RMT_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t rmt_rx_memory_reset(rmt_channel_t channel) +{ + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_ENTER_CRITICAL(); + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_set_memory_owner(rmt_channel_t channel, rmt_mem_owner_t owner) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(owner < RMT_MEM_OWNER_MAX, RMT_MEM_OWNER_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, owner); + rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), owner); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_get_memory_owner(rmt_channel_t channel, rmt_mem_owner_t *owner) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(owner != NULL, RMT_MEM_OWNER_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - *owner = (rmt_mem_owner_t)rmt_ll_get_mem_owner(rmt_contex.hal.regs, channel); + *owner = (rmt_mem_owner_t)rmt_ll_rx_get_mem_owner(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_set_tx_loop_mode(rmt_channel_t channel, bool loop_en) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_tx_loop(rmt_contex.hal.regs, channel, loop_en); + rmt_ll_tx_enable_loop(rmt_contex.hal.regs, channel, loop_en); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool *loop_en) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); *loop_en = rmt_ll_is_tx_loop_enabled(rmt_contex.hal.regs, channel); RMT_EXIT_CRITICAL(); @@ -341,10 +380,10 @@ esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool *loop_en) esp_err_t rmt_set_rx_filter(rmt_channel_t channel, bool rx_filter_en, uint8_t thresh) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_rx_filter(rmt_contex.hal.regs, channel, rx_filter_en); - rmt_ll_set_rx_filter_thres(rmt_contex.hal.regs, channel, thresh); + rmt_ll_rx_enable_filter(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), rx_filter_en); + rmt_ll_rx_set_filter_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), thresh); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -354,7 +393,7 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk) RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(base_clk < RMT_BASECLK_MAX, RMT_BASECLK_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_counter_clock_src(rmt_contex.hal.regs, channel, base_clk); + rmt_ll_set_counter_clock_src(rmt_contex.hal.regs, channel, base_clk, 0, 0, 0); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -373,8 +412,8 @@ esp_err_t rmt_set_idle_level(rmt_channel_t channel, bool idle_out_en, rmt_idle_l RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(level < RMT_IDLE_LEVEL_MAX, "RMT IDLE LEVEL ERR", ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_tx_idle(rmt_contex.hal.regs, channel, idle_out_en); - rmt_ll_set_tx_idle_level(rmt_contex.hal.regs, channel, level); + rmt_ll_tx_enable_idle(rmt_contex.hal.regs, channel, idle_out_en); + rmt_ll_tx_set_idle_level(rmt_contex.hal.regs, channel, level); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -384,7 +423,7 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool *idle_out_en, rmt_idle_ RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); *idle_out_en = rmt_ll_is_tx_idle_enabled(rmt_contex.hal.regs, channel); - *level = rmt_ll_get_tx_idle_level(rmt_contex.hal.regs, channel); + *level = rmt_ll_tx_get_idle_level(rmt_contex.hal.regs, channel); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -393,7 +432,11 @@ esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t *status) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - *status = rmt_ll_get_channel_status(rmt_contex.hal.regs, channel); + if (RMT_IS_RX_CHANNEL(channel)) { + *status = rmt_ll_rx_get_channel_status(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + } else { + *status = rmt_ll_tx_get_channel_status(rmt_contex.hal.regs, channel); + } RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -414,9 +457,9 @@ void rmt_clr_intr_enable_mask(uint32_t mask) esp_err_t rmt_set_rx_intr_en(rmt_channel_t channel, bool en) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, en); + rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), en); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -424,17 +467,17 @@ esp_err_t rmt_set_rx_intr_en(rmt_channel_t channel, bool en) #if SOC_RMT_SUPPORT_RX_PINGPONG esp_err_t rmt_set_rx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); if (en) { - uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; + uint32_t item_block_len = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)) * RMT_MEM_ITEM_NUM; RMT_CHECK(evt_thresh <= item_block_len, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_rx_limit(rmt_contex.hal.regs, channel, evt_thresh); - rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, true); + rmt_ll_rx_set_limit(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), evt_thresh); + rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true); RMT_EXIT_CRITICAL(); } else { RMT_ENTER_CRITICAL(); - rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, false); + rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false); RMT_EXIT_CRITICAL(); } return ESP_OK; @@ -445,14 +488,18 @@ esp_err_t rmt_set_err_intr_en(rmt_channel_t channel, bool en) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_err_interrupt(rmt_contex.hal.regs, channel, en); + if (RMT_IS_RX_CHANNEL(channel)) { + rmt_ll_enable_rx_err_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), en); + } else { + rmt_ll_enable_tx_err_interrupt(rmt_contex.hal.regs, channel, en); + } RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, en); RMT_EXIT_CRITICAL(); @@ -461,12 +508,12 @@ esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en) esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); if (en) { - uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; + uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; RMT_CHECK(evt_thresh <= item_block_len, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_set_tx_limit(rmt_contex.hal.regs, channel, evt_thresh); + rmt_ll_tx_set_limit(rmt_contex.hal.regs, channel, evt_thresh); rmt_ll_enable_tx_thres_interrupt(rmt_contex.hal.regs, channel, true); RMT_EXIT_CRITICAL(); } else { @@ -487,19 +534,27 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); if (mode == RMT_MODE_TX) { + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(gpio_num, RMT_SIG_OUT0_IDX + channel, 0, 0); + esp_rom_gpio_connect_out_signal(gpio_num, rmt_periph_signals.channels[channel].tx_sig, 0, 0); } else { + RMT_CHECK(RMT_IS_RX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); gpio_set_direction(gpio_num, GPIO_MODE_INPUT); -#if SOC_RMT_TX_RX_CHANNEL_INDEPENDENT - esp_rom_gpio_connect_in_signal(gpio_num, RMT_SIG_IN0_IDX + channel - RMT_LL_TX_CHAN_NUM, 0); -#else - esp_rom_gpio_connect_in_signal(gpio_num, RMT_SIG_IN0_IDX + channel, 0); -#endif + esp_rom_gpio_connect_in_signal(gpio_num, rmt_periph_signals.channels[channel].rx_sig, 0); } return ESP_OK; } +static bool rmt_is_channel_number_valid(rmt_channel_t channel, uint8_t mode) +{ + // RX mode + if (mode == RMT_MODE_RX) { + return RMT_IS_RX_CHANNEL(channel) && (channel < RMT_CHANNEL_MAX); + } + // TX mode + return (channel >= 0) && RMT_IS_TX_CHANNEL(channel); +} + static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_param) { uint8_t mode = rmt_param->rmt_mode; @@ -511,7 +566,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par bool carrier_en = rmt_param->tx_config.carrier_en; uint32_t rmt_source_clk_hz; - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(rmt_is_channel_number_valid(channel, mode), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK((mem_cnt + channel <= 8 && mem_cnt > 0), RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK((clk_div > 0), RMT_CLK_DIV_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -520,59 +575,67 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par } RMT_ENTER_CRITICAL(); - rmt_ll_set_counter_clock_div(dev, channel, clk_div); rmt_ll_enable_mem_access(dev, true); - rmt_ll_reset_tx_pointer(dev, channel); - rmt_ll_reset_rx_pointer(dev, channel); + if (rmt_param->flags & RMT_CHANNEL_FLAGS_ALWAYS_ON) { -#ifdef SOC_RMT_SUPPORT_REF_TICK - // clock src: REF_CLK - rmt_source_clk_hz = REF_CLK_FREQ; - rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_REF); -#elif defined SOC_RMT_SUPPORT_XTAL_CLOCK +#if SOC_RMT_SUPPORT_XTAL // clock src: XTAL_CLK rmt_source_clk_hz = rtc_clk_xtal_freq_get() * 1000000; - rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_XTAL); + rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_XTAL, 0, 0, 0); +#elif SOC_RMT_SUPPORT_REF_TICK + // clock src: REF_CLK + rmt_source_clk_hz = REF_CLK_FREQ; + rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_REF, 0, 0, 0); #endif } else { // clock src: APB_CLK rmt_source_clk_hz = APB_CLK_FREQ; - rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_APB); + rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_APB, 0, 0, 0); } - esp_rom_printf("rmt_source_clk_hz: %d\n", rmt_source_clk_hz); - rmt_ll_set_mem_blocks(dev, channel, mem_cnt); - rmt_ll_set_mem_owner(dev, channel, RMT_MEM_OWNER_HW); RMT_EXIT_CRITICAL(); +#if SOC_RMT_SOURCE_CLK_INDEPENDENT + s_rmt_source_clock_hz[channel] = rmt_source_clk_hz; +#else + if (s_rmt_source_clock_hz && rmt_source_clk_hz != s_rmt_source_clock_hz) { + ESP_LOGW(RMT_TAG, "RMT clock source has been configured to %d by other channel, now reconfigure it to %d", s_rmt_source_clock_hz, rmt_source_clk_hz); + } + s_rmt_source_clock_hz = rmt_source_clk_hz; +#endif + ESP_LOGD(RMT_TAG, "rmt_source_clk_hz: %d\n", rmt_source_clk_hz); + if (mode == RMT_MODE_TX) { uint16_t carrier_duty_percent = rmt_param->tx_config.carrier_duty_percent; uint8_t carrier_level = rmt_param->tx_config.carrier_level; uint8_t idle_level = rmt_param->tx_config.idle_level; RMT_ENTER_CRITICAL(); - rmt_ll_enable_tx_loop(dev, channel, rmt_param->tx_config.loop_en); + rmt_ll_tx_set_counter_clock_div(dev, channel, clk_div); + rmt_ll_tx_set_mem_blocks(dev, channel, mem_cnt); + rmt_ll_tx_reset_pointer(dev, channel); + rmt_ll_tx_enable_loop(dev, channel, rmt_param->tx_config.loop_en); #if SOC_RMT_SUPPORT_TX_LOOP_COUNT if (rmt_param->tx_config.loop_en) { - rmt_ll_set_tx_loop_count(dev, channel, rmt_param->tx_config.loop_count); + rmt_ll_tx_set_loop_count(dev, channel, rmt_param->tx_config.loop_count); } #endif /* always enable tx ping-pong */ - rmt_ll_enable_tx_pingpong(dev, channel, true); + rmt_ll_tx_enable_pingpong(dev, channel, true); /*Set idle level */ - rmt_ll_enable_tx_idle(dev, channel, rmt_param->tx_config.idle_output_en); - rmt_ll_set_tx_idle_level(dev, channel, idle_level); + rmt_ll_tx_enable_idle(dev, channel, rmt_param->tx_config.idle_output_en); + rmt_ll_tx_set_idle_level(dev, channel, idle_level); /*Set carrier*/ - rmt_ll_enable_carrier(dev, channel, carrier_en); + rmt_ll_tx_enable_carrier_modulation(dev, channel, carrier_en); if (carrier_en) { uint32_t duty_div, duty_h, duty_l; duty_div = rmt_source_clk_hz / carrier_freq_hz; duty_h = duty_div * carrier_duty_percent / 100; duty_l = duty_div - duty_h; - rmt_ll_set_carrier_on_level(dev, channel, carrier_level); - rmt_ll_set_tx_carrier_high_low_ticks(dev, channel, duty_h, duty_l); + rmt_ll_tx_set_carrier_level(dev, channel, carrier_level); + rmt_ll_tx_set_carrier_high_low_ticks(dev, channel, duty_h, duty_l); } else { - rmt_ll_set_carrier_on_level(dev, channel, 0); - rmt_ll_set_tx_carrier_high_low_ticks(dev, channel, 0, 0); + rmt_ll_tx_set_carrier_level(dev, channel, 0); + rmt_ll_tx_set_carrier_high_low_ticks(dev, channel, 0, 0); } RMT_EXIT_CRITICAL(); @@ -583,25 +646,29 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par uint16_t threshold = rmt_param->rx_config.idle_threshold; RMT_ENTER_CRITICAL(); + rmt_ll_rx_set_counter_clock_div(dev, RMT_DECODE_RX_CHANNEL(channel), clk_div); + rmt_ll_rx_set_mem_blocks(dev, RMT_DECODE_RX_CHANNEL(channel), mem_cnt); + rmt_ll_rx_reset_pointer(dev, RMT_DECODE_RX_CHANNEL(channel)); + rmt_ll_rx_set_mem_owner(dev, RMT_DECODE_RX_CHANNEL(channel), RMT_MEM_OWNER_HW); /*Set idle threshold*/ - rmt_ll_set_rx_idle_thres(dev, channel, threshold); + rmt_ll_rx_set_idle_thres(dev, RMT_DECODE_RX_CHANNEL(channel), threshold); /* Set RX filter */ - rmt_ll_set_rx_filter_thres(dev, channel, filter_cnt); - rmt_ll_enable_rx_filter(dev, channel, rmt_param->rx_config.filter_en); + rmt_ll_rx_set_filter_thres(dev, RMT_DECODE_RX_CHANNEL(channel), filter_cnt); + rmt_ll_rx_enable_filter(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.filter_en); #if SOC_RMT_SUPPORT_RX_PINGPONG /* always enable rx ping-pong */ - rmt_ll_enable_rx_pingpong(dev, channel, true); + rmt_ll_rx_enable_pingpong(dev, RMT_DECODE_RX_CHANNEL(channel), true); #endif #if SOC_RMT_SUPPORT_RX_DEMODULATION - rmt_ll_enable_carrier(dev, channel, rmt_param->rx_config.rm_carrier); + rmt_ll_rx_enable_carrier_demodulation(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.rm_carrier); if (rmt_param->rx_config.rm_carrier) { - uint32_t duty_total = rmt_source_clk_hz / rmt_ll_get_counter_clock_div(dev, channel) / rmt_param->rx_config.carrier_freq_hz; + uint32_t duty_total = rmt_source_clk_hz / rmt_ll_rx_get_counter_clock_div(dev, RMT_DECODE_RX_CHANNEL(channel)) / rmt_param->rx_config.carrier_freq_hz; uint32_t duty_high = duty_total * rmt_param->rx_config.carrier_duty_percent / 100; // there could be residual in timing the carrier pulse, so double enlarge the theoretical value - rmt_ll_set_rx_carrier_high_low_ticks(dev, channel, duty_high * 2, (duty_total - duty_high) * 2); - rmt_ll_set_carrier_on_level(dev, channel, rmt_param->rx_config.carrier_level); + rmt_ll_rx_set_carrier_high_low_ticks(dev, RMT_DECODE_RX_CHANNEL(channel), duty_high * 2, (duty_total - duty_high) * 2); + rmt_ll_rx_set_carrier_level(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.carrier_level); } #endif RMT_EXIT_CRITICAL(); @@ -609,6 +676,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par ESP_LOGD(RMT_TAG, "Rmt Rx Channel %u|Gpio %u|Sclk_Hz %u|Div %u|Thresold %u|Filter %u", channel, gpio_num, rmt_source_clk_hz, clk_div, threshold, filter_cnt); } + return ESP_OK; } @@ -629,20 +697,18 @@ static void IRAM_ATTR rmt_fill_memory(rmt_channel_t channel, const rmt_item32_t uint16_t item_num, uint16_t mem_offset) { RMT_ENTER_CRITICAL(); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW); rmt_ll_write_memory(rmt_contex.hal.mem, channel, item, item_num, mem_offset); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW); RMT_EXIT_CRITICAL(); } esp_err_t rmt_fill_tx_items(rmt_channel_t channel, const rmt_item32_t *item, uint16_t item_num, uint16_t mem_offset) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, (0)); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, (0)); RMT_CHECK((item != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK((item_num > 0), RMT_DRIVER_LENGTH_ERROR_STR, ESP_ERR_INVALID_ARG); /*Each block has 64 x 32 bits of data*/ - uint8_t mem_cnt = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel); + uint8_t mem_cnt = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel); RMT_CHECK((mem_cnt * RMT_MEM_ITEM_NUM >= item_num), RMT_WR_MEM_OVF_ERROR_STR, ESP_ERR_INVALID_ARG); rmt_fill_memory(channel, item, item_num, mem_offset); return ESP_OK; @@ -653,7 +719,7 @@ esp_err_t rmt_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, RMT_CHECK((fn != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(rmt_contex.rmt_driver_channels == 0, "RMT driver installed, can not install generic ISR handler", ESP_FAIL); - return esp_intr_alloc(ETS_RMT_INTR_SOURCE, intr_alloc_flags, fn, arg, handle); + return esp_intr_alloc(rmt_periph_signals.irq, intr_alloc_flags, fn, arg, handle); } esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle) @@ -661,11 +727,11 @@ esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle) return esp_intr_free(handle); } -static int IRAM_ATTR rmt_get_mem_len(rmt_channel_t channel) +static int IRAM_ATTR rmt_rx_get_mem_len_in_isr(rmt_channel_t channel) { - int block_num = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel); + int block_num = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, channel); int item_block_len = block_num * RMT_MEM_ITEM_NUM; - volatile rmt_item32_t *data = (rmt_item32_t *)RMTMEM.chan[channel].data32; + volatile rmt_item32_t *data = (rmt_item32_t *)RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32; int idx; for (idx = 0; idx < item_block_len; idx++) { if (data[idx].duration0 == 0) { @@ -693,7 +759,7 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) rmt_obj_t *p_rmt = p_rmt_obj[channel]; if (p_rmt) { xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken); - rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); p_rmt->tx_data = NULL; p_rmt->tx_len_rem = 0; p_rmt->tx_offset = 0; @@ -761,13 +827,13 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) while (status) { channel = __builtin_ffs(status) - 1; status &= ~(1 << channel); - rmt_obj_t *p_rmt = p_rmt_obj[channel]; + rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)]; if (p_rmt) { - rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false); - int item_len = rmt_get_mem_len(channel); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW); + rmt_ll_rx_enable(rmt_contex.hal.regs, channel, false); + int item_len = rmt_rx_get_mem_len_in_isr(channel); + rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW); if (p_rmt->rx_buf) { - addr = RMTMEM.chan[channel].data32; + addr = RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32; #if SOC_RMT_SUPPORT_RX_PINGPONG if (item_len > p_rmt->rx_item_start_idx) { item_len = item_len - p_rmt->rx_item_start_idx; @@ -790,9 +856,9 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) p_rmt->rx_item_len = 0; memset((void *)p_rmt->rx_item_buf, 0, p_rmt->rx_item_buf_size); #endif - rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW); - rmt_ll_enable_rx(rmt_contex.hal.regs, channel, true); + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, channel); + rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW); + rmt_ll_rx_enable(rmt_contex.hal.regs, channel, true); } rmt_ll_clear_rx_end_interrupt(hal->regs, channel); } @@ -803,14 +869,14 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) while (status) { channel = __builtin_ffs(status) - 1; status &= ~(1 << channel); - rmt_obj_t *p_rmt = p_rmt_obj[channel]; - int mem_item_size = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; - int rx_thres_lim = rmt_ll_get_rx_limit(rmt_contex.hal.regs, channel); + rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)]; + int mem_item_size = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; + int rx_thres_lim = rmt_ll_rx_get_limit(rmt_contex.hal.regs, channel); int item_len = (p_rmt->rx_item_start_idx == 0) ? rx_thres_lim : (mem_item_size - rx_thres_lim); if ((p_rmt->rx_item_len + item_len) < (p_rmt->rx_item_buf_size / 4)) { - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW); - memcpy((void *)(p_rmt->rx_item_buf + p_rmt->rx_item_len), (void *)(RMTMEM.chan[channel].data32 + p_rmt->rx_item_start_idx), item_len * 4); - rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW); + rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW); + memcpy((void *)(p_rmt->rx_item_buf + p_rmt->rx_item_len), (void *)(RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32 + p_rmt->rx_item_start_idx), item_len * 4); + rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW); p_rmt->rx_item_len += item_len; p_rmt->rx_item_start_idx += item_len; if (p_rmt->rx_item_start_idx >= mem_item_size) { @@ -840,20 +906,34 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) } #endif - // Err interrupt - status = rmt_ll_get_err_interrupt_status(hal->regs); + // RX Err interrupt + status = rmt_ll_get_rx_err_interrupt_status(hal->regs); + while (status) { + channel = __builtin_ffs(status) - 1; + status &= ~(1 << channel); + rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)]; + if (p_rmt) { + // Reset the receiver's write/read addresses to prevent endless err interrupts. + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, channel); + ESP_EARLY_LOGD(RMT_TAG, "RMT RX channel %d error", channel); + ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_rx_get_channel_status(rmt_contex.hal.regs, channel)); + } + rmt_ll_clear_rx_err_interrupt(hal->regs, channel); + } + + // TX Err interrupt + status = rmt_ll_get_tx_err_interrupt_status(hal->regs); while (status) { channel = __builtin_ffs(status) - 1; status &= ~(1 << channel); rmt_obj_t *p_rmt = p_rmt_obj[channel]; if (p_rmt) { - // Reset the receiver/transmitter's write/read addresses to prevent endless err interrupts. - rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel); - rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel); - ESP_EARLY_LOGD(RMT_TAG, "RMT[%d] ERR", channel); - ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_get_channel_status(rmt_contex.hal.regs, channel)); + // Reset the transmitter's write/read addresses to prevent endless err interrupts. + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); + ESP_EARLY_LOGD(RMT_TAG, "RMT TX channel %d error", channel); + ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_tx_get_channel_status(rmt_contex.hal.regs, channel)); } - rmt_ll_clear_err_interrupt(hal->regs, channel); + rmt_ll_clear_tx_err_interrupt(hal->regs, channel); } if (HPTaskAwoken == pdTRUE) { @@ -873,16 +953,23 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel) if (p_rmt_obj[channel]->wait_done) { xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); } - rmt_set_rx_intr_en(channel, 0); - rmt_set_err_intr_en(channel, 0); - rmt_set_tx_intr_en(channel, 0); - rmt_set_tx_thr_intr_en(channel, false, 0xffff); + + RMT_ENTER_CRITICAL(); + // check channel's working mode + if (p_rmt_obj[channel]->rx_buf) { + rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0); + rmt_ll_enable_rx_err_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0); #if SOC_RMT_SUPPORT_RX_PINGPONG - rmt_set_rx_thr_intr_en(channel, false, 0xffff); + rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0); #endif + } else { + rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, 0); + rmt_ll_enable_tx_err_interrupt(rmt_contex.hal.regs, channel, 0); + rmt_ll_enable_tx_thres_interrupt(rmt_contex.hal.regs, channel, false); + } + RMT_EXIT_CRITICAL(); _lock_acquire_recursive(&(rmt_contex.rmt_driver_isr_lock)); - rmt_contex.rmt_driver_channels &= ~BIT(channel); if (rmt_contex.rmt_driver_channels == 0) { rmt_module_disable(); @@ -890,7 +977,6 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel) err = rmt_isr_deregister(rmt_contex.rmt_driver_intr_handle); rmt_contex.rmt_driver_intr_handle = NULL; } - _lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock)); if (err != ESP_OK) { @@ -1007,17 +1093,21 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr rmt_contex.rmt_driver_channels |= BIT(channel); } _lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock)); + rmt_module_enable(); - rmt_set_err_intr_en(channel, 0); - rmt_hal_channel_reset(&rmt_contex.hal, channel); - rmt_set_err_intr_en(channel, 1); + + if (RMT_IS_RX_CHANNEL(channel)) { + rmt_hal_rx_channel_reset(&rmt_contex.hal, RMT_DECODE_RX_CHANNEL(channel)); + } else { + rmt_hal_tx_channel_reset(&rmt_contex.hal, channel); + } return err; } esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, int item_num, bool wait_tx_done) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); RMT_CHECK(rmt_item != NULL, RMT_ADDR_ERROR_STR, ESP_FAIL); RMT_CHECK(item_num > 0, RMT_DRIVER_LENGTH_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -1030,7 +1120,7 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, i } #endif rmt_obj_t *p_rmt = p_rmt_obj[channel]; - int block_num = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel); + int block_num = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel); int item_block_len = block_num * RMT_MEM_ITEM_NUM; int item_sub_len = block_num * RMT_MEM_ITEM_NUM / 2; int len_rem = item_num; @@ -1071,7 +1161,7 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, i esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); if (xSemaphoreTake(p_rmt_obj[channel]->tx_sem, wait_time) == pdTRUE) { p_rmt_obj[channel]->wait_done = false; @@ -1106,9 +1196,9 @@ rmt_tx_end_callback_t rmt_register_tx_end_callback(rmt_tx_end_fn_t function, voi esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn) { RMT_CHECK(fn != NULL, RMT_TRANSLATOR_NULL_STR, ESP_ERR_INVALID_ARG); - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); - const uint32_t block_size = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * + const uint32_t block_size = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM * sizeof(rmt_item32_t); if (p_rmt_obj[channel]->tx_buf == NULL) { #if !CONFIG_SPIRAM_USE_MALLOC @@ -1134,7 +1224,7 @@ esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn) esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); RMT_CHECK(p_rmt_obj[channel]->sample_to_rmt != NULL, RMT_TRANSLATOR_UNINIT_STR, ESP_FAIL); #if CONFIG_SPIRAM_USE_MALLOC @@ -1148,7 +1238,7 @@ esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src size_t item_num = 0; size_t translated_size = 0; rmt_obj_t *p_rmt = p_rmt_obj[channel]; - const uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; + const uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM; const uint32_t item_sub_len = item_block_len / 2; xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY); p_rmt->sample_to_rmt((void *)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num); @@ -1202,20 +1292,16 @@ esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz) RMT_CHECK(clock_hz, "parameter clock_hz can't be null", ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); uint32_t rmt_source_clk_hz = 0; - if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_APB) { - rmt_source_clk_hz = APB_CLK_FREQ; - } -#ifdef SOC_RMT_SUPPORT_REF_TICK - else if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_REF) { - rmt_source_clk_hz = REF_CLK_FREQ; - } +#if SOC_RMT_SOURCE_CLK_INDEPENDENT + rmt_source_clk_hz = s_rmt_source_clock_hz[channel]; +#else + rmt_source_clk_hz = s_rmt_source_clock_hz; #endif -#ifdef SOC_RMT_SUPPORT_XTAL_CLOCK - else if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_XTAL) { - rmt_source_clk_hz = rtc_clk_xtal_freq_get() * 1000000; + if (RMT_IS_RX_CHANNEL(channel)) { + *clock_hz = rmt_source_clk_hz / rmt_ll_rx_get_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + } else { + *clock_hz = rmt_source_clk_hz / rmt_ll_tx_get_counter_clock_div(rmt_contex.hal.regs, channel); } -#endif - *clock_hz = rmt_hal_get_counter_clock(&rmt_contex.hal, channel, rmt_source_clk_hz); RMT_EXIT_CRITICAL(); return ESP_OK; } @@ -1223,21 +1309,34 @@ esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz) #if SOC_RMT_SUPPORT_TX_GROUP esp_err_t rmt_add_channel_to_group(rmt_channel_t channel) { - RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - rmt_ll_enable_tx_sync(rmt_contex.hal.regs, true); - rmt_ll_add_channel_to_group(rmt_contex.hal.regs, channel); - rmt_ll_reset_counter_clock_div(rmt_contex.hal.regs, channel); + rmt_ll_tx_enable_sync(rmt_contex.hal.regs, true); + rmt_ll_tx_add_channel_to_group(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_counter_clock_div(rmt_contex.hal.regs, channel); RMT_EXIT_CRITICAL(); return ESP_OK; } esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel) +{ + RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_ENTER_CRITICAL(); + if (rmt_ll_tx_remove_channel_from_group(rmt_contex.hal.regs, channel) == 0) { + rmt_ll_tx_enable_sync(rmt_contex.hal.regs, false); + } + RMT_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t rmt_memory_rw_rst(rmt_channel_t channel) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_ENTER_CRITICAL(); - if (rmt_ll_remove_channel_from_group(rmt_contex.hal.regs, channel) == 0) { - rmt_ll_enable_tx_sync(rmt_contex.hal.regs, false); + if (RMT_IS_RX_CHANNEL(channel)) { + rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)); + } else { + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); } RMT_EXIT_CRITICAL(); return ESP_OK; diff --git a/components/driver/test/test_rmt.c b/components/driver/test/test_rmt.c index 8bef9ed829..28b4293f2f 100644 --- a/components/driver/test/test_rmt.c +++ b/components/driver/test/test_rmt.c @@ -12,7 +12,8 @@ #include "test_utils.h" #include "esp_rom_gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) +#define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_NUM-SOC_RMT_TX_CHANNELS_NUM) +#define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1) // CI ONLY: Don't connect any other signals to this GPIO #define RMT_DATA_IO (12) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO @@ -123,7 +124,7 @@ TEST_CASE("RMT wrong configuration", "[rmt][error]") TEST_CASE("RMT miscellaneous functions", "[rmt]") { - rmt_channel_t channel = SOC_RMT_CHANNELS_NUM - 2; + rmt_channel_t channel = 0; uint8_t div_cnt; rmt_source_clk_t src_clk; uint8_t memNum; @@ -147,15 +148,12 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]") TEST_ASSERT_EQUAL_INT(RMT_BASECLK_REF, src_clk); #endif -#if SOC_RMT_SUPPORT_XTAL_CLOCK +#if SOC_RMT_SUPPORT_XTAL TEST_ESP_OK(rmt_set_source_clk(channel, RMT_BASECLK_XTAL)); TEST_ESP_OK(rmt_get_source_clk(channel, &src_clk)); TEST_ASSERT_EQUAL_INT(RMT_BASECLK_XTAL, src_clk); #endif - TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX)); - TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); - TEST_ASSERT_EQUAL_INT(RMT_MEM_OWNER_RX, owner); TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 1, 0, 1)); TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0)); @@ -163,6 +161,7 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]") rmt_clean_testbench(channel, -1); // RX related functions + channel = RMT_RX_CHANNEL_ENCODING_START; rmt_setup_testbench(-1, channel, 0); TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, 200)); @@ -171,6 +170,10 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]") TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100)); + TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + TEST_ASSERT_EQUAL_INT(RMT_MEM_OWNER_RX, owner); + rmt_clean_testbench(-1, channel); } @@ -196,7 +199,13 @@ TEST_CASE("RMT multiple channels", "[rmt]") TEST_CASE("RMT install/uninstall test", "[rmt][pressure]") { - rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, SOC_RMT_CHANNELS_NUM - 2); + rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, RMT_TX_CHANNEL_ENCODING_END); + TEST_ESP_OK(rmt_config(&tx_cfg)); + for (int i = 0; i < 100; i++) { + TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 1000, 0)); + TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel)); + } + rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START); TEST_ESP_OK(rmt_config(&rx_cfg)); for (int i = 0; i < 100; i++) { TEST_ESP_OK(rmt_driver_install(rx_cfg.channel, 1000, 0)); @@ -213,11 +222,7 @@ static void do_nec_tx_rx(uint32_t flags) uint32_t cmd = 0x20; bool repeat = false; int tx_channel = 0; -#ifdef CONFIG_IDF_TARGET_ESP32S3 - int rx_channel = 4; -#else - int rx_channel = 1; -#endif + int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1; // test on different flags combinations rmt_setup_testbench(tx_channel, rx_channel, flags); @@ -273,7 +278,7 @@ TEST_CASE("RMT NEC TX and RX (APB)", "[rmt]") } // test with RMT_TESTBENCH_FLAGS_ALWAYS_ON will take a long time (REF_TICK is much slower than APB CLOCK) -TEST_CASE("RMT NEC TX and RX (REF_TICK)", "[rmt][timeout=240]") +TEST_CASE("RMT NEC TX and RX (always on)", "[rmt][timeout=240]") { do_nec_tx_rx(RMT_TESTBENCH_FLAGS_ALWAYS_ON); } @@ -314,11 +319,7 @@ TEST_CASE("RMT TX stop", "[rmt]") uint32_t cmd = 0x20; bool repeat = false; int tx_channel = 0; -#ifdef CONFIG_IDF_TARGET_ESP32S3 - int rx_channel = 4; -#else - int rx_channel = 1; -#endif + int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1; rmt_setup_testbench(tx_channel, rx_channel, 0); @@ -377,11 +378,7 @@ TEST_CASE("RMT TX stop", "[rmt]") TEST_CASE("RMT Ping-Pong operation", "[rmt]") { int tx_channel = 0; -#ifdef CONFIG_IDF_TARGET_ESP32S3 - int rx_channel = 4; -#else - int rx_channel = 1; -#endif + int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1; rmt_item32_t frames[SOC_RMT_CHANNEL_MEM_WORDS * 2]; // send two block data using ping-pong RingbufHandle_t rb = NULL; uint32_t size = sizeof(frames) / sizeof(frames[0]); @@ -498,11 +495,7 @@ TEST_CASE("RMT TX loop", "[rmt]") uint32_t cmd = 0x20; bool repeat = false; int tx_channel = 0; -#ifdef CONFIG_IDF_TARGET_ESP32S3 - int rx_channel = 4; -#else - int rx_channel = 1; -#endif + int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1; uint32_t count = 0; rmt_setup_testbench(tx_channel, rx_channel, RMT_TESTBENCH_FLAGS_LOOP_ON); @@ -545,5 +538,3 @@ TEST_CASE("RMT TX loop", "[rmt]") rmt_clean_testbench(tx_channel, rx_channel); } #endif - -#endif diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index 9531c0972f..e6435f18eb 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -24,47 +24,14 @@ extern "C" { #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) +// Note: TX and RX channel number are all index from zero in the LL driver +// i.e. tx_channel belongs to [0,7], and rx_channel belongs to [0,7] + static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable) { dev->conf_ch[0].conf0.clk_en = enable; } -static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.ref_cnt_rst = 1; - dev->conf_ch[channel].conf1.ref_cnt_rst = 0; -} - -static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.mem_rd_rst = 1; - dev->conf_ch[channel].conf1.mem_rd_rst = 0; -} - -static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.mem_wr_rst = 1; - dev->conf_ch[channel].conf1.mem_wr_rst = 0; -} - -static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.tx_start = 1; -} - -static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel) -{ - RMTMEM.chan[channel].data32[0].val = 0; - dev->conf_ch[channel].conf1.tx_start = 0; - dev->conf_ch[channel].conf1.mem_rd_rst = 1; - dev->conf_ch[channel].conf1.mem_rd_rst = 0; -} - -static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.rx_en = enable; -} - static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) { dev->conf_ch[0].conf0.mem_pd = enable; // Only conf0 register of channel0 has `mem_pd` @@ -75,78 +42,12 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev) return dev->conf_ch[0].conf0.mem_pd; // Only conf0 register of channel0 has `mem_pd` } -static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) -{ - dev->conf_ch[channel].conf0.mem_size = block_num; -} - -static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf0.mem_size; -} - -static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) -{ - dev->conf_ch[channel].conf0.div_cnt = div; -} - -static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; - return div == 0 ? 256 : div; -} - -static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->apb_conf.mem_tx_wrap_en = enable; -} - static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable) { dev->apb_conf.fifo_mask = enable; } -static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) -{ - dev->conf_ch[channel].conf0.idle_thres = thres; -} - -static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf0.idle_thres; -} - -static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) -{ - dev->conf_ch[channel].conf1.mem_owner = owner; -} - -static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf1.mem_owner; -} - -static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.tx_conti_mode = enable; -} - -static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf1.tx_conti_mode; -} - -static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.rx_filter_en = enable; -} - -static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) -{ - dev->conf_ch[channel].conf1.rx_filter_thres = thres; -} - -static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src) +static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b) { dev->conf_ch[channel].conf1.ref_always_on = src; } @@ -156,7 +57,136 @@ static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t cha return dev->conf_ch[channel].conf1.ref_always_on; } -static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.ref_cnt_rst = 1; + dev->conf_ch[channel].conf1.ref_cnt_rst = 0; +} + +static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.ref_cnt_rst = 1; + dev->conf_ch[channel].conf1.ref_cnt_rst = 0; +} + +static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.mem_rd_rst = 1; + dev->conf_ch[channel].conf1.mem_rd_rst = 0; +} + +static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.mem_wr_rst = 1; + dev->conf_ch[channel].conf1.mem_wr_rst = 0; +} + +static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.tx_start = 1; +} + +static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel) +{ + RMTMEM.chan[channel].data32[0].val = 0; + dev->conf_ch[channel].conf1.tx_start = 0; + dev->conf_ch[channel].conf1.mem_rd_rst = 1; + dev->conf_ch[channel].conf1.mem_rd_rst = 0; +} + +static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.rx_en = enable; +} + +static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->conf_ch[channel].conf0.mem_size = block_num; +} + +static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->conf_ch[channel].conf0.mem_size = block_num; +} + +static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.mem_size; +} + +static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.mem_size; +} + +static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->conf_ch[channel].conf0.div_cnt = div; +} + +static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->conf_ch[channel].conf0.div_cnt = div; +} + +static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + return div == 0 ? 256 : div; +} + +static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + return div == 0 ? 256 : div; +} + +static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->apb_conf.mem_tx_wrap_en = enable; +} + +static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->conf_ch[channel].conf0.idle_thres = thres; +} + +static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.idle_thres; +} + +static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) +{ + dev->conf_ch[channel].conf1.mem_owner = owner; +} + +static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf1.mem_owner; +} + +static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.tx_conti_mode = enable; +} + +static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf1.tx_conti_mode; +} + +static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.rx_filter_en = enable; +} + +static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->conf_ch[channel].conf1.rx_filter_thres = thres; +} + +static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->conf_ch[channel].conf1.idle_out_en = enable; } @@ -166,22 +196,27 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel) return dev->conf_ch[channel].conf1.idle_out_en; } -static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) { dev->conf_ch[channel].conf1.idle_out_lv = level; } -static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel) { return dev->conf_ch[channel].conf1.idle_out_lv; } -static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel) { return dev->status_ch[channel]; } -static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel) +{ + return dev->status_ch[channel]; +} + +static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) { dev->tx_lim_ch[channel].limit = limit; } @@ -198,7 +233,13 @@ static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t chann dev->int_ena.val |= (enable << (channel * 3 + 1)); } -static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->int_ena.val &= ~(1 << (channel * 3 + 2)); + dev->int_ena.val |= (enable << (channel * 3 + 2)); +} + +static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->int_ena.val &= ~(1 << (channel * 3 + 2)); dev->int_ena.val |= (enable << (channel * 3 + 2)); @@ -220,7 +261,12 @@ static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channe dev->int_clr.val = (1 << (channel * 3 + 1)); } -static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel) +{ + dev->int_clr.val = (1 << (channel * 3 + 2)); +} + +static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel) { dev->int_clr.val = (1 << (channel * 3 + 2)); } @@ -244,7 +290,14 @@ static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev) ((status & 0x2000) >> 9) | ((status & 0x10000) >> 11) | ((status & 0x80000) >> 13) | ((status & 0x400000) >> 15); } -static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev) +static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev) +{ + uint32_t status = dev->int_st.val; + return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8) | + ((status & 0x4000) >> 10) | ((status & 0x20000) >> 12) | ((status & 0x100000) >> 14) | ((status & 0x800000) >> 16); +} + +static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev) { uint32_t status = dev->int_st.val; return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8) | @@ -257,24 +310,24 @@ static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev) return (status & 0xFF000000) >> 24; } -static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +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) { dev->carrier_duty_ch[channel].high = high_ticks; dev->carrier_duty_ch[channel].low = low_ticks; } -static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) +static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { *high_ticks = dev->carrier_duty_ch[channel].high; *low_ticks = dev->carrier_duty_ch[channel].low; } -static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->conf_ch[channel].conf0.carrier_en = enable; } -static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) { dev->conf_ch[channel].conf0.carrier_out_lv = level; } @@ -288,8 +341,12 @@ static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const r } } +static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel) +{ +} + /************************************************************************************************ - * Following Low Level APIs only used for backward compatible, will be deprecated in the future! + * Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0 ***********************************************************************************************/ static inline void rmt_ll_set_intr_enable_mask(uint32_t mask) diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 3eb2c074af..608b72e455 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -24,45 +24,15 @@ extern "C" { #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) +// Note: TX and RX channel number are all index from zero in the LL driver +// i.e. tx_channel belongs to [0,3], and rx_channel belongs to [0,3] + static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable) { dev->apb_conf.clk_en = enable; // register clock gating dev->apb_conf.mem_clk_force_on = enable; // memory clock gating } -static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - dev->ref_cnt_rst.val |= (1 << channel); - dev->ref_cnt_rst.val &= ~(1 << channel); -} - -static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.mem_rd_rst = 1; - dev->conf_ch[channel].conf1.mem_rd_rst = 0; -} - -static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.mem_wr_rst = 1; - dev->conf_ch[channel].conf1.mem_wr_rst = 0; -} - -static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.tx_start = 1; -} - -static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel) -{ - dev->conf_ch[channel].conf1.tx_stop = 1; -} - -static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.rx_en = enable; -} - static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) { dev->apb_conf.mem_force_pu = !enable; @@ -77,110 +47,12 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev) return (dev->apb_conf.mem_force_pd) || !(dev->apb_conf.mem_force_pu); } -static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) -{ - dev->conf_ch[channel].conf0.mem_size = block_num; -} - -static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf0.mem_size; -} - -static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) -{ - dev->conf_ch[channel].conf0.div_cnt = div; -} - -static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; - return div == 0 ? 256 : div; -} - -static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->apb_conf.mem_tx_wrap_en = enable; -} - static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable) { dev->apb_conf.fifo_mask = enable; } -static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) -{ - dev->conf_ch[channel].conf0.idle_thres = thres; -} - -static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf0.idle_thres; -} - -static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) -{ - dev->conf_ch[channel].conf1.mem_owner = owner; -} - -static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf1.mem_owner; -} - -static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.tx_conti_mode = enable; -} - -static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) -{ - return dev->conf_ch[channel].conf1.tx_conti_mode; -} - -static inline void rmt_ll_set_tx_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) -{ - dev->tx_lim_ch[channel].tx_loop_num = count; -} - -static inline void rmt_ll_reset_tx_loop(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_lim_ch[channel].loop_count_reset = 1; - dev->tx_lim_ch[channel].loop_count_reset = 0; -} - -static inline void rmt_ll_enable_tx_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->tx_lim_ch[channel].tx_loop_cnt_en = enable; -} - -static inline void rmt_ll_enable_tx_sync(rmt_dev_t *dev, bool enable) -{ - dev->tx_sim.en = enable; -} - -static inline void rmt_ll_add_channel_to_group(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_sim.val |= 1 << channel; -} - -static inline uint32_t rmt_ll_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_sim.val &= ~(1 << channel); - return dev->tx_sim.val & 0x0F; -} - -static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->conf_ch[channel].conf1.rx_filter_en = enable; -} - -static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) -{ - dev->conf_ch[channel].conf1.rx_filter_thres = thres; -} - -static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src) +static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b) { dev->conf_ch[channel].conf1.ref_always_on = src; } @@ -190,7 +62,165 @@ static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t cha return dev->conf_ch[channel].conf1.ref_always_on; } -static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + dev->ref_cnt_rst.val |= (1 << channel); + dev->ref_cnt_rst.val &= ~(1 << channel); +} + +static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + dev->ref_cnt_rst.val |= (1 << channel); + dev->ref_cnt_rst.val &= ~(1 << channel); +} + +static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.mem_rd_rst = 1; + dev->conf_ch[channel].conf1.mem_rd_rst = 0; +} + +static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.mem_wr_rst = 1; + dev->conf_ch[channel].conf1.mem_wr_rst = 0; +} + +static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.tx_start = 1; +} + +static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel) +{ + dev->conf_ch[channel].conf1.tx_stop = 1; +} + +static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.rx_en = enable; +} + +static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->conf_ch[channel].conf0.mem_size = block_num; +} + +static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->conf_ch[channel].conf0.mem_size = block_num; +} + +static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.mem_size; +} + +static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.mem_size; +} + +static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->conf_ch[channel].conf0.div_cnt = div; +} + +static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->conf_ch[channel].conf0.div_cnt = div; +} + +static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + return div == 0 ? 256 : div; +} + +static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + return div == 0 ? 256 : div; +} + +static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->apb_conf.mem_tx_wrap_en = enable; +} + +static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->conf_ch[channel].conf0.idle_thres = thres; +} + +static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf0.idle_thres; +} + +static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) +{ + dev->conf_ch[channel].conf1.mem_owner = owner; +} + +static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf1.mem_owner; +} + +static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.tx_conti_mode = enable; +} + +static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) +{ + return dev->conf_ch[channel].conf1.tx_conti_mode; +} + +static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) +{ + dev->tx_lim_ch[channel].tx_loop_num = count; +} + +static inline void rmt_ll_tx_reset_loop(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_lim_ch[channel].loop_count_reset = 1; + dev->tx_lim_ch[channel].loop_count_reset = 0; +} + +static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->tx_lim_ch[channel].tx_loop_cnt_en = enable; +} + +static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable) +{ + dev->tx_sim.en = enable; +} + +static inline void rmt_ll_tx_add_channel_to_group(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_sim.val |= 1 << channel; +} + +static inline uint32_t rmt_ll_tx_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_sim.val &= ~(1 << channel); + return dev->tx_sim.val & 0x0F; +} + +static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf1.rx_filter_en = enable; +} + +static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->conf_ch[channel].conf1.rx_filter_thres = thres; +} + +static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->conf_ch[channel].conf1.idle_out_en = enable; } @@ -200,32 +230,37 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel) return dev->conf_ch[channel].conf1.idle_out_en; } -static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) { dev->conf_ch[channel].conf1.idle_out_lv = level; } -static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel) { return dev->conf_ch[channel].conf1.idle_out_lv; } -static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel) { return dev->status_ch[channel].val; } -static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel) +{ + return dev->status_ch[channel].val; +} + +static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) { dev->tx_lim_ch[channel].limit = limit; } -static inline void rmt_ll_set_rx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) { dev->tx_lim_ch[channel].rx_lim = limit; } -static inline uint32_t rmt_ll_get_rx_limit(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel) { return dev->tx_lim_ch[channel].rx_lim; } @@ -242,7 +277,13 @@ static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t chann dev->int_ena.val |= (enable << (channel * 3 + 1)); } -static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->int_ena.val &= ~(1 << (channel * 3 + 2)); + dev->int_ena.val |= (enable << (channel * 3 + 2)); +} + +static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->int_ena.val &= ~(1 << (channel * 3 + 2)); dev->int_ena.val |= (enable << (channel * 3 + 2)); @@ -276,7 +317,12 @@ static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channe dev->int_clr.val = (1 << (channel * 3 + 1)); } -static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel) +{ + dev->int_clr.val = (1 << (channel * 3 + 2)); +} + +static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel) { dev->int_clr.val = (1 << (channel * 3 + 2)); } @@ -308,7 +354,13 @@ static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev) return ((status & 0x02) >> 1) | ((status & 0x10) >> 3) | ((status & 0x80) >> 5) | ((status & 0x400) >> 7); } -static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev) +static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev) +{ + uint32_t status = dev->int_st.val; + return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8); +} + +static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev) { uint32_t status = dev->int_st.val; return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8); @@ -332,7 +384,7 @@ static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev) return (status & 0xF00000) >> 20; } -static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +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) { // In case the compiler optimise a 32bit instruction (e.g. s32i) into two 16bit instruction (e.g. s16i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. @@ -342,27 +394,42 @@ static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t dev->carrier_duty_ch[channel].val = reg.val; } -static inline void rmt_ll_set_rx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +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) { - dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch = high_ticks; - dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch = low_ticks; + typeof(dev->ch_rx_carrier_rm[0]) reg; + reg.carrier_high_thres_ch = high_ticks; + reg.carrier_low_thres_ch = low_ticks; + dev->ch_rx_carrier_rm[channel].val = reg.val; } -static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) +static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { *high_ticks = dev->carrier_duty_ch[channel].high; *low_ticks = dev->carrier_duty_ch[channel].low; } -// This function has different meaning for TX and RX -// TX: enable to modulate carrier -// RX: enable to demodulate carrier -static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) +{ + *high_ticks = dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch; + *low_ticks = dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch; +} + +static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->conf_ch[channel].conf0.carrier_en = enable; } -static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->conf_ch[channel].conf0.carrier_en = enable; +} + +static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +{ + dev->conf_ch[channel].conf0.carrier_out_lv = level; +} + +static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) { dev->conf_ch[channel].conf0.carrier_out_lv = level; } @@ -383,13 +450,17 @@ static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const r } } -static inline void rmt_ll_enable_rx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_rx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->conf_ch[channel].conf1.chk_rx_carrier_en = enable; } +static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel) +{ +} + /************************************************************************************************ - * Following Low Level APIs only used for backward compatible, will be deprecated in the future! + * Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0 ***********************************************************************************************/ static inline void rmt_ll_set_intr_enable_mask(uint32_t mask) diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index b3dab8f00d..781e664595 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -25,19 +25,8 @@ extern "C" { #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) -#define RMT_LL_TX_CHAN_NUM (4) -#define RMT_LL_TX_CHAN_MASK (0x0F) -#define RMT_LL_RX_CHAN_MASK (0xF0) - -static inline void rmt_ll_set_sclk(rmt_dev_t *dev, uint32_t source, uint32_t div_num, uint32_t div_frac_a, uint32_t div_frac_b) -{ - dev->sys_conf.sclk_active = 0; - dev->sys_conf.sclk_sel = source; - dev->sys_conf.sclk_div_num = div_num; - dev->sys_conf.sclk_div_a = div_frac_a; - dev->sys_conf.sclk_div_b = div_frac_b; - dev->sys_conf.sclk_active = 1; -} +// Note: TX and RX channel number are all index from zero in the LL driver +// i.e. tx_channel belongs to [0,3], and rx_channel belongs to [0,3] static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable) { @@ -45,46 +34,6 @@ static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable) dev->sys_conf.mem_clk_force_on = enable; // memory clock gating } -static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - dev->ref_cnt_rst.val |= (1 << channel); - dev->ref_cnt_rst.val &= ~(1 << channel); -} - -static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_conf[channel].mem_rd_rst = 1; - dev->tx_conf[channel].mem_rd_rst = 0; - dev->tx_conf[channel].apb_mem_rst = 1; - dev->tx_conf[channel].apb_mem_rst = 0; -} - -static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel) -{ - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_wr_rst = 1; - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_wr_rst = 0; - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.apb_mem_rst = 1; - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.apb_mem_rst = 0; -} - -static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_conf[channel].conf_update = 1; - dev->tx_conf[channel].tx_start = 1; -} - -static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel) -{ - dev->tx_conf[channel].tx_stop = 1; - dev->tx_conf[channel].conf_update = 1; -} - -static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_en = enable; - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.conf_update = 1; -} - static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable) { dev->sys_conf.mem_force_pu = !enable; @@ -99,67 +48,139 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev) return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu); } -static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) -{ - if(channel < RMT_LL_TX_CHAN_NUM) { - dev->tx_conf[channel].mem_size = block_num; - } else { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.mem_size = block_num; - } -} - -static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) -{ - return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_conf[channel].mem_size) : (dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.mem_size); -} - -static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) -{ - if(channel < RMT_LL_TX_CHAN_NUM) { - dev->tx_conf[channel].div_cnt = div; - } else { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.div_cnt = div; - } -} - -static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) -{ - return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_conf[channel].div_cnt) : (dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.div_cnt); -} - -static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) -{ - dev->tx_conf[channel].mem_tx_wrap_en = enable; -} - static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable) { dev->sys_conf.fifo_mask = enable; } -static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b) { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.idle_thres = thres; + // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) + dev->sys_conf.sclk_active = 0; + dev->sys_conf.sclk_sel = src; + dev->sys_conf.sclk_div_num = div_num; + dev->sys_conf.sclk_div_a = div_a; + dev->sys_conf.sclk_div_b = div_b; + dev->sys_conf.sclk_active = 1; } -static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.idle_thres; + return dev->sys_conf.sclk_sel; } -static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) +static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) { - if (channel >= RMT_LL_TX_CHAN_NUM) { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_owner = owner; - } + dev->ref_cnt_rst.val |= (1 << channel); + dev->ref_cnt_rst.val &= ~(1 << channel); } -static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_owner; + dev->ref_cnt_rst.val |= (1 << (channel + 4)); + dev->ref_cnt_rst.val &= ~(1 << (channel + 4)); } -static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_conf[channel].mem_rd_rst = 1; + dev->tx_conf[channel].mem_rd_rst = 0; + dev->tx_conf[channel].apb_mem_rst = 1; + dev->tx_conf[channel].apb_mem_rst = 0; +} + +static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel) +{ + dev->rx_conf[channel].conf1.mem_wr_rst = 1; + dev->rx_conf[channel].conf1.mem_wr_rst = 0; + dev->rx_conf[channel].conf1.apb_mem_rst = 1; + dev->rx_conf[channel].conf1.apb_mem_rst = 0; +} + +static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_conf[channel].conf_update = 1; + dev->tx_conf[channel].tx_start = 1; +} + +static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel) +{ + dev->tx_conf[channel].tx_stop = 1; + dev->tx_conf[channel].conf_update = 1; +} + +static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->rx_conf[channel].conf1.rx_en = enable; + dev->rx_conf[channel].conf1.conf_update = 1; +} + +static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->tx_conf[channel].mem_size = block_num; +} + +static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num) +{ + dev->rx_conf[channel].conf0.mem_size = block_num; +} + +static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->tx_conf[channel].mem_size; +} + +static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel) +{ + return dev->rx_conf[channel].conf0.mem_size; +} + +static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->tx_conf[channel].div_cnt = div; +} + +static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) +{ + dev->rx_conf[channel].conf0.div_cnt = div; +} + +static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + return dev->tx_conf[channel].div_cnt; +} + +static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel) +{ + return dev->rx_conf[channel].conf0.div_cnt; +} + +static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->tx_conf[channel].mem_tx_wrap_en = enable; +} + +static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +{ + dev->rx_conf[channel].conf0.idle_thres = thres; +} + +static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) +{ + return dev->rx_conf[channel].conf0.idle_thres; +} + +static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) +{ + dev->rx_conf[channel].conf1.mem_owner = owner; +} + +static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel) +{ + return dev->rx_conf[channel].conf1.mem_owner; +} + +static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->tx_conf[channel].tx_conti_mode = enable; } @@ -169,62 +190,49 @@ static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) return dev->tx_conf[channel].tx_conti_mode; } -static inline void rmt_ll_set_tx_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) +static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) { dev->tx_lim[channel].tx_loop_num = count; } -static inline void rmt_ll_reset_tx_loop(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_tx_reset_loop(rmt_dev_t *dev, uint32_t channel) { dev->tx_lim[channel].loop_count_reset = 1; dev->tx_lim[channel].loop_count_reset = 0; } -static inline void rmt_ll_enable_tx_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->tx_lim[channel].tx_loop_cnt_en = enable; } -static inline void rmt_ll_enable_tx_sync(rmt_dev_t *dev, bool enable) +static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable) { dev->tx_sim.en = enable; } -static inline void rmt_ll_add_channel_to_group(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_tx_add_channel_to_group(rmt_dev_t *dev, uint32_t channel) { dev->tx_sim.val |= 1 << channel; } -static inline uint32_t rmt_ll_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_tx_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel) { dev->tx_sim.val &= ~(1 << channel); - return dev->tx_sim.val & RMT_LL_TX_CHAN_MASK; + return dev->tx_sim.val & 0x0F; } -static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable) { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_filter_en = enable; + dev->rx_conf[channel].conf1.rx_filter_en = enable; } -static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) +static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_filter_thres = thres; + dev->rx_conf[channel].conf1.rx_filter_thres = thres; } -static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src) -{ - dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = 0; - dev->sys_conf.sclk_div_a = 0; - dev->sys_conf.sclk_div_b = 0; -} - -static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel) -{ - return dev->sys_conf.sclk_sel; -} - -static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) { dev->tx_conf[channel].idle_out_en = enable; } @@ -234,173 +242,175 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel) return dev->tx_conf[channel].idle_out_en; } -static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) { dev->tx_conf[channel].idle_out_lv = level; } -static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel) { return dev->tx_conf[channel].idle_out_lv; } -static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel) { - return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_status[channel].val) : (dev->rx_status[channel - RMT_LL_TX_CHAN_NUM].val); + return dev->rx_status[channel].val; } -static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel) +{ + return dev->tx_status[channel].val; +} + +static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) { dev->tx_lim[channel].limit = limit; } -static inline void rmt_ll_set_rx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) +static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit) { - dev->rx_lim[channel - RMT_LL_TX_CHAN_NUM].rx_lim = limit; + dev->rx_lim[channel].rx_lim = limit; } -static inline uint32_t rmt_ll_get_rx_limit(rmt_dev_t *dev, uint32_t channel) +static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_lim[channel - RMT_LL_TX_CHAN_NUM].rx_lim; + return dev->rx_lim[channel].rx_lim; } static inline void rmt_ll_enable_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { if (enable) { - dev->int_ena.val |= (BIT(0) << (channel)); + dev->int_ena.val |= (1 << channel); } else { - dev->int_ena.val &= ~(BIT(0) << (channel)); + dev->int_ena.val &= ~(1 << channel); + } +} + +static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + if (enable) { + dev->int_ena.val |= (1 << (channel + 4)); + } else { + dev->int_ena.val &= ~(1 << (channel + 4)); } } static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { if (enable) { - dev->int_ena.val |= (BIT(16) << (channel - RMT_LL_TX_CHAN_NUM)); + dev->int_ena.val |= (1 << (channel + 16)); } else { - dev->int_ena.val &= ~(BIT(16) << (channel - RMT_LL_TX_CHAN_NUM)); + dev->int_ena.val &= ~(1 << (channel + 16)); } } -static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { - if(channel < RMT_LL_TX_CHAN_NUM) { - if (enable) { - dev->int_ena.val |= (BIT(4) << (channel)); - } else { - dev->int_ena.val &= ~(BIT(4) << (channel)); - } + if (enable) { + dev->int_ena.val |= (1 << (channel + 20)); } else { - if (enable) { - dev->int_ena.val |= (BIT(20) << (channel - RMT_LL_TX_CHAN_NUM)); - } else { - dev->int_ena.val &= ~(BIT(20) << (channel - RMT_LL_TX_CHAN_NUM)); - } + dev->int_ena.val &= ~(1 << (channel + 20)); } } static inline void rmt_ll_enable_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { if (enable) { - dev->int_ena.val |= (BIT(8) << (channel)); + dev->int_ena.val |= (1 << (channel + 8)); } else { - dev->int_ena.val &= ~(BIT(8) << (channel)); + dev->int_ena.val &= ~(1 << (channel + 8)); } } static inline void rmt_ll_enable_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { if (enable) { - dev->int_ena.val |= (BIT(12) << (channel)); + dev->int_ena.val |= (1 << (channel + 12)); } else { - dev->int_ena.val &= ~(BIT(12) << (channel)); + dev->int_ena.val &= ~(1 << (channel + 12)); } } static inline void rmt_ll_enable_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable) { if (enable) { - dev->int_ena.val |= (BIT(24) << (channel - RMT_LL_TX_CHAN_NUM)); + dev->int_ena.val |= (1 << (channel + 24)); } else { - dev->int_ena.val &= ~(BIT(24) << (channel - RMT_LL_TX_CHAN_NUM)); + dev->int_ena.val &= ~(1 << (channel + 24)); } } static inline void rmt_ll_clear_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel) { - dev->int_clr.val = (BIT(0) << (channel)); + dev->int_clr.val = (1 << (channel)); } static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel) { - dev->int_clr.val = (BIT(16) << (channel - RMT_LL_TX_CHAN_NUM)); + dev->int_clr.val = (1 << (channel + 16)); } -static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel) +static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel) { - if(channel < RMT_LL_TX_CHAN_NUM) { - dev->int_clr.val = (BIT(4) << (channel)); - } else { - dev->int_clr.val = (BIT(20) << (channel - RMT_LL_TX_CHAN_NUM)); - } + dev->int_clr.val = (1 << (channel + 4)); +} + +static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel) +{ + dev->int_clr.val = (1 << (channel + 20)); } static inline void rmt_ll_clear_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel) { - dev->int_clr.val = (BIT(8) << (channel)); + dev->int_clr.val = (1 << (channel + 8)); } static inline void rmt_ll_clear_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel) { - dev->int_clr.val = (BIT(12) << (channel)); + dev->int_clr.val = (1 << (channel + 12)); } static inline void rmt_ll_clear_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel) { - dev->int_clr.val = (BIT(24) << (channel -RMT_LL_TX_CHAN_NUM)); + dev->int_clr.val = (1 << (channel + 24)); } static inline uint32_t rmt_ll_get_tx_end_interrupt_status(rmt_dev_t *dev) { - return dev->int_st.val & RMT_LL_TX_CHAN_MASK; + return dev->int_st.val & 0x0F; } static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 12) & RMT_LL_RX_CHAN_MASK; + return (dev->int_st.val >> 16) & 0x0F; } static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 4) & RMT_LL_TX_CHAN_MASK; + return (dev->int_st.val >> 4) & 0x0F; } static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 16) & RMT_LL_RX_CHAN_MASK; -} - -static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev) -{ - return ((dev->int_st.val >> 4) & RMT_LL_TX_CHAN_MASK) | ((dev->int_st.val >> 16) & RMT_LL_RX_CHAN_MASK); + return (dev->int_st.val >> 20) & 0x0F; } static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 8) & RMT_LL_TX_CHAN_MASK; + return (dev->int_st.val >> 8) & 0x0F; } static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 20) & RMT_LL_RX_CHAN_MASK; + return (dev->int_st.val >> 24) & 0x0F; } static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev) { - return (dev->int_st.val >> 12) & RMT_LL_TX_CHAN_MASK; + return (dev->int_st.val >> 12) & 0x0F; } -static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +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) { // In case the compiler optimise a 32bit instruction (e.g. s32i) into two 16bit instruction (e.g. s16i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. @@ -410,44 +420,44 @@ static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t dev->tx_carrier[channel].val = reg.val; } -static inline void rmt_ll_set_rx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) +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) { typeof(dev->rx_carrier[0]) reg; reg.high_thres = high_ticks; reg.low_thres = low_ticks; - dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].val = reg.val; + dev->rx_carrier[channel].val = reg.val; } -static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) +static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks ) { - if (channel < RMT_LL_TX_CHAN_NUM) { - *high_ticks = dev->tx_carrier[channel].high; - *low_ticks = dev->tx_carrier[channel].low; - } else { - *high_ticks = dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].high_thres; - *low_ticks = dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].low_thres; - } + *high_ticks = dev->tx_carrier[channel].high; + *low_ticks = dev->tx_carrier[channel].low; } -// This function has different meaning for TX and RX -// TX: enable to modulate carrier -// RX: enable to demodulate carrier -static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - if (channel < RMT_LL_TX_CHAN_NUM) { - dev->tx_conf[channel].carrier_en = enable; - } else { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.carrier_en = enable; - } + *high_ticks = dev->rx_carrier[channel].high_thres; + *low_ticks = dev->rx_carrier[channel].low_thres; } -static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) { - if (channel < RMT_LL_TX_CHAN_NUM) { - dev->tx_conf[channel].carrier_out_lv = level; - } else { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.carrier_out_lv = level; - } + dev->tx_conf[channel].carrier_en = enable; +} + +static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->rx_conf[channel].conf0.carrier_en = enable; +} + +static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +{ + dev->tx_conf[channel].carrier_out_lv = level; +} + +static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level) +{ + dev->rx_conf[channel].conf0.carrier_out_lv = level; } // set true, enable carrier in all RMT state (idle, reading, sending) @@ -457,37 +467,22 @@ static inline void rmt_ll_tx_set_carrier_always_on(rmt_dev_t *dev, uint32_t chan dev->tx_conf[channel].carrier_eff_en = !enable; } +//Writes items to the specified TX channel memory with the given offset and writen length. +//the caller should ensure that (length + off) <= (memory block * SOC_RMT_CHANNEL_MEM_WORDS) static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const rmt_item32_t *data, uint32_t length, uint32_t off) { - length = (off + length) > SOC_RMT_CHANNEL_MEM_WORDS ? (SOC_RMT_CHANNEL_MEM_WORDS - off) : length; for (uint32_t i = 0; i < length; i++) { mem->chan[channel].data32[i + off].val = data[i].val; } } -static inline void rmt_ll_enable_rx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) +static inline void rmt_ll_rx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_rx_wrap_en = enable; -} - -static inline void rmt_write_fifo(rmt_dev_t *dev, uint32_t channel, const rmt_item32_t *data, uint32_t length) -{ - for (uint32_t i = 0; i < length; i++) { - dev->data_ch[channel] = data[i].val; - } -} - -static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel) -{ - if(channel < RMT_LL_TX_CHAN_NUM) { - dev->tx_conf[channel].conf_update = 1; - } else { - dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.conf_update = 1; - } + dev->rx_conf[channel].conf1.mem_rx_wrap_en = enable; } /************************************************************************************************ - * Following Low Level APIs only used for backward compatible, will be deprecated in the future! + * Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0 ***********************************************************************************************/ static inline void rmt_ll_set_intr_enable_mask(uint32_t mask) diff --git a/components/hal/include/hal/rmt_hal.h b/components/hal/include/hal/rmt_hal.h index 8a21ac9dd4..0576718e41 100644 --- a/components/hal/include/hal/rmt_hal.h +++ b/components/hal/include/hal/rmt_hal.h @@ -41,12 +41,20 @@ typedef struct { void rmt_hal_init(rmt_hal_context_t *hal); /** - * @brief Reset RMT Channel specific HAL driver + * @brief Reset RMT TX Channel * * @param hal: RMT HAL context * @param channel: RMT channel number */ -void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel); +void rmt_hal_tx_channel_reset(rmt_hal_context_t *hal, uint32_t channel); + +/** + * @brief Reset RMT TX Channel + * + * @param hal: RMT HAL context + * @param channel: RMT channel number + */ +void rmt_hal_rx_channel_reset(rmt_hal_context_t *hal, uint32_t channel); /** * @brief Set counter clock for RMT channel @@ -56,17 +64,7 @@ void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel); * @param base_clk_hz: base clock for RMT internal channel (counter clock will divide from it) * @param counter_clk_hz: target counter clock */ -void rmt_hal_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz); - -/** - * @brief Get counter clock for RMT channel - * - * @param hal: RMT HAL context - * @param channel: RMT channel number - * @param base_clk_hz: base clock for RMT internal channel (counter clock will divide from it) - * @return counter clock in Hz - */ -uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz); +void rmt_hal_tx_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz); /** * @brief Set carrier clock for RMT channel @@ -79,17 +77,6 @@ uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uin */ void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t carrier_clk_hz, float carrier_clk_duty); -/** - * @brief Get carrier clock for RMT channel - * - * @param hal: RMT HAL context - * @param channel: RMT channel number - * @param base_clk_hz: base clock for RMT carrier generation - * @param carrier_clk_hz: target carrier clock - * @param carrier_clk_duty: duty ratio of carrier clock - */ -void rmt_hal_get_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t *carrier_clk_hz, float *carrier_clk_duty); - /** * @brief Set filter threshold for RMT Receive channel * @@ -120,18 +107,6 @@ void rmt_hal_set_rx_idle_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_ */ uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t *buf); -/** - * @brief Transmit a from by RMT - * - * @param hal: RMT HAL context - * @param channel: RMT channel number - * @param src: RMT items to transmit - * @param length: length of RMT items to transmit - * @param offset: offset of RMT internal memory to store the items. - * Note: the caller should ensure that (length + offset) <= (memory block * SOC_RMT_CHANNEL_MEM_WORDS). - */ -void rmt_hal_transmit(rmt_hal_context_t *hal, uint32_t channel, const rmt_item32_t *src, uint32_t length, uint32_t offset); - #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/rmt_types.h b/components/hal/include/hal/rmt_types.h index b079077b34..478629bcc1 100644 --- a/components/hal/include/hal/rmt_types.h +++ b/components/hal/include/hal/rmt_types.h @@ -53,14 +53,11 @@ typedef enum { * */ typedef enum { -#ifdef SOC_RMT_SUPPORT_REF_TICK +#if SOC_RMT_SUPPORT_REF_TICK RMT_BASECLK_REF = 0, /*!< RMT source clock is REF_TICK, 1MHz by default */ #endif RMT_BASECLK_APB = 1, /*!< RMT source clock is APB CLK, 80Mhz by default */ -#ifdef SOC_RMT_SUPPORT_RTC8M_CLOCK - RMT_BASECLK_RTC8M = 2, /*!< RMT source clock is RTC 8M clock, 8Mhz by default */ -#endif -#ifdef SOC_RMT_SUPPORT_XTAL_CLOCK +#if SOC_RMT_SUPPORT_XTAL RMT_BASECLK_XTAL = 3, /*!< RMT source clock is XTAL clock, 40Mhz by default */ #endif RMT_BASECLK_MAX, diff --git a/components/hal/rmt_hal.c b/components/hal/rmt_hal.c index 40fdf393d1..14eb11bcca 100644 --- a/components/hal/rmt_hal.c +++ b/components/hal/rmt_hal.c @@ -20,30 +20,31 @@ void rmt_hal_init(rmt_hal_context_t *hal) hal->mem = &RMTMEM; } -void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel) +void rmt_hal_tx_channel_reset(rmt_hal_context_t *hal, uint32_t channel) { - rmt_ll_reset_tx_pointer(hal->regs, channel); - rmt_ll_reset_rx_pointer(hal->regs, channel); - rmt_ll_enable_err_interrupt(hal->regs, channel, false); + rmt_ll_tx_reset_pointer(hal->regs, channel); + rmt_ll_enable_tx_err_interrupt(hal->regs, channel, false); rmt_ll_enable_tx_end_interrupt(hal->regs, channel, false); rmt_ll_enable_tx_thres_interrupt(hal->regs, channel, false); - rmt_ll_enable_rx_end_interrupt(hal->regs, channel, false); - rmt_ll_clear_err_interrupt(hal->regs, channel); + rmt_ll_clear_tx_err_interrupt(hal->regs, channel); rmt_ll_clear_tx_end_interrupt(hal->regs, channel); rmt_ll_clear_tx_thres_interrupt(hal->regs, channel); +} + +void rmt_hal_rx_channel_reset(rmt_hal_context_t *hal, uint32_t channel) +{ + rmt_ll_rx_reset_pointer(hal->regs, channel); + rmt_ll_enable_rx_err_interrupt(hal->regs, channel, false); + rmt_ll_enable_rx_end_interrupt(hal->regs, channel, false); + rmt_ll_clear_rx_err_interrupt(hal->regs, channel); rmt_ll_clear_rx_end_interrupt(hal->regs, channel); } -void rmt_hal_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz) +void rmt_hal_tx_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz) { - rmt_ll_reset_counter_clock_div(hal->regs, channel); + rmt_ll_tx_reset_counter_clock_div(hal->regs, channel); uint32_t counter_div = (base_clk_hz + counter_clk_hz / 2) / counter_clk_hz; - rmt_ll_set_counter_clock_div(hal->regs, channel, counter_div); -} - -uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz) -{ - return base_clk_hz / rmt_ll_get_counter_clock_div(hal->regs, channel); + rmt_ll_tx_set_counter_clock_div(hal->regs, channel, counter_div); } void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t carrier_clk_hz, float carrier_clk_duty) @@ -51,34 +52,25 @@ void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_ uint32_t carrier_div = (base_clk_hz + carrier_clk_hz / 2) / carrier_clk_hz; uint32_t div_high = (uint32_t)(carrier_div * carrier_clk_duty); uint32_t div_low = carrier_div - div_high; - rmt_ll_set_tx_carrier_high_low_ticks(hal->regs, channel, div_high, div_low); -} - -void rmt_hal_get_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t *carrier_clk_hz, float *carrier_clk_duty) -{ - uint32_t div_high = 0; - uint32_t div_low = 0; - rmt_ll_get_carrier_high_low_ticks(hal->regs, channel, &div_high, &div_low); - *carrier_clk_hz = base_clk_hz / (div_high + div_low); - *carrier_clk_duty = (float)div_high / (div_high + div_low); + rmt_ll_tx_set_carrier_high_low_ticks(hal->regs, channel, div_high, div_low); } void rmt_hal_set_rx_filter_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t thres_us) { uint32_t thres = (uint32_t)(base_clk_hz / 1e6 * thres_us); - rmt_ll_set_rx_filter_thres(hal->regs, channel, thres); + rmt_ll_rx_set_filter_thres(hal->regs, channel, thres); } void rmt_hal_set_rx_idle_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t thres_us) { uint32_t thres = (uint32_t)(base_clk_hz / 1e6 * thres_us); - rmt_ll_set_rx_idle_thres(hal->regs, channel, thres); + rmt_ll_rx_set_idle_thres(hal->regs, channel, thres); } uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t *buf) { uint32_t len = 0; - rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW); + rmt_ll_rx_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW); for (len = 0; len < SOC_RMT_CHANNEL_MEM_WORDS; len++) { buf[len].val = hal->mem->chan[channel].data32[len].val; if (!(buf[len].val & 0x7FFF)) { @@ -88,14 +80,7 @@ uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t break; } } - rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW); - rmt_ll_reset_rx_pointer(hal->regs, channel); + rmt_ll_rx_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW); + rmt_ll_rx_reset_pointer(hal->regs, channel); return len; } - -void rmt_hal_transmit(rmt_hal_context_t *hal, uint32_t channel, const rmt_item32_t *src, uint32_t length, uint32_t offset) -{ - rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW); - rmt_ll_write_memory(hal->mem, channel, src, length, offset); - rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW); -} \ No newline at end of file diff --git a/components/soc/esp32/CMakeLists.txt b/components/soc/esp32/CMakeLists.txt index fd35be0d5d..da24107659 100644 --- a/components/soc/esp32/CMakeLists.txt +++ b/components/soc/esp32/CMakeLists.txt @@ -5,8 +5,9 @@ set(srcs "i2c_periph.c" "i2s_periph.c" "interrupts.c" - "pcnt_periph.c" "ledc_periph.c" + "pcnt_periph.c" + "rmt_periph.c" "rtc_io_periph.c" "rtc_periph.c" "sdio_slave_periph.c" diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index a168ef5fbe..b882876526 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -159,9 +159,12 @@ #define SOC_PCNT_UNIT_CHANNEL_NUM (2) /*-------------------------- RMT CAPS ----------------------------------------*/ -#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */ -#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */ -#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */ +#define SOC_RMT_TX_CHANNELS_NUM (8) /*!< Number of channels that capable of Transmit */ +#define SOC_RMT_RX_CHANNELS_NUM (8) /*!< Number of channels that capable of Receive */ +#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels (each channel can be configured to either TX or RX) */ +#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_SOURCE_CLK_INDEPENDENT (1) /*!< Can select different source clock for channels */ /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 18 diff --git a/components/soc/esp32/rmt_periph.c b/components/soc/esp32/rmt_periph.c new file mode 100644 index 0000000000..0228af8a53 --- /dev/null +++ b/components/soc/esp32/rmt_periph.c @@ -0,0 +1,56 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "soc/rmt_periph.h" +#include "soc/gpio_sig_map.h" +#include "soc/soc.h" + +const rmt_signal_conn_t rmt_periph_signals = { + .module = PERIPH_RMT_MODULE, + .irq = ETS_RMT_INTR_SOURCE, + .channels = { + [0] = { + .tx_sig = RMT_SIG_OUT0_IDX, + .rx_sig = -1 + }, + [1] = { + .tx_sig = RMT_SIG_OUT1_IDX, + .rx_sig = -1 + }, + [2] = { + .tx_sig = RMT_SIG_OUT2_IDX, + .rx_sig = -1 + }, + [3] = { + .tx_sig = RMT_SIG_OUT3_IDX, + .rx_sig = -1 + }, + [4] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN0_IDX + }, + [5] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN1_IDX + }, + [6] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN2_IDX + }, + [7] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN3_IDX + } + } +}; diff --git a/components/soc/esp32s2/CMakeLists.txt b/components/soc/esp32s2/CMakeLists.txt index e8846527f9..e25f98acb0 100644 --- a/components/soc/esp32s2/CMakeLists.txt +++ b/components/soc/esp32s2/CMakeLists.txt @@ -8,6 +8,7 @@ set(srcs "interrupts.c" "ledc_periph.c" "pcnt_periph.c" + "rmt_periph.c" "rtc_io_periph.c" "rtc_periph.c" "sigmadelta_periph.c" diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index f61e2796b6..f8a9b5205b 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -143,13 +143,16 @@ #define SOC_PCNT_UNIT_CHANNEL_NUM (2) /*-------------------------- RMT CAPS ----------------------------------------*/ -#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */ -#define SOC_RMT_CHANNELS_NUM (4) /*!< Total 4 channels */ -#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_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ -#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */ -#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */ +#define SOC_RMT_TX_CHANNELS_NUM (4) /*!< Number of channels that capable of Transmit */ +#define SOC_RMT_RX_CHANNELS_NUM (4) /*!< Number of channels that capable of Receive */ +#define SOC_RMT_CHANNELS_NUM (4) /*!< Total 4 channels (each channel can be configured to either TX or RX) */ +#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_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ +#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */ +#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */ +#define SOC_RMT_SOURCE_CLK_INDEPENDENT (1) /*!< Can select different source clock for channels */ /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 22 diff --git a/components/soc/esp32s2/rmt_periph.c b/components/soc/esp32s2/rmt_periph.c new file mode 100644 index 0000000000..35bd844145 --- /dev/null +++ b/components/soc/esp32s2/rmt_periph.c @@ -0,0 +1,39 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "soc/rmt_periph.h" +#include "soc/gpio_sig_map.h" + +const rmt_signal_conn_t rmt_periph_signals = { + .module = PERIPH_RMT_MODULE, + .irq = ETS_RMT_INTR_SOURCE, + .channels = { + [0] = { + .tx_sig = RMT_SIG_OUT0_IDX, + .rx_sig = RMT_SIG_IN0_IDX + }, + [1] = { + .tx_sig = RMT_SIG_OUT1_IDX, + .rx_sig = RMT_SIG_IN1_IDX + }, + [2] = { + .tx_sig = RMT_SIG_OUT2_IDX, + .rx_sig = RMT_SIG_IN2_IDX + }, + [3] = { + .tx_sig = RMT_SIG_OUT3_IDX, + .rx_sig = RMT_SIG_IN3_IDX + } + } +}; diff --git a/components/soc/esp32s3/CMakeLists.txt b/components/soc/esp32s3/CMakeLists.txt index 8372dfdbe9..92325f9976 100644 --- a/components/soc/esp32s3/CMakeLists.txt +++ b/components/soc/esp32s3/CMakeLists.txt @@ -8,6 +8,7 @@ set(srcs "interrupts.c" "ledc_periph.c" "pcnt_periph.c" + "rmt_periph.c" "rtc_io_periph.c" "rtc_periph.c" "sdio_slave_periph.c" diff --git a/components/soc/esp32s3/include/soc/rmt_caps.h b/components/soc/esp32s3/include/soc/rmt_caps.h deleted file mode 100644 index adbfa7508f..0000000000 --- a/components/soc/esp32s3/include/soc/rmt_caps.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ -#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */ -#define SOC_RMT_TX_RX_CHANNEL_INDEPENDENT (1) /*!< TX channels and RX channels are independent, channel0~3 transmit only and channel4~8 receive only */ -#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_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ -#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */ -#define SOC_RMT_SUPPORT_RTC8M_CLOCK (1) /*!< Support set RTC 8M clock as the RMT clock source */ -#define SOC_RMT_SUPPORT_XTAL_CLOCK (1) /*!< Support set XTAL clock as the RMT clock source */ - -#ifdef __cplusplus -} -#endif diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index cc8501cd0b..509c03b9ec 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -53,15 +53,15 @@ #define SOC_PCNT_UNIT_CHANNEL_NUM (2) /*-------------------------- RMT CAPS ----------------------------------------*/ -#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ -#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */ -#define SOC_RMT_TX_RX_CHANNEL_INDEPENDENT (1) /*!< TX channels and RX channels are independent, channel0~3 transmit only and channel4~8 receive only */ -#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_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ -#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */ -#define SOC_RMT_SUPPORT_RTC8M_CLOCK (1) /*!< Support set RTC 8M clock as the RMT clock source */ -#define SOC_RMT_SUPPORT_XTAL_CLOCK (1) /*!< Support set XTAL clock as the RMT clock source */ +#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ +#define SOC_RMT_TX_CHANNELS_NUM (4) /*!< Number of channels that capable of Transmit */ +#define SOC_RMT_RX_CHANNELS_NUM (4) /*!< Number of channels that capable of Receive */ +#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels (each channel can be configured to either TX or RX) */ +#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_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ +#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */ +#define SOC_RMT_SUPPORT_XTAL (1) /*!< Support set XTAL clock as the RMT clock source */ /*-------------------------- RTCIO CAPS --------------------------------------*/ #include "rtc_io_caps.h" diff --git a/components/soc/esp32s3/rmt_periph.c b/components/soc/esp32s3/rmt_periph.c new file mode 100644 index 0000000000..611d6425f6 --- /dev/null +++ b/components/soc/esp32s3/rmt_periph.c @@ -0,0 +1,55 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "soc/rmt_periph.h" +#include "soc/gpio_sig_map.h" + +const rmt_signal_conn_t rmt_periph_signals = { + .module = PERIPH_RMT_MODULE, + .irq = ETS_RMT_INTR_SOURCE, + .channels = { + [0] = { + .tx_sig = RMT_SIG_OUT0_IDX, + .rx_sig = -1 + }, + [1] = { + .tx_sig = RMT_SIG_OUT1_IDX, + .rx_sig = -1 + }, + [2] = { + .tx_sig = RMT_SIG_OUT2_IDX, + .rx_sig = -1 + }, + [3] = { + .tx_sig = RMT_SIG_OUT3_IDX, + .rx_sig = -1 + }, + [4] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN0_IDX + }, + [5] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN1_IDX + }, + [6] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN2_IDX + }, + [7] = { + .tx_sig = -1, + .rx_sig = RMT_SIG_IN3_IDX + } + } +}; diff --git a/components/soc/include/soc/rmt_periph.h b/components/soc/include/soc/rmt_periph.h index a46a6f526b..4f46d9255b 100644 --- a/components/soc/include/soc/rmt_periph.h +++ b/components/soc/include/soc/rmt_periph.h @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,5 +13,27 @@ // limitations under the License. #pragma once -#include "soc/rmt_reg.h" -#include "soc/rmt_struct.h" + +#include "soc/soc_caps.h" +#include "soc/periph_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + struct { + struct { + const int tx_sig; + const int rx_sig; + }; + } channels[SOC_RMT_CHANNELS_NUM]; + const int irq; + const periph_module_t module; +} rmt_signal_conn_t; + +extern const rmt_signal_conn_t rmt_periph_signals; + +#ifdef __cplusplus +} +#endif diff --git a/tools/unit-test-app/components/test_utils/ref_clock.c b/tools/unit-test-app/components/test_utils/ref_clock.c index d97244ec65..4be72e7db3 100644 --- a/tools/unit-test-app/components/test_utils/ref_clock.c +++ b/tools/unit-test-app/components/test_utils/ref_clock.c @@ -34,6 +34,8 @@ #include "driver/periph_ctrl.h" #include "soc/gpio_sig_map.h" #include "soc/gpio_periph.h" +#include "soc/soc_caps.h" +#include "hal/rmt_types.h" #include "hal/rmt_hal.h" #include "hal/rmt_ll.h" #include "hal/pcnt_hal.h" @@ -74,26 +76,26 @@ void ref_clock_init(void) }; rmt_ll_enable_drive_clock(s_rmt_hal.regs, true); -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 - rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 0); // select REF_TICK (1MHz) -#else - rmt_ll_set_sclk(s_rmt_hal.regs, 3, 39, 0, 0); // XTAL(40MHz), rmt_sclk => 1MHz (40/(1+39)) +#if SOC_RMT_SUPPORT_XTAL + rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, RMT_BASECLK_XTAL, 39, 0, 0); // XTAL(40MHz), rmt_sclk => 1MHz (40/(1+39)) +#elif SOC_RMT_SUPPORT_REF_TICK + rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, RMT_BASECLK_REF, 0, 0, 0); // select REF_TICK (1MHz) #endif - rmt_hal_set_counter_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 1000000); // counter clock: 1MHz - rmt_ll_enable_tx_idle(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); // enable idle output - rmt_ll_set_tx_idle_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); // idle level: 1 - rmt_ll_enable_carrier(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); + rmt_hal_tx_set_counter_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 1000000); // counter clock: 1MHz + rmt_ll_tx_enable_idle(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); // enable idle output + rmt_ll_tx_set_idle_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); // idle level: 1 + rmt_ll_tx_enable_carrier_modulation(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); #if !CONFIG_IDF_TARGET_ESP32 rmt_ll_tx_set_carrier_always_on(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); #endif rmt_hal_set_carrier_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 500000, 0.5); // set carrier to 500KHz - rmt_ll_set_carrier_on_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); + rmt_ll_tx_set_carrier_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); rmt_ll_enable_mem_access(s_rmt_hal.regs, true); - rmt_ll_reset_tx_pointer(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL); - rmt_ll_set_mem_blocks(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); + rmt_ll_tx_reset_pointer(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL); + rmt_ll_tx_set_mem_blocks(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); rmt_ll_write_memory(s_rmt_hal.mem, REF_CLOCK_RMT_CHANNEL, &data, 1, 0); - rmt_ll_enable_tx_loop(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false); - rmt_ll_start_tx(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL); + rmt_ll_tx_enable_loop(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false); + rmt_ll_tx_start(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL); // Route signal to PCNT esp_rom_gpio_connect_in_signal(REF_CLOCK_GPIO, PCNT_SIG_CH0_IN0_IDX, false); @@ -148,7 +150,7 @@ void ref_clock_deinit() s_intr_handle = NULL; // Disable RMT - rmt_ll_enable_carrier(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false); + rmt_ll_tx_enable_carrier_modulation(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false); periph_module_disable(PERIPH_RMT_MODULE); // Disable PCNT