Files
half-steering-basic-framework/.Doc/CAN发送非阻塞改造隐患.md
2026-08-29 19:55:45 +08:00

3.1 KiB
Raw Blame History

CAN 非阻塞发送改造 · 隐患记录

记录时间:2026-08-29 背景:修复“拔掉 CAN1 后,CAN2 上的 pitch / 摩擦轮 / 拨盘电机明显抖动”的问题。

一、本次改动摘要

文件 改动 目的
bsp/can/bsp_can.c CANTransmit() 由忙等改为非阻塞 避免某一路 CAN 离线时拖慢电机控制任务
bsp/can/bsp_can.c CANAddFilter() 对 can_filter_conf 先 memset 清零 避免未初始化字段成为垃圾匹配 ID
Src/can.c CAN1/CAN2 的 AutoBusOff 改为 ENABLE 断开后重新连接能自动从 bus-off 恢复

二、隐患与风险

1. 双板模式下的 CANCommSend 多帧发送可能丢包(当前为休眠隐患)

  • 相关位置:modules/can_comm/can_comm.c 的 CANCommSend()(约 106、116、121 行)。
  • CANCommSend() 按每 8 字节一帧连续发送。当待发送数据超过 24 字节(即超过 3 帧)时,第 4 帧起会因为 3 个发送邮箱都还在忙碌而被直接丢弃。
  • 原来的忙等版本会等待邮箱空闲后继续发完,非阻塞版本不会。
  • 当前工程为 ONE_BOARD,该路径未参与编译,暂无影响;一旦切换到 CHASSIS_BOARD / GIMBAL_BOARD,此问题会暴露。

2. 丢帧变为静默,失去诊断信息

  • 相关位置:bsp/can/bsp_can.c 的 CANTransmit()(约 107 行)。
  • 原实现邮箱满时会打印 LOGWARNING;现在直接 return 0,不重试、不记录。
  • 未来若总线设备增多或发送频率升高出现真实拥塞,丢帧将不可见,排查难度增加。
  • 对 DJI 电机本身影响较小:500 Hz 控制帧偶尔丢一两帧,电机内部看门狗时间远大于 2 ms,不会触发保护。

3. timeout 参数实际失效

  • CANTransmit() 签名仍保留 float timeout,但函数内部用 (void)timeout 忽略了它。
  • 调用方传入的 1、0.2、0.5 等值已不再生效,存在可读性与预期一致性隐患。

4. AutoBusOff 行为变化 + CubeMX 覆盖风险

  • 相关位置:Src/can.c(约 48、80 行)。
  • 改为 ENABLE 后,持续总线故障(如短路)会导致控制器在 bus-off ↔ 恢复之间反复循环;当前未开启 CAN 错误中断,不会产生中断风暴,但行为不同于 DISABLE 时的锁死状态。
  • Src/can.c 是 CubeMX 生成文件,从 basic_framework.ioc 重新生成工程时会被覆盖回 DISABLE,需要同步修改 .ioc 中的 Automatic Bus-Off Management 选项。

5. 过滤器配置 memset(基本无风险)

  • 相关位置:bsp/can/bsp_can.c 的 CANAddFilter()(约 32 行)。
  • 属于纯修正,无副作用。

三、建议后续动作

  • 若将来启用双板,给 CANCommSend() 的多帧发送增加“短且有界”的等待/重试,避免丢中间帧。
  • 评估是否为 CANTransmit() 增加可选的丢帧统计或低频告警,在“不阻塞任务”与“可诊断”之间取得平衡。
  • 在 basic_framework.ioc 中同步开启两个 CAN 的 Automatic Bus-Off Management,避免重新生成代码时被覆盖。

四、相关文件

  • bsp/can/bsp_can.c
  • modules/can_comm/can_comm.c
  • Src/can.c