fix(i2s): fixed the false buf catenate while use preload

Closes https://github.com/espressif/esp-idf/issues/15775
This commit is contained in:
laokaiyao
2025-04-22 23:03:19 +08:00
parent 63b29d8bc8
commit fb556c76e8
2 changed files with 27 additions and 4 deletions

View File

@@ -1017,8 +1017,11 @@ esp_err_t i2s_channel_enable(i2s_chan_handle_t handle)
#endif
handle->start(handle);
handle->state = I2S_CHAN_STATE_RUNNING;
/* Reset queue */
xQueueReset(handle->msg_queue);
if (handle->dir == I2S_DIR_RX) {
/* RX queue is reset when the channel is enabled
In case legacy data received during disable process */
xQueueReset(handle->msg_queue);
}
xSemaphoreGive(handle->mutex);
/* Give the binary semaphore to enable reading / writing task */
xSemaphoreGive(handle->binary);
@@ -1048,6 +1051,11 @@ esp_err_t i2s_channel_disable(i2s_chan_handle_t handle)
handle->dma.curr_ptr = NULL;
handle->dma.rw_pos = 0;
handle->stop(handle);
if (handle->dir == I2S_DIR_TX) {
/* TX queue is reset when the channel is disabled
In case the queue is wrongly reset after preload the data */
xQueueReset(handle->msg_queue);
}
#if CONFIG_PM_ENABLE
esp_pm_lock_release(handle->pm_lock);
#endif
@@ -1069,18 +1077,31 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
uint8_t *data_ptr = (uint8_t *)src;
size_t remain_bytes = size;
size_t total_loaded_bytes = 0;
esp_err_t ret = ESP_OK;
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];
xQueueReset(tx_handle->msg_queue);
/* Push the rest of descriptors to the queue */
for (int i = 1; i < tx_handle->dma.desc_num; i++) {
ESP_GOTO_ON_FALSE(xQueueSend(tx_handle->msg_queue, &(tx_handle->dma.desc[i]->buf), 0) == pdTRUE,
ESP_FAIL, err, TAG, "Failed to push the descriptor to the queue");
}
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) {
if (tx_handle->dma.rw_pos == tx_handle->dma.buf_size) {
if (xQueueReceive(tx_handle->msg_queue, &(tx_handle->dma.curr_ptr), 0) == pdFALSE) {
break;
}
tx_handle->dma.rw_pos = 0;
}
size_t bytes_can_load = remain_bytes > (tx_handle->dma.buf_size - tx_handle->dma.rw_pos) ?
(tx_handle->dma.buf_size - tx_handle->dma.rw_pos) : remain_bytes;
/* When all the descriptors has loaded data, no more bytes can be loaded, break directly */
@@ -1109,9 +1130,10 @@ esp_err_t i2s_channel_preload_data(i2s_chan_handle_t tx_handle, const void *src,
}
*bytes_loaded = total_loaded_bytes;
err:
xSemaphoreGive(tx_handle->mutex);
return ESP_OK;
return ret;
}
esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t size, size_t *bytes_written, uint32_t timeout_ms)

View File

@@ -171,6 +171,7 @@ esp_err_t i2s_channel_disable(i2s_chan_handle_t handle);
* @param[out] bytes_loaded The bytes that successfully been loaded into the TX DMA buffer
* @return
* - ESP_OK Load data successful
* - ESP_FAIL Failed to push the message queue
* - ESP_ERR_INVALID_ARG NULL pointer or not TX direction
* - ESP_ERR_INVALID_STATE This channel has not stated
*/