Merge branch 'bugfix/async_crc_timeout_v6.1' into 'release/v6.1'

fix(async_crc): limit blocking timeout support (v6.1)

See merge request espressif/esp-idf!49242
This commit is contained in:
morris
2026-06-04 22:40:02 +08:00
5 changed files with 21 additions and 33 deletions
@@ -53,6 +53,7 @@ typedef struct {
uint32_t backlog; /*!< Maximum number of pending CRC requests that can be queued per driver instance.
Higher values use more memory but provide better throughput for bursty workloads. */
size_t dma_burst_size; /*!< DMA transfer burst size, in bytes */
uint32_t intr_priority; /*!< DMA interrupt priority. 0 means default low/medium priority. */
} async_crc_config_t;
#if SOC_HAS(AHB_GDMA)
@@ -132,21 +133,18 @@ esp_err_t esp_async_crc_calc(async_crc_handle_t crc_hdl, const void *data, size_
* @brief Blocking CRC calculation function with timeout
*
* @note This function is blocking and should not be called from interrupt context.
* @note Only `timeout_ms=-1` is supported, which means waiting indefinitely.
*
* @param[in] crc_hdl Handle of async CRC driver that returned from install functions
* @param[in] data Pointer to data buffer for CRC calculation
* @param[in] size Size of data in bytes
* @param[in] params CRC calculation parameters
* @param[in] timeout_ms Timeout in milliseconds:
* - `< 0`: Wait forever (no timeout)
* - `0`: Return immediately (poll once)
* - `> 0`: Wait up to specified milliseconds
* @param[in] timeout_ms Timeout in milliseconds. Only -1 is supported.
* @param[out] result Pointer to store CRC calculation result
* @return
* - ESP_OK: Calculate CRC successfully
* - ESP_ERR_INVALID_ARG: Calculate CRC failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Function called from ISR context or driver in invalid state
* - ESP_ERR_TIMEOUT: Operation timed out
* - ESP_FAIL: Calculate CRC failed because of other error
*/
esp_err_t esp_crc_calc_blocking(async_crc_handle_t crc_hdl, const void *data, size_t size,
@@ -114,7 +114,9 @@ esp_err_t esp_async_crc_install_gdma_template(const async_crc_config_t *config,
ESP_GOTO_ON_FALSE(crc_gdma->transaction_pool, ESP_ERR_NO_MEM, err, TAG, "no mem for transaction pool");
// Create TX channel for CRC calculation with optimized allocation strategy
gdma_channel_alloc_config_t dma_chan_alloc_cfg = {0};
gdma_channel_alloc_config_t dma_chan_alloc_cfg = {
.intr_priority = config->intr_priority,
};
ESP_GOTO_ON_ERROR(new_channel_func(&dma_chan_alloc_cfg, &crc_gdma->tx_channel, NULL),
err, TAG, "alloc DMA channel failed");
gdma_reset(crc_gdma->tx_channel);
+7 -15
View File
@@ -45,12 +45,14 @@ esp_err_t esp_async_crc_calc(async_crc_handle_t crc_hdl, const void *data, size_
typedef struct {
uint32_t *result;
SemaphoreHandle_t semaphore;
StaticSemaphore_t semaphore_buffer;
} crc_blocking_context_t;
static bool crc_blocking_callback(async_crc_handle_t crc_hdl, async_crc_event_data_t *event, void *user_data)
{
BaseType_t task_woken = pdFALSE;
crc_blocking_context_t *ctx = (crc_blocking_context_t *)user_data;
(void)crc_hdl;
*(ctx->result) = event->crc_result;
@@ -65,26 +67,16 @@ esp_err_t esp_crc_calc_blocking(async_crc_handle_t crc_hdl, const void *data, si
{
ESP_RETURN_ON_FALSE(crc_hdl && data && size && params && result, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(!xPortInIsrContext(), ESP_ERR_INVALID_STATE, TAG, "called from ISR context is not allowed");
ESP_RETURN_ON_FALSE(timeout_ms == -1, ESP_ERR_INVALID_ARG, TAG, "only timeout_ms=-1 is supported");
crc_blocking_context_t ctx = {
.result = result,
.semaphore = xSemaphoreCreateBinary()
};
ESP_RETURN_ON_FALSE(ctx.semaphore, ESP_ERR_NO_MEM, TAG, "create semaphore failed");
ctx.semaphore = xSemaphoreCreateBinaryStatic(&ctx.semaphore_buffer);
esp_err_t ret = esp_async_crc_calc(crc_hdl, data, size, params, crc_blocking_callback, &ctx);
if (ret != ESP_OK) {
vSemaphoreDelete(ctx.semaphore);
return ret;
}
ESP_RETURN_ON_ERROR(esp_async_crc_calc(crc_hdl, data, size, params, crc_blocking_callback, &ctx), TAG, "failed to start CRC calculation");
// Wait for completion with timeout (<0 means wait forever)
TickType_t ticks = (timeout_ms < 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
if (xSemaphoreTake(ctx.semaphore, ticks) != pdTRUE) {
vSemaphoreDelete(ctx.semaphore);
return ESP_ERR_TIMEOUT;
}
vSemaphoreDelete(ctx.semaphore);
// Wait until the callback gives the semaphore
xSemaphoreTake(ctx.semaphore, portMAX_DELAY);
return ESP_OK;
}