在第

RIF
的“所有权”。
现在,我们要实现一个工业级的串口驱动。
为什么不用简单的HAL_UART_Receive_IT?因为在多核通讯或读取
IMU
数据时,数据长度往往是不固定的。
频繁的字节中断会拖累
M33
传输又无法感知数据何时结束。
本章实战方案:利用
STM32MP257
Line(空闲总线)检测,实现一个“零拷贝、非阻塞、变长接收”的串口框架。
/>4.1
Idle?
GPDMA:MP257
DMA
不同,它是基于通道索引和链接列表的,效率更高。
Idle
Line:当串口线路上超过一个字节的时间没有新数据时,硬件会自动触发
IDLE
中断。
组合拳:DMA
负责默默地把数据搬运到
M33,这阵子数据传完了,请处理!”
/>4.2
章所述),然后初始化。
UART_HandleTypeDef
huart7;
/>__HAL_RCC_GPDMA1_CLK_ENABLE();
//
GPDMA1
/>hdma_uart7_rx.Init.SrcDataWidth
=
/>hdma_uart7_rx.Init.DestDataWidth
=
DMA_LOW_PRIORITY_LOW_WEIGHT;
=
后重置
HAL_DMA_Init(&hdma_uart7_rx);
hdmarx,
/>__HAL_UART_ENABLE_IT(&huart7,
UART_IT_IDLE);
接收(预设一个足够大的缓冲区)
/>HAL_UART_Receive_DMA(&huart7,
rx_buffer,
的逻辑实现
这是整章的灵魂。
在stm32mp2xx_it.c中,我们需要处理UART7_IRQHandler。
#define
RX_BUF_SIZE
rx_buffer[RX_BUF_SIZE];
void
{
(__HAL_UART_GET_FLAG(&huart7,
UART_FLAG_IDLE))
/>__HAL_UART_CLEAR_IDLEFLAG(&huart7);
必须手动清除
//
__HAL_DMA_GET_COUNTER(&hdma_uart7_rx);
/>uint32_t
/>HAL_UART_DMAStop(&huart7);
/>
例如:Process_Data(rx_buffer,
length);
此处打印收到的字节数(实战中建议使用无锁队列转发)
%ld
/>HAL_UART_Receive_DMA(&huart7,
rx_buffer,
/>HAL_UART_IRQHandler(&huart7);
/>}4.5
性能优化:如何做到“不丢包”?
在工业实战中,如果在处理Process_Data时串口又有新数据进来,DMA
还没开启,就会丢包。
进阶技巧:双缓冲区
(Double
Buffering)
定义两个缓冲区
Buf_A和Buf_B。DMA
指向
Buf_A。IDLE
中断触发后,立即将
指向
Buf_B。M33
这样两个核/两个任务之间就形成了一个简单的乒乓切换,极大地提高了吞吐量。
/>4.6
部署与验证
接线:连接开发板的调试
虚拟串口)。
发送测试:使用串口助手(如
Mobaxterm)发送一串很长的、长度随机的字符串。
结果:观察
M33
串口输出,它应该能精准报出每一帧数据的长度,并原样打印或处理。
/>4.7
Tips)
陷阱
1:DMA
传输过快。
如果波特率极高且数据连续,IDLE
半完成中断
(HT)来处理。
陷阱
2:RIF
里的旧数据。
解决:在处理数据前调用
SCB_InvalidateDCache_by_Addr(rx_buffer,RX_BUF_SIZE);。
/>
总结:我们现在拥有了一个高效的串口“进出口”。
M33
Linux
侧应用)交换数据。


