uart_dma — приём UART через DMA
Принимает символы с USART1 (тот же порт, куда идёт лог) через DMA в кольцевой буфер, собирает
строки и выполняет команды: help, led on, led off, uptime. Любая другая строка
печатается обратно с длиной.
Включить
Заголовок раздела «Включить»cmake --preset Release -DH723_RECIPES="uart_dma"Терминал на USART1 115200 8N1: PB15 — вход платы (RX), PB14 — выход (TX). Через отладчик «Лобзик» это его виртуальный COM-порт; можно и любой USB-UART 3,3 В на J2 (13 — PB15, 14 — PB14).
Вывод на плате
Заголовок раздела «Вывод на плате»Команды отправлены с ПК в терминал USART1:
uart_dma: started, type 'help' in USART1 terminaluart_dma: commands: help, led on, led off, uptimeuart_dma: led onuart_dma: uptime 15503 msuart_dma: rx 'hello board 123' (15 bytes)При переполнении строка из 300 символов принимается и обрезается до 127 (длина буфера строки), восемь строк подряд по 42 байта принимаются целыми, хотя кольцевой буфер DMA (256 байт) за это время оборачивается несколько раз.
Как это работает
Заголовок раздела «Как это работает»- DMA в кольцевом режиме. DMA1 Stream3 по запросу
USART1_RXпишет каждый принятый байт в буфер 256 байт и, дойдя до конца, начинает сначала. Процессор в приёме байтов не участвует. - Когда разбирать буфер.
HAL_UARTEx_ReceiveToIdle_DMAвызывает колбэк в трёх случаях: буфер заполнен наполовину, заполнен целиком и линия замолчала (событие IDLE — пауза в один символ). Последнее важно: команда из 6 символов не заполнит буфер, но придёт сразу после паузы. - Новые данные — от прошлой позиции до текущей. Колбэк получает позицию DMA в буфере; байты
между прошлой и новой позицией (с переходом через край) уходят в
StreamBufferFreeRTOS. - Прерывание короткое. В колбэке только копирование в
StreamBuffer; строки собирает и команды выполняет обычная задачаuartRx, которой можно печатать и ждать. - Память для DMA. Буфер — в RAM_D1 (
pvPortMalloc), выровнен по 32 байта (строка кэша); RAM_D1 кэшируется, поэтому перед чтением —SCB_InvalidateDCache_by_Addr. - Шум на линии. Без подтяжки неподключённый вход ловит помехи и ошибки кадра; рецепт включает
подтяжку PB15 к 3,3 В. После ошибки UART приём перезапускается в
rxError. - Передача не тронута. Лог печатает через тот же
huart1(DMA1 Stream2); приём и передача у HAL независимы.
Переделать под себя
Заголовок раздела «Переделать под себя»- Свои команды — в
handleLine. - Свой протокол (бинарный, Modbus, NMEA) — байты берутся из
uartDmaRead()и разбираются своим кодом, безuartTask. - Другой UART: свободны USART2 (PA2/PA3), USART3 (PB10/PB11), UART4 (PA0/PA1) и другие — их
нужно сначала включить (CubeMX или вручную: такты, выводы,
HAL_UART_Init), затем поменятьhuart,DMA_REQUEST_...и, при занятом Stream3, номер потока DMA.
Исходники рецепта: recipes/uart_dma
