feat(i2s): supported getting the tx sync count and specify interrupt flags

This commit is contained in:
laokaiyao 2023-08-02 19:21:54 +08:00
parent cf889f3c6d
commit 0b0f25c30d
37 changed files with 749 additions and 222 deletions

View File

@ -17,6 +17,7 @@
#include "hal/adc_ll.h"
#include "hal/i2s_hal.h"
#include "hal/i2s_types.h"
#include "hal/clk_tree_ll.h"
#include "soc/i2s_periph.h"
#include "../dac_priv_dma.h"
#include "esp_private/i2s_platform.h"

View File

@ -58,6 +58,14 @@ static const char *TAG = "i2s(legacy)";
#define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num])
#define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
#if !SOC_RCC_IS_INDEPENDENT
#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV
#else
#define I2S_RCC_ATOMIC()
#define I2S_RCC_ENV_DECLARE
#endif
#define I2S_DMA_BUFFER_MAX_SIZE 4092
#if SOC_I2S_SUPPORTS_ADC_DAC
@ -1021,11 +1029,14 @@ static void i2s_set_clock_legacy(i2s_port_t i2s_num)
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_hal_clock_info_t clk_info;
i2s_calculate_clock(i2s_num, &clk_info);
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_set_rx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_set_rx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
}
}
}
@ -1479,17 +1490,6 @@ static esp_err_t i2s_init_legacy(i2s_port_t i2s_num, int intr_alloc_flag)
ESP_RETURN_ON_ERROR(i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx), TAG, "Allocate I2S dma rx buffer failed");
}
/* Initialize I2S DMA object */
#if SOC_I2S_HW_VERSION_2
/* Enable tx/rx submodule clock */
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_ll_tx_enable_clock(p_i2s[i2s_num]->hal.dev);
}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_ll_rx_enable_clock(p_i2s[i2s_num]->hal.dev);
}
#endif
return ESP_OK;
}
@ -1538,12 +1538,15 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
#if SOC_I2S_SUPPORTS_APLL
if (obj->use_apll) {
// switch back to PLL clock source
if (obj->dir & I2S_DIR_TX) {
i2s_ll_tx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT);
}
if (obj->dir & I2S_DIR_RX) {
i2s_ll_rx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
// switch back to PLL clock source
if (obj->dir & I2S_DIR_TX) {
i2s_ll_tx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT);
}
if (obj->dir & I2S_DIR_RX) {
i2s_ll_rx_clk_set_src(obj->hal.dev, I2S_CLK_SRC_DEFAULT);
}
}
periph_rtc_apll_release();
}
@ -1556,11 +1559,13 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
}
#endif
#if SOC_I2S_HW_VERSION_2
if (obj->dir & I2S_DIR_TX) {
i2s_ll_tx_disable_clock(obj->hal.dev);
}
if (obj->dir & I2S_DIR_RX) {
i2s_ll_rx_disable_clock(obj->hal.dev);
I2S_RCC_ATOMIC() {
if (obj->dir & I2S_DIR_TX) {
i2s_ll_tx_disable_clock(obj->hal.dev);
}
if (obj->dir & I2S_DIR_RX) {
i2s_ll_rx_disable_clock(obj->hal.dev);
}
}
#endif
/* Disable module clock */
@ -1904,8 +1909,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name)
if (!comp_using_i2s[id]) {
ret = ESP_OK;
comp_using_i2s[id] = comp_name;
periph_module_enable(i2s_periph_signal[id].module);
i2s_ll_enable_clock(I2S_LL_GET_HW(id));
I2S_RCC_ATOMIC() {
i2s_ll_enable_clock(I2S_LL_GET_HW(id));
}
}
portEXIT_CRITICAL(&i2s_spinlock[id]);
return ret;
@ -1920,8 +1926,9 @@ esp_err_t i2s_platform_release_occupation(int id)
ret = ESP_OK;
comp_using_i2s[id] = NULL;
/* Disable module clock */
periph_module_disable(i2s_periph_signal[id].module);
i2s_ll_disable_clock(I2S_LL_GET_HW(id));
I2S_RCC_ATOMIC() {
i2s_ll_disable_clock(I2S_LL_GET_HW(id));
}
}
portEXIT_CRITICAL(&i2s_spinlock[id]);
return ret;

View File

@ -25,6 +25,11 @@
#include "soc/soc_caps.h"
#include "hal/gpio_hal.h"
#include "hal/i2s_hal.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "rom/cache.h"
#endif
#if SOC_I2S_SUPPORTS_ADC_DAC
#include "hal/adc_ll.h"
@ -35,7 +40,6 @@
#endif
#include "esp_private/i2s_platform.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "driver/gpio.h"
@ -261,6 +265,7 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir,
new_chan->callbacks.on_send_q_ovf = NULL;
new_chan->dma.rw_pos = 0;
new_chan->dma.curr_ptr = NULL;
new_chan->dma.curr_desc = NULL;
new_chan->start = NULL;
new_chan->stop = NULL;
@ -330,6 +335,26 @@ uint32_t i2s_get_buf_size(i2s_chan_handle_t handle, uint32_t data_bit_width, uin
uint32_t bytes_per_sample = ((data_bit_width + 15) / 16) * 2;
uint32_t bytes_per_frame = bytes_per_sample * active_chan;
uint32_t bufsize = dma_frame_num * bytes_per_frame;
#if CONFIG_IDF_TARGET_ESP32P4
/* bufsize need to align with cache line size */
uint32_t alignment = cache_hal_get_cache_line_size(CACHE_TYPE_DATA);
uint32_t aligned_frame_num = dma_frame_num;
/* To make the buffer aligned with the cache line size, search for the ceil aligned size first,
If the buffer size exceed the max DMA buffer size, toggle the sign to search for the floor aligned size */
for (int sign = 1; bufsize % alignment != 0; aligned_frame_num += sign) {
bufsize = aligned_frame_num * bytes_per_frame;
/* If the buffer size exceed the max dma size */
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
sign = -1; // toggle the search sign
aligned_frame_num = dma_frame_num; // Reset the frame num
bufsize = aligned_frame_num * bytes_per_frame; // Reset the bufsize
}
}
if (bufsize / bytes_per_frame != dma_frame_num) {
ESP_LOGW(TAG, "dma frame num is adjusted to %"PRIu32" to algin the dma buffer with %"PRIu32
", bufsize = %"PRIu32, bufsize / bytes_per_frame, alignment, bufsize);
}
#endif
/* Limit DMA buffer size if it is out of range (DMA buffer limitation is 4092 bytes) */
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
uint32_t frame_num = I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame;
@ -348,18 +373,21 @@ esp_err_t i2s_free_dma_desc(i2s_chan_handle_t handle)
for (int i = 0; i < handle->dma.desc_num; i++) {
if (handle->dma.bufs[i]) {
free(handle->dma.bufs[i]);
handle->dma.bufs[i] = NULL;
}
if (handle->dma.desc[i]) {
free(handle->dma.desc[i]);
handle->dma.desc[i] = NULL;
}
}
if (handle->dma.bufs) {
free(handle->dma.bufs);
handle->dma.bufs = NULL;
}
if (handle->dma.desc) {
free(handle->dma.desc);
handle->dma.desc = NULL;
}
handle->dma.desc = NULL;
return ESP_OK;
}
@ -372,13 +400,20 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu
handle->dma.desc_num = num;
handle->dma.buf_size = bufsize;
#if SOC_GDMA_TRIG_PERIPH_I2S0_BUS == SOC_GDMA_BUS_AHB
uint32_t alignment = 32;
uint32_t desc_size = alignment;
#else
uint32_t alignment = 4;
uint32_t desc_size = sizeof(lldesc_t);
#endif
/* Descriptors must be in the internal RAM */
handle->dma.desc = (lldesc_t **)heap_caps_calloc(num, sizeof(lldesc_t *), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(handle->dma.desc, ESP_ERR_NO_MEM, err, TAG, "create I2S DMA decriptor array failed");
handle->dma.bufs = (uint8_t **)heap_caps_calloc(num, sizeof(uint8_t *), I2S_MEM_ALLOC_CAPS);
for (int i = 0; i < num; i++) {
/* Allocate DMA descriptor */
handle->dma.desc[i] = (lldesc_t *) heap_caps_calloc(1, sizeof(lldesc_t), I2S_DMA_ALLOC_CAPS);
handle->dma.desc[i] = (lldesc_t *) heap_caps_aligned_calloc(alignment, 1, desc_size, I2S_DMA_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(handle->dma.desc[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA description failed");
handle->dma.desc[i]->owner = 1;
handle->dma.desc[i]->eof = 1;
@ -386,15 +421,18 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu
handle->dma.desc[i]->length = bufsize;
handle->dma.desc[i]->size = bufsize;
handle->dma.desc[i]->offset = 0;
handle->dma.bufs[i] = (uint8_t *) heap_caps_calloc(1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS);
handle->dma.bufs[i] = (uint8_t *) heap_caps_aligned_calloc(alignment, 1, bufsize * sizeof(uint8_t), I2S_DMA_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(handle->dma.bufs[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed");
handle->dma.desc[i]->buf = handle->dma.bufs[i];
ESP_GOTO_ON_FALSE(handle->dma.desc[i]->buf, ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed");
ESP_LOGV(TAG, "desc addr: %8p\tbuffer addr:%8p", handle->dma.desc[i], handle->dma.bufs[i]);
}
/* Connect DMA descriptor as a circle */
for (int i = 0; i < num; i++) {
/* Link to the next descriptor */
STAILQ_NEXT(handle->dma.desc[i], qe) = (i < (num - 1)) ? (handle->dma.desc[i + 1]) : handle->dma.desc[0];
#if CONFIG_IDF_TARGET_ESP32P4
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(handle->dma.desc[i]), desc_size);
#endif
}
if (handle->dir == I2S_DIR_RX) {
i2s_ll_rx_set_eof_num(handle->controller->hal.dev, bufsize);
@ -459,6 +497,9 @@ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_e
uint32_t dummy;
finish_desc = (lldesc_t *)event_data->rx_eof_desc_addr;
#if CONFIG_IDF_TARGET_ESP32P4
Cache_Invalidate_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)finish_desc->buf, handle->dma.buf_size);
#endif
i2s_event_data_t evt = {
.data = &(finish_desc->buf),
.size = handle->dma.buf_size,
@ -487,7 +528,7 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e
lldesc_t *finish_desc;
uint32_t dummy;
finish_desc = (lldesc_t *)(event_data->tx_eof_desc_addr);
finish_desc = (lldesc_t *)event_data->tx_eof_desc_addr;
i2s_event_data_t evt = {
.data = &(finish_desc->buf),
.size = handle->dma.buf_size,
@ -505,6 +546,9 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e
if (handle->dma.auto_clear) {
uint8_t *sent_buf = (uint8_t *)finish_desc->buf;
memset(sent_buf, 0, handle->dma.buf_size);
#if CONFIG_IDF_TARGET_ESP32P4
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)sent_buf, handle->dma.buf_size);
#endif
}
xQueueSendFromISR(handle->msg_queue, &(finish_desc->buf), &need_yield2);
@ -646,7 +690,7 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag)
gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle);
}
#else
intr_flag |= ESP_INTR_FLAG_SHARED;
intr_flag |= handle->intr_flags ? handle->intr_flags : ESP_INTR_FLAG_LOWMED;
/* Initialize I2S module interrupt */
if (handle->dir == I2S_DIR_TX) {
esp_intr_alloc_intrstatus(i2s_periph_signal[port_id].irq, intr_flag,
@ -771,6 +815,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_TX, chan_cfg->dma_desc_num),
err, TAG, "register I2S tx channel failed");
i2s_obj->tx_chan->role = chan_cfg->role;
i2s_obj->tx_chan->intr_flags = chan_cfg->intr_flags;
i2s_obj->tx_chan->dma.auto_clear = chan_cfg->auto_clear;
i2s_obj->tx_chan->dma.desc_num = chan_cfg->dma_desc_num;
i2s_obj->tx_chan->dma.frame_num = chan_cfg->dma_frame_num;
@ -784,6 +829,7 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t *
ESP_GOTO_ON_ERROR(i2s_register_channel(i2s_obj, I2S_DIR_RX, chan_cfg->dma_desc_num),
err, TAG, "register I2S rx channel failed");
i2s_obj->rx_chan->role = chan_cfg->role;
i2s_obj->rx_chan->intr_flags = chan_cfg->intr_flags;
i2s_obj->rx_chan->dma.desc_num = chan_cfg->dma_desc_num;
i2s_obj->rx_chan->dma.frame_num = chan_cfg->dma_frame_num;
i2s_obj->rx_chan->start = i2s_rx_channel_start;
@ -821,10 +867,12 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle)
bool is_bound = true;
#if SOC_I2S_HW_VERSION_2
if (dir == I2S_DIR_TX) {
i2s_ll_tx_disable_clock(handle->controller->hal.dev);
} else {
i2s_ll_rx_disable_clock(handle->controller->hal.dev);
I2S_RCC_ATOMIC() {
if (dir == I2S_DIR_TX) {
i2s_ll_tx_disable_clock(handle->controller->hal.dev);
} else {
i2s_ll_rx_disable_clock(handle->controller->hal.dev);
}
}
#endif
#if SOC_I2S_SUPPORTS_APLL
@ -978,6 +1026,7 @@ esp_err_t i2s_channel_disable(i2s_chan_handle_t handle)
xSemaphoreTake(handle->binary, portMAX_DELAY);
/* Reset the descriptor pointer */
handle->dma.curr_ptr = NULL;
handle->dma.curr_desc = NULL;
handle->dma.rw_pos = 0;
handle->stop(handle);
#if CONFIG_PM_ENABLE
@ -1005,11 +1054,11 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
xSemaphoreTake(tx_handle->mutex, portMAX_DELAY);
/* The pre-load data will be loaded from the first descriptor */
if (tx_handle->dma.curr_ptr == NULL) {
tx_handle->dma.curr_ptr = tx_handle->dma.desc[0];
if (tx_handle->dma.curr_desc == NULL) {
tx_handle->dma.curr_desc = tx_handle->dma.desc[0];
tx_handle->dma.curr_ptr = (void *)tx_handle->dma.desc[0]->buf;
tx_handle->dma.rw_pos = 0;
}
lldesc_t *desc_ptr = (lldesc_t *)tx_handle->dma.curr_ptr;
/* Loop until no bytes in source buff remain or the descriptors are full */
while (remain_bytes) {
@ -1020,7 +1069,10 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
break;
}
/* Load the data from the last loaded position */
memcpy((uint8_t *)(desc_ptr->buf + tx_handle->dma.rw_pos), data_ptr, bytes_can_load);
memcpy((uint8_t *)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), data_ptr, bytes_can_load);
#if CONFIG_IDF_TARGET_ESP32P4
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)(tx_handle->dma.curr_ptr + tx_handle->dma.rw_pos), (uint32_t)bytes_can_load);
#endif
data_ptr += bytes_can_load; // Move forward the data pointer
total_loaded_bytes += bytes_can_load; // Add to the total loaded bytes
remain_bytes -= bytes_can_load; // Update the remaining bytes to be loaded
@ -1030,9 +1082,9 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
/* If the next descriptor is not the first descriptor, keep load to the first descriptor
* otherwise all descriptor has been loaded, break directly, the dma buffer position
* will remain at the end of the last dma buffer */
if (STAILQ_NEXT(desc_ptr, qe) != tx_handle->dma.desc[0]) {
desc_ptr = STAILQ_NEXT(desc_ptr, qe);
tx_handle->dma.curr_ptr = (void *)desc_ptr;
if (STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe) != tx_handle->dma.desc[0]) {
tx_handle->dma.curr_desc = STAILQ_NEXT((lldesc_t *)tx_handle->dma.curr_desc, qe);
tx_handle->dma.curr_ptr = (void *)(((lldesc_t *)tx_handle->dma.curr_desc)->buf);
tx_handle->dma.rw_pos = 0;
} else {
break;
@ -1077,6 +1129,9 @@ esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t si
bytes_can_write = size;
}
memcpy(data_ptr, src_byte, bytes_can_write);
#if CONFIG_IDF_TARGET_ESP32P4
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)data_ptr, (uint32_t)bytes_can_write);
#endif
size -= bytes_can_write;
src_byte += bytes_can_write;
handle->dma.rw_pos += bytes_can_write;
@ -1146,8 +1201,9 @@ esp_err_t i2s_platform_acquire_occupation(int id, const char *comp_name)
if ((!g_i2s.controller[id]) && (g_i2s.comp_name[id] == NULL)) {
g_i2s.comp_name[id] = comp_name;
/* Enable module clock */
periph_module_enable(i2s_periph_signal[id].module);
i2s_ll_enable_clock(I2S_LL_GET_HW(id));
I2S_RCC_ATOMIC() {
i2s_ll_enable_clock(I2S_LL_GET_HW(id));
}
} else {
occupied_comp = g_i2s.comp_name[id];
ret = ESP_ERR_NOT_FOUND;
@ -1167,8 +1223,9 @@ esp_err_t i2s_platform_release_occupation(int id)
if (!g_i2s.controller[id]) {
g_i2s.comp_name[id] = NULL;
/* Disable module clock */
periph_module_disable(i2s_periph_signal[id].module);
i2s_ll_disable_clock(I2S_LL_GET_HW(id));
I2S_RCC_ATOMIC() {
i2s_ll_disable_clock(I2S_LL_GET_HW(id));
}
} else {
ret = ESP_ERR_INVALID_STATE;
}
@ -1183,3 +1240,25 @@ size_t inline i2s_platform_get_dma_buffer_offset(void)
* then find the corresponding field , the address of this field is the offset of this type */
return (size_t)&(((i2s_chan_handle_t)0)->dma.bufs);
}
#if SOC_I2S_SUPPORTS_TX_SYNC_CNT
uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle)
{
return i2s_ll_tx_get_bclk_sync_count(tx_handle->controller->hal.dev);
}
uint32_t i2s_sync_get_fifo_count(i2s_chan_handle_t tx_handle)
{
return i2s_ll_tx_get_fifo_sync_count(tx_handle->controller->hal.dev);
}
void i2s_sync_reset_bclk_count(i2s_chan_handle_t tx_handle)
{
i2s_ll_tx_reset_bclk_sync_counter(tx_handle->controller->hal.dev);
}
void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle)
{
i2s_ll_tx_reset_fifo_sync_counter(tx_handle->controller->hal.dev);
}
#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT

View File

@ -70,7 +70,10 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx
portENTER_CRITICAL(&g_i2s.spinlock);
/* Set clock configurations in HAL*/
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
}
#if SOC_I2S_HW_VERSION_2
/* Work around for PDM TX clock, overwrite the raw division directly to reduce the noise
* This set of coefficients is a special division to reduce the background noise in PDM TX mode */
@ -187,10 +190,7 @@ esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_t
ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed");
i2s_ll_tx_enable_pdm(handle->controller->hal.dev);
#if SOC_I2S_HW_VERSION_2
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
i2s_ll_tx_enable_clock(handle->controller->hal.dev);
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL
@ -357,7 +357,10 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx
portENTER_CRITICAL(&g_i2s.spinlock);
/* Set clock configurations in HAL*/
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
}
portEXIT_CRITICAL(&g_i2s.spinlock);
/* Update the mode info: clock configuration */
@ -467,10 +470,7 @@ esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_r
ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed");
i2s_ll_rx_enable_pdm(handle->controller->hal.dev);
#if SOC_I2S_HW_VERSION_2
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
i2s_ll_rx_enable_clock(handle->controller->hal.dev);
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
#if SOC_I2S_SUPPORTS_APLL

View File

@ -16,8 +16,10 @@
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
#endif
#include "esp_private/periph_ctrl.h"
#include "esp_pm.h"
#include "esp_err.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
@ -26,14 +28,22 @@ extern "C" {
// If ISR handler is allowed to run whilst cache is disabled,
// Make sure all the code and related variables used by the handler are in the SRAM
#if CONFIG_I2S_ISR_IRAM_SAFE
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
#define I2S_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED)
#define I2S_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
#define I2S_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif //CONFIG_I2S_ISR_IRAM_SAFE
#define I2S_DMA_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA)
#if !SOC_RCC_IS_INDEPENDENT
#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#define I2S_RCC_ENV_DECLARE (void)__DECLARE_RCC_ATOMIC_ENV
#else
#define I2S_RCC_ATOMIC()
#define I2S_RCC_ENV_DECLARE
#endif
#define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL")
/**
@ -61,6 +71,7 @@ typedef struct {
bool auto_clear; /*!< Set to auto clear DMA TX descriptor, i2s will always send zero automatically if no data to send */
uint32_t rw_pos; /*!< reading/writing pointer position */
void *curr_ptr; /*!< Pointer to current dma buffer */
void *curr_desc; /*!< Pointer to current dma descriptor used for pre-load */
lldesc_t **desc; /*!< dma descriptor array */
uint8_t **bufs; /*!< dma buffer array */
} i2s_dma_t;
@ -88,6 +99,7 @@ struct i2s_channel_obj_t {
i2s_dma_t dma; /*!< i2s dma object */
i2s_state_t state; /*!< i2s driver state. Ensuring the driver working in a correct sequence */
/* Stored configurations */
int intr_flags;
void *mode_info; /*!< Slot, clock and gpio information of each mode */
#if SOC_I2S_SUPPORTS_APLL
bool apll_en; /*!< Flag of wether APLL enabled */

View File

@ -77,10 +77,13 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c
portENTER_CRITICAL(&g_i2s.spinlock);
/* Set clock configurations in HAL*/
if (handle->dir == I2S_DIR_TX) {
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
} else {
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
if (handle->dir == I2S_DIR_TX) {
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
} else {
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
}
}
portEXIT_CRITICAL(&g_i2s.spinlock);
@ -226,10 +229,8 @@ esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_conf
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
if (handle->dir == I2S_DIR_TX) {
i2s_ll_tx_enable_std(handle->controller->hal.dev);
i2s_ll_tx_enable_clock(handle->controller->hal.dev);
} else {
i2s_ll_rx_enable_std(handle->controller->hal.dev);
i2s_ll_rx_enable_clock(handle->controller->hal.dev);
}
#endif

View File

@ -79,10 +79,13 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c
portENTER_CRITICAL(&g_i2s.spinlock);
/* Set clock configurations in HAL*/
if (handle->dir == I2S_DIR_TX) {
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
} else {
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
I2S_RCC_ATOMIC() {
I2S_RCC_ENV_DECLARE;
if (handle->dir == I2S_DIR_TX) {
i2s_hal_set_tx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
} else {
i2s_hal_set_rx_clock(&handle->controller->hal, &clk_info, clk_cfg->clk_src);
}
}
portEXIT_CRITICAL(&g_i2s.spinlock);
@ -232,10 +235,8 @@ esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_conf
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
if (handle->dir == I2S_DIR_TX) {
i2s_ll_tx_enable_tdm(handle->controller->hal.dev);
i2s_ll_tx_enable_clock(handle->controller->hal.dev);
} else {
i2s_ll_rx_enable_tdm(handle->controller->hal.dev);
i2s_ll_rx_enable_clock(handle->controller->hal.dev);
}
#endif
#ifdef CONFIG_PM_ENABLE
@ -275,12 +276,12 @@ esp_err_t i2s_channel_reconfig_tdm_clock(i2s_chan_handle_t handle, const i2s_tdm
#if SOC_I2S_SUPPORTS_APLL
/* Enable APLL and acquire its lock when the clock source is changed to APLL */
if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && clk_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) {
if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) {
periph_rtc_apll_acquire();
handle->apll_en = true;
}
/* Disable APLL and release its lock when clock source is changed to 160M_PLL */
if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && clk_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) {
if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) {
periph_rtc_apll_release();
handle->apll_en = false;
}

View File

@ -25,6 +25,7 @@ extern "C" {
.dma_desc_num = 6, \
.dma_frame_num = 240, \
.auto_clear = false, \
.intr_flags = 0, \
}
#define I2S_GPIO_UNUSED GPIO_NUM_NC /*!< Used in i2s_gpio_config_t for signals which are not used */
@ -63,6 +64,7 @@ typedef struct {
* it should be the multiple of '3' when the data bit width is 24.
*/
bool auto_clear; /*!< Set to auto clear DMA TX buffer, i2s will always send zero automatically if no data to send */
int intr_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
} i2s_chan_config_t;
/**

View File

@ -23,6 +23,23 @@ extern "C" {
#if SOC_I2S_SUPPORTS_PDM_RX
#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
/**
* @brief PDM format in 2 slots(RX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \
.hpf_en = true, \
.hpf_cut_off_freq_hz = 35.5, \
.amplify_num = 1, \
}
#else
/**
* @brief PDM format in 2 slots(RX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
@ -35,6 +52,7 @@ extern "C" {
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \
}
#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
/**
* @brief i2s default pdm rx clock configuration
@ -48,23 +66,7 @@ extern "C" {
.bclk_div = 8, \
}
#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
/**
* @brief PDM format in 2 slots(RX)
* @param bits_per_sample i2s data bit width, only support 16 bits for PDM mode
* @param mono_or_stereo I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO
*/
#define I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bits_per_sample, mono_or_stereo) { \
.data_bit_width = bits_per_sample, \
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, \
.slot_mode = mono_or_stereo, \
.slot_mask = (mono_or_stereo == I2S_SLOT_MODE_MONO) ? \
I2S_PDM_SLOT_LEFT : I2S_PDM_SLOT_BOTH, \
.hp_en = true, \
.hp_cut_off_freq_hz = 35.5, \
.amplify_num = 1, \ /* TODO: maybe need an enum */
}
#endif // SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
/**
* @brief I2S slot configuration for pdm rx mode
@ -329,8 +331,8 @@ typedef struct {
i2s_pdm_sig_scale_t sinc_scale; /*!< Sinc filter scaling value */
#if SOC_I2S_HW_VERSION_2
i2s_pdm_tx_line_mode_t line_mode; /*!< PDM TX line mode, one-line codec, one-line dac, two-line dac mode can be selected */
bool hp_en; /*!< High pass filter enable */
float hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */
bool hpf_en; /*!< High pass filter enable */
float hpf_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */
uint32_t sd_dither; /*!< Sigma-delta filter dither */
uint32_t sd_dither2; /*!< Sigma-delta filter dither2 */
#endif // SOC_I2S_HW_VERSION_2

View File

@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// DO NOT USE THESE APIS IN YOUR APPLICATIONS
// The following APIs are for internal use, public to other IDF components, but not for users' applications.
/**
* This file is used for getting the bclk and fifo sending count
* for the synchronization among different I2S ports.
*
* The APIs in this file might be called frequently, so they are made light-weight and flexible to be called
*
* NOTE: These APIs are private for ESP internal usages.
* Please be aware of the risk that APIs might be changed regarding the use case.
*/
#pragma once
#include <stdint.h>
#include "driver/i2s_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_I2S_SUPPORTS_TX_SYNC_CNT
/**
* @brief Get the counter number of BCLK ticks
* @note The BCLK tick count reflects the real data that have sent on line
*
* @param[in] tx_handle The I2S tx channel handle
* @return
* - BCLK tick count
*/
uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle);
/**
* @brief Get the counter number of fifo
* @note The FIFO count reflects how many slots have processed
* Normally, fifo_cnt = slot_bit_width * bclk_cnt
* If fifo_cnt < slot_bit_width * bclk_cnt, that means some data are still stuck in the I2S controller
*
* @param[in] tx_handle The I2S tx channel handle
* @return
* - FIFO slot count
*/
uint32_t i2s_sync_get_fifo_count(i2s_chan_handle_t tx_handle);
/**
* @brief Reset the bclk counter
*
* @param[in] tx_handle The I2S tx channel handle
*/
void i2s_sync_reset_bclk_count(i2s_chan_handle_t tx_handle);
/**
* @brief Reset the fifo counter
*
* @param[in] tx_handle The I2S tx channel handle
*/
void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle);
#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT
#ifdef __cplusplus
}
#endif

View File

@ -33,15 +33,27 @@ components/driver/test_apps/i2c_test_apps:
components/driver/test_apps/i2s_test_apps:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/i2s:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/i2s_multi_dev:
disable:
- if: SOC_I2S_SUPPORTED != 1
- if: SOC_I2S_HW_VERSION_2 != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac:
disable:
@ -50,6 +62,10 @@ components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac:
components/driver/test_apps/i2s_test_apps/legacy_i2s_driver:
disable:
- if: SOC_I2S_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
components/driver/test_apps/ledc:
disable:

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -11,6 +11,7 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "hal/gpio_hal.h"
#include "esp_err.h"
@ -775,7 +776,7 @@ static void i2s_test_common_sample_rate(i2s_chan_handle_t rx_chan, i2s_std_clk_c
// pcnt will count the pulse number on WS signal in 100ms
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit));
TEST_ESP_OK(pcnt_unit_start(pcnt_unit));
vTaskDelay(pdMS_TO_TICKS(TEST_I2S_PERIOD_MS));
esp_rom_delay_us(100 * 1000);
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &real_pulse));
printf("[%"PRIu32" Hz] %d pulses, expected %d, err %d\n", test_freq[i], real_pulse, expt_pulse, real_pulse - expt_pulse);
@ -803,9 +804,10 @@ TEST_CASE("I2S_default_PLL_clock_test", "[i2s]")
TEST_ESP_OK(i2s_new_channel(&chan_cfg, NULL, &rx_handle));
TEST_ESP_OK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
#if SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M
// ESP32-P4 has no PLL except XTAL
#if !CONFIG_IDF_TARGET_ESP32P4
i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg);
#endif // SOC_I2S_SUPPORTS_PLL_F160M || SOC_I2S_SUPPORTS_PLL_F96M
#endif // CONFIG_IDF_TARGET_ESP32P4
#if SOC_I2S_SUPPORTS_XTAL
std_cfg.clk_cfg.clk_src = I2S_CLK_SRC_XTAL;
i2s_test_common_sample_rate(rx_handle, &std_cfg.clk_cfg);
@ -882,7 +884,6 @@ TEST_CASE("I2S_package_lost_test", "[i2s]")
for (i = 0; i < test_num; i++) {
printf("Testing %"PRIu32" Hz sample rate\n", test_freq[i]);
std_cfg.clk_cfg.sample_rate_hz = test_freq[i];
std_cfg.clk_cfg.sample_rate_hz = test_freq[i];
TEST_ESP_OK(i2s_channel_reconfig_std_clock(rx_handle, &std_cfg.clk_cfg));
TEST_ESP_OK(i2s_channel_enable(rx_handle));
for (int j = 0; j < 10; j++) {

View File

@ -13,6 +13,9 @@
#include "driver/i2s_std.h"
#include "esp_attr.h"
#include "soc/soc_caps.h"
#if CONFIG_IDF_TARGET_ESP32P4
#include "rom/cache.h"
#endif
#include "esp_private/i2s_platform.h"
#include "esp_private/spi_flash_os.h"
#include "../../test_inc/test_i2s.h"
@ -39,9 +42,13 @@ static void IRAM_ATTR test_i2s_iram_write(i2s_chan_handle_t tx_handle)
// disable cache and non-iram ISR handlers
spi_flash_guard_get()->start();
// write data into dma buffer directly, the data in dma buffer will be sent automatically
for (int i=0; i < 100; i++) {
dma_bufs[0][i] = i + 1;
for (int i = 0; i < 400; i++) {
dma_bufs[0][i] = i % 100 + 1;
}
#if CONFIG_IDF_TARGET_ESP32P4
// TODO: need to consider PSRAM if I2S driver supports EDMA
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)dma_bufs[0], 400);
#endif
// enable cache and non-iram ISR handlers
spi_flash_guard_get()->end();
}
@ -52,8 +59,8 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]")
i2s_chan_handle_t rx_chan = NULL;
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
chan_cfg.dma_desc_num = 6;
chan_cfg.dma_frame_num = 200;
chan_cfg.dma_desc_num = 2;
chan_cfg.dma_frame_num = 100;
TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan));
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
@ -73,14 +80,14 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]")
};
TEST_ESP_OK(i2s_channel_init_std_mode(tx_chan, &std_cfg));
TEST_ESP_OK(i2s_channel_init_std_mode(rx_chan, &std_cfg));
int is_triggerred = 0;
int is_triggered = 0;
i2s_event_callbacks_t cbs = {
.on_recv = NULL,
.on_recv_q_ovf = NULL,
.on_sent = test_i2s_tx_done_callback,
.on_send_q_ovf = NULL,
};
TEST_ESP_OK(i2s_channel_register_event_callback(tx_chan, &cbs, &is_triggerred));
TEST_ESP_OK(i2s_channel_register_event_callback(tx_chan, &cbs, &is_triggered));
TEST_ESP_OK(i2s_channel_enable(tx_chan));
TEST_ESP_OK(i2s_channel_enable(rx_chan));
@ -92,7 +99,7 @@ TEST_CASE("i2s_iram_interrupt_safe", "[i2s]")
for (int retry = 0; retry < 3; retry++) {
i2s_channel_read(rx_chan, recv_buf, 2000, &r_bytes, pdMS_TO_TICKS(1000));
for (i = 0; i < 2000 - 100; i++) {
if (recv_buf[i] != 0) {
if (recv_buf[i] == 1 && recv_buf[i + 1] == 2) {
goto finish;
}
}
@ -107,7 +114,7 @@ finish:
for (int j = 1; j <= 100; j++) {
TEST_ASSERT_EQUAL_UINT8(recv_buf[i++], j);
}
TEST_ASSERT(is_triggerred);
TEST_ASSERT(is_triggered);
free(recv_buf);
}

View File

@ -1,3 +1,3 @@
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -44,6 +44,14 @@ extern "C" {
#define SLAVE_WS_IO 15
#define DATA_IN_IO 19
#define DATA_OUT_IO 18
#elif CONFIG_IDF_TARGET_ESP32P4
#define MASTER_MCK_IO 34
#define MASTER_BCK_IO 35
#define MASTER_WS_IO 48
#define SLAVE_BCK_IO 10
#define SLAVE_WS_IO 11
#define DATA_IN_IO 12
#define DATA_OUT_IO 49
#else
#define MASTER_MCK_IO 0
#define MASTER_BCK_IO 4

View File

@ -18,6 +18,7 @@
#include "hal/misc.h"
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "soc/dport_reg.h"
#include "hal/i2s_types.h"
#include "hal/hal_utils.h"
@ -90,12 +91,23 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en)
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
if (hw == &I2S0) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
} else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
}
if (hw->clkm_conf.clk_en == 0) {
hw->clkm_conf.clk_en = 1;
hw->conf2.val = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__)
/**
* @brief I2S module disable clock.
*
@ -106,8 +118,19 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
if (hw->clkm_conf.clk_en == 1) {
hw->clkm_conf.clk_en = 0;
}
if (hw == &I2S0) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
} else {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__)
/**
* @brief I2S tx msb right enable
*

View File

@ -17,6 +17,7 @@
#include "hal/assert.h"
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "soc/system_struct.h"
#include "hal/i2s_types.h"
#include "hal/hal_utils.h"
@ -43,9 +44,15 @@ extern "C" {
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 1;
SYSTEM.perip_rst_en0.reg_i2s1_rst = 0;
hw->tx_clkm_conf.clk_en = 1;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__)
/**
* @brief I2S module disable I2S clock.
*
@ -54,8 +61,14 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
{
hw->tx_clkm_conf.clk_en = 0;
SYSTEM.perip_clk_en0.reg_i2s1_clk_en = 0;
SYSTEM.perip_rst_en0.reg_i2s1_rst = 1;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__)
/**
* @brief Enable I2S tx module clock
*
@ -86,6 +99,11 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
hw->tx_clkm_conf.tx_clk_active = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity
#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__)
/**
* @brief Disable I2S rx module clock
*
@ -96,6 +114,11 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
hw->rx_clkm_conf.rx_clk_active = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity
#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__)
/**
* @brief I2S mclk use tx module clock
*

View File

@ -44,8 +44,8 @@ extern "C" {
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
// The clock gate enabling is moved to `periph_module_enable`
(void)hw;
PCR.i2s_conf.i2s_clk_en = 1;
PCR.i2s_conf.i2s_rst_en = 0;
}
/**
@ -55,8 +55,8 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
{
// The clock gate disabling is moved to `periph_module_disable`
(void)hw;
PCR.i2s_conf.i2s_clk_en = 0;
PCR.i2s_conf.i2s_rst_en = 1;
}
/**

View File

@ -45,8 +45,8 @@ extern "C" {
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
// The clock gate enabling is moved to `periph_module_enable`
(void)hw;
PCR.i2s_conf.i2s_clk_en = 1;
PCR.i2s_conf.i2s_rst_en = 0;
}
/**
@ -56,8 +56,8 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
{
// The clock gate disabling is moved to `periph_module_disable`
(void)hw;
PCR.i2s_conf.i2s_clk_en = 0;
PCR.i2s_conf.i2s_rst_en = 1;
}
/**

View File

@ -36,12 +36,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return HP_SYS_CLKRST_REG_I2C0_APB_CLK_EN;
case PERIPH_I2C1_MODULE:
return HP_SYS_CLKRST_REG_I2C1_APB_CLK_EN;
case PERIPH_I2S0_MODULE:
return HP_SYS_CLKRST_REG_I2S0_TX_CLK_EN | HP_SYS_CLKRST_REG_I2S0_RX_CLK_EN;
case PERIPH_I2S1_MODULE:
return HP_SYS_CLKRST_REG_I2S1_RX_CLK_EN | HP_SYS_CLKRST_REG_I2S1_TX_CLK_EN;
case PERIPH_I2S2_MODULE:
return HP_SYS_CLKRST_REG_I2S2_RX_CLK_EN | HP_SYS_CLKRST_REG_I2S2_TX_CLK_EN;
case PERIPH_LCD_MODULE:
return HP_SYS_CLKRST_REG_LCD_CLK_EN;
case PERIPH_UART0_MODULE:
@ -151,12 +145,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return HP_SYS_CLKRST_REG_RST_EN_CAN2;
case PERIPH_LEDC_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_LEDC;
case PERIPH_I2S0_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_I2S0_APB;
case PERIPH_I2S1_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_I2S1_APB;
case PERIPH_I2S2_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_I2S2_APB;
case PERIPH_GPSPI2_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_SPI2;
case PERIPH_GPSPI3_MODULE:
@ -294,10 +282,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
case PERIPH_TWAI1_MODULE:
case PERIPH_TWAI2_MODULE:
case PERIPH_LEDC_MODULE:
case PERIPH_I2S0_MODULE:
return HP_SYS_CLKRST_HP_RST_EN1_REG;
case PERIPH_I2S1_MODULE:
case PERIPH_I2S2_MODULE:
case PERIPH_GPSPI2_MODULE:
case PERIPH_GPSPI3_MODULE:
case PERIPH_CAM_MODULE:

View File

@ -17,7 +17,7 @@
#include "hal/assert.h"
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "soc/pcr_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "hal/i2s_types.h"
@ -26,6 +26,7 @@ extern "C" {
#endif
#define I2S_LL_GET_HW(num) (((num) == 0)? (&I2S0) : ((num) == 1) ? (&I2S1) : (&I2S2))
#define I2S_LL_GET_ID(hw) (((hw) == &I2S0)? 0 : ((hw) == &I2S1) ? 1 : 2)
#define I2S_LL_TDM_CH_MASK (0xffff)
#define I2S_LL_PDM_BCK_FACTOR (64)
@ -53,10 +54,30 @@ typedef struct {
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
// The clock gate enabling is moved to `periph_module_enable`
(void)hw;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 1;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 0;
break;
case 1:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 1;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 0;
break;
case 2:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 1;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 0;
break;
default:
// Never reach
HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__)
/**
* @brief I2S module disable I2S clock.
*
@ -64,10 +85,30 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
{
// The clock gate disabling is moved to `periph_module_disable`
(void)hw;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s0_apb_clk_en = 0;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s0_apb = 1;
break;
case 1:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s1_apb_clk_en = 0;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s1_apb = 1;
break;
case 2:
HP_SYS_CLKRST.soc_clk_ctrl2.reg_i2s2_apb_clk_en = 0;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_i2s2_apb = 1;
break;
default:
// Never reach
HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__)
/**
* @brief Enable I2S tx module clock
*
@ -75,8 +116,18 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 1;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_en = 1;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_en = 1;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_en = 1;
return;
}
}
/**
@ -86,8 +137,18 @@ static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 1;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_en = 1;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_en = 1;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_en = 1;
return;
}
}
/**
@ -97,10 +158,24 @@ static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_en = 0;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_en = 0;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_en = 0;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_en = 0;
return;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__)
/**
* @brief Disable I2S rx module clock
*
@ -108,10 +183,24 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_en = 0;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_en = 0;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_en = 0;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_en = 0;
return;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__)
/**
* @brief I2S mclk use tx module clock
*
@ -119,8 +208,18 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
*/
static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 0;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_mst_clk_sel = 0;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_mst_clk_sel = 0;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_mst_clk_sel = 0;
return;
}
}
/**
@ -130,8 +229,18 @@ static inline void i2s_ll_mclk_bind_to_tx_clk(i2s_dev_t *hw)
*/
static inline void i2s_ll_mclk_bind_to_rx_clk(i2s_dev_t *hw)
{
(void)hw;
PCR.i2s_rx_clkm_conf.i2s_mclk_sel = 1;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_mst_clk_sel = 1;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_mst_clk_sel = 1;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_mst_clk_sel = 1;
return;
}
}
/**
@ -200,6 +309,22 @@ static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw)
hw->rx_conf.rx_fifo_reset = 0;
}
static inline uint32_t i2s_ll_get_clk_src(i2s_clock_src_t src)
{
switch (src)
{
case I2S_CLK_SRC_XTAL:
return 0;
case I2S_CLK_SRC_APLL:
return 1;
case I2S_CLK_SRC_EXTERNAL:
return 2;
default:
HAL_ASSERT(false && "unsupported clock source");
break;
}
}
/**
* @brief Set TX source clock
*
@ -208,18 +333,18 @@ static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw)
*/
static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src)
{
(void)hw;
switch (src)
{
case I2S_CLK_SRC_XTAL:
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0;
break;
case I2S_CLK_SRC_APLL:
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1;
break;
default:
HAL_ASSERT(false && "unsupported clock source");
break;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
uint32_t clk_src = i2s_ll_get_clk_src(src);
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_clk_src_sel = clk_src;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_tx_clk_src_sel = clk_src;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_tx_clk_src_sel = clk_src;
return;
}
}
@ -231,18 +356,18 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src)
*/
static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src)
{
(void)hw;
switch (src)
{
case I2S_CLK_SRC_XTAL:
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0;
break;
case I2S_CLK_SRC_APLL:
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1;
break;
default:
HAL_ASSERT(false && "unsupported clock source");
break;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
uint32_t clk_src = i2s_ll_get_clk_src(src);
switch (I2S_LL_GET_ID(hw)) {
case 0:
HP_SYS_CLKRST.peri_clk_ctrl11.reg_i2s0_rx_clk_src_sel = clk_src;
return;
case 1:
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s1_rx_clk_src_sel = clk_src;
return;
case 2:
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_clk_src_sel = clk_src;
return;
}
}
@ -269,14 +394,30 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
*/
static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1)
{
(void)hw;
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int);
typeof(PCR.i2s_tx_clkm_div_conf) div = {};
div.i2s_tx_clkm_div_x = x;
div.i2s_tx_clkm_div_y = y;
div.i2s_tx_clkm_div_z = z;
div.i2s_tx_clkm_div_yn1 = yn1;
PCR.i2s_tx_clkm_div_conf.val = div.val;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl13, reg_i2s0_tx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_tx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl14.reg_i2s0_tx_div_yn1 = yn1;
return;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl16, reg_i2s1_tx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl16.reg_i2s1_tx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s1_tx_div_yn1 = yn1;
return;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl18, reg_i2s2_tx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl19.reg_i2s2_tx_div_yn1 = yn1;
return;
}
}
/**
@ -291,14 +432,30 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui
*/
static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1)
{
(void)hw;
HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int);
typeof(PCR.i2s_rx_clkm_div_conf) div = {};
div.i2s_rx_clkm_div_x = x;
div.i2s_rx_clkm_div_y = y;
div.i2s_rx_clkm_div_z = z;
div.i2s_rx_clkm_div_yn1 = yn1;
PCR.i2s_rx_clkm_div_conf.val = div.val;
// Note: this function involves HP_SYS_CLKRST register which is shared with other peripherals, need lock in upper layer
switch (I2S_LL_GET_ID(hw)) {
case 0:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl12, reg_i2s0_rx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl12.reg_i2s0_rx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl13.reg_i2s0_rx_div_yn1 = yn1;
return;
case 1:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl14, reg_i2s1_rx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl15.reg_i2s1_rx_div_yn1 = yn1;
return;
case 2:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl17, reg_i2s2_rx_div_n, div_int);
HP_SYS_CLKRST.peri_clk_ctrl17.reg_i2s2_rx_div_x = x;
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_y = y;
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_z = z;
HP_SYS_CLKRST.peri_clk_ctrl18.reg_i2s2_rx_div_yn1 = yn1;
return;
}
}
/**
@ -890,13 +1047,12 @@ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw)
* @brief Enable RX PDM mode.
*
* @param hw Peripheral I2S hardware instance address.
* @param pdm_enable Set true to RX enable PDM mode
*/
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable)
static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
{
hw->rx_conf.rx_pdm_en = pdm_enable;
hw->rx_conf.rx_tdm_en = !pdm_enable;
hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = pdm_enable;
hw->rx_conf.rx_pdm_en = 1;
hw->rx_conf.rx_tdm_en = 0;
hw->rx_pdm2pcm_conf.rx_pdm2pcm_en = 1;
}
/**
@ -1198,6 +1354,7 @@ static inline void i2s_ll_tx_pdm_line_mode(i2s_dev_t *hw, i2s_pdm_tx_line_mode_t
*
* @param hw Peripheral I2S hardware instance address.
*/
__attribute__((always_inline))
static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw)
{
hw->fifo_cnt.tx_fifo_cnt_rst = 1;
@ -1209,8 +1366,9 @@ static inline void i2s_ll_tx_reset_fifo_sync_counter(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
* @return
* count value
* bclk count value
*/
__attribute__((always_inline))
static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw)
{
return hw->fifo_cnt.tx_fifo_cnt;
@ -1221,6 +1379,7 @@ static inline uint32_t i2s_ll_tx_get_fifo_sync_count(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
*/
__attribute__((always_inline))
static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw)
{
hw->bck_cnt.tx_bck_cnt_rst = 1;
@ -1232,9 +1391,10 @@ static inline void i2s_ll_tx_reset_bclk_sync_counter(i2s_dev_t *hw)
*
* @param hw Peripheral I2S hardware instance address.
* @return
* count value
* fifo count value
*/
static inline void i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw)
__attribute__((always_inline))
static inline uint32_t i2s_ll_tx_get_bclk_sync_count(i2s_dev_t *hw)
{
return hw->bck_cnt.tx_bck_cnt;
}

View File

@ -18,6 +18,8 @@
#include "hal/misc.h"
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "soc/system_reg.h"
#include "soc/dport_access.h"
#include "hal/i2s_types.h"
#include "hal/hal_utils.h"
@ -87,6 +89,13 @@ static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en)
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
if (hw == &I2S0) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
} else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
}
if (hw->clkm_conf.clk_en == 0) {
hw->clkm_conf.clk_sel = 2;
hw->clkm_conf.clk_en = 1;
@ -94,6 +103,10 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__)
/**
* @brief I2S module disable clock.
*
@ -104,8 +117,19 @@ static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
if (hw->clkm_conf.clk_en == 1) {
hw->clkm_conf.clk_en = 0;
}
if (hw == &I2S0) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
} else {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__)
/**
* @brief I2S tx msb right enable
*

View File

@ -17,6 +17,7 @@
#include "hal/assert.h"
#include "soc/i2s_periph.h"
#include "soc/i2s_struct.h"
#include "soc/system_struct.h"
#include "hal/i2s_types.h"
#include "hal/hal_utils.h"
@ -44,9 +45,20 @@ extern "C" {
*/
static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
{
if (hw == &I2S0) {
SYSTEM.perip_clk_en0.i2s0_clk_en = 1;
SYSTEM.perip_rst_en0.i2s0_rst = 0;
} else {
SYSTEM.perip_clk_en0.i2s1_clk_en = 1;
SYSTEM.perip_rst_en0.i2s1_rst = 0;
}
hw->tx_clkm_conf.clk_en = 1;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_enable_clock(__VA_ARGS__)
/**
* @brief I2S module disable I2S clock.
*
@ -55,8 +67,19 @@ static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
{
hw->tx_clkm_conf.clk_en = 0;
if (hw == &I2S0) {
SYSTEM.perip_clk_en0.i2s0_clk_en = 0;
SYSTEM.perip_rst_en0.i2s0_rst = 1;
} else {
SYSTEM.perip_clk_en0.i2s1_clk_en = 0;
SYSTEM.perip_rst_en0.i2s1_rst = 1;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define i2s_ll_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_disable_clock(__VA_ARGS__)
/**
* @brief Enable I2S tx module clock
*
@ -87,6 +110,11 @@ static inline void i2s_ll_tx_disable_clock(i2s_dev_t *hw)
hw->tx_clkm_conf.tx_clk_active = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
// i2s_ll_tx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity
#define i2s_ll_tx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_tx_disable_clock(__VA_ARGS__)
/**
* @brief Disable I2S rx module clock
*
@ -97,6 +125,11 @@ static inline void i2s_ll_rx_disable_clock(i2s_dev_t *hw)
hw->rx_clkm_conf.rx_clk_active = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
// i2s_ll_rx_disable_clock don't need RCC ENV actually, but still defined here for compatiblity
#define i2s_ll_rx_disable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; i2s_ll_rx_disable_clock(__VA_ARGS__)
/**
* @brief I2S mclk use tx module clock
*

View File

@ -243,7 +243,7 @@ void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha
i2s_ll_rx_set_active_chan_mask(hal->dev, slot_mask);
#endif // SOC_I2S_HW_VERSION_1
#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER // TODO: add this macro to soc_caps
#if SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
uint32_t param0;
uint32_t param5;
s_i2s_hal_get_cut_off_coef(slot_cfg->pdm_rx.hp_cut_off_freq_hz, &param0, &param5);

View File

@ -29,7 +29,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_out_sigs[1] = I2SO_SD1_OUT_IDX,
.data_in_sig = I2SI_SD_IN_IDX,
.irq = -1,
.irq = ETS_I2S1_INTR_SOURCE,
.module = PERIPH_I2S1_MODULE,
}
};

View File

@ -29,7 +29,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_out_sigs[1] = I2SO_SD1_OUT_IDX,
.data_in_sig = I2SI_SD_IN_IDX,
.irq = -1,
.irq = ETS_I2S1_INTR_SOURCE,
.module = PERIPH_I2S1_MODULE,
}
};

View File

@ -28,7 +28,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_out_sig = I2SO_SD_OUT_IDX,
.data_in_sig = I2SI_SD_IN_IDX,
.irq = -1,
.irq = ETS_I2S1_INTR_SOURCE,
.module = PERIPH_I2S1_MODULE,
}
};

View File

@ -13,6 +13,7 @@
const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
[0] = {
.mck_out_sig = I2S0_MCLK_PAD_OUT_IDX,
.mck_in_sig = I2S0_MCLK_PAD_IN_IDX,
.m_tx_bck_sig = I2S0_O_BCK_PAD_OUT_IDX,
.m_rx_bck_sig = I2S0_I_BCK_PAD_OUT_IDX,
@ -31,11 +32,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_in_sigs[2] = I2S0_I_SD2_PAD_IN_IDX,
.data_in_sigs[3] = I2S0_I_SD3_PAD_IN_IDX,
.irq = -1,
.irq = ETS_I2S0_INTR_SOURCE,
.module = PERIPH_I2S0_MODULE,
},
[1] = {
.mck_out_sig = I2S1_MCLK_PAD_OUT_IDX,
.mck_in_sig = I2S1_MCLK_PAD_IN_IDX,
.m_tx_bck_sig = I2S1_O_BCK_PAD_OUT_IDX,
.m_rx_bck_sig = I2S1_I_BCK_PAD_OUT_IDX,
@ -54,11 +56,12 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_in_sigs[2] = -1,
.data_in_sigs[3] = -1,
.irq = -1,
.irq = ETS_I2S1_INTR_SOURCE,
.module = PERIPH_I2S1_MODULE,
},
[2] = {
.mck_out_sig = I2S2_MCLK_PAD_OUT_IDX,
.mck_in_sig = I2S2_MCLK_PAD_IN_IDX,
.m_tx_bck_sig = I2S2_O_BCK_PAD_OUT_IDX,
.m_rx_bck_sig = I2S2_I_BCK_PAD_OUT_IDX,
@ -77,7 +80,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_in_sigs[2] = -1,
.data_in_sigs[3] = -1,
.irq = -1,
.irq = ETS_I2S2_INTR_SOURCE,
.module = PERIPH_I2S2_MODULE,
},
};

View File

@ -67,11 +67,11 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_I2C_SUPPORTED
config SOC_I2S_SUPPORTED
bool
default y
config SOC_I2S_SUPPORTED
config SOC_I2C_SUPPORTED
bool
default y
@ -471,6 +471,10 @@ config SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER
bool
default y
config SOC_I2S_SUPPORTS_TX_SYNC_CNT
bool
default y
config SOC_I2S_SUPPORTS_TDM
bool
default y
@ -1127,6 +1131,10 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT
bool
default n
config SOC_CLK_APLL_SUPPORTED
bool
default y
config SOC_CLK_XTAL32K_SUPPORTED
bool
default y

View File

@ -338,7 +338,7 @@ typedef enum {
/**
* @brief Array initializer for all supported clock sources of I2S
*/
#define SOC_I2S_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL}
#define SOC_I2S_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_APLL, I2S_CLK_SRC_EXTERNAL}
/**
* @brief I2S clock source enum
@ -347,6 +347,7 @@ typedef enum {
I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default source clock */
I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */
} soc_periph_i2s_clk_src_t;
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////

View File

@ -486,6 +486,44 @@ bool rtc_dig_8m_enabled(void);
*/
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
/**
* @brief Enable or disable APLL
*
* Output frequency is given by the formula:
* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
*
* The dividend in this expression should be in the range of 240 - 600 MHz.
*
* In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
*
* @param enable true to enable, false to disable
*/
void rtc_clk_apll_enable(bool enable);
/**
* @brief Calculate APLL clock coeffifcients
*
* @param freq expected APLL frequency
* @param o_div frequency divider, 0..31
* @param sdm0 frequency adjustment parameter, 0..255
* @param sdm1 frequency adjustment parameter, 0..255
* @param sdm2 frequency adjustment parameter, 0..63
*
* @return
* - 0 Failed
* - else Sucess
*/
uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2);
/**
* @brief Set APLL clock coeffifcients
*
* @param o_div frequency divider, 0..31
* @param sdm0 frequency adjustment parameter, 0..255
* @param sdm1 frequency adjustment parameter, 0..255
* @param sdm2 frequency adjustment parameter, 0..63
*/
void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2);
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
// **WARNING**: The following are only for backwards compatibility.

View File

@ -251,6 +251,7 @@
#define SOC_I2S_SUPPORTS_PDM_TX (1)
#define SOC_I2S_SUPPORTS_PDM_RX (1)
#define SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER (1)
#define SOC_I2S_SUPPORTS_TX_SYNC_CNT (1)
#define SOC_I2S_SUPPORTS_TDM (1)
#define SOC_I2S_PDM_MAX_TX_LINES (2) // On I2S0
#define SOC_I2S_PDM_MAX_RX_LINES (4) // On I2S0
@ -515,6 +516,7 @@
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (0)
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (0)
#define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */

View File

@ -32,7 +32,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_in_sigs[2] = I2S0I_SD2_IN_IDX,
.data_in_sigs[3] = I2S0I_SD3_IN_IDX,
.irq = -1,
.irq = ETS_I2S0_INTR_SOURCE,
.module = PERIPH_I2S0_MODULE,
},
{
@ -56,7 +56,7 @@ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = {
.data_in_sigs[2] = -1,
.data_in_sigs[3] = -1,
.irq = -1,
.irq = ETS_I2S1_INTR_SOURCE,
.module = PERIPH_I2S1_MODULE,
}
};

View File

@ -55,28 +55,48 @@ examples/peripherals/i2c/i2c_tools:
examples/peripherals/i2s/i2s_basic/i2s_pdm:
disable:
- if: SOC_I2S_SUPPORTS_PDM != 1 or IDF_TARGET == "esp32p4"
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
examples/peripherals/i2s/i2s_basic/i2s_std:
disable:
- if: SOC_I2S_SUPPORTED != 1 or IDF_TARGET == "esp32p4"
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
examples/peripherals/i2s/i2s_basic/i2s_tdm:
disable:
- if: SOC_I2S_SUPPORTS_TDM != 1 or IDF_TARGET == "esp32p4"
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm:
disable:
- if: SOC_I2S_SUPPORTS_TDM != 1 or (SOC_I2C_SUPPORTED != 1 or SOC_GPSPI_SUPPORTED != 1)
reason: rely on I2S TDM mode to receive audio, I2C to config es7210 and SPI to save audio to SD card
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
examples/peripherals/i2s/i2s_codec/i2s_es8311:
disable:
- if: (SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1) or IDF_TARGET == "esp32p4"
- if: (SOC_I2S_SUPPORTED != 1 or SOC_I2C_SUPPORTED != 1)
reason: rely on I2S STD mode and I2C to config es7210
disable_test:
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: lack of runners
examples/peripherals/i2s/i2s_recorder:
disable:
- if: IDF_TARGET == "esp32p4"
- if: SOC_SDMMC_HOST_SUPPORTED != 1 or IDF_TARGET == "esp32p4"
enable:
- if: SOC_I2S_SUPPORTS_PDM_RX > 0

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# I2S ES8311 Example