mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'feature/bringup_esp32s3_fpga_update_rmt_driver' into 'master'
rmt: support esp32s3 Closes IDF-1773 See merge request espressif/esp-idf!10292
This commit is contained in:
commit
3882c2b8ed
@ -28,7 +28,11 @@ 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_AWARE_DFS (1 << 0) /*!< Channel can work during APB clock scaling */
|
||||
|
||||
/** @cond */
|
||||
#define RMT_CHANNEL_FLAGS_ALWAYS_ON RMT_CHANNEL_FLAGS_AWARE_DFS /*!< Deprecated name, defined here for compatibility */
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Define memory space of each RMT channel (in words = 4 bytes)
|
||||
@ -357,7 +361,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 +369,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 +519,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 +832,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
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.h>
|
||||
#include "esp_compiler.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
@ -24,6 +25,8 @@
|
||||
#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"
|
||||
#include "esp_rom_gpio.h"
|
||||
@ -46,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;
|
||||
@ -107,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();
|
||||
@ -124,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();
|
||||
@ -134,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;
|
||||
}
|
||||
@ -144,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;
|
||||
}
|
||||
@ -173,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;
|
||||
}
|
||||
@ -183,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;
|
||||
}
|
||||
@ -191,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;
|
||||
}
|
||||
@ -221,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
|
||||
@ -232,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();
|
||||
@ -340,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;
|
||||
}
|
||||
@ -353,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;
|
||||
}
|
||||
@ -372,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;
|
||||
}
|
||||
@ -383,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;
|
||||
}
|
||||
@ -392,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;
|
||||
}
|
||||
@ -413,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;
|
||||
}
|
||||
@ -423,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;
|
||||
@ -444,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();
|
||||
@ -460,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 {
|
||||
@ -486,15 +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);
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, RMT_SIG_IN0_IDX + channel, 0);
|
||||
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;
|
||||
@ -506,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);
|
||||
|
||||
@ -515,52 +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) {
|
||||
|
||||
if (rmt_param->flags & RMT_CHANNEL_FLAGS_AWARE_DFS) {
|
||||
#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, 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);
|
||||
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);
|
||||
}
|
||||
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, 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();
|
||||
|
||||
@ -571,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();
|
||||
@ -597,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;
|
||||
}
|
||||
|
||||
@ -617,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;
|
||||
@ -641,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)
|
||||
@ -649,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) {
|
||||
@ -681,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;
|
||||
@ -749,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;
|
||||
@ -778,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);
|
||||
}
|
||||
@ -791,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) {
|
||||
@ -828,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) {
|
||||
@ -861,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();
|
||||
@ -878,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) {
|
||||
@ -995,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);
|
||||
@ -1018,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;
|
||||
@ -1059,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;
|
||||
@ -1094,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
|
||||
@ -1122,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
|
||||
@ -1136,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);
|
||||
@ -1189,10 +1291,16 @@ esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz)
|
||||
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
RMT_CHECK(clock_hz, "parameter clock_hz can't be null", ESP_ERR_INVALID_ARG);
|
||||
RMT_ENTER_CRITICAL();
|
||||
if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_REF) {
|
||||
*clock_hz = rmt_hal_get_counter_clock(&rmt_contex.hal, channel, REF_CLK_FREQ);
|
||||
uint32_t rmt_source_clk_hz = 0;
|
||||
#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
|
||||
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_hal_get_counter_clock(&rmt_contex.hal, channel, APB_CLK_FREQ);
|
||||
*clock_hz = rmt_source_clk_hz / rmt_ll_tx_get_counter_clock_div(rmt_contex.hal.regs, channel);
|
||||
}
|
||||
RMT_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
@ -1201,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;
|
||||
|
@ -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
|
||||
@ -31,7 +32,7 @@ static void rmt_setup_testbench(int tx_channel, int rx_channel, uint32_t flags)
|
||||
if (tx_channel >= 0) {
|
||||
rmt_config_t tx_config = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, tx_channel);
|
||||
if (flags & RMT_TESTBENCH_FLAGS_ALWAYS_ON) {
|
||||
tx_config.flags |= RMT_CHANNEL_FLAGS_ALWAYS_ON;
|
||||
tx_config.flags |= RMT_CHANNEL_FLAGS_AWARE_DFS;
|
||||
}
|
||||
if (flags & RMT_TESTBENCH_FLAGS_CARRIER_ON) {
|
||||
tx_config.tx_config.carrier_en = true;
|
||||
@ -48,7 +49,7 @@ static void rmt_setup_testbench(int tx_channel, int rx_channel, uint32_t flags)
|
||||
if (rx_channel >= 0) {
|
||||
rmt_config_t rx_config = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, rx_channel);
|
||||
if (flags & RMT_TESTBENCH_FLAGS_ALWAYS_ON) {
|
||||
rx_config.flags |= RMT_CHANNEL_FLAGS_ALWAYS_ON;
|
||||
rx_config.flags |= RMT_CHANNEL_FLAGS_AWARE_DFS;
|
||||
}
|
||||
#if SOC_RMT_SUPPORT_RX_DEMODULATION
|
||||
if (flags & RMT_TESTBENCH_FLAGS_CARRIER_ON) {
|
||||
@ -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;
|
||||
@ -141,13 +142,18 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]")
|
||||
TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt));
|
||||
TEST_ASSERT_EQUAL_UINT8(160, div_cnt);
|
||||
|
||||
#if SOC_RMT_SUPPORT_REF_TICK
|
||||
TEST_ESP_OK(rmt_set_source_clk(channel, RMT_BASECLK_REF));
|
||||
TEST_ESP_OK(rmt_get_source_clk(channel, &src_clk));
|
||||
TEST_ASSERT_EQUAL_INT(RMT_BASECLK_REF, src_clk);
|
||||
#endif
|
||||
|
||||
#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));
|
||||
@ -155,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));
|
||||
@ -163,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);
|
||||
}
|
||||
|
||||
@ -188,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));
|
||||
@ -205,7 +222,7 @@ static void do_nec_tx_rx(uint32_t flags)
|
||||
uint32_t cmd = 0x20;
|
||||
bool repeat = false;
|
||||
int tx_channel = 0;
|
||||
int rx_channel = 1;
|
||||
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
|
||||
|
||||
// test on different flags combinations
|
||||
rmt_setup_testbench(tx_channel, rx_channel, flags);
|
||||
@ -261,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);
|
||||
}
|
||||
@ -302,7 +319,7 @@ TEST_CASE("RMT TX stop", "[rmt]")
|
||||
uint32_t cmd = 0x20;
|
||||
bool repeat = false;
|
||||
int tx_channel = 0;
|
||||
int rx_channel = 1;
|
||||
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
|
||||
|
||||
rmt_setup_testbench(tx_channel, rx_channel, 0);
|
||||
|
||||
@ -361,7 +378,7 @@ TEST_CASE("RMT TX stop", "[rmt]")
|
||||
TEST_CASE("RMT Ping-Pong operation", "[rmt]")
|
||||
{
|
||||
int tx_channel = 0;
|
||||
int rx_channel = 1;
|
||||
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]);
|
||||
@ -478,7 +495,7 @@ TEST_CASE("RMT TX loop", "[rmt]")
|
||||
uint32_t cmd = 0x20;
|
||||
bool repeat = false;
|
||||
int tx_channel = 0;
|
||||
int rx_channel = 1;
|
||||
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);
|
||||
@ -521,5 +538,3 @@ TEST_CASE("RMT TX loop", "[rmt]")
|
||||
rmt_clean_testbench(tx_channel, rx_channel);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -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, 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)
|
||||
|
@ -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, 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)
|
||||
|
@ -25,15 +25,8 @@ extern "C" {
|
||||
#define RMT_LL_HW_BASE (&RMT)
|
||||
#define RMT_LL_MEM_BASE (&RMTMEM)
|
||||
|
||||
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)
|
||||
{
|
||||
@ -41,38 +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].apb_mem_rst = 1;
|
||||
dev->tx_conf[channel].mem_rd_rst = 1;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.apb_mem_rst = 1;
|
||||
dev->rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->sys_conf.mem_force_pu = !enable;
|
||||
@ -87,113 +48,191 @@ 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)
|
||||
{
|
||||
dev->tx_conf[channel].mem_size = block_num;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
|
||||
{
|
||||
dev->tx_conf[channel].div_cnt = div;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].div_cnt;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, bool 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)
|
||||
{
|
||||
// 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 0;
|
||||
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)
|
||||
{
|
||||
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 0;
|
||||
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;
|
||||
}
|
||||
|
||||
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return false;
|
||||
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.tx_sim_en = 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 & 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].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].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 uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -203,138 +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 0;
|
||||
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].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 0;
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel * 3));
|
||||
dev->int_ena.val |= (enable << (channel * 3));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << channel);
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel * 3 + 1));
|
||||
dev->int_ena.val |= (enable << (channel * 3 + 1));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 16));
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel * 3 + 2));
|
||||
dev->int_ena.val |= (enable << (channel * 3 + 2));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 20));
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel + 12));
|
||||
dev->int_ena.val |= (enable << (channel + 12));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 8));
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel + 16));
|
||||
dev->int_ena.val |= (enable << (channel + 16));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 12));
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
dev->int_ena.val &= ~(1 << (channel + 20));
|
||||
dev->int_ena.val |= (enable << (channel + 20));
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 24));
|
||||
} else {
|
||||
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 = (1 << (channel * 3));
|
||||
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 = (1 << (channel * 3 + 1));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel * 3 + 2));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 12));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 16));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_rx_thres_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 + 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 = (1 << (channel + 8));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_loop_interrupt(rmt_dev_t *dev, uint32_t 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 = (1 << (channel + 24));
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_end_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
uint32_t status = dev->int_st.val;
|
||||
return ((status & 0x01) >> 0) | ((status & 0x08) >> 2) | ((status & 0x40) >> 4) | ((status & 0x200) >> 6);
|
||||
return dev->int_st.val & 0x0F;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
uint32_t status = dev->int_st.val;
|
||||
return ((status & 0x02) >> 1) | ((status & 0x10) >> 3) | ((status & 0x80) >> 5) | ((status & 0x400) >> 7);
|
||||
return (dev->int_st.val >> 16) & 0x0F;
|
||||
}
|
||||
|
||||
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);
|
||||
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 >> 20) & 0x0F;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
uint32_t status = dev->int_st.val;
|
||||
return (status & 0xF000) >> 12;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
uint32_t status = dev->int_st.val;
|
||||
return (status & 0xF0000) >> 16;
|
||||
return (dev->int_st.val >> 8) & 0x0F;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
uint32_t status = dev->int_st.val;
|
||||
return (status & 0xF00000) >> 20;
|
||||
return (dev->int_st.val >> 24) & 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 uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 12) & 0x0F;
|
||||
}
|
||||
|
||||
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.
|
||||
@ -344,7 +420,7 @@ 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;
|
||||
@ -352,20 +428,38 @@ static inline void rmt_ll_set_rx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t
|
||||
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 )
|
||||
{
|
||||
*high_ticks = dev->tx_carrier[channel].high;
|
||||
*low_ticks = dev->tx_carrier[channel].low;
|
||||
}
|
||||
|
||||
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->rx_carrier[channel].high_thres;
|
||||
*low_ticks = dev->rx_carrier[channel].low_thres;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].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->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)
|
||||
// set false, enable carrier only in sending state (i.e. there're effective data in RAM to be sent)
|
||||
static inline void rmt_ll_tx_set_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
@ -373,20 +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].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)
|
||||
|
@ -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
|
||||
|
@ -53,8 +53,13 @@ typedef enum {
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
RMT_BASECLK_REF, /*!< RMT source clock is REF_TICK, 1MHz by default */
|
||||
RMT_BASECLK_APB, /*!< RMT source clock is APB CLK, 80Mhz by default */
|
||||
#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 */
|
||||
#if SOC_RMT_SUPPORT_XTAL
|
||||
RMT_BASECLK_XTAL = 3, /*!< RMT source clock is XTAL clock, 40Mhz by default */
|
||||
#endif
|
||||
RMT_BASECLK_MAX,
|
||||
} rmt_source_clk_t;
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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"
|
||||
|
@ -159,8 +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_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
|
||||
|
56
components/soc/esp32/rmt_periph.c
Normal file
56
components/soc/esp32/rmt_periph.c
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
};
|
@ -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"
|
||||
|
@ -143,12 +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_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
|
||||
|
39
components/soc/esp32s2/rmt_periph.c
Normal file
39
components/soc/esp32s2/rmt_periph.c
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
};
|
@ -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"
|
||||
|
@ -1,30 +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 (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 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef volatile struct {
|
||||
uint32_t data_ch[8];
|
||||
union {
|
||||
@ -281,11 +283,11 @@ typedef volatile struct {
|
||||
} sys_conf;
|
||||
union {
|
||||
struct {
|
||||
uint32_t tx_sim_ch0 : 1;
|
||||
uint32_t tx_sim_ch1 : 1;
|
||||
uint32_t tx_sim_ch2 : 1;
|
||||
uint32_t tx_sim_ch3 : 1;
|
||||
uint32_t tx_sim_en : 1;
|
||||
uint32_t ch0 : 1;
|
||||
uint32_t ch1 : 1;
|
||||
uint32_t ch2 : 1;
|
||||
uint32_t ch3 : 1;
|
||||
uint32_t en : 1;
|
||||
uint32_t reserved5 : 27;
|
||||
};
|
||||
uint32_t val;
|
||||
|
@ -53,7 +53,15 @@
|
||||
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
|
||||
|
||||
/*-------------------------- RMT CAPS ----------------------------------------*/
|
||||
#include "rmt_caps.h"
|
||||
#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"
|
||||
|
55
components/soc/esp32s3/rmt_periph.c
Normal file
55
components/soc/esp32s3/rmt_periph.c
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
};
|
@ -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
|
||||
|
@ -115,9 +115,9 @@ Common Parameters
|
||||
* How many **memory blocks** will be used by the channel, set with **mem_block_num**.
|
||||
* Extra miscellaneous parameters for the channel can be set in the **flags**.
|
||||
|
||||
* When **RMT_CHANNEL_FLAGS_ALWAYS_ON** is set, RMT channel will take REF_TICK as source clock. The benefit is, RMT channel can continue work even when APB clock is changing. See :doc:`power_management <../system/power_management>` for more information.
|
||||
* When **RMT_CHANNEL_FLAGS_AWARE_DFS** is set, RMT channel will take REF_TICK or XTAL as source clock. The benefit is, RMT channel can continue work even when APB clock is changing. See :doc:`power_management <../system/power_management>` for more information.
|
||||
|
||||
* A **clock divider**, that will determine the range of pulse length generated by the RMT transmitter or discriminated by the receiver. Selected by setting **clk_div** to a value within [1 .. 255] range. The RMT source clock is typically APB CLK, 80Mhz by default. But when **RMT_CHANNEL_FLAGS_ALWAYS_ON** is set in **flags**, RMT source clock is changed to REF_TICK.
|
||||
* A **clock divider**, that will determine the range of pulse length generated by the RMT transmitter or discriminated by the receiver. Selected by setting **clk_div** to a value within [1 .. 255] range. The RMT source clock is typically APB CLK, 80Mhz by default. But when **RMT_CHANNEL_FLAGS_AWARE_DFS** is set in **flags**, RMT source clock is changed to REF_TICK or XTAL.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -93,7 +93,7 @@ The following peripherals work normally even when the APB frequency is changing:
|
||||
|
||||
- **UART**: if REF_TICK is used as a clock source. See `use_ref_tick` member of :cpp:class:`uart_config_t`.
|
||||
- **LEDC**: if REF_TICK is used as a clock source. See :cpp:func:`ledc_timer_config` function.
|
||||
- **RMT**: if REF_TICK is used as a clock source. See `flags` member of :cpp:class:`rmt_config_t` and macro `RMT_CHANNEL_FLAGS_ALWAYS_ON`.
|
||||
- **RMT**: if REF_TICK or XTAL is used as a clock source. See `flags` member of :cpp:class:`rmt_config_t` and macro `RMT_CHANNEL_FLAGS_AWARE_DFS`.
|
||||
|
||||
Currently, the following peripheral drivers are aware of DFS and will use the ``ESP_PM_APB_FREQ_MAX`` lock for the duration of the transaction:
|
||||
|
||||
|
@ -89,7 +89,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
|
||||
|
||||
- **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`。
|
||||
- **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。
|
||||
- **RMT**:如果 REF_TICK 用作时钟源,则 RMT 不受 APB 频率变更影响。请查看 :cpp:class:`rmt_config_t` 结构体中的 `flags` 成员以及 `RMT_CHANNEL_FLAGS_ALWAYS_ON` 宏。
|
||||
- **RMT**:如果 REF_TICK 或者 XTAL 被用作时钟源,则 RMT 不受 APB 频率变更影响。请查看 :cpp:class:`rmt_config_t` 结构体中的 `flags` 成员以及 `RMT_CHANNEL_FLAGS_AWARE_DFS` 宏。
|
||||
|
||||
目前以下外设驱动程序可感知动态调频,并在调频期间使用 ``ESP_PM_APB_FREQ_MAX`` 锁:
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user