mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 09:39:10 -04:00
Merge branch 'feat/rmt_support_esp32c5mp' into 'master'
feat(rmt): add driver support on esp32c5 Closes IDF-8726 See merge request espressif/esp-idf!30879
This commit is contained in:
commit
404ffa299b
@ -74,7 +74,7 @@ typedef dma_descriptor_align4_t rmt_dma_descriptor_t;
|
||||
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
|
||||
|
||||
// Use retention link only when the target supports sleep retention and PM is enabled
|
||||
#define RMT_USE_RETENTION_LINK (SOC_RMT_SUPPORT_SLEEP_BACKUP && CONFIG_PM_ENABLE && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
#define RMT_USE_RETENTION_LINK (SOC_RMT_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
|
@ -70,7 +70,8 @@ static esp_err_t rmt_rx_init_dma_link(rmt_rx_channel_t *rx_channel, const rmt_rx
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_done = rmt_dma_rx_one_block_cb,
|
||||
};
|
||||
gdma_register_rx_event_callbacks(rx_channel->base.dma_chan, &cbs, rx_channel);
|
||||
// register the DMA callbacks may fail if the interrupt service can not be installed successfully
|
||||
ESP_RETURN_ON_ERROR(gdma_register_rx_event_callbacks(rx_channel->base.dma_chan, &cbs, rx_channel), TAG, "register DMA callbacks failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // SOC_RMT_SUPPORT_DMA
|
||||
@ -188,9 +189,9 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_
|
||||
ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported");
|
||||
#endif // SOC_RMT_SUPPORT_DMA
|
||||
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.backup_before_sleep == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// malloc channel memory
|
||||
uint32_t mem_caps = RMT_MEM_ALLOC_CAPS;
|
||||
|
@ -92,7 +92,8 @@ static esp_err_t rmt_tx_init_dma_link(rmt_tx_channel_t *tx_channel, const rmt_tx
|
||||
gdma_tx_event_callbacks_t cbs = {
|
||||
.on_trans_eof = rmt_dma_tx_eof_cb,
|
||||
};
|
||||
gdma_register_tx_event_callbacks(tx_channel->base.dma_chan, &cbs, tx_channel);
|
||||
// register the DMA callbacks may fail if the interrupt service can not be installed successfully
|
||||
ESP_RETURN_ON_ERROR(gdma_register_tx_event_callbacks(tx_channel->base.dma_chan, &cbs, tx_channel), TAG, "register DMA callbacks failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // SOC_RMT_SUPPORT_DMA
|
||||
@ -256,9 +257,9 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_
|
||||
ESP_RETURN_ON_FALSE(config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA not supported");
|
||||
#endif
|
||||
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.backup_before_sleep == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// malloc channel memory
|
||||
uint32_t mem_caps = RMT_MEM_ALLOC_CAPS;
|
||||
|
@ -132,7 +132,7 @@ static void test_rmt_tx_rx_sleep_retention(bool back_up_before_sleep)
|
||||
TEST_CASE("rmt tx+rx after light sleep", "[rmt]")
|
||||
{
|
||||
test_rmt_tx_rx_sleep_retention(false);
|
||||
#if SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#if SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
test_rmt_tx_rx_sleep_retention(true);
|
||||
#endif
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ bool peripheral_domain_pd_allowed(void)
|
||||
const uint32_t created_modules = sleep_retention_get_created_modules();
|
||||
uint32_t mask = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH));
|
||||
|
||||
#if SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#if SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_RMT0);
|
||||
#endif
|
||||
|
||||
|
@ -485,7 +485,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
|
@ -427,7 +427,7 @@ static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel,
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param channel RMT TX channel number
|
||||
* @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data
|
||||
* @param enable True to output carrier signal in all RMT state, False to only output carrier signal for effective data
|
||||
*/
|
||||
static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
@ -658,7 +658,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "sdkconfig.h" // TODO: [ESP32C5] IDF-8726
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
#include "hal/rmt_types.h"
|
||||
@ -24,8 +23,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
|
||||
|
||||
#define RMT_LL_EVENT_TX_DONE(channel) (1 << (channel))
|
||||
#define RMT_LL_EVENT_TX_THRES(channel) (1 << ((channel) + 8))
|
||||
#define RMT_LL_EVENT_TX_LOOP_END(channel) (1 << ((channel) + 12))
|
||||
@ -436,7 +433,7 @@ static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel,
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param channel RMT TX channel number
|
||||
* @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data
|
||||
* @param enable True to output carrier signal in all RMT state, False to only output carrier signal for effective data
|
||||
*/
|
||||
static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
@ -667,7 +664,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
@ -883,8 +880,6 @@ static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev)
|
||||
return (dev->int_st.val >> 12) & 0x03;
|
||||
}
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -463,7 +463,7 @@ static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel,
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param channel RMT TX channel number
|
||||
* @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data
|
||||
* @param enable True to output carrier signal in all RMT state, False to only output carrier signal for effective data
|
||||
*/
|
||||
static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
@ -706,7 +706,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
|
@ -423,7 +423,7 @@ static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel,
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param channel RMT TX channel number
|
||||
* @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data
|
||||
* @param enable True to output carrier signal in all RMT state, False to only output carrier signal for effective data
|
||||
*/
|
||||
static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
@ -628,7 +628,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
|
@ -453,7 +453,7 @@ static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel,
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param channel RMT TX channel number
|
||||
* @param enable True to output carrier signal in all RMT state, False to only ouput carrier signal for effective data
|
||||
* @param enable True to output carrier signal in all RMT state, False to only output carrier signal for effective data
|
||||
*/
|
||||
static inline void rmt_ll_tx_enable_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
@ -696,7 +696,7 @@ static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool e
|
||||
* @brief Clear RMT interrupt status by mask
|
||||
*
|
||||
* @param dev Peripheral instance address
|
||||
* @param mask Interupt status mask
|
||||
* @param mask Interrupt status mask
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
|
||||
|
@ -12,7 +12,7 @@ void rmt_hal_init(rmt_hal_context_t *hal)
|
||||
hal->regs = &RMT;
|
||||
rmt_ll_power_down_mem(hal->regs, false); // turn on RMTMEM power domain
|
||||
rmt_ll_enable_mem_access_nonfifo(hal->regs, true); // APB access the RMTMEM in nonfifo mode
|
||||
rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events
|
||||
rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interrupt events
|
||||
rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events
|
||||
#if SOC_RMT_SUPPORT_TX_SYNCHRO
|
||||
rmt_ll_tx_clear_sync_group(hal->regs);
|
||||
@ -21,7 +21,7 @@ void rmt_hal_init(rmt_hal_context_t *hal)
|
||||
|
||||
void rmt_hal_deinit(rmt_hal_context_t *hal)
|
||||
{
|
||||
rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interupt events
|
||||
rmt_ll_enable_interrupt(hal->regs, UINT32_MAX, false); // disable all interrupt events
|
||||
rmt_ll_clear_interrupt_status(hal->regs, UINT32_MAX); // clear all pending events
|
||||
rmt_ll_power_down_mem(hal->regs, true); // turn off RMTMEM power domain
|
||||
hal->regs = NULL;
|
||||
|
@ -51,6 +51,10 @@ config SOC_I2S_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_GPSPI_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -821,13 +821,13 @@ typedef union {
|
||||
} rmt_date_reg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct rmt_dev_t {
|
||||
volatile rmt_chndata_reg_t chndata[4];
|
||||
volatile rmt_chnconf0_reg_t chnconf0[2];
|
||||
volatile rmt_chmconf0_reg_t ch2conf0;
|
||||
volatile rmt_chmconf1_reg_t ch2conf1;
|
||||
volatile rmt_chmconf0_reg_t ch3conf0;
|
||||
volatile rmt_chmconf1_reg_t ch3conf1;
|
||||
volatile struct {
|
||||
rmt_chmconf0_reg_t conf0;
|
||||
rmt_chmconf1_reg_t conf1;
|
||||
} chmconf[2];;
|
||||
volatile rmt_chnstatus_reg_t chnstatus[2];
|
||||
volatile rmt_chmstatus_reg_t chmstatus[2];
|
||||
volatile rmt_int_raw_reg_t int_raw;
|
||||
|
@ -39,7 +39,7 @@
|
||||
#define SOC_RTC_FAST_MEM_SUPPORTED 1
|
||||
#define SOC_RTC_MEM_SUPPORTED 1
|
||||
#define SOC_I2S_SUPPORTED 1
|
||||
// #define SOC_RMT_SUPPORTED 1 // TODO: [ESP32C5] IDF-8726
|
||||
#define SOC_RMT_SUPPORTED 1
|
||||
// #define SOC_SDM_SUPPORTED 1 // TODO: [ESP32C5] IDF-8687
|
||||
#define SOC_GPSPI_SUPPORTED 1
|
||||
// #define SOC_LEDC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8684
|
||||
|
@ -799,7 +799,7 @@ config SOC_RMT_SUPPORT_RC_FAST
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
config SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
|
@ -314,7 +314,7 @@
|
||||
#define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */
|
||||
#define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */
|
||||
#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */
|
||||
#define SOC_RMT_SUPPORT_SLEEP_BACKUP 1 /*!< Support back up registers before sleep */
|
||||
#define SOC_RMT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up RMT registers before sleep */
|
||||
|
||||
/*-------------------------- MCPWM CAPS --------------------------------------*/
|
||||
#define SOC_MCPWM_GROUPS (1U) ///< 1 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals)
|
||||
|
@ -783,7 +783,7 @@ config SOC_RMT_SUPPORT_RC_FAST
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
config SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
|
@ -306,7 +306,7 @@
|
||||
#define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */
|
||||
#define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */
|
||||
#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */
|
||||
#define SOC_RMT_SUPPORT_SLEEP_BACKUP 1 /*!< Support back up registers before sleep */
|
||||
#define SOC_RMT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up RMT registers before sleep */
|
||||
|
||||
/*-------------------------- MCPWM CAPS --------------------------------------*/
|
||||
#define SOC_MCPWM_GROUPS (1U) ///< 1 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals)
|
||||
|
@ -30,7 +30,7 @@ typedef struct {
|
||||
|
||||
extern const rmt_signal_conn_t rmt_periph_signals;
|
||||
|
||||
#if SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#if SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
typedef struct {
|
||||
const regdma_entries_config_t *regdma_entry_array;
|
||||
uint32_t array_size;
|
||||
@ -40,7 +40,7 @@ typedef struct {
|
||||
// - save memory when not all RMT channels are used
|
||||
// - specify different retention dependency, e.g. only RMT channel x is capable to use DMA, we only want to add the DMA dependency for that channel
|
||||
extern const rmt_reg_retention_info_t rmt_reg_retention_info[SOC_RMT_GROUPS];
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
#endif // SOC_RMT_SUPPORTED
|
||||
|
||||
|
@ -138,7 +138,6 @@ api-reference/peripherals/spi_master.rst
|
||||
api-reference/peripherals/index.rst
|
||||
api-reference/peripherals/sdmmc_host.rst
|
||||
api-reference/peripherals/ecdsa.rst
|
||||
api-reference/peripherals/rmt.rst
|
||||
api-reference/kconfig.rst
|
||||
api-reference/network/esp_openthread.rst
|
||||
api-reference/network/esp_eth.rst
|
||||
|
@ -555,7 +555,7 @@ When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the syste
|
||||
|
||||
The driver can prevent the above issue by creating a power management lock. The lock type is set based on different clock sources. The driver will acquire the lock in :cpp:func:`rmt_enable`, and release it in :cpp:func:`rmt_disable`. That means, any RMT transactions in between these two functions are guaranteed to work correctly, regardless of the power management strategy. The clock source won't be disabled or adjusted its frequency during this time.
|
||||
|
||||
.. only:: SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
.. only:: SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
Besides the potential changes to the clock source, when the power management is enabled, the system can also power down a domain where RMT register located. To ensure the RMT driver can continue work after sleep, we can either backup the RMT registers to the RAM, or just refuse to power down. You can choose what to do in :cpp:member:`rmt_tx_channel_config_t::backup_before_sleep` and :cpp:member:`rmt_rx_channel_config_t::backup_before_sleep`. It's a balance between power saving and memory consumption. Set it based on your application requirements.
|
||||
|
||||
|
@ -555,7 +555,7 @@ RMT 编码器是 RMT TX 事务的一部分,用于在特定时间生成正确
|
||||
|
||||
驱动程序可以通过创建一个电源管理锁来防止上述问题。锁的类型会根据不同的时钟源来设置。驱动程序将在 :cpp:func:`rmt_enable` 中拿锁,并在 :cpp:func:`rmt_disable` 中释放锁。这意味着,无论电源管理策略如何,在这两个函数之间的任何 RMT 事务都可以保证正常工作。在此期间,时钟源不会被禁用或调整频率。
|
||||
|
||||
.. only:: SOC_RMT_SUPPORT_SLEEP_BACKUP
|
||||
.. only:: SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
除了时钟源的潜在变化外,当启用电源管理时,系统还可以关闭 RMT 寄存器所在的电源域。为确保 RMT 驱动程序在睡眠后继续工作,用户要么选择将 RMT 相关的寄存器备份到 RAM 中,要么拒绝关闭电源域。你可以根据应用需求在 :cpp:member:`rmt_tx_channel_config_t::backup_before_sleep` 和 :cpp:member:`rmt_rx_channel_config_t::backup_before_sleep` 中设置是否需要启用寄存器备份,在功耗和内存使用之间做权衡。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user