STM32 ↔ 上位机 UART 参数协议移植
目标
建立可验证、可维护、与具体设备业务解耦的通信模块:
应用状态与参数宿主
↓
参数注册表 + 命令执行器
↓
纯字节线协议(帧、CRC、流解析)
↓
UART/USB/TCP 等传输适配器
主机库只处理 bytes,不依赖 rospy、rclpy 或 pyserial,也不替用户决定 topic、service、parameter 名称。
适用协议轮廓
0xAA:由接收方向配置长度的固定数据帧,可承载状态或高频控制数据。0xA5:[HEAD][CMD][LEN][DATA][CRC16_LE]变长命令帧。CMD.bit7=1:回执方向;回执逐字节回显原命令以匹配事务。- 参数值统一占 4 B,但按
U8/I8/U16/I32/F32各自编码。 - 参数表支持只读/读写、clamp/reject、宿主就绪和 must-idle 策略。
具体设备的状态字段、数据帧长度、参数 ID 与单位必须由目标工程自己定义。本技能不带任何产品参数清单。
开始前确认
- 读取目标 MCU、工具链、RTOS/裸机模式、UART、DMA、IRQ 优先级和代码生成边界。
- 决定是保持既有线上兼容,还是只复用框架。若改变固定帧长度、字段偏移、参数 ID、类型或 CRC,明确标记不兼容。
- 明确参数是否掉电保存;本模板默认只改 RAM,不自动加入 Flash/EEPROM。
- 不知道引脚、DMA request/stream 或 IRQ 数值时标记待确认,不从相似型号猜测。
详见 协议骨架、移植指南 和 并发安全。
工作流
1. 盘点现有协议
记录:
- 物理接口、波特率、8N1/校验方式;
- 每个方向
0xAA的固定长度; 0xA5最大 payload;- CRC 参数和端序;
- 参数数量、ID、wire type 和单一事实来源;
- ISR、协议任务、应用任务、TX DMA 缓冲的所有权;
- 是否存在 CAN/RS485 等慢速下游代理。
代码和静态断言优先于手写文档。参数总数和分片数必须动态计算,不在多处写死。
2. 复用纯协议核心
使用 assets/mcu/:
uart_param_protocol.*:CRC、LE 编解码、流解析、命令与回执组帧;param_registry.*:类型安全参数值、范围策略和 callback+context 宿主注入;command_executor.*:任务上下文的参数命令执行和应用命令转发。
纯协议层不得 include HAL、RTOS、业务类或全局 UART handle。
3. 接入平台
使用 assets/integration/ 作为接线参考:
- RX DMA/IDLE ISR 只复制字节、入队、重挂接接收;
- 持久流解析器保留跨回调残帧,支持噪声、拆包和粘包;
- ISR 不执行 setter、慢速总线往返、日志或 TX DMA;
- 一个任务/主循环点独占参数执行和协议 TX;
- TX DMA 完成前发送缓冲不可修改;
- 按数值核对 FromISR API 与 FreeRTOS IRQ 优先级边界。
裸机可把 FreeRTOS 队列替换为固定容量主循环队列,但保持相同所有权模型。
4. 定义目标设备契约
先写状态/控制字段表:偏移、类型、单位、来源、无效值和刷新周期,再实现固定数据帧。参数定义保持单一事实来源,至少包含 ID、机器名、wire type、权限、flags、范围、单位和 callback。
getter 返回真实当前值;写回执携带 setter 执行后重新读取的实际值。慢速下游单读可以实时,批量读应使用缓存或异步预取。
5. 接入主机
使用 assets/host/uart_param_protocol.py:
StreamParser接收任意大小 chunk;- 参数 builders 负责读、写、读全部;
encode_value/decode_value按每个参数自己的类型处理;parse_reply校验回显并返回状态和实际值;- 固定
0xAA数据帧由应用按自己的字段契约解码。
主机应用负责串口 I/O、事务串行化、超时和重试。不要把所有 4 B 参数值都按 float32 解码。
6. 验证
先运行:
python scripts/validate_skill.py
移植后还要:
- 编译 MCU Debug/Release,检查告警、Flash/RAM 和任务栈;
- 测 CRC 标准向量、五种 wire type、短帧、坏 CRC、噪声、粘包、跨 chunk、队列满和 TX busy;
- 真实串口测试固定数据帧、单读、写入、分片读全部、超时和断线恢复;
- 涉及运动设备时固定执行机构、准备独立断电手段,从零目标和低限幅开始;
- 明确记录未完成的硬件验证。编译通过不等于 DMA 时序或控制安全通过。
脚手架
预览:
python scripts/scaffold_protocol.py --target <目标目录>
确认后写入:
python scripts/scaffold_protocol.py --target <目标目录> --write
默认拒绝覆盖;只有查看目标文件并明确需要替换时才使用 --force。脚手架不会猜 UART、DMA、IRQ、状态字段或参数宿主。
交付要求
说明:
- 兼容移植还是框架复用;
- 协议核心、平台适配、参数定义和主机文件的变化;
- 固定帧、命令或参数契约是否有破坏性变化;
- ISR/任务/DMA 缓冲所有权和超时策略;
- 已运行的离线测试、构建和板级验证;
- 尚未验证的串口时序、丢包恢复、设备安全或持久化行为。
资源
- 协议骨架
- 移植指南
- 并发安全
assets/mcu/— C++11 通用核心assets/integration/— HAL+FreeRTOS 与参数表接入模板assets/host/uart_param_protocol.py— 无传输/ROS 依赖的主机编解码库scripts/scaffold_protocol.py— 不覆盖式脚手架scripts/validate_skill.py— 离线自检