diff --git a/components/esp_driver_dma/include/esp_async_crc.h b/components/esp_driver_dma/include/esp_async_crc.h index af953dbb66f..64bea6ca066 100644 --- a/components/esp_driver_dma/include/esp_async_crc.h +++ b/components/esp_driver_dma/include/esp_async_crc.h @@ -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, diff --git a/components/esp_driver_dma/src/async_crc_gdma.c b/components/esp_driver_dma/src/async_crc_gdma.c index b5aad0ac84b..ac1f730db20 100644 --- a/components/esp_driver_dma/src/async_crc_gdma.c +++ b/components/esp_driver_dma/src/async_crc_gdma.c @@ -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); diff --git a/components/esp_driver_dma/src/esp_async_crc.c b/components/esp_driver_dma/src/esp_async_crc.c index c8f841d4821..bfdf5a1143e 100644 --- a/components/esp_driver_dma/src/esp_async_crc.c +++ b/components/esp_driver_dma/src/esp_async_crc.c @@ -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; } diff --git a/docs/en/api-reference/peripherals/async_crc.rst b/docs/en/api-reference/peripherals/async_crc.rst index f440c305e6f..fe2b4c21c43 100644 --- a/docs/en/api-reference/peripherals/async_crc.rst +++ b/docs/en/api-reference/peripherals/async_crc.rst @@ -100,6 +100,7 @@ First, you need to install the Async CRC driver. The driver supports both AHB-GD When creating a driver instance, you need to configure: - **backlog**: Maximum number of pending CRC requests that can be queued. Higher values use more memory but provide better throughput for bursty workloads. +- **intr_priority**: DMA interrupt priority. Set to ``0`` to use the default low/medium priority, or set a non-zero value to request a specific interrupt priority. - **dma_burst_size**: DMA transfer burst size in bytes. The driver handle ``crc_hdl`` is an opaque pointer that you use for all subsequent operations. @@ -161,15 +162,12 @@ For simpler use cases or when async operations are not required, use the blockin const char *data = "Hello, World!"; size_t data_len = strlen(data); - // Blocking CRC with 1000ms timeout - ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, 1000, &crc_result)); + // Blocking CRC, wait indefinitely + ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, -1, &crc_result)); printf("CRC result: 0x%08X\n", crc_result); -The blocking API supports: - -- **timeout_ms >= 0**: Wait for specified milliseconds -- **timeout_ms < 0**: Wait indefinitely +The blocking API only supports ``timeout_ms = -1``, which means waiting indefinitely until the CRC calculation completes. Uninstalling the Driver ------------------------ diff --git a/docs/zh_CN/api-reference/peripherals/async_crc.rst b/docs/zh_CN/api-reference/peripherals/async_crc.rst index 7d06d4a5f20..b257d027d9c 100644 --- a/docs/zh_CN/api-reference/peripherals/async_crc.rst +++ b/docs/zh_CN/api-reference/peripherals/async_crc.rst @@ -100,6 +100,7 @@ 创建驱动程序实例时,您需要配置: - **backlog**:可排队等待的最大 CRC 请求数。较高的值使用更多内存,但在突发工作负载下提供更好的吞吐量。 +- **intr_priority**:DMA 中断优先级。设置为 ``0`` 时使用默认的低/中优先级;设置为非零值时请求指定的中断优先级。 - **dma_burst_size**:DMA 传输突发大小(字节)。 驱动程序句柄 ``crc_hdl`` 是一个不透明指针,用于所有后续操作。 @@ -161,15 +162,12 @@ CRC 计算完成时会在中断上下文中调用回调函数。回调接收: const char *data = "Hello, World!"; size_t data_len = strlen(data); - // 阻塞 CRC,1000ms 超时 - ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, 1000, &crc_result)); + // 阻塞 CRC,无限期等待 + ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, -1, &crc_result)); printf("CRC 结果: 0x%08X\n", crc_result); -阻塞 API 支持: - -- **timeout_ms >= 0**:等待指定的毫秒数 -- **timeout_ms < 0**:无限期等待 +阻塞 API 仅支持 ``timeout_ms = -1``,表示无限期等待直到 CRC 计算完成。 卸载驱动程序 ------------