From b286e363fd7e788d4722bfae5440794062c4a2b4 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 21 Oct 2025 11:17:49 +0800 Subject: [PATCH] fix(i2s): fixed invalid offset in the big gap writing scenario --- components/esp_driver_i2s/i2s_common.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 84eb46a5de..8f9d19a05c 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -1220,7 +1220,12 @@ esp_err_t i2s_channel_write(i2s_chan_handle_t handle, const void *src, size_t si ESP_RETURN_ON_FALSE(xSemaphoreTake(handle->binary, pdMS_TO_TICKS(timeout_ms)) == pdTRUE, ESP_ERR_INVALID_STATE, TAG, "The channel is not enabled"); src_byte = (char *)src; while (size > 0 && handle->state == I2S_CHAN_STATE_RUNNING) { - if (handle->dma.rw_pos == handle->dma.buf_size || handle->dma.curr_ptr == NULL) { + /* Acquire the new DMA buffer while: + * 1. The current buffer is fully filled + * 2. The current buffer is not set + * 3. The queue is almost full, i.e., the curr_ptr is nearly to be invalid + */ + if (handle->dma.rw_pos == handle->dma.buf_size || handle->dma.curr_ptr == NULL || uxQueueSpacesAvailable(handle->msg_queue) <= (handle->dma.desc_num > 2 ? 1 : 0)) { if (xQueueReceive(handle->msg_queue, &(handle->dma.curr_ptr), pdMS_TO_TICKS(timeout_ms)) == pdFALSE) { ret = ESP_ERR_TIMEOUT; break; @@ -1265,7 +1270,12 @@ esp_err_t i2s_channel_read(i2s_chan_handle_t handle, void *dest, size_t size, si /* The binary semaphore can only be taken when the channel has been enabled and no other reading operation in progress */ ESP_RETURN_ON_FALSE(xSemaphoreTake(handle->binary, pdMS_TO_TICKS(timeout_ms)) == pdTRUE, ESP_ERR_INVALID_STATE, TAG, "The channel is not enabled"); while (size > 0 && handle->state == I2S_CHAN_STATE_RUNNING) { - if (handle->dma.rw_pos == handle->dma.buf_size || handle->dma.curr_ptr == NULL) { + /* Acquire the new DMA buffer while: + * 1. The current buffer is fully filled + * 2. The current buffer is not set + * 3. The queue is almost full, i.e., the curr_ptr is nearly to be invalid + */ + if (handle->dma.rw_pos == handle->dma.buf_size || handle->dma.curr_ptr == NULL || uxQueueSpacesAvailable(handle->msg_queue) <= (handle->dma.desc_num > 2 ? 1 : 0)) { if (xQueueReceive(handle->msg_queue, &(handle->dma.curr_ptr), pdMS_TO_TICKS(timeout_ms)) == pdFALSE) { ret = ESP_ERR_TIMEOUT; break;