Merge branch 'feat/i2s_duplex_update_v6.1' into 'release/v6.1'

feat(i2s): allow full duplex mode in less strict condition (v6.1)

See merge request espressif/esp-idf!50865
This commit is contained in:
morris
2026-07-29 19:12:34 +08:00
10 changed files with 394 additions and 127 deletions

View File

@@ -900,6 +900,10 @@ Full-duplex mode registers TX and RX channel in an I2S port at the same time, an
Note that one handle can only stand for one channel. Therefore, it is still necessary to configure the slot and clock for both TX and RX channels one by one.
.. note::
In full-duplex mode, only one channel can work as the master that generates BCLK and WS. If both paired handles are configured as ``I2S_ROLE_MASTER``, the handle initialized later is automatically switched to ``I2S_ROLE_SLAVE``.
There are two methods to allocate a pair of full-duplex channels:
1. Allocate both TX and RX handles in a single call of :cpp:func:`i2s_new_channel`.
@@ -917,7 +921,7 @@ There are two methods to allocate a pair of full-duplex channels:
/* Allocate for TX and RX channel at the same time, then they will work in full-duplex mode */
i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle);
/* Set the configurations for BOTH TWO channels, since TX and RX channel have to be same in full-duplex mode */
/* Set the configurations for both channels. BCLK/WS and frame timing must match in full-duplex mode. */
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
@@ -942,7 +946,7 @@ There are two methods to allocate a pair of full-duplex channels:
...
2. Allocate TX and RX handles separately, and initialize them with the same configuration.
2. Allocate TX and RX handles separately, and initialize them with compatible configurations.
.. code-block:: c
@@ -957,7 +961,7 @@ There are two methods to allocate a pair of full-duplex channels:
/* Allocate for TX and RX channel separately, they are not full-duplex yet */
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));
/* Set the configurations for BOTH TWO channels, they will constitute in full-duplex mode automatically */
/* Set compatible configurations for both channels, then they will constitute in full-duplex mode automatically */
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
@@ -983,6 +987,15 @@ There are two methods to allocate a pair of full-duplex channels:
...
.. only:: SOC_I2S_HW_VERSION_2
When the TX and RX channels are allocated separately (the second method above), they do not have to be configured exactly the same to constitute full-duplex. The driver lets them share the BCLK and WS lines as long as:
- both channels use the same valid ``bclk`` and ``ws`` pins;
- both channels use the same BCLK/WS inversion settings;
- both channels produce the same frame timing, i.e. the same ``sample_rate_hz`` and the same total bits per frame (``total_slot * slot_bit_width``).
The clock source, external clock frequency (``ext_clk_freq_hz``), and MCLK-related configuration, including the ``mclk`` pin, ``mclk_multiple``, and MCLK inversion setting, are not used as conditions for constituting full-duplex. The slot layout itself may also differ. For example, an STD channel and a TDM channel, or a 2-slot/32-bit channel paired with a 4-slot/16-bit channel, can still constitute full-duplex because the number of bits per frame is the same. Once a pair of full-duplex channels is established, the paired channel handle can be retrieved from :cpp:type:`i2s_chan_info_t`::pair_chan returned by :cpp:func:`i2s_channel_get_info`.
.. only:: SOC_I2S_HW_VERSION_1

View File

@@ -900,6 +900,10 @@ STD RX 模式
请注意,一个句柄只能代表一个通道,因此仍然需要对 TX 和 RX 通道逐个进行声道和时钟配置。
.. note::
全双工模式下只能有一个通道作为 master 生成 BCLK 和 WS。如果配对的两个句柄都配置为 ``I2S_ROLE_MASTER``,后初始化的句柄会被自动切换为 ``I2S_ROLE_SLAVE``
驱动支持两种分配全双工通道的方法:
1. 在调用 :cpp:func:`i2s_new_channel` 函数时,同时分配 TX 和 RX 通道两个通道。
@@ -917,7 +921,7 @@ STD RX 模式
/* 同时分配给 TX 和 RX 通道,使其进入全双工模式。 */
i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle);
/* 配置两个通道,因为在全双工模式TX 和 RX 通道必须相同。 */
/* 配置两个通道全双工模式要求 BCLK/WS 与帧时序匹配。 */
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
@@ -942,7 +946,7 @@ STD RX 模式
...
2. 调用两次 :cpp:func:`i2s_new_channel` 函数分别分配 TX 和 RX 通道,使用相同配置初始化 TX 和 RX 通道。
2. 调用两次 :cpp:func:`i2s_new_channel` 函数分别分配 TX 和 RX 通道,使用兼容配置初始化 TX 和 RX 通道。
.. code-block:: c
@@ -957,7 +961,7 @@ STD RX 模式
/* 分别分配给 TX 和 RX 通道 */
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, NULL));
/* 为两个通道设置完全相同的配置TX 和 RX 将自动组成全双工模式 */
/* 为两个通道设置兼容配置TX 和 RX 将自动组成全双工模式 */
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(32000),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
@@ -983,6 +987,15 @@ STD RX 模式
...
.. only:: SOC_I2S_HW_VERSION_2
当 TX 和 RX 通道分别分配时(即上述第二种方法),二者无需配置得完全相同即可组成全双工。只要满足以下条件,驱动就会让它们共享 BCLK 和 WS 信号线:
- 两个通道使用相同且有效的 ``bclk````ws`` 管脚;
- 两个通道使用相同的 BCLK/WS 反相配置;
- 二者产生相同的帧时序,即 ``sample_rate_hz`` 相同且每帧总位数(``total_slot * slot_bit_width``)相同。
时钟源、外部时钟频率(``ext_clk_freq_hz``)以及 MCLK 相关配置不作为组成全双工的判据MCLK 相关配置包括 ``mclk`` 管脚、``mclk_multiple`` 和 MCLK 反相配置。槽slot布局本身也可以不同。例如一个 STD 通道与一个 TDM 通道,或者 2 槽/32 位通道与 4 槽/16 位通道配对,只要每帧的位数相同,仍可组成全双工。一旦组成了一对全双工通道,便可通过 :cpp:func:`i2s_channel_get_info` 返回的 :cpp:type:`i2s_chan_info_t`::pair_chan 获取配对通道的句柄。
.. only:: SOC_I2S_HW_VERSION_1