driver: deprecate legacy rmt driver

The legacy driver is still available, but new feature won't be added.
Enable RMT_SUPPRESS_DEPRECATE_WARN if you don't want to see the
deprecated warnings.
This commit is contained in:
morris
2022-04-07 11:50:41 +08:00
parent 9a8c8e5db4
commit 5bfe873725
25 changed files with 458 additions and 388 deletions

View File

@@ -279,4 +279,15 @@ menu "Driver configurations"
Note that, this option only controls the PCNT driver log, won't affect other drivers. Note that, this option only controls the PCNT driver log, won't affect other drivers.
endmenu # PCNT Configuration endmenu # PCNT Configuration
menu "RMT Configuration"
depends on SOC_RMT_SUPPORTED
config RMT_SUPPRESS_DEPRECATE_WARN
bool "Suppress legacy driver deprecated warning"
default n
help
Wether to suppress the deprecation warnings when using legacy rmt driver (driver/rmt.h).
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
you can enable this option.
endmenu # RMT Configuration
endmenu # Driver configurations endmenu # Driver configurations

View File

@@ -6,281 +6,22 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_err.h" #include "esp_err.h"
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/ringbuf.h" #include "freertos/ringbuf.h"
#include "hal/rmt_types.h" #include "driver/rmt_types_legacy.h"
#if !CONFIG_RMT_SUPPRESS_DEPRECATE_WARN
#warning "The legacy RMT driver is deprecated, please use driver/rmt_tx.h and/or driver/rmt_rx.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define RMT_CHANNEL_FLAGS_AWARE_DFS (1 << 0) /*!< Channel can work during APB clock scaling */
#define RMT_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /*!< Invert RMT signal */
/** @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)
*
*/
#define RMT_MEM_ITEM_NUM SOC_RMT_MEM_WORDS_PER_CHANNEL
/**
* @brief Definition of RMT item
*/
typedef struct {
union {
struct {
uint32_t duration0 : 15; /*!< Duration of level0 */
uint32_t level0 : 1; /*!< Level of the first part */
uint32_t duration1 : 15; /*!< Duration of level1 */
uint32_t level1 : 1; /*!< Level of the second part */
};
uint32_t val; /*!< Equivalent unsigned value for the RMT item */
};
} rmt_item32_t;
/**
* @brief RMT hardware memory layout
*/
typedef struct {
struct {
volatile rmt_item32_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
} chan[SOC_RMT_CHANNELS_PER_GROUP];
} rmt_mem_t;
/**
* @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 */
#if SOC_RMT_CHANNELS_PER_GROUP > 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
*
*/
typedef enum {
RMT_MEM_OWNER_TX, /*!< RMT RX mode, RMT transmitter owns the memory block*/
RMT_MEM_OWNER_RX, /*!< RMT RX mode, RMT receiver owns the memory block*/
RMT_MEM_OWNER_MAX,
} rmt_mem_owner_t;
/**
* @brief Clock Source of RMT Channel
*
*/
typedef soc_periph_rmt_clk_src_legacy_t rmt_source_clk_t;
/**
* @brief RMT Data Mode
*
* @note We highly recommended to use MEM mode not FIFO mode since there will be some gotcha in FIFO mode.
*
*/
typedef enum {
RMT_DATA_MODE_FIFO, /*<! RMT memory access in FIFO mode */
RMT_DATA_MODE_MEM, /*<! RMT memory access in memory mode */
RMT_DATA_MODE_MAX,
} rmt_data_mode_t;
/**
* @brief RMT Channel Working Mode (TX or RX)
*
*/
typedef enum {
RMT_MODE_TX, /*!< RMT TX mode */
RMT_MODE_RX, /*!< RMT RX mode */
RMT_MODE_MAX
} rmt_mode_t;
/**
* @brief RMT Idle Level
*
*/
typedef enum {
RMT_IDLE_LEVEL_LOW, /*!< RMT TX idle level: low Level */
RMT_IDLE_LEVEL_HIGH, /*!< RMT TX idle level: high Level */
RMT_IDLE_LEVEL_MAX,
} rmt_idle_level_t;
/**
* @brief RMT Carrier Level
*
*/
typedef enum {
RMT_CARRIER_LEVEL_LOW, /*!< RMT carrier wave is modulated for low Level output */
RMT_CARRIER_LEVEL_HIGH, /*!< RMT carrier wave is modulated for high Level output */
RMT_CARRIER_LEVEL_MAX
} rmt_carrier_level_t;
/**
* @brief RMT Channel Status
*
*/
typedef enum {
RMT_CHANNEL_UNINIT, /*!< RMT channel uninitialized */
RMT_CHANNEL_IDLE, /*!< RMT channel status idle */
RMT_CHANNEL_BUSY, /*!< RMT channel status busy */
} rmt_channel_status_t;
/**
* @brief Data struct of RMT channel status
*/
typedef struct {
rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */
} rmt_channel_status_result_t;
/**
* @brief Data struct of RMT TX configure parameters
*/
typedef struct {
uint32_t carrier_freq_hz; /*!< RMT carrier frequency */
rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */
rmt_idle_level_t idle_level; /*!< RMT idle level */
uint8_t carrier_duty_percent; /*!< RMT carrier duty (%) */
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
uint32_t loop_count; /*!< Maximum loop count */
#endif
bool carrier_en; /*!< RMT carrier enable */
bool loop_en; /*!< Enable sending RMT items in a loop */
bool idle_output_en; /*!< RMT idle level output enable */
} rmt_tx_config_t;
/**
* @brief Data struct of RMT RX configure parameters
*/
typedef struct {
uint16_t idle_threshold; /*!< RMT RX idle threshold */
uint8_t filter_ticks_thresh; /*!< RMT filter tick number */
bool filter_en; /*!< RMT receiver filter enable */
#if SOC_RMT_SUPPORT_RX_DEMODULATION
bool rm_carrier; /*!< RMT receiver remove carrier enable */
uint32_t carrier_freq_hz; /*!< RMT carrier frequency */
uint8_t carrier_duty_percent; /*!< RMT carrier duty (%) */
rmt_carrier_level_t carrier_level; /*!< The level to remove the carrier */
#endif
} rmt_rx_config_t;
/**
* @brief Data struct of RMT configure parameters
*/
typedef struct {
rmt_mode_t rmt_mode; /*!< RMT mode: transmitter or receiver */
rmt_channel_t channel; /*!< RMT channel */
gpio_num_t gpio_num; /*!< RMT GPIO number */
uint8_t clk_div; /*!< RMT channel counter divider */
uint8_t mem_block_num; /*!< RMT memory block number */
uint32_t flags; /*!< RMT channel extra configurations, OR'd with RMT_CHANNEL_FLAGS_[*] */
union {
rmt_tx_config_t tx_config; /*!< RMT TX parameter */
rmt_rx_config_t rx_config; /*!< RMT RX parameter */
};
} rmt_config_t;
/**
* @brief Default configuration for Tx channel
*
*/
#define RMT_DEFAULT_CONFIG_TX(gpio, channel_id) \
{ \
.rmt_mode = RMT_MODE_TX, \
.channel = channel_id, \
.gpio_num = gpio, \
.clk_div = 80, \
.mem_block_num = 1, \
.flags = 0, \
.tx_config = { \
.carrier_freq_hz = 38000, \
.carrier_level = RMT_CARRIER_LEVEL_HIGH, \
.idle_level = RMT_IDLE_LEVEL_LOW, \
.carrier_duty_percent = 33, \
.carrier_en = false, \
.loop_en = false, \
.idle_output_en = true, \
} \
}
/**
* @brief Default configuration for RX channel
*
*/
#define RMT_DEFAULT_CONFIG_RX(gpio, channel_id) \
{ \
.rmt_mode = RMT_MODE_RX, \
.channel = channel_id, \
.gpio_num = gpio, \
.clk_div = 80, \
.mem_block_num = 1, \
.flags = 0, \
.rx_config = { \
.idle_threshold = 12000, \
.filter_ticks_thresh = 100, \
.filter_en = true, \
} \
}
/**
* @brief RMT interrupt handle
*
*/
typedef intr_handle_t rmt_isr_handle_t;
/**
* @brief Type of RMT Tx End callback function
*
*/
typedef void (*rmt_tx_end_fn_t)(rmt_channel_t channel, void *arg);
/**
* @brief Structure encapsulating a RMT TX end callback
*/
typedef struct {
rmt_tx_end_fn_t function; /*!< Function which is called on RMT TX end */
void *arg; /*!< Optional argument passed to function */
} rmt_tx_end_callback_t;
/**
* @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
*
* This function may be called from an ISR, so, the code should be short and efficient.
*
* @param src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
* @param[out] dest Pointer to the buffer storing the rmt format data.
* @param src_size The raw data size.
* @param wanted_num The number of rmt format data that wanted to get.
* @param[out] translated_size The size of the raw data that has been converted to rmt format,
* it should return 0 if no data is converted in user callback.
* @param[out] item_num The number of the rmt format data that actually converted to,
* it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
* it should return 0 if no data was converted.
*
* @note
* In fact, item_num should be a multiple of translated_size, e.g. :
* When we convert each byte of uint8_t type data to rmt format data,
* the relation between item_num and translated_size should be `item_num = translated_size*8`.
*/
typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
/** /**
* @brief Set RMT clock divider, channel clock is divided from source clock. * @brief Set RMT clock divider, channel clock is divided from source clock.
* *

View File

@@ -0,0 +1,279 @@
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "driver/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RMT_CHANNEL_FLAGS_AWARE_DFS (1 << 0) /*!< Channel can work during APB clock scaling */
#define RMT_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /*!< Invert RMT signal */
#define RMT_CHANNEL_FLAGS_ALWAYS_ON _Pragma ("GCC warning \"'RMT_CHANNEL_FLAGS_ALWAYS_ON' macro is deprecated\"") RMT_CHANNEL_FLAGS_AWARE_DFS
/**
* @brief Define memory space of each RMT channel (in words = 4 bytes)
*
*/
#define RMT_MEM_ITEM_NUM SOC_RMT_MEM_WORDS_PER_CHANNEL
/**
* @brief Definition of RMT item
*/
typedef struct {
union {
struct {
uint32_t duration0 : 15; /*!< Duration of level0 */
uint32_t level0 : 1; /*!< Level of the first part */
uint32_t duration1 : 15; /*!< Duration of level1 */
uint32_t level1 : 1; /*!< Level of the second part */
};
uint32_t val; /*!< Equivalent unsigned value for the RMT item */
};
} rmt_item32_t;
/**
* @brief RMT hardware memory layout
*/
typedef struct {
struct {
volatile rmt_item32_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
} chan[SOC_RMT_CHANNELS_PER_GROUP];
} rmt_mem_t;
/**
* @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 */
#if SOC_RMT_CHANNELS_PER_GROUP > 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
*
*/
typedef enum {
RMT_MEM_OWNER_TX, /*!< RMT RX mode, RMT transmitter owns the memory block*/
RMT_MEM_OWNER_RX, /*!< RMT RX mode, RMT receiver owns the memory block*/
RMT_MEM_OWNER_MAX,
} rmt_mem_owner_t;
/**
* @brief Clock Source of RMT Channel
*
*/
typedef soc_periph_rmt_clk_src_legacy_t rmt_source_clk_t;
/**
* @brief RMT Data Mode
*
* @note We highly recommended to use MEM mode not FIFO mode since there will be some gotcha in FIFO mode.
*
*/
typedef enum {
RMT_DATA_MODE_FIFO, /*<! RMT memory access in FIFO mode */
RMT_DATA_MODE_MEM, /*<! RMT memory access in memory mode */
RMT_DATA_MODE_MAX,
} rmt_data_mode_t;
/**
* @brief RMT Channel Working Mode (TX or RX)
*
*/
typedef enum {
RMT_MODE_TX, /*!< RMT TX mode */
RMT_MODE_RX, /*!< RMT RX mode */
RMT_MODE_MAX
} rmt_mode_t;
/**
* @brief RMT Idle Level
*
*/
typedef enum {
RMT_IDLE_LEVEL_LOW, /*!< RMT TX idle level: low Level */
RMT_IDLE_LEVEL_HIGH, /*!< RMT TX idle level: high Level */
RMT_IDLE_LEVEL_MAX,
} rmt_idle_level_t;
/**
* @brief RMT Carrier Level
*
*/
typedef enum {
RMT_CARRIER_LEVEL_LOW, /*!< RMT carrier wave is modulated for low Level output */
RMT_CARRIER_LEVEL_HIGH, /*!< RMT carrier wave is modulated for high Level output */
RMT_CARRIER_LEVEL_MAX
} rmt_carrier_level_t;
/**
* @brief RMT Channel Status
*
*/
typedef enum {
RMT_CHANNEL_UNINIT, /*!< RMT channel uninitialized */
RMT_CHANNEL_IDLE, /*!< RMT channel status idle */
RMT_CHANNEL_BUSY, /*!< RMT channel status busy */
} rmt_channel_status_t;
/**
* @brief Data struct of RMT channel status
*/
typedef struct {
rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */
} rmt_channel_status_result_t;
/**
* @brief Data struct of RMT TX configure parameters
*/
typedef struct {
uint32_t carrier_freq_hz; /*!< RMT carrier frequency */
rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */
rmt_idle_level_t idle_level; /*!< RMT idle level */
uint8_t carrier_duty_percent; /*!< RMT carrier duty (%) */
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
uint32_t loop_count; /*!< Maximum loop count */
#endif
bool carrier_en; /*!< RMT carrier enable */
bool loop_en; /*!< Enable sending RMT items in a loop */
bool idle_output_en; /*!< RMT idle level output enable */
} rmt_tx_config_t;
/**
* @brief Data struct of RMT RX configure parameters
*/
typedef struct {
uint16_t idle_threshold; /*!< RMT RX idle threshold */
uint8_t filter_ticks_thresh; /*!< RMT filter tick number */
bool filter_en; /*!< RMT receiver filter enable */
#if SOC_RMT_SUPPORT_RX_DEMODULATION
bool rm_carrier; /*!< RMT receiver remove carrier enable */
uint32_t carrier_freq_hz; /*!< RMT carrier frequency */
uint8_t carrier_duty_percent; /*!< RMT carrier duty (%) */
rmt_carrier_level_t carrier_level; /*!< The level to remove the carrier */
#endif
} rmt_rx_config_t;
/**
* @brief Data struct of RMT configure parameters
*/
typedef struct {
rmt_mode_t rmt_mode; /*!< RMT mode: transmitter or receiver */
rmt_channel_t channel; /*!< RMT channel */
gpio_num_t gpio_num; /*!< RMT GPIO number */
uint8_t clk_div; /*!< RMT channel counter divider */
uint8_t mem_block_num; /*!< RMT memory block number */
uint32_t flags; /*!< RMT channel extra configurations, OR'd with RMT_CHANNEL_FLAGS_[*] */
union {
rmt_tx_config_t tx_config; /*!< RMT TX parameter */
rmt_rx_config_t rx_config; /*!< RMT RX parameter */
};
} rmt_config_t;
/**
* @brief Default configuration for Tx channel
*
*/
#define RMT_DEFAULT_CONFIG_TX(gpio, channel_id) \
{ \
.rmt_mode = RMT_MODE_TX, \
.channel = channel_id, \
.gpio_num = gpio, \
.clk_div = 80, \
.mem_block_num = 1, \
.flags = 0, \
.tx_config = { \
.carrier_freq_hz = 38000, \
.carrier_level = RMT_CARRIER_LEVEL_HIGH, \
.idle_level = RMT_IDLE_LEVEL_LOW, \
.carrier_duty_percent = 33, \
.carrier_en = false, \
.loop_en = false, \
.idle_output_en = true, \
} \
}
/**
* @brief Default configuration for RX channel
*
*/
#define RMT_DEFAULT_CONFIG_RX(gpio, channel_id) \
{ \
.rmt_mode = RMT_MODE_RX, \
.channel = channel_id, \
.gpio_num = gpio, \
.clk_div = 80, \
.mem_block_num = 1, \
.flags = 0, \
.rx_config = { \
.idle_threshold = 12000, \
.filter_ticks_thresh = 100, \
.filter_en = true, \
} \
}
/**
* @brief RMT interrupt handle
*
*/
typedef intr_handle_t rmt_isr_handle_t;
/**
* @brief Type of RMT Tx End callback function
*
*/
typedef void (*rmt_tx_end_fn_t)(rmt_channel_t channel, void *arg);
/**
* @brief Structure encapsulating a RMT TX end callback
*/
typedef struct {
rmt_tx_end_fn_t function; /*!< Function which is called on RMT TX end */
void *arg; /*!< Optional argument passed to function */
} rmt_tx_end_callback_t;
/**
* @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
*
* This function may be called from an ISR, so, the code should be short and efficient.
*
* @param src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
* @param[out] dest Pointer to the buffer storing the rmt format data.
* @param src_size The raw data size.
* @param wanted_num The number of rmt format data that wanted to get.
* @param[out] translated_size The size of the raw data that has been converted to rmt format,
* it should return 0 if no data is converted in user callback.
* @param[out] item_num The number of the rmt format data that actually converted to,
* it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
* it should return 0 if no data was converted.
*
* @note
* In fact, item_num should be a multiple of translated_size, e.g. :
* When we convert each byte of uint8_t type data to rmt format data,
* the relation between item_num and translated_size should be `item_num = translated_size*8`.
*/
typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
#ifdef __cplusplus
}
#endif

View File

@@ -13,7 +13,8 @@
#include "esp_check.h" #include "esp_check.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#include "driver/rmt.h" #include "driver/rmt_types_legacy.h"
#include "driver_ng.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
@@ -44,7 +45,7 @@
#define RMT_TRANSLATOR_UNINIT_STR "RMT translator not init" #define RMT_TRANSLATOR_UNINIT_STR "RMT translator not init"
#define RMT_PARAM_ERR_STR "RMT param error" #define RMT_PARAM_ERR_STR "RMT param error"
static const char *TAG = "rmt"; static const char *TAG = "rmt(legacy)";
// Spinlock for protecting concurrent register-level access only // Spinlock for protecting concurrent register-level access only
#define RMT_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock)) #define RMT_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock))
@@ -414,7 +415,7 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk)
{ {
ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
RMT_ENTER_CRITICAL(); RMT_ENTER_CRITICAL();
// `rmt_clock_source_t` and `rmt_source_clk_t` are binary competible, as the underlying enum entries come from the same `soc_module_clk_t` // `rmt_clock_source_t` and `rmt_source_clk_t` are binary compatible, as the underlying enum entries come from the same `soc_module_clk_t`
rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0); rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0);
RMT_EXIT_CRITICAL(); RMT_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
@@ -424,7 +425,7 @@ esp_err_t rmt_get_source_clk(rmt_channel_t channel, rmt_source_clk_t *src_clk)
{ {
ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
RMT_ENTER_CRITICAL(); RMT_ENTER_CRITICAL();
// `rmt_clock_source_t` and `rmt_source_clk_t` are binary competible, as the underlying enum entries come from the same `soc_module_clk_t` // `rmt_clock_source_t` and `rmt_source_clk_t` are binary compatible, as the underlying enum entries come from the same `soc_module_clk_t`
*src_clk = (rmt_source_clk_t)rmt_ll_get_group_clock_src(rmt_contex.hal.regs, channel); *src_clk = (rmt_source_clk_t)rmt_ll_get_group_clock_src(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL(); RMT_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
@@ -1355,3 +1356,19 @@ esp_err_t rmt_enable_tx_loop_autostop(rmt_channel_t channel, bool en)
return ESP_OK; return ESP_OK;
} }
#endif #endif
/**
* @brief This function will be called during start up, to check that this legacy RMT driver is not running along with the new driver
*/
__attribute__((constructor))
static void check_rmt_legacy_driver_conflict(void)
{
// This function was declared as weak here. The new RMT driver has one implementation.
// So if the new RMT driver is not linked in, then `rmt_acquire_group_handle()` should be NULL at runtime.
extern __attribute__((weak)) void *rmt_acquire_group_handle(int group_id);
if ((void *)rmt_acquire_group_handle != NULL) {
ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
abort();
}
ESP_EARLY_LOGW(TAG, "legacy driver is deprecated, please migrate to `driver/rmt_tx.h` and/or `driver/rmt_rx.h`");
}

View File

@@ -161,7 +161,7 @@ static void check_legacy_temp_sensor_driver_conflict(void)
// This function was declared as weak here. temperature_sensor driver has one implementation. // This function was declared as weak here. temperature_sensor driver has one implementation.
// So if temperature_sensor driver is not linked in, then `temperature_sensor_install()` should be NULL at runtime. // So if temperature_sensor driver is not linked in, then `temperature_sensor_install()` should be NULL at runtime.
extern __attribute__((weak)) esp_err_t temperature_sensor_install(const void *tsens_config, void **ret_tsens); extern __attribute__((weak)) esp_err_t temperature_sensor_install(const void *tsens_config, void **ret_tsens);
if (temperature_sensor_install != NULL) { if ((void *)temperature_sensor_install != NULL) {
ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver"); ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
abort(); abort();
} }

View File

@@ -1,4 +1,4 @@
idf_component_register(SRC_DIRS . param_test touch_sensor_test adc_dma_test dac_dma_test idf_component_register(SRC_DIRS . param_test touch_sensor_test adc_dma_test dac_dma_test
PRIV_INCLUDE_DIRS include param_test/include touch_sensor_test/include PRIV_INCLUDE_DIRS include param_test/include touch_sensor_test/include
PRIV_REQUIRES cmock test_utils driver nvs_flash esp_serial_slave_link PRIV_REQUIRES cmock test_utils driver nvs_flash esp_serial_slave_link
infrared_tools esp_adc_cal esp_timer) esp_adc_cal esp_timer)

View File

@@ -0,0 +1,5 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(legacy_rmt_test)

View File

@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 |
| ----------------- | ----- | -------- | -------- | -------- |

View File

@@ -1,8 +1,3 @@
if(IDF_TARGET STREQUAL "esp32c2")
# ESP32-C2 does't support rmt
return()
endif()
set(component_srcs "src/ir_builder_rmt_nec.c" set(component_srcs "src/ir_builder_rmt_nec.c"
"src/ir_builder_rmt_rc5.c" "src/ir_builder_rmt_rc5.c"
"src/ir_parser_rmt_nec.c" "src/ir_parser_rmt_nec.c"
@@ -10,6 +5,4 @@ set(component_srcs "src/ir_builder_rmt_nec.c"
idf_component_register(SRCS "${component_srcs}" idf_component_register(SRCS "${component_srcs}"
INCLUDE_DIRS "include" INCLUDE_DIRS "include"
PRIV_INCLUDE_DIRS "" PRIV_REQUIRES "driver")
PRIV_REQUIRES "driver"
REQUIRES "")

View File

@@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Timings for NEC protocol
*
*/
#define NEC_LEADING_CODE_HIGH_US (9000)
#define NEC_LEADING_CODE_LOW_US (4500)
#define NEC_PAYLOAD_ONE_HIGH_US (560)
#define NEC_PAYLOAD_ONE_LOW_US (1690)
#define NEC_PAYLOAD_ZERO_HIGH_US (560)
#define NEC_PAYLOAD_ZERO_LOW_US (560)
#define NEC_REPEAT_CODE_HIGH_US (9000)
#define NEC_REPEAT_CODE_LOW_US (2250)
#define NEC_ENDING_CODE_HIGH_US (560)
/**
* @brief Timings for RC5 protocol
*
*/
#define RC5_PULSE_DURATION_US (889)
#ifdef __cplusplus
}
#endif

View File

@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 <stdlib.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "esp_log.h" #include "esp_log.h"
#include "ir_tools.h" #include "ir_tools.h"

View File

@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 <stdlib.h> #include <stdlib.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "esp_log.h" #include "esp_log.h"

View File

@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 <stdlib.h> #include <stdlib.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "esp_log.h" #include "esp_log.h"

View File

@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 <stdlib.h> #include <stdlib.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "esp_log.h" #include "esp_log.h"

View File

@@ -0,0 +1,5 @@
set(srcs "test_app_main.c"
"test_legacy_rmt.c")
idf_component_register(SRCS ${srcs}
WHOLE_ARCHIVE)

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (-600)
static size_t before_free_8bit;
static size_t before_free_32bit;
static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
}
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
check_leak(before_free_8bit, after_free_8bit, "8BIT");
check_leak(before_free_32bit, after_free_32bit, "32BIT");
}
void app_main(void)
{
unity_run_menu();
}

View File

@@ -3,7 +3,6 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
// RMT driver unit test is based on extended NEC protocol
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -14,10 +13,8 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_log.h" #include "esp_log.h"
#include "unity.h" #include "unity.h"
#include "test_utils.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#if SOC_RMT_SUPPORTED
#include "ir_tools.h" #include "ir_tools.h"
#include "driver/rmt.h" #include "driver/rmt.h"
@@ -32,6 +29,7 @@
#define RMT_TESTBENCH_FLAGS_LOOP_ON (1<<2) #define RMT_TESTBENCH_FLAGS_LOOP_ON (1<<2)
static const char *TAG = "RMT.test"; static const char *TAG = "RMT.test";
static ir_builder_t *s_ir_builder = NULL; static ir_builder_t *s_ir_builder = NULL;
static ir_parser_t *s_ir_parser = NULL; static ir_parser_t *s_ir_parser = NULL;
@@ -598,5 +596,3 @@ TEST_CASE("RMT TX loop", "[rmt]")
rmt_clean_testbench(tx_channel, rx_channel); rmt_clean_testbench(tx_channel, rx_channel);
} }
#endif #endif
#endif // SOC_RMT_SUPPORTED

View File

@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@pytest.mark.generic
@pytest.mark.parametrize('config', [
'release',
], indirect=True)
def test_legacy_rmt(dut: Dut) -> None:
dut.expect('Press ENTER to see the list of tests')
dut.write('*')
dut.expect_unity_test_output(timeout=120)

View File

@@ -0,0 +1,5 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

View File

@@ -0,0 +1,3 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n
CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y

View File

@@ -1,43 +0,0 @@
// Copyright 2019 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
/**
* @brief Timings for NEC protocol
*
*/
#define NEC_LEADING_CODE_HIGH_US (9000)
#define NEC_LEADING_CODE_LOW_US (4500)
#define NEC_PAYLOAD_ONE_HIGH_US (560)
#define NEC_PAYLOAD_ONE_LOW_US (1690)
#define NEC_PAYLOAD_ZERO_HIGH_US (560)
#define NEC_PAYLOAD_ZERO_LOW_US (560)
#define NEC_REPEAT_CODE_HIGH_US (9000)
#define NEC_REPEAT_CODE_LOW_US (2250)
#define NEC_ENDING_CODE_HIGH_US (560)
/**
* @brief Timings for RC5 protocol
*
*/
#define RC5_PULSE_DURATION_US (889)
#ifdef __cplusplus
}
#endif

View File

@@ -2073,11 +2073,6 @@ examples/peripherals/mcpwm/mcpwm_brushed_dc_control/main/mcpwm_brushed_dc_contro
examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c examples/peripherals/mcpwm/mcpwm_capture_hc_sr04/main/mcpwm_capture_hc_sr04.c
examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c examples/peripherals/mcpwm/mcpwm_servo_control/main/mcpwm_servo_control_example_main.c
examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c examples/peripherals/mcpwm/mcpwm_sync_example/main/mcpwm_sync_example.c
examples/peripherals/rmt/ir_protocols/components/infrared_tools/include/ir_timings.h
examples/peripherals/rmt/ir_protocols/components/infrared_tools/src/ir_builder_rmt_nec.c
examples/peripherals/rmt/ir_protocols/components/infrared_tools/src/ir_builder_rmt_rc5.c
examples/peripherals/rmt/ir_protocols/components/infrared_tools/src/ir_parser_rmt_nec.c
examples/peripherals/rmt/ir_protocols/components/infrared_tools/src/ir_parser_rmt_rc5.c
examples/peripherals/rmt/ir_protocols/example_test.py examples/peripherals/rmt/ir_protocols/example_test.py
examples/peripherals/rmt/ir_protocols/main/ir_protocols_main.c examples/peripherals/rmt/ir_protocols/main/ir_protocols_main.c
examples/peripherals/rmt/led_strip/main/led_strip_main.c examples/peripherals/rmt/led_strip/main/led_strip_main.c

View File

@@ -2,8 +2,7 @@
# 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)
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/" list(APPEND 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

@@ -25,8 +25,8 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#include "driver/rmt.h"
#include "driver/pulse_cnt.h" #include "driver/pulse_cnt.h"
#include "driver/rmt_types_legacy.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/gpio_periph.h" #include "soc/gpio_periph.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"