底软不是单纯的「驱动开发」,它是整个模组的实时运行基础。下面 6 块按从启动到安全的顺序展开:
上电到应用可运行的完整路径,量产/升级/安全的根。
芯片支持包、实时内核、任务分层,是底软的时间骨架。
PWM/ADC/温度/保护,电机驱动的硬件接口层。
多源采集、采样同步、扭簧观测链,R6 力矩感知源头。
4 类参数 + 权限/版本/回滚,量产可维护的关键。
故障等级 5 档 + 故障上下文 + 现场可维护性。
一体化关节模组上电之后,从硬件复位到应用可运行,要经过一长串动作。任何一个环节出错都会导致模组起不来,所以启动链必须可控、可观察、可恢复。
上电 / 复位
↓
硬件自检 (POR, 复位源识别, 看门狗状态)
↓
Bootloader 入口(双备份选择)
↓
芯片初始化(时钟 · PLL · 电源域 · Flash 等待)
↓
RAM 自检(栈指针校验 · 内存测试)
↓
Flash 校验(CRC · 固件版本识别)
↓
参数区加载(出厂标定 · 现场标定 · 自适应参数)
↓
外设自检(编码器 · 温度 · ADC · 通信口)
↓
安全启动校验(固件签名 · 防回滚版本)
↓
RTOS 启动 · 创建任务 · 进入主循环
| 问题 | 必须考虑 |
|---|---|
| 升级失败 | A/B 双备份自动回退,看门狗保护 |
| 参数与程序版本错配 | 程序升级后参数兼容性矩阵校验 |
| Flash 寿命 | 磨损均衡、坏块管理、写入计数统计 |
| 首次上电(工厂状态) | 检测到空参数区时使用默认参数,写入出厂初始值 |
| 长时间运行断电 | 关键状态写入非易失存储 |
| 出厂状态恢复 | 专门入口,恢复出厂标定参数 |
| 供应链安全 | Bootloader 锁死后只能通过特殊方式解锁 |
关节模组从 POR 到「电机可指令使能」总时长目标 ≤ 350ms。超时意味着客户机器人上电延迟、产线节拍被拖、用户感知「开机慢」。下表是参考预算(按 STM32H7 @ 480MHz + 外部 16MHz 晶振举例,实际值以自家 MCU 实测为准):
| 阶段 | 动作 | 预算时长 | 超时容忍 | 超时处理 |
|---|---|---|---|---|
| ① 硬件复位 | POR / 看门狗复位识别 | 1 ms | — | 复位源记录到寄存器 |
| ② 晶振起振 | HSE 16MHz 起振 + 稳定 | 2-5 ms | ≤ 10 ms | 超时切内部 HSI |
| ③ PLL 锁 | PLL 480MHz 锁定 | 1-2 ms | ≤ 5 ms | 重试 / 切低速 |
| ④ 芯片初始化 | 时钟树 + 电源域 + Flash 等待 | 5-10 ms | ≤ 20 ms | 记录异常,继续 |
| ⑤ RAM 自检 | March C- 覆盖关键 64KB | 20-40 ms | 可选跳过 | 标记坏区,不跑 |
| ⑥ Flash 校验 | CRC32 / SHA-256 头部 | 30-60 ms | ≤ 100 ms | 切换 B 槽 |
| ⑦ 参数加载 | 参数区 CRC + 解码 | 10-20 ms | ≤ 50 ms | 用出厂默认值 |
| ⑧ 外设 + 安全启动 | 编码器 / ADC / 通信 / 签名校验 | 40-80 ms | ≤ 150 ms | 记录 + 进入安全模式 |
| 累计 | POR → 电机可指令使能 | ~109-217 ms | ≤ 350 ms | 超时强制进入 Bootloader |
芯片初始化是启动链里最容易被「写寄存器不写顺序」埋雷的环节。下面是规范化时序:
例:目标 SYSCLK = 480 MHz(H7 / 同档次 MCU)
HSI(16MHz 内置)
↓
HSE 使能 → 等待 HSERDY → HSE = 16MHz 稳定
↓
PLL 配置(M=2, N=120, P=2)→ PLL 输出 = 16 / 2 × 120 / 2 = 480 MHz
↓
Flash 等待周期 = 5 WS(480MHz 对应)
↓
设 AHB 不分频 / APB1 4 分频 / APB2 2 分频
↓
切 SYSCLK → PLL → CPU 跑 480 MHz
关节模组有多路电源,必须按顺序上电,否则可能产生浪涌或闩锁(Latch-up):
| 顺序 | 电源域 | 对象 | 上电延迟 | 原因 |
|---|---|---|---|---|
| ① | VDD / VDDD | 数字核心 | 0 ms | 芯片主电源 |
| ② | VDDA | 模拟(ADC / DAC / 参考) | 5 ms | 先于模拟电路稳定 |
| ③ | VBAT | RTC / 后备寄存器 | 5 ms | 实时时钟 |
| ④ | 编码器电源 | SPI/ABZ 编码器 | 10 ms | 等传感器稳定 |
| ⑤ | 通信 PHY | EtherCAT / CAN PHY | 20 ms | PHY 链路建立 |
| ⑥ | 栅极驱动 VCC | 电机驱动 IC | 30 ms | 驱动 IC 启动 + 故障清除 |
| ⑦ | 母线电容预充 | 电机母线大容量电容 | 50-100 ms(限流) | 避免浪涌 |
| ⑧ | 电机使能 | PWM 输出允许 | — | 必须最后 |
CPU 主频越高,Flash 读取越跟不上,必须配等待周期,否则取指错误:
| CPU 主频 | Flash WS(典型值) | 备注 |
|---|---|---|
| ≤ 30 MHz | 0 WS | 零等待 |
| 30-60 MHz | 1 WS | 单等待 |
| 60-90 MHz | 2 WS | — |
| 90-120 MHz | 3 WS | — |
| 120-150 MHz | 4 WS | — |
| 150-180 MHz | 5 WS | — |
| 480 MHz(H7 举例) | 5 WS | 必须查手册,不同工艺不一样 |
关节模组上每台设备都有远程升级需求,一次升级失败 = 整机报废。所以必须双备份:
0x0800_0000 ┌──────────────────┐
│ Bootloader │ ~32 KB(不可升级 / 可通过特殊方式解锁)
0x0800_8000 ├──────────────────┤
│ Slot A(主用) │ ~200 KB(应用固件 v1.x)
0x0803_A000 ├──────────────────┤
│ Slot B(备份) │ ~200 KB(应用固件 v0.x 或 待升级 v2.x)
0x0806_C000 ├──────────────────┤
│ 参数区 + 日志区 │ ~64 KB(出厂标定 + 运行参数 + 故障日志)
0x0807_C000 ├──────────────────┤
│ 密钥 / 公钥区 │ ~16 KB(一次性烧录 / 锁定)
0x0808_0000 └──────────────────┘
客户上位机发 OTA 指令 → 关节进入 Bootloader
↓
Bootloader 接收固件包(分包校验 · SHA-256)
↓
写入「空闲槽」(如 Slot B)→ 写入完成后 CRC 校验
↓
写入「槽位标志」:Slot B 健康 + 待切换 + 启动计数 = 0
↓
重启 → Bootloader 读标志 → 启动 Slot B
↓
Slot B 应用在 5 秒内上报「健康心跳」给 Bootloader
↓
┌──────────────┬─────────────────────────────┐
│ 健康心跳到达 │ → Bootloader 标记 Slot B 健康,清标志 │
│ 健康心跳超时 │ → Bootloader 重启,回退 Slot A │
└──────────────┴─────────────────────────────┘
Bootloader 上电时按以下优先级决定跑哪个槽:
| 设计点 | 必须做什么 | 翻车后果 |
|---|---|---|
| 健康心跳协议 | 新槽启动 5s 内必须上报心跳 | 超时回退 → 用户感觉重启了一次 |
| 启动计数 | 单槽连续失败 3 次 → 强制标记为坏 | 避免反复在坏固件上挣扎 |
| 反回滚版本号 | 新槽版本号必须 ≥ 旧槽 | 防止降级到已知漏洞版本 |
| 参数版本兼容 | 固件头含「参数兼容矩阵」 | 新固件读旧参数可能崩 |
| 升级断电保护 | 每写一包就更新进度标志 | 断电后能续传,不全擦 |
| 双重签名 | 主固件 + 升级包都用私钥签 | 防止中间人篡改 |
关节模组装到客户设备里之后,任何攻击者拿到串口就能刷恶意固件 = 安全灾难。所以必须安全启动:
固件包 = [Header | Code | Signature]
↓
Bootloader 读取 Header → 取得 code_length + version + sig_offset
↓
Bootloader 计算 Code 段 SHA-256 哈希 H
↓
Bootloader 用 OTP 烧入的公钥 验签:verify(H, Signature, PubKey)
↓
┌──────────────┬────────────────────────────┐
│ 验签通过 │ → 检查 version ≥ current → 启动 │
│ 验签失败 │ → 不启动,记录异常,可回退旧版本 │
└──────────────┴────────────────────────────┘
对于客户定制场景,客户可以用自己的子公钥重新签名玉洁的固件:
启动链必须对所有异常有预案,下面是关节模组实战中遇到过的全部异常路径:
| 异常 | 触发条件 | 检测时机 | 恢复策略 | 用户感知 |
|---|---|---|---|---|
| 外部晶振失振 | HSE 不起振 / 受干扰 | PLL 配置前 | 切内部 HSI,低速运行 | 功能受限,不报警 |
| PLL 失锁 | PLL 配置后 LOCK=0 | PLL 配置后 5ms | 复位重试 1 次 | 延迟 ~50ms |
| RAM 坏块 | March C- 失败 | RAM 自检时 | 标记坏块,申请避让 | 日志记录 |
| Flash CRC 失败 | Slot A CRC32 不通过 | Flash 校验时 | 切 Slot B | 无感知 |
| 参数 CRC 失败 | 参数区校验不通过 | 参数加载时 | 用出厂默认值 | 需重新标定 |
| 编码器无应答 | SPI 超时 / ABZ 无脉冲 | 外设自检时 | 禁用电机使能,报编码器故障 | 关节不能动,需维修 |
| 通信口环回失败 | CAN / EtherCAT 自环失败 | 外设自检时 | 降级为离线模式 | 不能远程控制 |
| 电机绕组断路 | U/V/W 三相任意一相电阻无穷大 | 电机使能前 | 禁止使能,报故障 | 关节锁死 |
| OTA 升级中断 | 通信断开 / 突然断电 | 下次启动 | 续传 / 回退 | 无感知 |
| 签名验证失败 | 固件被篡改 | Bootloader 启动时 | 不启动,等远程救援 | 关节锁死,需返厂 |
| 双槽都坏 | Slot A 和 B 都校验失败 | 启动槽位选择时 | 进入安全模式 | 仅通信,需救援 |
| 温度过高 | 驱动器温度 > 110°C | 运行中持续监测 | 降额 → 关断 | 性能下降或锁死 |
| 看门狗复位 | 主循环卡死 / 中断风暴 | 硬件自动 | 复位 + 记录复位源 | 重启一次 |
| 看门狗 Boot 卡 | Bootloader 自身喂狗失败 | Bootloader 内看门狗 | 硬复位 → 跳过 Boot → 直跑 Slot A | 升级失败,但旧版本能跑 |
BSP(Board Support Package)是芯片支持包,把 MCU 寄存器级别的细节封装成可调用接口。它是上层实时控制算法和硬件之间的"翻译官"。
一体化关节模组的控制任务有强实时要求(电流环 10-20 kHz),单纯裸跑 main + while 循环很难管理多周期任务。RTOS 提供:
常见选择:
| RTOS | 特点 | 典型场景 |
|---|---|---|
| FreeRTOS | 开源、轻量、生态成熟 | 单关节 MCU |
| RT-Thread | 国产、生态丰富、内置组件 | 国产化项目 |
| Zephyr | Linux 基金会、新一代 | 需要长期维护的项目 |
| 裸跑(Super-loop) | 无 RTOS,确定性最好 | 单任务、极致实时 |
底软必须把不同周期的任务分清楚,否则上层一个复杂算法就会打断电流环。
| 周期 | 任务 | 实现方式 | 优先级 |
|---|---|---|---|
| 10-50 μs | PWM 更新 · ADC 采样 | 硬件定时器触发 + DMA | 最高 |
| 50-100 μs | FOC 电流环(10-20 kHz) | DMA 完成中断 | 高 |
| 0.5-1 ms | 速度环 · 位置环 · 力矩估计(1-2 kHz) | 高优先级任务 | 中高 |
| 1-5 ms | 状态机 · 保护 · 温控 | 中优先级任务 | 中 |
| 10-100 ms | 诊断 · 日志 · 参数管理 | 低优先级任务 | 低 |
| 100 ms 以上 | OTA · 统计 · 后台维护 | 后台任务 | 最低 |
一体化关节模组的功率级由以下几个部分构成:
上层控制算法不应该直接操作寄存器,而是通过底软抽象出来的接口。这是最容易混乱的地方,必须把接口设计清楚。
// 上层调用(伪代码)
// PWM 控制
set_pwm(phase_u, phase_v, phase_w);
set_duty(duty_u, duty_v, duty_w);
// 采样读取
read_phase_current(); // 返回 [Iu, Iv, Iw]
read_bus_voltage();
read_motor_temperature();
read_driver_temperature();
// 功率级控制
enable_power_stage(); // 使能栅极驱动
disable_power_stage(); // 关闭栅极驱动(高阻态)
apply_brake(); // 主动制动
release_brake(); // 释放抱闸
// 保护状态
get_fault_status(); // 故障位
clear_fault(); // 清除可恢复故障
一体化关节模组的传感器比普通电机伺服多,因为要做R6 双编码器 + 力矩感知,需要完整观测链:
| 传感器 | 位置 | 用途 |
|---|---|---|
| 电机侧编码器 | 电机轴端(≥ 19 bit) | 电机转子角度 · FOC 解算源头 |
| 输出侧编码器 | 减速器输出端 | 关节实际位置 · 扭簧解算 |
| 扭簧两端角度 | 扭簧前后轴承位置 | 扭簧变形量 → 力矩 |
| 母线电流 | 母线侧 | 总功率监控 |
| 三相电流 | U/V/W 相 | FOC 电流环 |
| 电机温度 | 绕组 / 铁芯 | 过温保护 · 温度补偿 |
| 壳体温度 | 减速器外壳 | 过温保护 |
| 减速器温度 | 润滑相关 | 润滑状态监测 |
| 抱闸状态 | 抱闸机构 | 抱闸可靠性监测 |
| 振动传感器(可选) | 壳体 / 减速器 | 异常噪声 / 磨损检测 |
多源数据的时间对齐是力矩感知的前提。如果各传感器在不同时间采样,扭簧解算会有相位误差。
这是 R6 力矩感知能不能 work 的物理基础。底软要把这条链的数据质量做好。
电机角度 θm(电机侧编码器)
↓
减速器传动比 N
↓
理论输出角度 θo_theory = θm / N
↓
实际输出角度 θo(输出侧编码器)
↓
扭簧变形量 Δθ = θo_theory - θo
↓
扭簧特性表 f(Δθ, temperature, speed)
↓
输出侧力矩估计 τ = f(Δθ, T, ω)
↓
DOB / 自适应 K / 阻抗控制
高安全等级应用需要考虑冗余:
一体化关节模组有 4 类参数,每类的访问权限、修改流程、回滚要求都不同。混在一起管理会出现:
| 类别 | 典型参数 | 修改权限 | 存放位置 |
|---|---|---|---|
| 电机参数 | 电阻 · 电感 · 反电动势常数 · 极对数 · 转矩常数 · 最大电流 | 工厂 · 高级用户 | 出厂标定区 |
| 减速器参数 | 减速比 · 回差 · 效率 · 摩擦模型 · 温度相关特性 | 工厂 | 出厂标定区 |
| 传感器参数 | 零偏 · 增益 · 方向 · 安装角 · 温漂补偿 · 非线性修正 | 工厂 · 现场标定 | 出厂 + 现场标定区 |
| 安全参数 | 最大位置 · 最大速度 · 最大力矩 · 最大温度 · 过载时间 · 降额曲线 | 仅认证工程师 | 安全区(独立校验) |
除了按"类别"分,还需要按生命周期分:
工厂标定工位
↓
电机参数辨识(电阻 · 电感 · 反电动势)
↓
编码器零点标定(机械角度 ↔ 编码器值)
↓
扭簧特性表生成(Δθ → 力矩)
↓
减速器参数测量(减速比 · 回差 · 摩擦)
↓
温度特性测试(多温度点参数)
↓
参数写入 + CRC + 签名
↓
现场标定(机械安装 · 客户工艺)
↓
交付使用
工程样机阶段,日志可以多;量产阶段,日志必须可控。需要把故障按严重程度分级:
| 等级 | 处理 | 举例 |
|---|---|---|
| Warning | 继续运行,记录 + 上报 | 温度接近上限 · 编码器信号质量下降 |
| Derating | 限制电流/速度/力矩 | 温度达到降额区间 · 母线电压低 |
| Recoverable Fault | 进入安全状态,条件满足后恢复 | 通信超时 · 编码器丢帧 |
| Latched Fault | 必须人工确认或重新上电 | 过流保护 · 编码器断线 · 抱闸异常 |
| Critical Fault | 立即关断功率级 + 抱闸 | 硬件短路 · 驱动器损坏 · 通信完全中断 |
光记录「发生了故障」是不够的,必须记录故障时的状态,才能事后复盘。
检测异常
↓
确认是否真实故障(去抖 · 多源校验)
↓
进入降额或安全状态
↓
停止输出 / 限制输出 / 抱闸
↓
记录故障上下文(波形 · 时间戳 · 上下文)
↓
上报上位机(实时告警)
↓
等待自动恢复 或 人工确认
不能把安全停机和正常停止混为一谈:
| 类型 | 目标 | 允许代价 |
|---|---|---|
| 正常停止 | 减速到 0,动作平滑 | 不能损失轨迹精度 |
| 急停 | 保证人和设备安全 | 可以牺牲运动平滑性 |
| 机械卡死 | 保护电机和机械 | 不能继续加大电流硬顶 |
| 通信断开 | 进入安全姿态 | 不能简单保持最后一个力矩指令无限运行 |
不只是记录故障,还要预测故障。这部分交给上层算法应用(参见 2-10)。
底软 6 块全部展开完了。今天聊的范围:
下一步建议:2-9 中层控制详细拆解已 lock(7 节:三环 PID / FOC / 摩擦 / 力矩 / 阻抗 / 状态机 / 多关节)。如果要继续深挖底层,可以挑某一块再展开(比如 R6 双编码器观测链的具体实现)。