Skip to content

Commit 1a242d1

Browse files
committed
Merge branch 'feature/support_i2s_and_etm_on_h4' into 'master'
feat(i2s & etm): support i2s and etm on esp32-h4 Closes IDF-12385, IDF-12355, and IDF-13396 See merge request espressif/esp-idf!39698
2 parents b37a159 + 263a056 commit 1a242d1

File tree

52 files changed

+2647
-1362
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2647
-1362
lines changed

components/esp_driver_i2s/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ endif()
3737
idf_component_register(SRCS ${srcs}
3838
INCLUDE_DIRS ${include}
3939
PRIV_REQUIRES esp_driver_gpio esp_pm esp_mm
40+
LDFRAGMENTS linker.lf
4041
)

components/esp_driver_i2s/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ menu "ESP-Driver:I2S Configurations"
88
Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be
99
executable when the cache is disabled (e.g. SPI Flash write).
1010

11+
config I2S_CTRL_FUNC_IN_IRAM
12+
bool "Place I2S control functions into IRAM"
13+
default n
14+
help
15+
Place I2S control functions into IRAM,
16+
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
17+
1118
config I2S_ENABLE_DEBUG_LOG
1219
bool "Enable I2S debug log"
1320
default n

components/esp_driver_i2s/i2s_common.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
#include "driver/gpio.h"
4949
#include "esp_private/gpio.h"
50+
#include "esp_private/i2s_sync.h"
5051
#include "driver/i2s_common.h"
5152
#include "i2s_private.h"
5253

@@ -574,7 +575,7 @@ uint32_t i2s_get_source_clk_freq(i2s_clock_src_t clk_src, uint32_t mclk_freq_hz)
574575
}
575576

576577
#if SOC_GDMA_SUPPORTED
577-
static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
578+
static bool i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
578579
{
579580
i2s_chan_handle_t handle = (i2s_chan_handle_t)user_data;
580581
BaseType_t need_yield1 = 0;
@@ -605,7 +606,7 @@ static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_e
605606
return need_yield1 | need_yield2 | user_need_yield;
606607
}
607608

608-
static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
609+
static bool i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
609610
{
610611
i2s_chan_handle_t handle = (i2s_chan_handle_t)user_data;
611612
BaseType_t need_yield1 = 0;
@@ -652,7 +653,7 @@ static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_e
652653

653654
#else
654655

655-
static void IRAM_ATTR i2s_dma_rx_callback(void *arg)
656+
static void i2s_dma_rx_callback(void *arg)
656657
{
657658
BaseType_t need_yield1 = 0;
658659
BaseType_t need_yield2 = 0;
@@ -690,7 +691,7 @@ static void IRAM_ATTR i2s_dma_rx_callback(void *arg)
690691
}
691692
}
692693

693-
static void IRAM_ATTR i2s_dma_tx_callback(void *arg)
694+
static void i2s_dma_tx_callback(void *arg)
694695
{
695696
BaseType_t need_yield1 = 0;
696697
BaseType_t need_yield2 = 0;
@@ -1483,3 +1484,46 @@ void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle)
14831484
i2s_ll_tx_reset_fifo_sync_counter(tx_handle->controller->hal.dev);
14841485
}
14851486
#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT
1487+
1488+
#if SOC_I2S_SUPPORTS_TX_FIFO_SYNC
1489+
uint32_t i2s_sync_get_fifo_sync_diff_count(i2s_chan_handle_t tx_handle)
1490+
{
1491+
return i2s_ll_tx_get_fifo_sync_diff_count(tx_handle->controller->hal.dev);
1492+
}
1493+
1494+
void i2s_sync_reset_fifo_sync_diff_count(i2s_chan_handle_t tx_handle)
1495+
{
1496+
i2s_ll_tx_reset_fifo_sync_diff_counter(tx_handle->controller->hal.dev);
1497+
}
1498+
1499+
esp_err_t i2s_sync_enable_hw_fifo_sync(i2s_chan_handle_t tx_handle, bool enable)
1500+
{
1501+
if (tx_handle->dir == I2S_DIR_RX) {
1502+
return ESP_ERR_NOT_SUPPORTED;
1503+
}
1504+
i2s_ll_tx_enable_hw_fifo_sync(tx_handle->controller->hal.dev, enable);
1505+
return ESP_OK;
1506+
}
1507+
1508+
esp_err_t i2s_sync_config_hw_fifo_sync(i2s_chan_handle_t tx_handle, const i2s_sync_fifo_sync_config_t *config)
1509+
{
1510+
if (!(tx_handle && config)) {
1511+
return ESP_ERR_INVALID_ARG;
1512+
}
1513+
if (tx_handle->dir == I2S_DIR_RX) {
1514+
return ESP_ERR_NOT_SUPPORTED;
1515+
}
1516+
if (config->sw_high_thresh < config->hw_low_thresh) {
1517+
return ESP_ERR_INVALID_ARG;
1518+
}
1519+
1520+
i2s_ll_tx_set_etm_sync_ideal_cnt(tx_handle->controller->hal.dev, config->ideal_cnt);
1521+
i2s_ll_tx_set_fifo_sync_diff_conter_sw_threshold(tx_handle->controller->hal.dev, config->sw_high_thresh);
1522+
i2s_ll_tx_set_fifo_sync_diff_conter_hw_threshold(tx_handle->controller->hal.dev, config->hw_low_thresh);
1523+
i2s_ll_tx_set_hw_fifo_sync_suppl_mode(tx_handle->controller->hal.dev, (uint32_t)config->suppl_mode);
1524+
if (config->suppl_mode == I2S_SYNC_SUPPL_MODE_STATIC_DATA) {
1525+
i2s_ll_tx_set_hw_fifo_sync_static_suppl_data(tx_handle->controller->hal.dev, config->suppl_data);
1526+
}
1527+
return ESP_OK;
1528+
}
1529+
#endif

components/esp_driver_i2s/i2s_etm.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -84,6 +84,11 @@ esp_err_t i2s_new_etm_task(i2s_chan_handle_t handle, const i2s_etm_task_config_t
8484
{
8585
ESP_RETURN_ON_FALSE(handle && config && out_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
8686
ESP_RETURN_ON_FALSE(config->task_type < I2S_ETM_TASK_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid task type");
87+
#if SOC_I2S_SUPPORTS_TX_FIFO_SYNC
88+
ESP_RETURN_ON_FALSE(config->task_type != I2S_ETM_TASK_SYNC_FIFO || handle->dir == I2S_DIR_TX,
89+
ESP_ERR_NOT_SUPPORTED, TAG, "rx does not support sync check");
90+
#endif
91+
8792
i2s_etm_task_t *task = heap_caps_calloc(1, sizeof(i2s_etm_task_t), ETM_MEM_ALLOC_CAPS);
8893
ESP_RETURN_ON_FALSE(task, ESP_ERR_NO_MEM, TAG, "no memory for ETM task");
8994

components/esp_driver_i2s/include/esp_private/i2s_sync.h

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -21,6 +21,7 @@
2121

2222
#include <stdint.h>
2323
#include "driver/i2s_types.h"
24+
#include "esp_err.h"
2425

2526
#ifdef __cplusplus
2627
extern "C" {
@@ -31,6 +32,7 @@ extern "C" {
3132
/**
3233
* @brief Get the counter number of BCLK ticks
3334
* @note The BCLK tick count reflects the real data that have sent on line
35+
* @note It will be reset automatically when `I2S_ETM_TASK_SYNC_FIFO` is triggered
3436
*
3537
* @param[in] tx_handle The I2S tx channel handle
3638
* @return
@@ -43,6 +45,7 @@ uint32_t i2s_sync_get_bclk_count(i2s_chan_handle_t tx_handle);
4345
* @note The FIFO count reflects how many slots have processed
4446
* Normally, fifo_cnt = slot_bit_width * bclk_cnt
4547
* If fifo_cnt < slot_bit_width * bclk_cnt, that means some data are still stuck in the I2S controller
48+
* @note It will be reset automatically when `I2S_ETM_TASK_SYNC_FIFO` is triggered
4649
*
4750
* @param[in] tx_handle The I2S tx channel handle
4851
* @return
@@ -66,6 +69,78 @@ void i2s_sync_reset_fifo_count(i2s_chan_handle_t tx_handle);
6669

6770
#endif // SOC_I2S_SUPPORTS_TX_SYNC_CNT
6871

72+
#if SOC_I2S_SUPPORTS_TX_FIFO_SYNC
73+
/**
74+
* @brief I2S hardware FIFO synchronization supplement mode
75+
* @note When the FIFO sync difference count is out of threshold, the hardware will supplement data automatically
76+
* This type is to specify which data will be supplemented
77+
*/
78+
typedef enum {
79+
I2S_SYNC_SUPPL_MODE_LAST_DATA = 0, /*!< Supplement with the last transmitted data */
80+
I2S_SYNC_SUPPL_MODE_STATIC_DATA = 1, /*!< Supplement with static data specified in config */
81+
} i2s_sync_suppl_mode_t;
82+
83+
/**
84+
* @brief I2S hardware FIFO synchronization configuration
85+
* @note This configuration is used for multi I2S port synchronization via ETM
86+
*/
87+
typedef struct {
88+
uint32_t hw_low_thresh; /*!< Lower threshold for FIFO sync difference counter
89+
- If difference count < hw_low_thresh, do nothing
90+
- If difference count >= hw_low_thresh, the hardware will supplement data automatically */
91+
uint32_t sw_high_thresh; /*!< Upper threshold for FIFO sync difference counter
92+
- If difference count <= sw_high_thresh, the hardware supplement data automatically
93+
- If difference count > sw_high_thresh, sync interrupt triggered and
94+
the software is responsible to decide how to handle this severe asynchronization */
95+
uint32_t ideal_cnt; /*!< Ideal count for FIFO sync difference counter, it depends on the ETM sync task interval and the data rate */
96+
i2s_sync_suppl_mode_t suppl_mode; /*!< Data supplement mode when FIFO sync difference is out of threshold */
97+
uint32_t suppl_data; /*!< Static supplement data, only valid when suppl_mode is I2S_SYNC_SUPPL_MODE_STATIC_DATA */
98+
} i2s_sync_fifo_sync_config_t;
99+
100+
/**
101+
* @brief Get the counter number of FIFO sync difference
102+
* @note The FIFO sync difference count reflects the difference between current FIFO count and ideal count
103+
*
104+
* @param[in] tx_handle The I2S tx channel handle
105+
* @return
106+
* - FIFO sync difference count
107+
*/
108+
uint32_t i2s_sync_get_fifo_sync_diff_count(i2s_chan_handle_t tx_handle);
109+
110+
/**
111+
* @brief Reset the FIFO sync difference counter
112+
*
113+
* @param[in] tx_handle The I2S tx channel handle
114+
*/
115+
void i2s_sync_reset_fifo_sync_diff_count(i2s_chan_handle_t tx_handle);
116+
117+
/**
118+
* @brief Enable or disable hardware FIFO synchronization
119+
* @note When enabled, hardware will automatically supplement data when FIFO sync difference is greater than hw_low_thresh
120+
*
121+
* @param[in] tx_handle The I2S tx channel handle
122+
* @param[in] enable true to enable, false to disable
123+
* @return
124+
* - ESP_OK on success
125+
* - ESP_ERR_NOT_SUPPORTED if called on RX channel
126+
*/
127+
esp_err_t i2s_sync_enable_hw_fifo_sync(i2s_chan_handle_t tx_handle, bool enable);
128+
129+
/**
130+
* @brief Configure hardware FIFO synchronization parameters
131+
* @note This function configures the thresholds and supplement mode for hardware FIFO sync
132+
*
133+
* @param[in] tx_handle The I2S tx channel handle
134+
* @param[in] config Configuration for hardware FIFO synchronization
135+
* @return
136+
* - ESP_OK on success
137+
* - ESP_ERR_INVALID_ARG if invalid arguments
138+
* - ESP_ERR_NOT_SUPPORTED if called on RX channel
139+
*/
140+
esp_err_t i2s_sync_config_hw_fifo_sync(i2s_chan_handle_t tx_handle, const i2s_sync_fifo_sync_config_t *config);
141+
142+
#endif
143+
69144
#ifdef __cplusplus
70145
}
71146
#endif
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[mapping:i2s_driver]
2+
archive: libesp_driver_i2s.a
3+
entries:
4+
if I2S_ISR_IRAM_SAFE = y:
5+
i2s_common: i2s_dma_rx_callback (noflash)
6+
i2s_common: i2s_dma_tx_callback (noflash)
7+
if I2S_CTRL_FUNC_IN_IRAM = y:
8+
if SOC_I2S_SUPPORTS_TX_SYNC_CNT = y:
9+
i2s_common: i2s_sync_get_bclk_count (noflash)
10+
i2s_common: i2s_sync_get_fifo_count (noflash)
11+
i2s_common: i2s_sync_reset_bclk_count (noflash)
12+
i2s_common: i2s_sync_reset_fifo_count (noflash)
13+
if SOC_I2S_SUPPORTS_TX_FIFO_SYNC = y:
14+
i2s_common: i2s_sync_get_fifo_sync_diff_count (noflash)
15+
i2s_common: i2s_sync_reset_fifo_sync_diff_count (noflash)
16+
i2s_common: i2s_sync_enable_hw_fifo_sync (noflash)
17+
i2s_common: i2s_sync_config_hw_fifo_sync (noflash)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2-
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
1+
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2+
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | -------- |

components/esp_driver_i2s/test_apps/i2s/main/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
set(srcs "test_app_main.c"
22
"test_i2s.c"
3-
"test_i2s_iram.c"
4-
"test_i2s_sleep.c")
3+
"test_i2s_iram.c")
54

65
if(CONFIG_SOC_I2S_SUPPORTS_ETM AND CONFIG_SOC_GPIO_SUPPORT_ETM)
76
set(srcs ${srcs} "test_i2s_etm.c")
87
endif()
98

9+
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED)
10+
list(APPEND srcs "test_i2s_sleep.c")
11+
endif()
12+
1013
idf_component_register(SRCS ${srcs}
1114
PRIV_REQUIRES unity esp_driver_pcnt spi_flash
1215
esp_driver_gpio esp_driver_i2s esp_driver_uart esp_psram

components/esp_driver_i2s/test_apps/i2s/sdkconfig.ci.iram_safe

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
CONFIG_COMPILER_DUMP_RTL_FILES=y
22
CONFIG_I2S_ISR_IRAM_SAFE=y
3+
CONFIG_I2S_CTRL_FUNC_IN_IRAM=y
34
CONFIG_COMPILER_OPTIMIZATION_NONE=y
45
# silent the error check, as the error string are stored in rodata, causing RTL check failure
56
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
2-
| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
1+
| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 | ESP32-S3 |
2+
| ----------------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
33

0 commit comments

Comments
 (0)