Merge branch 'feature/rmt_clock_support_ref_tick' into 'master'

rmt: support ref tick && refactor unit test && re-enable unit test on ESP32-S2

Closes IDFGH-1715

See merge request espressif/esp-idf!7614
This commit is contained in:
Angus Gratton
2020-03-06 15:03:52 +08:00
15 changed files with 297 additions and 764 deletions

View File

@@ -28,6 +28,8 @@ extern "C" {
#include "soc/rmt_struct.h" #include "soc/rmt_struct.h"
#include "hal/rmt_types.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) */
/** /**
* @brief Define memory space of each RMT channel (in words = 4 bytes) * @brief Define memory space of each RMT channel (in words = 4 bytes)
* *
@@ -65,6 +67,7 @@ typedef struct {
gpio_num_t gpio_num; /*!< RMT GPIO number */ gpio_num_t gpio_num; /*!< RMT GPIO number */
uint8_t clk_div; /*!< RMT channel counter divider */ uint8_t clk_div; /*!< RMT channel counter divider */
uint8_t mem_block_num; /*!< RMT memory block number */ uint8_t mem_block_num; /*!< RMT memory block number */
uint32_t flags; /*!< RMT channel extra configurations, OR'd with RMT_CHANNEL_FLAGS_[*] */
union { union {
rmt_tx_config_t tx_config; /*!< RMT TX parameter */ rmt_tx_config_t tx_config; /*!< RMT TX parameter */
rmt_rx_config_t rx_config; /*!< RMT RX parameter */ rmt_rx_config_t rx_config; /*!< RMT RX parameter */
@@ -82,6 +85,7 @@ typedef struct {
.gpio_num = gpio, \ .gpio_num = gpio, \
.clk_div = 80, \ .clk_div = 80, \
.mem_block_num = 1, \ .mem_block_num = 1, \
.flags = 0, \
.tx_config = { \ .tx_config = { \
.carrier_freq_hz = 38000, \ .carrier_freq_hz = 38000, \
.carrier_level = RMT_CARRIER_LEVEL_HIGH, \ .carrier_level = RMT_CARRIER_LEVEL_HIGH, \
@@ -104,6 +108,7 @@ typedef struct {
.gpio_num = gpio, \ .gpio_num = gpio, \
.clk_div = 80, \ .clk_div = 80, \
.mem_block_num = 1, \ .mem_block_num = 1, \
.flags = 0, \
.rx_config = { \ .rx_config = { \
.idle_threshold = 12000, \ .idle_threshold = 12000, \
.filter_ticks_thresh = 100, \ .filter_ticks_thresh = 100, \

View File

@@ -27,11 +27,6 @@
#include "hal/rmt_hal.h" #include "hal/rmt_hal.h"
#include "hal/rmt_ll.h" #include "hal/rmt_ll.h"
#define RMT_SOUCCE_CLK_APB (APB_CLK_FREQ) /*!< RMT source clock is APB_CLK */
#define RMT_SOURCE_CLK_REF (1 * 1000000) /*!< not used yet */
#define RMT_SOURCE_CLK(select) ((select == RMT_BASECLK_REF) ? (RMT_SOURCE_CLK_REF) : (RMT_SOUCCE_CLK_APB))
#define RMT_CHANNEL_ERROR_STR "RMT CHANNEL ERR" #define RMT_CHANNEL_ERROR_STR "RMT CHANNEL ERR"
#define RMT_ADDR_ERROR_STR "RMT ADDRESS ERR" #define RMT_ADDR_ERROR_STR "RMT ADDRESS ERR"
#define RMT_MEM_CNT_ERROR_STR "RMT MEM BLOCK NUM ERR" #define RMT_MEM_CNT_ERROR_STR "RMT MEM BLOCK NUM ERR"
@@ -89,7 +84,8 @@ typedef struct {
const uint8_t *sample_cur; const uint8_t *sample_cur;
} rmt_obj_t; } rmt_obj_t;
rmt_obj_t *p_rmt_obj[RMT_CHANNEL_MAX] = {0}; static rmt_obj_t *p_rmt_obj[RMT_CHANNEL_MAX] = {0};
static uint32_t s_rmt_src_clock_hz[RMT_CHANNEL_MAX] = {0};
// Event called when transmission is ended // Event called when transmission is ended
static rmt_tx_end_callback_t rmt_tx_end_callback; static rmt_tx_end_callback_t rmt_tx_end_callback;
@@ -160,7 +156,7 @@ esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t hi
RMT_ENTER_CRITICAL(); RMT_ENTER_CRITICAL();
rmt_ll_set_carrier_high_low_ticks(p_rmt_obj[channel]->hal.regs, channel, high_level, low_level); rmt_ll_set_carrier_high_low_ticks(p_rmt_obj[channel]->hal.regs, channel, high_level, low_level);
rmt_ll_set_carrier_to_level(p_rmt_obj[channel]->hal.regs, channel, carrier_level); rmt_ll_set_carrier_to_level(p_rmt_obj[channel]->hal.regs, channel, carrier_level);
rmt_ll_enable_tx_carrier(p_rmt_obj[channel]->hal.regs, channel, carrier_en); rmt_ll_enable_carrier(p_rmt_obj[channel]->hal.regs, channel, carrier_en);
RMT_EXIT_CRITICAL(); RMT_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
} }
@@ -425,6 +421,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
uint8_t clk_div = rmt_param->clk_div; uint8_t clk_div = rmt_param->clk_div;
uint32_t carrier_freq_hz = rmt_param->tx_config.carrier_freq_hz; uint32_t carrier_freq_hz = rmt_param->tx_config.carrier_freq_hz;
bool carrier_en = rmt_param->tx_config.carrier_en; bool carrier_en = rmt_param->tx_config.carrier_en;
uint32_t rmt_source_clk_hz = 0;
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(channel < RMT_CHANNEL_MAX, 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((mem_cnt + channel <= 8 && mem_cnt > 0), RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG);
@@ -439,12 +436,21 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
rmt_ll_enable_mem_access(dev, true); rmt_ll_enable_mem_access(dev, true);
rmt_ll_reset_tx_pointer(dev, channel); rmt_ll_reset_tx_pointer(dev, channel);
rmt_ll_reset_rx_pointer(dev, channel); rmt_ll_reset_rx_pointer(dev, channel);
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_APB); // only support APB clock for now if (rmt_param->flags & RMT_CHANNEL_FLAGS_ALWAYS_ON) {
// clock src: REF_CLK
rmt_source_clk_hz = REF_CLK_FREQ;
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_REF);
} 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_mem_blocks(dev, channel, mem_cnt); rmt_ll_set_mem_blocks(dev, channel, mem_cnt);
rmt_ll_set_mem_owner(dev, channel, RMT_MEM_OWNER_HW); rmt_ll_set_mem_owner(dev, channel, RMT_MEM_OWNER_HW);
rmt_ll_enable_carrier(dev, channel, false); // disable carrier feature by default
RMT_EXIT_CRITICAL(); RMT_EXIT_CRITICAL();
uint32_t rmt_source_clk_hz = RMT_SOURCE_CLK(RMT_BASECLK_APB); s_rmt_src_clock_hz[channel] = rmt_source_clk_hz;
if (mode == RMT_MODE_TX) { if (mode == RMT_MODE_TX) {
uint16_t carrier_duty_percent = rmt_param->tx_config.carrier_duty_percent; uint16_t carrier_duty_percent = rmt_param->tx_config.carrier_duty_percent;
@@ -458,7 +464,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
rmt_ll_enable_tx_idle(dev, channel, rmt_param->tx_config.idle_output_en); 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_set_tx_idle_level(dev, channel, idle_level);
/*Set carrier*/ /*Set carrier*/
rmt_ll_enable_tx_carrier(dev, channel, carrier_en); rmt_ll_enable_carrier(dev, channel, carrier_en);
if (carrier_en) { if (carrier_en) {
uint32_t duty_div, duty_h, duty_l; uint32_t duty_div, duty_h, duty_l;
duty_div = rmt_source_clk_hz / carrier_freq_hz; duty_div = rmt_source_clk_hz / carrier_freq_hz;
@@ -990,7 +996,7 @@ 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(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_CHECK(clock_hz, "parameter clock_hz can't be null", ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL(); RMT_ENTER_CRITICAL();
*clock_hz = rmt_hal_get_counter_clock(&p_rmt_obj[channel]->hal, channel, RMT_SOURCE_CLK(RMT_BASECLK_APB)); *clock_hz = rmt_hal_get_counter_clock(&p_rmt_obj[channel]->hal, channel, s_rmt_src_clock_hz[channel]);
RMT_EXIT_CRITICAL(); RMT_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
} }

View File

@@ -1,4 +1,3 @@
idf_component_register(SRC_DIRS . param_test idf_component_register(SRC_DIRS . param_test
INCLUDE_DIRS include param_test/include INCLUDE_DIRS include param_test/include
REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link infrared_tools)
)

File diff suppressed because it is too large Load Diff

View File

@@ -18,11 +18,25 @@
extern "C" { extern "C" {
#endif #endif
#include "soc/rmt_caps.h"
/** /**
* @brief RMT Channel Type * @brief RMT channel ID
* *
*/ */
typedef rmt_channel_id_t rmt_channel_t; typedef enum {
RMT_CHANNEL_0, /*!< RMT channel number 0 */
RMT_CHANNEL_1, /*!< RMT channel number 1 */
RMT_CHANNEL_2, /*!< RMT channel number 2 */
RMT_CHANNEL_3, /*!< RMT channel number 3 */
#if RMT_CHANNELS_NUM > 4
RMT_CHANNEL_4, /*!< RMT channel number 4 */
RMT_CHANNEL_5, /*!< RMT channel number 5 */
RMT_CHANNEL_6, /*!< RMT channel number 6 */
RMT_CHANNEL_7, /*!< RMT channel number 7 */
#endif
RMT_CHANNEL_MAX /*!< Number of RMT channels */
} rmt_channel_t;
/** /**
* @brief RMT Internal Memory Owner * @brief RMT Internal Memory Owner
@@ -39,7 +53,7 @@ typedef enum {
* *
*/ */
typedef enum { typedef enum {
RMT_BASECLK_REF, /*!< RMT source clock system reference tick, 1MHz by default (not supported in this version) */ RMT_BASECLK_REF, /*!< RMT source clock is REF_TICK, 1MHz by default */
RMT_BASECLK_APB, /*!< RMT source clock is APB CLK, 80Mhz by default */ RMT_BASECLK_APB, /*!< RMT source clock is APB CLK, 80Mhz by default */
RMT_BASECLK_MAX, RMT_BASECLK_MAX,
} rmt_source_clk_t; } rmt_source_clk_t;

View File

@@ -18,25 +18,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdint.h>
#define RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */ #define RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */
#define RMT_CHANNELS_NUM (8) /*!< Total 8 channels */
/**
* @brief RMT channel ID
*
*/
typedef enum {
RMT_CHANNEL_0, /*!< RMT channel number 0 */
RMT_CHANNEL_1, /*!< RMT channel number 1 */
RMT_CHANNEL_2, /*!< RMT channel number 2 */
RMT_CHANNEL_3, /*!< RMT channel number 3 */
RMT_CHANNEL_4, /*!< RMT channel number 4 */
RMT_CHANNEL_5, /*!< RMT channel number 5 */
RMT_CHANNEL_6, /*!< RMT channel number 6 */
RMT_CHANNEL_7, /*!< RMT channel number 7 */
RMT_CHANNEL_MAX /*!< Number of RMT channels */
} rmt_channel_id_t;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -18,21 +18,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdint.h>
#define RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */ #define RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */
#define RMT_CHANNELS_NUM (4) /*!< Total 4 channels */
/**
* @brief RMT channel ID
*
*/
typedef enum {
RMT_CHANNEL_0, /*!< RMT channel number 0 */
RMT_CHANNEL_1, /*!< RMT channel number 1 */
RMT_CHANNEL_2, /*!< RMT channel number 2 */
RMT_CHANNEL_3, /*!< RMT channel number 3 */
RMT_CHANNEL_MAX /*!< Number of RMT channels */
} rmt_channel_id_t;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -260,7 +260,7 @@ static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t ch
*low_ticks = dev->carrier_duty_ch[channel].low; *low_ticks = dev->carrier_duty_ch[channel].low;
} }
static inline void rmt_ll_enable_tx_carrier(rmt_dev_t *dev, uint32_t channel, bool enable) static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable)
{ {
dev->conf_ch[channel].conf0.carrier_en = enable; dev->conf_ch[channel].conf0.carrier_en = enable;
} }

View File

@@ -253,7 +253,7 @@ static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t ch
*low_ticks = dev->carrier_duty_ch[channel].low; *low_ticks = dev->carrier_duty_ch[channel].low;
} }
static inline void rmt_ll_enable_tx_carrier(rmt_dev_t *dev, uint32_t channel, bool enable) static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable)
{ {
dev->conf_ch[channel].conf0.carrier_en = enable; dev->conf_ch[channel].conf0.carrier_en = enable;
} }

View File

@@ -113,7 +113,11 @@ Common Parameters
* The RMT **operation mode** - whether this channel is used to transmit or receive data, selected by setting a **rmt_mode** members to one of the values from :cpp:type:`rmt_mode_t`. * The RMT **operation mode** - whether this channel is used to transmit or receive data, selected by setting a **rmt_mode** members to one of the values from :cpp:type:`rmt_mode_t`.
* What is the **pin number** to transmit or receive RMT signals, selected by setting **gpio_num**. * What is the **pin number** to transmit or receive RMT signals, selected by setting **gpio_num**.
* How many **memory blocks** will be used by the channel, set with **mem_block_num**. * How many **memory blocks** will be used by the channel, set with **mem_block_num**.
* 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. * 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.
* 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.
.. note:: .. note::

View File

@@ -77,7 +77,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`. - **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. - **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. Although the driver does not support REF_TICK, this feature can be enabled by clearing the ``RMT_REF_ALWAYS_ON_CHx`` bit for the respective channel. - **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`.
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: 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:

View File

@@ -72,7 +72,7 @@ ESP32 支持下表中所述的三种电源管理锁。
- **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick` - **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`
- **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。 - **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。
- **RMT**:如果 REF_TICK 用作时钟源,则 RMT 不受 APB 频率变更影响。此驱动程序尚不支持 REF_TICK但可以清除相应通道的 ``RMT_REF_ALWAYS_ON_CHx`` 位来启用该功能 - **RMT**:如果 REF_TICK 用作时钟源,则 RMT 不受 APB 频率变更影响。请查看 :cpp:class:`rmt_config_t` 结构体中的 `flags` 成员以及 `RMT_CHANNEL_FLAGS_ALWAYS_ON`
目前以下外设驱动程序可感知动态调频,并在调频期间使用 ``ESP_PM_APB_FREQ_MAX`` 锁: 目前以下外设驱动程序可感知动态调频,并在调频期间使用 ``ESP_PM_APB_FREQ_MAX`` 锁:

View File

@@ -2,7 +2,8 @@
# CMakeLists in this exact order for cmake to work correctly # CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/") set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/"
"$ENV{IDF_PATH}/examples/peripherals/rmt/ir_protocols/components")
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(unit-test-app) project(unit-test-app)

View File

@@ -5,6 +5,8 @@
PROJECT_NAME := unit-test-app PROJECT_NAME := unit-test-app
EXTRA_COMPONENT_DIRS += ${IDF_PATH}/examples/peripherals/rmt/ir_protocols/components
ifeq ($(MAKELEVEL),0) ifeq ($(MAKELEVEL),0)
# Set default target # Set default target
all: all:

View File

@@ -49,7 +49,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
/* Select which RMT and PCNT channels, and GPIO to use */ /* Select which RMT and PCNT channels, and GPIO to use */
#define REF_CLOCK_RMT_CHANNEL RMT_CHANNEL_MAX - 1 #define REF_CLOCK_RMT_CHANNEL RMT_CHANNELS_NUM - 1
#define REF_CLOCK_PCNT_UNIT 0 #define REF_CLOCK_PCNT_UNIT 0
#define REF_CLOCK_GPIO 21 #define REF_CLOCK_GPIO 21
@@ -97,7 +97,7 @@ void ref_clock_init()
rmt_ll_start_tx(s_rmt.regs, REF_CLOCK_RMT_CHANNEL); rmt_ll_start_tx(s_rmt.regs, REF_CLOCK_RMT_CHANNEL);
rmt_ll_set_mem_owner(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 0); rmt_ll_set_mem_owner(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 0);
rmt_ll_reset_tx_pointer(s_rmt.regs, REF_CLOCK_RMT_CHANNEL); rmt_ll_reset_tx_pointer(s_rmt.regs, REF_CLOCK_RMT_CHANNEL);
rmt_ll_enable_tx_carrier(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, false); rmt_ll_enable_carrier(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, false);
rmt_ll_set_counter_clock_div(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 1); rmt_ll_set_counter_clock_div(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_set_mem_blocks(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 1); rmt_ll_set_mem_blocks(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_set_counter_clock_src(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 0); rmt_ll_set_counter_clock_src(s_rmt.regs, REF_CLOCK_RMT_CHANNEL, 0);