039、DMA与运动控制数据搬运
一、一个让我熬夜三天的bug
去年做六轴机械臂的实时轨迹插补,伺服周期压到500微秒。上位机通过EtherCAT发位置指令,下位机STM32H7负责解析并驱动电机。一切看起来完美——直到我发现在高速运行时,电机偶尔会“抽搐”一下,像被蚊子叮了一口。
示波器抓波形,发现每隔几百个周期,PWM脉冲会突然丢失一个。查中断优先级、查RTOS调度、查Cache一致性,折腾两天无果。最后用逻辑分析仪看SPI总线,发现一个诡异现象:DMA传输完成中断里,我读取的SPI数据寄存器值,竟然是上一次传输的旧数据。
问题出在哪?DMA搬运数据时,CPU和DMA在抢同一个内存地址的访问权。我那个“优雅”的双缓冲设计,因为Cache没做clean和invalidate,导致DMA搬完了数据,CPU读到的却是Cache里的旧副本。这个坑,让我对DMA在运动控制中的使用有了刻骨铭心的认识。
二、DMA不是“自动搬砖工”那么简单
很多初学者把DMA当成“不用CPU干预就能搬数据”的黑盒子。在运动控制场景下,这种理解会出大问题。
运动控制的数据搬运,核心矛盾在于:实时性要求极高(微秒级),数据量不大但频率极高(位置指令、编码器反馈),且数据一致性必须保证(一个错误的脉冲可能导致机械臂撞限位)。
DMA在这里扮演的角色,不是批量搬大文件,而是在精确的时间窗口内,完成确定性的数据交换。比如:
- 从SPI接口读取编码器位置(每次