STM32 DMA 与 CMSIS V2 队列一起使用时不会重新启动

STM32 DMA is not restarting when used with CMSIS V2 Queue

提问人:fossil 提问时间:11/12/2023 最后编辑:fossil 更新时间:11/12/2023 访问量:47

问:

我正在开发基于 FreeRTOS 的 STM32 固件。我正在使用 Nucleo-G491RE 板。

我正在使用 CMSIS V2 和队列来处理 UART 上接收的数据。UART 在收到数据时正确触发,并将数据发送到队列。队列处理程序任务正在接收数据并处理数据。

DMA 在处理第一个中断后未重新启动。

下面是处理 UART 中断的代码。

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(huart->Instance == UART5)
    {
        char buffer[3]; // Buffer to hold the formatted hex byte (2 characters) plus null terminator

        for (uint8_t i = 0; i < Size; i++) {
            sprintf(buffer, "%02X", RemoteRxBuf[i]); // Format the hex byte
            HAL_UART_Transmit(&hlpuart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
            HAL_UART_Transmit(&hlpuart1, (uint8_t*)" ", 1, HAL_MAX_DELAY); // Add space between hex bytes
        }

        HAL_UART_Transmit(&hlpuart1, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY); // Newline at the end

        remote_cmd_t *remote_cmd = (remote_cmd_t *)malloc(sizeof(remote_cmd_t));
        // remote_cmd = pvPortMalloc(sizeof(remote_cmd_t));

        remote_cmd->Count = 1000;
        remote_cmd->Size = 5;
        memcpy(remote_cmd->Payload, RemoteRxBuf, 5);

        // Notify the task that new data is available
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;

        // Send the received data to the remoteQueueHandle
        xQueueSendFromISR(remoteQueueHandle, &remote_cmd, &xHigherPriorityTaskWoken);

        // If sending to the queue caused a task switch, request a context switch
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

        HAL_UARTEx_ReceiveToIdle_DMA(&huart5, RemoteRxBuf, RemoteRxBuf_SIZE);
        __HAL_DMA_DISABLE_IT(&hdma_uart5_rx, DMA_IT_HT);
    }
}

以下是处理队列的任务代码

void StartRemoteCmdTask(void *argument)
{
    /* USER CODE BEGIN 5 */
    char *buffer;
    remote_cmd_t *receivedData;
    /* Infinite loop */
    while(1)
    {
        if(xQueueReceive(remoteQueueHandle, &receivedData, portMAX_DELAY) == pdPASS)
        {
            char *msg = "Received data from ISR\r\r";
            HAL_UART_Transmit(&hlpuart1, (uint8_t *)msg, strlen(msg), 1000);
            buffer = pvPortMalloc(3 * sizeof(char));
            for (uint8_t i = 0; i < receivedData->Size; i++)
            {
                sprintf(buffer, "%02X", receivedData->Payload[i]);
                HAL_UART_Transmit(&hlpuart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
                HAL_UART_Transmit(&hlpuart1, (uint8_t*)" ", 1, HAL_MAX_DELAY);
            }
            HAL_UART_Transmit(&hlpuart1, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY);
            vPortFree(buffer);
        }

        vPortFree(receivedData);

        vTaskDelay(100);
    }
    /* USER CODE END 5 */
}
STM32 FreeRTOS CMSIS

评论

0赞 HS2 11/12/2023
不能在 ISR 中使用 malloc 或 pvPortMalloc。您需要自己的 ISR 安全分配器。最好使用“按值”的队列。同样在任务代码中,我不会从堆中分配一个 3 字节的缓冲区。
1赞 0___________ 11/12/2023
您可以在 ISR 中执行许多操作,例如阻止传输等。在这个非常短的代码中,你有很多问题。也不要使用(即使你有 ISR 安全版本)样式分配。改为实现类似内存池的东西。malloc
0赞 fossil 11/13/2023
根据 @HS2 和 @0___ 的建议,我重构了代码,为队列使用预分配的缓冲区。ISR 中不再有 malloc。此外,我正在探索重构任务中的 3 字节缓冲区。pvPortMalloc

答: 暂无答案