mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(async_crc): limit the blocking API only accept infinite timeout
also support user configured interrupt priority
This commit is contained in:
@@ -53,6 +53,7 @@ typedef struct {
|
|||||||
uint32_t backlog; /*!< Maximum number of pending CRC requests that can be queued per driver instance.
|
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. */
|
Higher values use more memory but provide better throughput for bursty workloads. */
|
||||||
size_t dma_burst_size; /*!< DMA transfer burst size, in bytes */
|
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;
|
} async_crc_config_t;
|
||||||
|
|
||||||
#if SOC_HAS(AHB_GDMA)
|
#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
|
* @brief Blocking CRC calculation function with timeout
|
||||||
*
|
*
|
||||||
* @note This function is blocking and should not be called from interrupt context.
|
* @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] crc_hdl Handle of async CRC driver that returned from install functions
|
||||||
* @param[in] data Pointer to data buffer for CRC calculation
|
* @param[in] data Pointer to data buffer for CRC calculation
|
||||||
* @param[in] size Size of data in bytes
|
* @param[in] size Size of data in bytes
|
||||||
* @param[in] params CRC calculation parameters
|
* @param[in] params CRC calculation parameters
|
||||||
* @param[in] timeout_ms Timeout in milliseconds:
|
* @param[in] timeout_ms Timeout in milliseconds. Only -1 is supported.
|
||||||
* - `< 0`: Wait forever (no timeout)
|
|
||||||
* - `0`: Return immediately (poll once)
|
|
||||||
* - `> 0`: Wait up to specified milliseconds
|
|
||||||
* @param[out] result Pointer to store CRC calculation result
|
* @param[out] result Pointer to store CRC calculation result
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: Calculate CRC successfully
|
* - ESP_OK: Calculate CRC successfully
|
||||||
* - ESP_ERR_INVALID_ARG: Calculate CRC failed because of invalid argument
|
* - 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_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_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,
|
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");
|
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
|
// 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),
|
ESP_GOTO_ON_ERROR(new_channel_func(&dma_chan_alloc_cfg, &crc_gdma->tx_channel, NULL),
|
||||||
err, TAG, "alloc DMA channel failed");
|
err, TAG, "alloc DMA channel failed");
|
||||||
gdma_reset(crc_gdma->tx_channel);
|
gdma_reset(crc_gdma->tx_channel);
|
||||||
|
|||||||
@@ -45,12 +45,14 @@ esp_err_t esp_async_crc_calc(async_crc_handle_t crc_hdl, const void *data, size_
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t *result;
|
uint32_t *result;
|
||||||
SemaphoreHandle_t semaphore;
|
SemaphoreHandle_t semaphore;
|
||||||
|
StaticSemaphore_t semaphore_buffer;
|
||||||
} crc_blocking_context_t;
|
} crc_blocking_context_t;
|
||||||
|
|
||||||
static bool crc_blocking_callback(async_crc_handle_t crc_hdl, async_crc_event_data_t *event, void *user_data)
|
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;
|
BaseType_t task_woken = pdFALSE;
|
||||||
crc_blocking_context_t *ctx = (crc_blocking_context_t *)user_data;
|
crc_blocking_context_t *ctx = (crc_blocking_context_t *)user_data;
|
||||||
|
(void)crc_hdl;
|
||||||
|
|
||||||
*(ctx->result) = event->crc_result;
|
*(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(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(!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 = {
|
crc_blocking_context_t ctx = {
|
||||||
.result = result,
|
.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);
|
ESP_RETURN_ON_ERROR(esp_async_crc_calc(crc_hdl, data, size, params, crc_blocking_callback, &ctx), TAG, "failed to start CRC calculation");
|
||||||
if (ret != ESP_OK) {
|
|
||||||
vSemaphoreDelete(ctx.semaphore);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for completion with timeout (<0 means wait forever)
|
// Wait until the callback gives the semaphore
|
||||||
TickType_t ticks = (timeout_ms < 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
xSemaphoreTake(ctx.semaphore, portMAX_DELAY);
|
||||||
if (xSemaphoreTake(ctx.semaphore, ticks) != pdTRUE) {
|
|
||||||
vSemaphoreDelete(ctx.semaphore);
|
|
||||||
return ESP_ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
vSemaphoreDelete(ctx.semaphore);
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:
|
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.
|
- **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.
|
- **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.
|
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!";
|
const char *data = "Hello, World!";
|
||||||
size_t data_len = strlen(data);
|
size_t data_len = strlen(data);
|
||||||
|
|
||||||
// Blocking CRC with 1000ms timeout
|
// Blocking CRC, wait indefinitely
|
||||||
ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, 1000, &crc_result));
|
ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, -1, &crc_result));
|
||||||
|
|
||||||
printf("CRC result: 0x%08X\n", crc_result);
|
printf("CRC result: 0x%08X\n", crc_result);
|
||||||
|
|
||||||
The blocking API supports:
|
The blocking API only supports ``timeout_ms = -1``, which means waiting indefinitely until the CRC calculation completes.
|
||||||
|
|
||||||
- **timeout_ms >= 0**: Wait for specified milliseconds
|
|
||||||
- **timeout_ms < 0**: Wait indefinitely
|
|
||||||
|
|
||||||
Uninstalling the Driver
|
Uninstalling the Driver
|
||||||
------------------------
|
------------------------
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
创建驱动程序实例时,您需要配置:
|
创建驱动程序实例时,您需要配置:
|
||||||
|
|
||||||
- **backlog**:可排队等待的最大 CRC 请求数。较高的值使用更多内存,但在突发工作负载下提供更好的吞吐量。
|
- **backlog**:可排队等待的最大 CRC 请求数。较高的值使用更多内存,但在突发工作负载下提供更好的吞吐量。
|
||||||
|
- **intr_priority**:DMA 中断优先级。设置为 ``0`` 时使用默认的低/中优先级;设置为非零值时请求指定的中断优先级。
|
||||||
- **dma_burst_size**:DMA 传输突发大小(字节)。
|
- **dma_burst_size**:DMA 传输突发大小(字节)。
|
||||||
|
|
||||||
驱动程序句柄 ``crc_hdl`` 是一个不透明指针,用于所有后续操作。
|
驱动程序句柄 ``crc_hdl`` 是一个不透明指针,用于所有后续操作。
|
||||||
@@ -161,15 +162,12 @@ CRC 计算完成时会在中断上下文中调用回调函数。回调接收:
|
|||||||
const char *data = "Hello, World!";
|
const char *data = "Hello, World!";
|
||||||
size_t data_len = strlen(data);
|
size_t data_len = strlen(data);
|
||||||
|
|
||||||
// 阻塞 CRC,1000ms 超时
|
// 阻塞 CRC,无限期等待
|
||||||
ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, 1000, &crc_result));
|
ESP_ERROR_CHECK(esp_crc_calc_blocking(crc_hdl, data, data_len, ¶ms, -1, &crc_result));
|
||||||
|
|
||||||
printf("CRC 结果: 0x%08X\n", crc_result);
|
printf("CRC 结果: 0x%08X\n", crc_result);
|
||||||
|
|
||||||
阻塞 API 支持:
|
阻塞 API 仅支持 ``timeout_ms = -1``,表示无限期等待直到 CRC 计算完成。
|
||||||
|
|
||||||
- **timeout_ms >= 0**:等待指定的毫秒数
|
|
||||||
- **timeout_ms < 0**:无限期等待
|
|
||||||
|
|
||||||
卸载驱动程序
|
卸载驱动程序
|
||||||
------------
|
------------
|
||||||
|
|||||||
Reference in New Issue
Block a user