feat(i2s): support TX FIFO sync on esp32s31

This commit is contained in:
Chen Chen
2026-05-22 15:53:00 +08:00
parent 41582e1777
commit f44f4a82e6
5 changed files with 74 additions and 23 deletions

View File

@@ -1673,6 +1673,7 @@ esp_err_t i2s_sync_enable_hw_fifo_sync(i2s_chan_handle_t tx_handle, bool enable)
return ESP_ERR_NOT_SUPPORTED;
}
i2s_ll_tx_enable_hw_fifo_sync(tx_handle->controller->hal.dev, enable);
i2s_ll_tx_update(tx_handle->controller->hal.dev);
return ESP_OK;
}
@@ -1695,6 +1696,7 @@ esp_err_t i2s_sync_config_hw_fifo_sync(i2s_chan_handle_t tx_handle, const i2s_sy
if (config->suppl_mode == I2S_SYNC_SUPPL_MODE_STATIC_DATA) {
i2s_ll_tx_set_hw_fifo_sync_static_suppl_data(tx_handle->controller->hal.dev, config->suppl_data);
}
i2s_ll_tx_update(tx_handle->controller->hal.dev);
return ESP_OK;
}
#endif

View File

@@ -104,7 +104,7 @@ esp_err_t i2s_new_etm_task(i2s_chan_handle_t handle, const i2s_etm_task_config_t
if (config->task_type == I2S_ETM_TASK_START) {
// The i2s start will be controlled by etm
handle->is_etm_start = true;
} else {
} else if (config->task_type == I2S_ETM_TASK_STOP) {
// The i2s stop will be controlled by etm
handle->is_etm_stop = true;
}

View File

@@ -82,20 +82,24 @@ extern "C" {
[I2S_DIR_RX - 1] = { \
[I2S_ETM_TASK_START] = I2S0_TASK_START_RX, \
[I2S_ETM_TASK_STOP] = I2S0_TASK_STOP_RX, \
[I2S_ETM_TASK_SYNC_FIFO] = -1, \
}, \
[I2S_DIR_TX - 1] = { \
[I2S_ETM_TASK_START] = I2S0_TASK_START_TX, \
[I2S_ETM_TASK_STOP] = I2S0_TASK_STOP_TX, \
[I2S_ETM_TASK_SYNC_FIFO] = I2S0_TASK_SYNC_CHECK, \
}, \
}, \
[1] = { \
[I2S_DIR_RX - 1] = { \
[I2S_ETM_TASK_START] = I2S1_TASK_START_RX, \
[I2S_ETM_TASK_STOP] = I2S1_TASK_STOP_RX, \
[I2S_ETM_TASK_SYNC_FIFO] = -1, \
}, \
[I2S_DIR_TX - 1] = { \
[I2S_ETM_TASK_START] = I2S1_TASK_START_TX, \
[I2S_ETM_TASK_STOP] = I2S1_TASK_STOP_TX, \
[I2S_ETM_TASK_SYNC_FIFO] = I2S1_TASK_SYNC_CHECK, \
}, \
}, \
}[i2s_port][(chan_dir) - 1][task]
@@ -1803,56 +1807,96 @@ static inline uint32_t i2s_ll_tx_get_ideal_cnt(i2s_dev_t *hw)
}
/**
* @brief Set TX sync software threshold
* @brief Get TX FIFO synchronization difference count value
*
* @param hw Peripheral I2S hardware instance address.
* @param thres Software threshold value
* @param hw Peripheral I2S hardware instance address.
* @return
* fifo count value
*/
static inline void i2s_ll_tx_set_sync_sw_thres(i2s_dev_t *hw, uint32_t thres)
__attribute__((always_inline))
static inline uint32_t i2s_ll_tx_get_fifo_sync_diff_count(i2s_dev_t *hw)
{
hw->sync_sw_thres.tx_cnt_diff_sw_thres = thres;
return hw->cnt_diff.tx_cnt_diff;
}
/**
* @brief Set TX sync hardware threshold
* @brief Reset TX FIFO synchronization difference counter
*
* @param hw Peripheral I2S hardware instance address.
* @param thres Hardware threshold value
* @param hw Peripheral I2S hardware instance address.
*/
static inline void i2s_ll_tx_set_sync_hw_thres(i2s_dev_t *hw, uint32_t thres)
__attribute__((always_inline))
static inline void i2s_ll_tx_reset_fifo_sync_diff_counter(i2s_dev_t *hw)
{
hw->sync_hw_thres.tx_cnt_diff_hw_thres = thres;
hw->cnt_diff.tx_cnt_diff_rst = 1;
hw->cnt_diff.tx_cnt_diff_rst = 0;
}
/**
* @brief Enable TX hardware sync
* @brief Set TX FIFO synchronization difference counter software threshold
* @note It determines the up threshold that the hardware synchronize the data automatically.
* - If diff_count <= sw_threshold, the hardware will synchronize the data automatically.
* - If diff_count > sw_threshold, the automatic synchronization is not proper for this case,
* interrupt will be triggered to let the software decide how to handle this case.
*
* @param hw Peripheral I2S hardware instance address.
* @param enable Set true to enable hardware sync
* @param hw Peripheral I2S hardware instance address.
* @param thresh The threshold that send
*/
static inline void i2s_ll_tx_enable_hw_sync(i2s_dev_t *hw, bool enable)
__attribute__((always_inline))
static inline void i2s_ll_tx_set_fifo_sync_diff_conter_sw_threshold(i2s_dev_t *hw, uint32_t thresh)
{
hw->sync_sw_thres.tx_cnt_diff_sw_thres = thresh;
}
/**
* @brief Set TX FIFO synchronization difference counter hardware threshold
* @note It determines the down threshold that the hardware synchronize the data automatically.
* - If diff_count < hw_threshold, synchronization check pass, do nothing
* - If diff_count >= hw_threshold, the hardware will synchronize the data automatically.
*
* @param hw Peripheral I2S hardware instance address.
* @param thresh The threshold that send
*/
__attribute__((always_inline))
static inline void i2s_ll_tx_set_fifo_sync_diff_conter_hw_threshold(i2s_dev_t *hw, uint32_t thresh)
{
hw->sync_hw_thres.tx_cnt_diff_hw_thres = thresh;
}
/**
* @brief Enable TX FIFO synchronization hardware mode
*
* @param hw Peripheral I2S hardware instance address.
* @param enable Set true to enable hardware mode
*/
__attribute__((always_inline))
static inline void i2s_ll_tx_enable_hw_fifo_sync(i2s_dev_t *hw, bool enable)
{
hw->hw_sync_conf.tx_hw_sync_en = enable;
}
/**
* @brief Set TX hardware sync supplement mode
* @brief Set TX FIFO synchronization hardware data supplementation mode
* @note It determines the supplementation data when the actual sent data is less than the `diff_count - threshold`
*
* @param hw Peripheral I2S hardware instance address.
* @param mode Supplement mode: 0 = last data, 1 = configured data
* @param hw Peripheral I2S hardware instance address.
* @param mode Data supplementation mode
* - 0: Supplement the last data
* - 1: Supplement the data configured in `hw_sync_data` reg
*/
static inline void i2s_ll_tx_set_hw_sync_suppl_mode(i2s_dev_t *hw, bool mode)
__attribute__((always_inline))
static inline void i2s_ll_tx_set_hw_fifo_sync_suppl_mode(i2s_dev_t *hw, uint32_t mode)
{
hw->hw_sync_conf.tx_hw_sync_suppl_mode = mode;
}
/**
* @brief Set TX hardware sync supplement data
* @brief Set TX FIFO synchronization hardware supplementation data when `tx_hw_sync_suppl_mode` is 1
*
* @param hw Peripheral I2S hardware instance address.
* @param data Supplement data value
* @param hw Peripheral I2S hardware instance address.
* @param data Data to be supplemented when `tx_hw_sync_suppl_mode` is 1
*/
static inline void i2s_ll_tx_set_hw_sync_suppl_data(i2s_dev_t *hw, uint32_t data)
__attribute__((always_inline))
static inline void i2s_ll_tx_set_hw_fifo_sync_static_suppl_data(i2s_dev_t *hw, uint32_t data)
{
hw->hw_sync_data.tx_hw_sync_suppl_data = data;
}

View File

@@ -1795,6 +1795,10 @@ config SOC_I2S_SUPPORTS_TX_SYNC_CNT
bool
default y
config SOC_I2S_SUPPORTS_TX_FIFO_SYNC
bool
default y
config SOC_I2S_SUPPORTS_RX_RECOMB
bool
default y

View File

@@ -666,6 +666,7 @@
#define SOC_I2S_SUPPORTS_PDM2PCM (1) // Support to input PDM format but read PCM format data with the help of PDM to PCM filter (only on I2S0)
#define SOC_I2S_SUPPORTS_PDM_RX_HP_FILTER (1)
#define SOC_I2S_SUPPORTS_TX_SYNC_CNT (1) // Support TX synchronization count (ideal_cnt)
#define SOC_I2S_SUPPORTS_TX_FIFO_SYNC (1)
#define SOC_I2S_SUPPORTS_RX_RECOMB (1) // Support RX recomb for DMA data format reorganization
#define SOC_I2S_SUPPORTS_TDM (1)
#define SOC_I2S_SUPPORTS_BT_DEST (1) // Support routing I2S TX/RX data to Bluetooth (Classic sync link / voice path), not via DMA