feat(rmt): enable RMT support on esp32s31

Enable esp32s31 RMT caps and clock source definitions for
esp_driver_rmt.

Add esp32s31 RMT LL/periph hooks, sleep retention metadata, and RMTMEM
linker symbol.
This commit is contained in:
morris
2026-03-31 00:22:37 +08:00
parent ae710978ae
commit ae8acf82e7
35 changed files with 1069 additions and 115 deletions
@@ -4,66 +4,66 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <strings.h> #include <strings.h>
#include "esp_secure_boot.h" #include "esp_secure_boot.h"
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_efuse_table.h" #include "esp_efuse_table.h"
#include "esp_log.h" #include "esp_log.h"
#include "sdkconfig.h" #include "sdkconfig.h"
ESP_LOG_ATTR_TAG(TAG, "secure_boot"); ESP_LOG_ATTR_TAG(TAG, "flash_encrypt");
esp_err_t esp_secure_boot_enable_secure_features(void) esp_err_t esp_flash_encryption_enable_secure_features(void)
{ {
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT); esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE #ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
ESP_LOGI(TAG, "Enabling Security download mode..."); ESP_LOGI(TAG, "Enabling Security download mode...");
esp_err_t err = esp_efuse_enable_rom_secure_download_mode(); esp_err_t err = esp_efuse_enable_rom_secure_download_mode();
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not enable Security download mode..."); ESP_LOGE(TAG, "Could not enable Security download mode...");
return err; return err;
} }
#elif CONFIG_SECURE_DISABLE_ROM_DL_MODE #elif CONFIG_SECURE_DISABLE_ROM_DL_MODE
ESP_LOGI(TAG, "Disable ROM Download mode..."); ESP_LOGI(TAG, "Disable ROM Download mode...");
esp_err_t err = esp_efuse_disable_rom_download_mode(); esp_err_t err = esp_efuse_disable_rom_download_mode();
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not disable ROM Download mode..."); ESP_LOGE(TAG, "Could not disable ROM Download mode...");
return err; return err;
} }
#else #else
ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED"); ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
#endif #endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable hardware & software JTAG..."); ESP_LOGI(TAG, "Disable hardware & software JTAG...");
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG); esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG); esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count);
#else #else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif #endif
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE #ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE); esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
#endif #endif
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS #ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool rd_dis_now = true; bool rd_dis_now = true;
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
/* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
when Flash Encryption is being enabled */ when Flash Encryption is being enabled */
rd_dis_now = esp_efuse_is_flash_encryption_enabled(); rd_dis_now = esp_efuse_is_flash_encryption_enabled();
#endif #endif
if (rd_dis_now) { if (rd_dis_now) {
ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS);
} }
#else #else
ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
#endif #endif
return ESP_OK; return ESP_OK;
} }
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
@@ -14,7 +14,9 @@ from pytest_embedded_idf.utils import idf_parametrize
], ],
indirect=True, indirect=True,
) )
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) @idf_parametrize(
'target', ['esp32', 'esp32s2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32s31'], indirect=['target']
)
def test_rmt(dut: Dut) -> None: def test_rmt(dut: Dut) -> None:
dut.run_all_single_board_cases() dut.run_all_single_board_cases()
@@ -0,0 +1,2 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0
@@ -54,7 +54,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -55,7 +55,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -55,7 +55,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -55,7 +55,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -55,7 +55,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -55,7 +55,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -54,7 +54,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -54,7 +54,6 @@ extern "C" {
// Maximum values due to limited register bit width // Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 #define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 #define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64
typedef enum { typedef enum {
RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_SW = 0,
@@ -0,0 +1,816 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @note TX and RX channels are index from 0 in the LL driver, i.e. tx_channel = [0,3], rx_channel = [0,3]
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "hal/rmt_types.h"
#include "soc/rmt_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/hp_system_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get RMT attribute
#define RMT_LL_GET(_attr) (RMT_LL_ ## _attr)
#define RMT_LL_SUPPORT(_feat) (RMT_LL_SUPPORT_ ## _feat)
// SoC-based capabilities
#define RMT_LL_INST_NUM (1) /*!< Number of RMT group */
#define RMT_LL_TX_CANDIDATES_PER_INST (4) /*!< Number of channels that capable of Transmit in each group */
#define RMT_LL_RX_CANDIDATES_PER_INST (4) /*!< Number of channels that capable of Receive in each group */
#define RMT_LL_CHANS_PER_INST (8) /*!< Total 8 channels */
#define RMT_LL_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define RMT_LL_SUPPORT_ASYNC_STOP (1) /*!< Support stop transmission asynchronously */
#define RMT_LL_SUPPORT_TX_SYNCHRO (1) /*!< Support coordinate a group of TX channels to start simultaneously */
#define RMT_LL_SUPPORT_RC_FAST (1) /*!< Support set RC_FAST clock as the RMT clock source */
#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))
#define RMT_LL_EVENT_TX_ERROR(channel) (1 << ((channel) + 4))
#define RMT_LL_EVENT_RX_DONE(channel) (1 << ((channel) + 16))
#define RMT_LL_EVENT_RX_THRES(channel) (1 << ((channel) + 24))
#define RMT_LL_EVENT_RX_ERROR(channel) (1 << ((channel) + 20))
#define RMT_LL_EVENT_TX_MASK(channel) (RMT_LL_EVENT_TX_DONE(channel) | RMT_LL_EVENT_TX_THRES(channel) | RMT_LL_EVENT_TX_LOOP_END(channel))
#define RMT_LL_EVENT_RX_MASK(channel) (RMT_LL_EVENT_RX_DONE(channel) | RMT_LL_EVENT_RX_THRES(channel))
#define RMT_LL_MAX_LOOP_COUNT_PER_BATCH 1023
#define RMT_LL_MAX_FILTER_VALUE 255
#define RMT_LL_MAX_IDLE_VALUE 32767
// Maximum values due to limited register bit width
#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256
#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256
typedef enum {
RMT_LL_MEM_OWNER_SW = 0,
RMT_LL_MEM_OWNER_HW = 1,
} rmt_ll_mem_owner_t;
typedef enum {
RMT_LL_MEM_LP_MODE_DEEP_SLEEP, // memory will enter deep sleep during low power stage, keep memory data
RMT_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory will enter light sleep during low power stage, keep memory data
RMT_LL_MEM_LP_MODE_SHUT_DOWN, // memory will be powered down during low power stage
RMT_LL_MEM_LP_MODE_DISABLE, // disable the low power stage
} rmt_ll_mem_lp_mode_t;
/**
* @brief Enable the bus clock for RMT module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void rmt_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_sys_clk_en = enable;
}
/**
* @brief Reset the RMT module
*
* @param group_id Group ID
*/
static inline void rmt_ll_reset_register(int group_id)
{
(void)group_id;
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_rst_en = 1;
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_rst_en = 0;
}
/**
* @brief Force power on the RMT memory block, regardless of the outside PMU logic
*
* @param dev Peripheral instance address
*/
static inline void rmt_ll_mem_force_power_on(rmt_dev_t *dev)
{
(void)dev;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_force_ctrl = 1;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_en = 0;
}
/**
* @brief Force the RMT memory block into low power mode, regardless of the outside PMU logic
*
* @param dev Peripheral instance address
*/
static inline void rmt_ll_mem_force_low_power(rmt_dev_t *dev)
{
(void)dev;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_force_ctrl = 1;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_en = 1;
}
/**
* @brief Power control the RMT memory block by the outside PMU logic
*
* @param dev Peripheral instance address
* @param mode RMT memory low power mode in low power stage
*/
static inline void rmt_ll_mem_power_by_pmu(rmt_dev_t *dev)
{
(void)dev;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_en = 0;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_force_ctrl = 0;
}
/**
* @brief Set low power mode for RMT memory block
*
* @param dev Peripheral instance address
* @param mode RMT memory low power mode in low power stage
*/
static inline void rmt_ll_mem_set_low_power_mode(rmt_dev_t *dev, rmt_ll_mem_lp_mode_t mode)
{
(void)dev;
HP_SYSTEM.sys_rmt_mem_lp_ctrl.sys_rmt_mem_lp_mode = mode;
}
/**
* @brief Enable APB accessing RMT memory in nonfifo mode
*
* @param dev Peripheral instance address
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_enable_mem_access_nonfifo(rmt_dev_t *dev, bool enable)
{
dev->sys_conf.apb_fifo_mask = enable;
}
/**
* @brief Set clock source and divider for RMT channel group
*
* @param dev Peripheral instance address
* @param channel not used as clock source is set for all channels
* @param src Clock source
* @param divider_integral Integral part of the divider
* @param divider_denominator Denominator part of the divider
* @param divider_numerator Numerator part of the divider
*/
static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, rmt_clock_source_t src,
uint32_t divider_integral, uint32_t divider_denominator, uint32_t divider_numerator)
{
(void)dev;
// Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b)
(void)channel; // the source clock is set for all channels
HAL_ASSERT(divider_integral >= 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.rmt_ctrl0, reg_rmt_clk_div_num, divider_integral - 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.rmt_ctrl0, reg_rmt_clk_div_numerator, divider_numerator);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.rmt_ctrl0, reg_rmt_clk_div_denominator, divider_denominator);
switch (src) {
case RMT_CLK_SRC_PLL_F80M:
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_clk_src_sel = 2;
break;
case RMT_CLK_SRC_RC_FAST:
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_clk_src_sel = 1;
break;
case RMT_CLK_SRC_XTAL:
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_clk_src_sel = 0;
break;
default:
HAL_ASSERT(false);
break;
}
}
/**
* @brief Enable RMT peripheral source clock
*
* @param dev Peripheral instance address
* @param en True to enable, False to disable
*/
static inline void rmt_ll_enable_group_clock(rmt_dev_t *dev, bool en)
{
(void)dev;
HP_SYS_CLKRST.rmt_ctrl0.reg_rmt_clk_en = en;
}
////////////////////////////////////////TX Channel Specific/////////////////////////////////////////////////////////////
/**
* @brief Reset clock divider for TX channels by mask
*
* @param dev Peripheral instance address
* @param channel_mask Mask of TX channels
*/
static inline void rmt_ll_tx_reset_channels_clock_div(rmt_dev_t *dev, uint32_t channel_mask)
{
// write 1 to reset
dev->ref_cnt_rst.val |= channel_mask & 0x0F;
}
/**
* @brief Set TX channel clock divider
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param div Division value
*/
static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
HAL_ASSERT(div >= 1 && div <= 256 && "divider out of range");
// limit the maximum divider to 256
if (div >= 256) {
div = 0; // 0 means 256 division
}
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_chn, div);
}
/**
* @brief Reset RMT reading pointer for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->chnconf0[channel].mem_rd_rst_chn = 1;
dev->chnconf0[channel].mem_rd_rst_chn = 0;
dev->chnconf0[channel].apb_mem_rst_chn = 1;
dev->chnconf0[channel].apb_mem_rst_chn = 0;
}
/**
* @brief Enable DMA access for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_tx_enable_dma(rmt_dev_t *dev, uint32_t channel, bool enable)
{
HAL_ASSERT(channel == 3 && "only TX channel 3 has DMA ability");
dev->chnconf0[channel].dma_access_en_chn = enable;
}
/**
* @brief Start transmitting for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel)
{
// update other configuration registers before start transmitting
dev->chnconf0[channel].conf_update_chn = 1;
dev->chnconf0[channel].tx_start_chn = 1;
}
/**
* @brief Stop transmitting for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel)
{
dev->chnconf0[channel].tx_stop_chn = 1;
// stop won't take place until configurations updated
dev->chnconf0[channel].conf_update_chn = 1;
}
/**
* @brief Set memory block number for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param block_num memory block number
*/
static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->chnconf0[channel].mem_size_chn = block_num;
}
/**
* @brief Enable TX wrap
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_tx_enable_wrap(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chnconf0[channel].mem_tx_wrap_en_chn = enable;
}
/**
* @brief Enable transmitting in a loop
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chnconf0[channel].tx_conti_mode_chn = enable;
}
/**
* @brief Set loop count for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param count TX loop count
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
{
HAL_ASSERT(count <= RMT_LL_MAX_LOOP_COUNT_PER_BATCH && "loop count out of range");
dev->chn_tx_lim[channel].tx_loop_num_chn = count;
}
/**
* @brief Reset loop count for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_reset_loop_count(rmt_dev_t *dev, uint32_t channel)
{
dev->chn_tx_lim[channel].loop_count_reset_chn = 1;
dev->chn_tx_lim[channel].loop_count_reset_chn = 0;
}
/**
* @brief Enable loop count for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chn_tx_lim[channel].tx_loop_cnt_en_chn = enable;
}
/**
* @brief Enable loop stop at count value automatically
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_enable_loop_autostop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chn_tx_lim[channel].loop_stop_en_chn = enable;
}
/**
* @brief Enable transmit multiple channels synchronously
*
* @param dev Peripheral instance address
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable)
{
dev->tx_sim.tx_sim_en = enable;
}
/**
* @brief Clear the TX channels synchronous group
*
* @param dev Peripheral instance address
*/
static inline void rmt_ll_tx_clear_sync_group(rmt_dev_t *dev)
{
dev->tx_sim.val &= ~(0x0F);
}
/**
* @brief Add TX channels to the synchronous group
*
* @param dev Peripheral instance address
* @param channel_mask Mask of TX channels to be added to the synchronous group
*/
static inline void rmt_ll_tx_sync_group_add_channels(rmt_dev_t *dev, uint32_t channel_mask)
{
dev->tx_sim.val |= (channel_mask & 0x0F);
}
/**
* @brief Remove TX channels from the synchronous group
*
* @param dev Peripheral instance address
* @param channel_mask Mask of TX channels to be removed from the synchronous group
*/
static inline void rmt_ll_tx_sync_group_remove_channels(rmt_dev_t *dev, uint32_t channel_mask)
{
dev->tx_sim.val &= ~channel_mask;
}
/**
* @brief Fix the output level when TX channel is in IDLE state
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param level IDLE level (1 => high, 0 => low)
* @param enable True to fix the IDLE level, otherwise the IDLE level is determined by EOF encoder
*/
__attribute__((always_inline))
static inline void rmt_ll_tx_fix_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level, bool enable)
{
dev->chnconf0[channel].idle_out_en_chn = enable;
dev->chnconf0[channel].idle_out_lv_chn = level;
}
/**
* @brief Set the amount of RMT symbols that can trigger the limitation interrupt
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param limit Specify the number of symbols
*/
static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->chn_tx_lim[channel].tx_lim_chn = limit;
}
/**
* @brief Set high and low duration of carrier signal
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param high_ticks Duration of high level
* @param low_ticks Duration of low level
*/
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)
{
HAL_ASSERT(high_ticks >= 1 && high_ticks <= 65536 && low_ticks >= 1 && low_ticks <= 65536 && "out of range high/low ticks");
// ticks=0 means 65536 in hardware
if (high_ticks >= 65536) {
high_ticks = 0;
}
if (low_ticks >= 65536) {
low_ticks = 0;
}
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_high_chn, high_ticks);
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_low_chn, low_ticks);
}
/**
* @brief Enable modulating carrier signal to TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chnconf0[channel].carrier_en_chn = enable;
}
/**
* @brief Set on high or low to modulate the carrier signal
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @param level Which level to modulate on (0=>low level, 1=>high level)
*/
static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->chnconf0[channel].carrier_out_lv_chn = level;
}
/**
* @brief Enable to always output carrier signal, regardless of a valid data transmission
*
* @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 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)
{
dev->chnconf0[channel].carrier_eff_en_chn = !enable;
}
////////////////////////////////////////RX Channel Specific/////////////////////////////////////////////////////////////
/**
* @brief Reset clock divider for RX channels by mask
*
* @param dev Peripheral instance address
* @param channel_mask Mask of RX channels
*/
static inline void rmt_ll_rx_reset_channels_clock_div(rmt_dev_t *dev, uint32_t channel_mask)
{
// write 1 to reset
dev->ref_cnt_rst.val |= ((channel_mask & 0x0F) << 4);
}
/**
* @brief Set RX channel clock divider
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param div Division value
*/
static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
HAL_ASSERT(div >= 1 && div <= 256 && "divider out of range");
// limit the maximum divider to 256
if (div >= 256) {
div = 0; // 0 means 256 division
}
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_chm, div);
}
/**
* @brief Reset RMT writing pointer for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->chmconf[channel].conf1.mem_wr_rst_chm = 1;
dev->chmconf[channel].conf1.mem_wr_rst_chm = 0;
dev->chmconf[channel].conf1.apb_mem_rst_chm = 1;
dev->chmconf[channel].conf1.apb_mem_rst_chm = 0;
}
/**
* @brief Enable DMA access for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_rx_enable_dma(rmt_dev_t *dev, uint32_t channel, bool enable)
{
HAL_ASSERT(channel == 3 && "only RX channel 3 has DMA ability");
dev->chmconf[channel].conf0.dma_access_en_chm = enable;
}
/**
* @brief Enable receiving for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.rx_en_chm = enable;
// rx won't be enabled until configurations updated
dev->chmconf[channel].conf1.conf_update_chm = 1;
}
/**
* @brief Set memory block number for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param block_num memory block number
*/
static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->chmconf[channel].conf0.mem_size_chm = block_num;
}
/**
* @brief Set the time length for RX channel before going into IDLE state
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param thres Time length threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->chmconf[channel].conf0.idle_thres_chm = thres;
}
/**
* @brief Set RMT memory owner for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param owner Memory owner
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, rmt_ll_mem_owner_t owner)
{
dev->chmconf[channel].conf1.mem_owner_chm = owner;
}
/**
* @brief Enable filter for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX chanenl number
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.rx_filter_en_chm = enable;
}
/**
* @brief Set RX channel filter threshold (i.e. the maximum width of one pulse signal that would be treated as a noise)
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param thres Filter threshold
*/
__attribute__((always_inline))
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_chm, thres);
}
/**
* @brief Get RMT memory write cursor offset
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @return writer offset
*/
__attribute__((always_inline))
static inline uint32_t rmt_ll_rx_get_memory_writer_offset(rmt_dev_t *dev, uint32_t channel)
{
return dev->chmstatus[channel].mem_waddr_ex_chm - (channel + 4) * 48;
}
/**
* @brief Set the amount of RMT symbols that can trigger the limitation interrupt
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param limit Specify the number of symbols
*/
static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->chm_rx_lim[channel].rx_lim_chm = limit;
}
/**
* @brief Set high and low duration of carrier signal
*
* @param dev dev Peripheral instance address
* @param channel RMT TX channel number
* @param high_ticks Duration of high level
* @param low_ticks Duration of low level
*/
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)
{
HAL_ASSERT(high_ticks >= 1 && high_ticks <= 65536 && low_ticks >= 1 && low_ticks <= 65536 && "out of range high/low ticks");
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_high_thres_chm, high_ticks - 1);
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_low_thres_chm, low_ticks - 1);
}
/**
* @brief Enable demodulating the carrier on RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf0.carrier_en_chm = enable;
}
/**
* @brief Set on high or low to demodulate the carrier signal
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param level Which level to demodulate (0=>low level, 1=>high level)
*/
static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->chmconf[channel].conf0.carrier_out_lv_chm = level;
}
/**
* @brief Enable RX wrap
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @param enable True to enable, False to disable
*/
static inline void rmt_ll_rx_enable_wrap(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->chmconf[channel].conf1.mem_rx_wrap_en_chm = enable;
}
//////////////////////////////////////////Interrupt Specific////////////////////////////////////////////////////////////
/**
* @brief Enable RMT interrupt for specific event mask
*
* @param dev Peripheral instance address
* @param mask Event mask
* @param enable True to enable, False to disable
*/
__attribute__((always_inline))
static inline void rmt_ll_enable_interrupt(rmt_dev_t *dev, uint32_t mask, bool enable)
{
if (enable) {
dev->int_ena.val |= mask;
} else {
dev->int_ena.val &= ~mask;
}
}
/**
* @brief Clear RMT interrupt status by mask
*
* @param dev Peripheral instance address
* @param mask Interrupt status mask
*/
__attribute__((always_inline))
static inline void rmt_ll_clear_interrupt_status(rmt_dev_t *dev, uint32_t mask)
{
dev->int_clr.val = mask;
}
/**
* @brief Get interrupt status register address
*
* @param dev Peripheral instance address
* @return Register address
*/
static inline volatile void *rmt_ll_get_interrupt_status_reg(rmt_dev_t *dev)
{
return &dev->int_st;
}
/**
* @brief Get interrupt status for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @return Interrupt status
*/
__attribute__((always_inline))
static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->int_st.val & RMT_LL_EVENT_TX_MASK(channel);
}
/**
* @brief Get interrupt raw status for TX channel
*
* @param dev Peripheral instance address
* @param channel RMT TX channel number
* @return Interrupt raw status
*/
static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
{
return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
}
/**
* @brief Get interrupt raw status for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @return Interrupt raw status
*/
static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
{
return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
}
/**
* @brief Get interrupt status for RX channel
*
* @param dev Peripheral instance address
* @param channel RMT RX channel number
* @return Interrupt status
*/
__attribute__((always_inline))
static inline uint32_t rmt_ll_rx_get_interrupt_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->int_st.val & RMT_LL_EVENT_RX_MASK(channel);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,80 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/rmt_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/rmt_reg.h"
const soc_rmt_signal_desc_t soc_rmt_signals[1] = {
[0] = {
.irq = ETS_RMT_INTR_SOURCE,
.module_name = "rmt0",
.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
},
}
}
};
/**
* RMT Registers to be saved during sleep retention
* - Channel configuration registers, e.g.: RMT_CH0CONF0_REG, RMT_CH3CONF0_REG, RMT_CH3CONF1_REG, RMT_CH0_TX_LIM_REG, RMT_CH3_RX_LIM_REG
* - TX synchronization registers, e.g.: RMT_TX_SIM_REG
* - Interrupt enable registers, e.g.: RMT_INT_ENA_REG
* - Carrier duty registers, e.g.: RMT_CH0CARRIER_DUTY_REG, RMT_CH3_RX_CARRIER_RM_REG
* - Global configuration registers, e.g.: RMT_SYS_CONF_REG
*/
#define RMT_RETENTION_REGS_CNT 31
#define RMT_RETENTION_REGS_BASE (DR_REG_RMT_BASE + 0x20)
static const uint32_t rmt_regs_map[4] = {0xff400fff, 0x3ff, 0x0, 0x0};
static const regdma_entries_config_t rmt_regdma_entries[] = {
[0] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_RMT_LINK(0x00),
RMT_RETENTION_REGS_BASE, RMT_RETENTION_REGS_BASE,
RMT_RETENTION_REGS_CNT, 0, 0,
rmt_regs_map[0], rmt_regs_map[1],
rmt_regs_map[2], rmt_regs_map[3]),
.owner = ENTRY(0),
},
};
const rmt_reg_retention_info_t rmt_reg_retention_info[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_RMT0,
.regdma_entry_array = rmt_regdma_entries,
.array_size = ARRAY_SIZE(rmt_regdma_entries),
},
};
@@ -59,6 +59,10 @@ config SOC_RTC_MEM_SUPPORTED
bool bool
default y default y
config SOC_RMT_SUPPORTED
bool
default y
config SOC_SDM_SUPPORTED config SOC_SDM_SUPPORTED
bool bool
default y default y
@@ -319,6 +323,30 @@ config SOC_LEDC_CHANNEL_NUM
int int
default 6 default 6
config SOC_RMT_MEM_WORDS_PER_CHANNEL
int
default 48
config SOC_RMT_SUPPORT_RX_PINGPONG
bool
default y
config SOC_RMT_SUPPORT_TX_LOOP_COUNT
bool
default y
config SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP
bool
default y
config SOC_RMT_SUPPORT_DMA
bool
default y
config SOC_RMT_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_MMU_PERIPH_NUM config SOC_MMU_PERIPH_NUM
int int
default 2 default 2
@@ -209,6 +209,21 @@ typedef enum {
//////////////////////////////////////////////////RMT/////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////RMT///////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of RMT
*/
#define SOC_RMT_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL}
/**
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */
RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default choice */
} soc_periph_rmt_clk_src_t;
///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/** /**
@@ -54,7 +54,7 @@
#define SOC_EFUSE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14688 #define SOC_EFUSE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14688
#define SOC_RTC_FAST_MEM_SUPPORTED 1 #define SOC_RTC_FAST_MEM_SUPPORTED 1
#define SOC_RTC_MEM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14645 #define SOC_RTC_MEM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14645
// #define SOC_RMT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14794 #define SOC_RMT_SUPPORTED 1
// #define SOC_I2S_SUPPORTED 1 // TODO: [ESP32S31] IDF-14771 // #define SOC_I2S_SUPPORTED 1 // TODO: [ESP32S31] IDF-14771
#define SOC_SDM_SUPPORTED 1 #define SOC_SDM_SUPPORTED 1
// #define SOC_GPSPI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14734 // #define SOC_GPSPI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14734
@@ -208,6 +208,14 @@
// TODO: [ESP32S31] IDF-14709 // TODO: [ESP32S31] IDF-14709
#define SOC_LEDC_CHANNEL_NUM (6) #define SOC_LEDC_CHANNEL_NUM (6)
/*--------------------------- RMT CAPS ---------------------------------------*/
#define SOC_RMT_MEM_WORDS_PER_CHANNEL 48 /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
#define SOC_RMT_SUPPORT_RX_PINGPONG 1 /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP 1 /*!< Hardware support of auto-stop in loop mode */
#define SOC_RMT_SUPPORT_DMA 1 /*!< RMT peripheral can connect to DMA channel */
#define SOC_RMT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up RMT registers before sleep */
/*-------------------------- MMU CAPS ----------------------------------------*/ /*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PERIPH_NUM (2U) #define SOC_MMU_PERIPH_NUM (2U)
#define SOC_MMU_LINEAR_ADDRESS_REGION_NUM (2U) #define SOC_MMU_LINEAR_ADDRESS_REGION_NUM (2U)
@@ -15,6 +15,7 @@ PROVIDE ( AXI_DMA = 0x20348000 );
PROVIDE ( GMAC = 0x20350000 ); PROVIDE ( GMAC = 0x20350000 );
PROVIDE ( PVT = 0x20354000 ); PROVIDE ( PVT = 0x20354000 );
PROVIDE ( RMT = 0x20355000 ); PROVIDE ( RMT = 0x20355000 );
PROVIDE ( RMTMEM = 0x20355800 );
PROVIDE ( BITSCRAMBLER = 0x20356000 ); PROVIDE ( BITSCRAMBLER = 0x20356000 );
PROVIDE ( ASRC = 0x20357000 ); PROVIDE ( ASRC = 0x20357000 );
PROVIDE ( CNNT_SYS_REG = 0x20359000 ); PROVIDE ( CNNT_SYS_REG = 0x20359000 );
@@ -108,7 +108,11 @@ typedef union {
* synchronization bit for CHANNELn * synchronization bit for CHANNELn
*/ */
uint32_t conf_update_chn:1; uint32_t conf_update_chn:1;
uint32_t reserved_25:7; /** dma_access_en_chn : WT; bitpos: [25]; default: 0;
* DMA access control bit for CHANNELn (only CHANNEL3 has this control bit)
*/
uint32_t dma_access_en_chn: 1;
uint32_t reserved_26: 6;
}; };
uint32_t val; uint32_t val;
} rmt_chnconf0_reg_t; } rmt_chnconf0_reg_t;
@@ -127,7 +131,10 @@ typedef union {
* than this register value, received process is finished. * than this register value, received process is finished.
*/ */
uint32_t idle_thres_chm:15; uint32_t idle_thres_chm:15;
uint32_t reserved_23:1; /** dma_access_en_m : WT; bitpos: [23]; default: 0;
* DMA access control bit for CHANNELm (only channel7 has this control bit)
*/
uint32_t dma_access_en_chm: 1;
/** mem_size_chm : R/W; bitpos: [27:24]; default: 1; /** mem_size_chm : R/W; bitpos: [27:24]; default: 1;
* This register is used to configure the maximum size of memory allocated to CHANNELm. * This register is used to configure the maximum size of memory allocated to CHANNELm.
*/ */
@@ -1038,18 +1045,14 @@ typedef union {
} rmt_date_reg_t; } rmt_date_reg_t;
typedef struct { typedef struct rmt_dev_t {
volatile rmt_chndata_reg_t chndata[4]; volatile rmt_chndata_reg_t chndata[4];
volatile rmt_chmdata_reg_t chmdata[4]; volatile rmt_chmdata_reg_t chmdata[4];
volatile rmt_chnconf0_reg_t chnconf0[4]; volatile rmt_chnconf0_reg_t chnconf0[4];
volatile rmt_chmconf0_reg_t ch4conf0; volatile struct {
volatile rmt_chmconf1_reg_t ch4conf1; rmt_chmconf0_reg_t conf0;
volatile rmt_chmconf0_reg_t ch5conf0; rmt_chmconf1_reg_t conf1;
volatile rmt_chmconf1_reg_t ch5conf1; } chmconf[4];
volatile rmt_chmconf0_reg_t ch6conf0;
volatile rmt_chmconf1_reg_t ch6conf1;
volatile rmt_chmconf0_reg_t ch7conf0;
volatile rmt_chmconf1_reg_t ch7conf1;
volatile rmt_chnstatus_reg_t chnstatus[4]; volatile rmt_chnstatus_reg_t chnstatus[4];
volatile rmt_chmstatus_reg_t chmstatus[4]; volatile rmt_chmstatus_reg_t chmstatus[4];
volatile rmt_int_raw_reg_t int_raw; volatile rmt_int_raw_reg_t int_raw;
@@ -1066,6 +1069,8 @@ typedef struct {
volatile rmt_date_reg_t date; volatile rmt_date_reg_t date;
} rmt_dev_t; } rmt_dev_t;
extern rmt_dev_t RMT;
#ifndef __cplusplus #ifndef __cplusplus
_Static_assert(sizeof(rmt_dev_t) == 0xd0, "Invalid size of rmt_dev_t structure"); _Static_assert(sizeof(rmt_dev_t) == 0xd0, "Invalid size of rmt_dev_t structure");
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# Blink Example # Blink Example
@@ -10,7 +10,6 @@ from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize('target', ['supported_targets'], indirect=['target']) @idf_parametrize('target', ['supported_targets'], indirect=['target'])
@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='s31 bringup on this module is not done')
def test_blink(dut: IdfDut) -> None: def test_blink(dut: IdfDut) -> None:
# check and log bin size # check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'blink.bin') binary_file = os.path.join(dut.app.binary_path, 'blink.bin')
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# RMT Infinite Loop Transmit Example -- Dshot ESC (Electronic Speed Controller) # RMT Infinite Loop Transmit Example -- Dshot ESC (Electronic Speed Controller)
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
@@ -3,14 +3,11 @@
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize( @idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORTED == 1'), indirect=['target'])
'target',
['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'],
indirect=['target'],
)
def test_dshot_esc_example(dut: Dut) -> None: def test_dshot_esc_example(dut: Dut) -> None:
dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Create RMT TX channel')
dut.expect_exact('example: Install Dshot ESC encoder') dut.expect_exact('example: Install Dshot ESC encoder')
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# IR NEC Encoding and Decoding Example # IR NEC Encoding and Decoding Example
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# RMT Transmit Example -- LED Strip # RMT Transmit Example -- LED Strip
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
@@ -3,14 +3,11 @@
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize( @idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORTED == 1'), indirect=['target'])
'target',
['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'],
indirect=['target'],
)
def test_led_strip_example(dut: Dut) -> None: def test_led_strip_example(dut: Dut) -> None:
dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Create RMT TX channel')
dut.expect_exact('example: Install led strip encoder') dut.expect_exact('example: Install led strip encoder')
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# RMT Transmit Example -- LED Strip # RMT Transmit Example -- LED Strip
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)
@@ -11,7 +11,7 @@
#include "driver/rmt_tx.h" #include "driver/rmt_tx.h"
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define RMT_LED_STRIP_GPIO_NUM 8 #define RMT_LED_STRIP_GPIO_NUM 0
#define EXAMPLE_LED_NUMBERS 24 #define EXAMPLE_LED_NUMBERS 24
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic
@idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORTED == 1'), indirect=['target'])
def test_led_strip_simple_encoder_example(dut: Dut) -> None:
dut.expect_exact('example: Create RMT TX channel')
dut.expect_exact('example: Create simple callback-based encoder')
dut.expect_exact('example: Enable RMT TX channel')
dut.expect_exact('example: Start LED rainbow chase')
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# RMT Transmit Loop Count Example -- Musical Buzzer # RMT Transmit Loop Count Example -- Musical Buzzer
@@ -3,12 +3,11 @@
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize( @idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORT_TX_LOOP_COUNT == 1'), indirect=['target'])
'target', ['esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']
)
def test_musical_buzzer_example(dut: Dut) -> None: def test_musical_buzzer_example(dut: Dut) -> None:
dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Create RMT TX channel')
dut.expect_exact('example: Install musical score encoder') dut.expect_exact('example: Install musical score encoder')
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus # Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus
@@ -3,14 +3,11 @@
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize( @idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORTED == 1'), indirect=['target'])
'target',
['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'],
indirect=['target'],
)
def test_onewire_example(dut: Dut) -> None: def test_onewire_example(dut: Dut) -> None:
dut.expect_exact('example: 1-Wire bus installed on GPIO') dut.expect_exact('example: 1-Wire bus installed on GPIO')
dut.expect_exact('example: Device iterator created, start searching') dut.expect_exact('example: Device iterator created, start searching')
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S3 | | Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S3 | ESP32-S31 |
| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | | ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | --------- |
# RMT Based Stepper Motor Smooth Controller # RMT Based Stepper Motor Smooth Controller
@@ -3,10 +3,11 @@
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic @pytest.mark.generic
@idf_parametrize('target', ['esp32s3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4'], indirect=['target']) @idf_parametrize('target', soc_filtered_targets('SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP == 1'), indirect=['target'])
def test_stepper_motor_example(dut: Dut) -> None: def test_stepper_motor_example(dut: Dut) -> None:
dut.expect_exact('example: Initialize EN + DIR GPIO') dut.expect_exact('example: Initialize EN + DIR GPIO')
dut.expect_exact('example: Create RMT TX channel') dut.expect_exact('example: Create RMT TX channel')