mirror of
https://github.com/espressif/esp-idf
synced 2025-03-12 10:39:11 -04:00
feat(i2s): supported getting the tx sync count and specify interrupt flags
This commit is contained in:
parent
cf889f3c6d
commit
0b0f25c30d
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
71
components/driver/include/esp_private/i2s_sync.h
Normal file
71
components/driver/include/esp_private/i2s_sync.h
Normal 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
|
@ -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:
|
||||
|
@ -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 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
|
@ -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 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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, ¶m0, ¶m5);
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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////////////////////////////////////////////////////////////////////
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user