diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index a1bd56fa1aa..2ece6490502 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -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 diff --git a/components/esp_driver_i2s/i2s_etm.c b/components/esp_driver_i2s/i2s_etm.c index cdecd3e2b0a..6c06565ab7a 100644 --- a/components/esp_driver_i2s/i2s_etm.c +++ b/components/esp_driver_i2s/i2s_etm.c @@ -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; } diff --git a/components/esp_hal_i2s/esp32s31/include/hal/i2s_ll.h b/components/esp_hal_i2s/esp32s31/include/hal/i2s_ll.h index cfcbcbaeab7..20abf78f950 100644 --- a/components/esp_hal_i2s/esp32s31/include/hal/i2s_ll.h +++ b/components/esp_hal_i2s/esp32s31/include/hal/i2s_ll.h @@ -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; } diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 023070cf68a..f16d6384364 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index f0549b97bc7..0c5472ad768 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -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