0 · 6 块内容地图

底软不是单纯的「驱动开发」,它是整个模组的实时运行基础。下面 6 块按从启动到安全的顺序展开:

1Boot 与启动链

上电到应用可运行的完整路径,量产/升级/安全的根。

2BSP 与 RTOS

芯片支持包、实时内核、任务分层,是底软的时间骨架。

3电机与功率级

PWM/ADC/温度/保护,电机驱动的硬件接口层。

4编码器与传感器

多源采集、采样同步、扭簧观测链,R6 力矩感知源头。

5参数与标定管理

4 类参数 + 权限/版本/回滚,量产可维护的关键。

6诊断与故障日志

故障等级 5 档 + 故障上下文 + 现场可维护性。

为什么这个顺序:① 启动 → ② 操作系统 → ③ 硬件驱动 → ④ 传感器 → ⑤ 参数 → ⑥ 故障,正好对应一颗 MCU 上电、运行、出故障、恢复的完整生命周期。
为什么必须先有底软再聊控制:电流环跑 10kHz,需要底层提供:稳定的中断 + 准确的 PWM + 同步的 ADC + 可靠的看门狗 + 失败可控的故障关断。少一块,控制都调不稳。

1 · 1Boot 与启动链

1.1 启动链全流程

一体化关节模组上电之后,从硬件复位到应用可运行,要经过一长串动作。任何一个环节出错都会导致模组起不来,所以启动链必须可控、可观察、可恢复。

上电 / 复位
  ↓
硬件自检 (POR, 复位源识别, 看门狗状态)
  ↓
Bootloader 入口(双备份选择)
  ↓
芯片初始化(时钟 · PLL · 电源域 · Flash 等待)
  ↓
RAM 自检(栈指针校验 · 内存测试)
  ↓
Flash 校验(CRC · 固件版本识别)
  ↓
参数区加载(出厂标定 · 现场标定 · 自适应参数)
  ↓
外设自检(编码器 · 温度 · ADC · 通信口)
  ↓
安全启动校验(固件签名 · 防回滚版本)
  ↓
RTOS 启动 · 创建任务 · 进入主循环
    

1.2 关键子项拆解

Bootloader

芯片初始化

RAM 与栈自检

Flash 与固件校验

参数区加载

外设自检

安全启动(Secure Boot)

1.3 工程化要点

问题必须考虑
升级失败A/B 双备份自动回退,看门狗保护
参数与程序版本错配程序升级后参数兼容性矩阵校验
Flash 寿命磨损均衡、坏块管理、写入计数统计
首次上电(工厂状态)检测到空参数区时使用默认参数,写入出厂初始值
长时间运行断电关键状态写入非易失存储
出厂状态恢复专门入口,恢复出厂标定参数
供应链安全Bootloader 锁死后只能通过特殊方式解锁

1.4 启动时间预算(8 个阶段实测)

关节模组从 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- 覆盖关键 64KB20-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
为什么时间预算重要:① 产线节拍(每多 100ms 一年损失 N 万元)② 用户体验(开机快慢)③ OTA 失败回滚不能卡(卡 5s 用户会拔电)④ 车规 / 医疗启动有时延硬指标(≤ 500ms)。

1.5 芯片初始化时序详解(PLL + 电源域 + Flash 等待)

芯片初始化是启动链里最容易被「写寄存器不写顺序」埋雷的环节。下面是规范化时序:

1.5.1 时钟源选择与切换

  1. 上电默认:内部 HSI(高速内部 RC)≈ 16MHz,先用这个让 CPU 跑起来
  2. 外部晶振 HSE:配置并使能 16MHz 晶振,等待就绪标志位置位(HSERDY=1)
  3. PLL 配置:PLL 输入 = HSE / 分频 M;PLL VCO = 输入 × 倍频 N;PLL 输出 = VCO / 分频 P
  4. 系统时钟切换:先设分频(AHB / APB1 / APB2),再切 SYSCLK 到 PLL 输出
  5. 关掉 HSI:可选省电
例:目标 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
    

1.5.2 电源域使能顺序(关节模组专用)

关节模组有多路电源,必须按顺序上电,否则可能产生浪涌或闩锁(Latch-up):

顺序电源域对象上电延迟原因
①VDD / VDDD数字核心0 ms芯片主电源
②VDDA模拟(ADC / DAC / 参考)5 ms先于模拟电路稳定
③VBATRTC / 后备寄存器5 ms实时时钟
④编码器电源SPI/ABZ 编码器10 ms等传感器稳定
⑤通信 PHYEtherCAT / CAN PHY20 msPHY 链路建立
⑥栅极驱动 VCC电机驱动 IC30 ms驱动 IC 启动 + 故障清除
⑦母线电容预充电机母线大容量电容50-100 ms(限流)避免浪涌
⑧电机使能PWM 输出允许—必须最后

1.5.3 Flash 等待周期(WS)配置

CPU 主频越高,Flash 读取越跟不上,必须配等待周期,否则取指错误:

CPU 主频Flash WS(典型值)备注
≤ 30 MHz0 WS零等待
30-60 MHz1 WS单等待
60-90 MHz2 WS—
90-120 MHz3 WS—
120-150 MHz4 WS—
150-180 MHz5 WS—
480 MHz(H7 举例)5 WS必须查手册,不同工艺不一样
关键错误示范:主频跳到 480MHz 但 WS 仍是 0 → 启动后第一条指令就取错 → HardFault → 看门狗复位 → 永远起不来。芯片初始化不是「调通就行」,是按手册每个 bit 都不能漏。

1.6 Bootloader 双备份(A/B 槽位)机制详解

关节模组上每台设备都有远程升级需求,一次升级失败 = 整机报废。所以必须双备份:

1.6.1 Flash 槽位布局(典型 512KB MCU)

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  └──────────────────┘
    

1.6.2 升级流程(升级失败自动回退)

客户上位机发 OTA 指令 → 关节进入 Bootloader
   ↓
Bootloader 接收固件包(分包校验 · SHA-256)
   ↓
写入「空闲槽」(如 Slot B)→ 写入完成后 CRC 校验
   ↓
写入「槽位标志」:Slot B 健康 + 待切换 + 启动计数 = 0
   ↓
重启 → Bootloader 读标志 → 启动 Slot B
   ↓
Slot B 应用在 5 秒内上报「健康心跳」给 Bootloader
   ↓
┌──────────────┬─────────────────────────────┐
│ 健康心跳到达 │ → Bootloader 标记 Slot B 健康,清标志 │
│ 健康心跳超时 │ → Bootloader 重启,回退 Slot A     │
└──────────────┴─────────────────────────────┘
    

1.6.3 启动槽位选择算法

Bootloader 上电时按以下优先级决定跑哪个槽:

  1. OTA 触发:收到显式升级指令 → 强制进入 Bootloader 等待区
  2. 强制回退标志:上一轮 Slot B 上报超时 → 直接回退 Slot A
  3. 主用槽健康:Slot A CRC 通过 + 启动计数未超阈值 → 跑 Slot A
  4. 主用槽异常:Slot A 校验失败 → 自动跑 Slot B
  5. 双槽都坏:进入「安全模式」→ 不出 PWM · 只保留通信 · 等远程救援

1.6.4 关键设计要点

设计点必须做什么翻车后果
健康心跳协议新槽启动 5s 内必须上报心跳超时回退 → 用户感觉重启了一次
启动计数单槽连续失败 3 次 → 强制标记为坏避免反复在坏固件上挣扎
反回滚版本号新槽版本号必须 ≥ 旧槽防止降级到已知漏洞版本
参数版本兼容固件头含「参数兼容矩阵」新固件读旧参数可能崩
升级断电保护每写一包就更新进度标志断电后能续传,不全擦
双重签名主固件 + 升级包都用私钥签防止中间人篡改

1.7 安全启动(Secure Boot)与签名验证链

关节模组装到客户设备里之后,任何攻击者拿到串口就能刷恶意固件 = 安全灾难。所以必须安全启动:

1.7.1 信任根(Root of Trust)

1.7.2 验证流程(Ed25519 / ECDSA 推荐)

固件包 = [Header | Code | Signature]
   ↓
Bootloader 读取 Header → 取得 code_length + version + sig_offset
   ↓
Bootloader 计算 Code 段 SHA-256 哈希 H
   ↓
Bootloader 用 OTP 烧入的公钥 验签:verify(H, Signature, PubKey)
   ↓
┌──────────────┬────────────────────────────┐
│ 验签通过     │ → 检查 version ≥ current → 启动  │
│ 验签失败     │ → 不启动,记录异常,可回退旧版本 │
└──────────────┴────────────────────────────┘
    

1.7.3 公钥链(多层级信任)

对于客户定制场景,客户可以用自己的子公钥重新签名玉洁的固件:

为什么这样做:客户拿到模组后可以用自己的私钥重新签名,限制只有客户授权的代码才能跑上设备。客户也可以随时收回授权,把模组变回「只认玉洁签名」状态。这种双层信任链在工业 / 医疗 / 国防客户那里是硬要求。

1.7.4 防回滚(Anti-Rollback)

1.8 异常路径与恢复策略

启动链必须对所有异常有预案,下面是关节模组实战中遇到过的全部异常路径:

异常触发条件检测时机恢复策略用户感知
外部晶振失振HSE 不起振 / 受干扰PLL 配置前切内部 HSI,低速运行功能受限,不报警
PLL 失锁PLL 配置后 LOCK=0PLL 配置后 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升级失败,但旧版本能跑
为什么 Boot 决定产品力:关节模组一旦批量装机到客户设备里,不能依赖拆机刷固件。Bootloader、升级、回滚不是后期附加功能,而是量产底座的一部分。一个不能远程升级、不能自动恢复的关节,本质上只能算半成品。

核心原则:① 启动链是状态机不是流程图(每个阶段都有兜底出口)② 启动失败 ≠ 整机报废(双备份兜底)③ 安全不是可选(公钥烧入是必须的)④ 时间是可量化指标(≤350ms 是硬指标)⑤ 异常路径必须有预案(上面 14 类异常都必须在代码里有分支)。

2 · 2BSP 与 RTOS

2.1 BSP 是什么

BSP(Board Support Package)是芯片支持包,把 MCU 寄存器级别的细节封装成可调用接口。它是上层实时控制算法和硬件之间的"翻译官"。

BSP 提供的接口

2.2 RTOS 是什么,为什么需要

一体化关节模组的控制任务有强实时要求(电流环 10-20 kHz),单纯裸跑 main + while 循环很难管理多周期任务。RTOS 提供:

常见选择:

RTOS特点典型场景
FreeRTOS开源、轻量、生态成熟单关节 MCU
RT-Thread国产、生态丰富、内置组件国产化项目
ZephyrLinux 基金会、新一代需要长期维护的项目
裸跑(Super-loop)无 RTOS,确定性最好单任务、极致实时

2.3 实时任务分层(6 档周期)

底软必须把不同周期的任务分清楚,否则上层一个复杂算法就会打断电流环。

周期任务实现方式优先级
10-50 μsPWM 更新 · ADC 采样硬件定时器触发 + DMA最高
50-100 μsFOC 电流环(10-20 kHz)DMA 完成中断高
0.5-1 ms速度环 · 位置环 · 力矩估计(1-2 kHz)高优先级任务中高
1-5 ms状态机 · 保护 · 温控中优先级任务中
10-100 ms诊断 · 日志 · 参数管理低优先级任务低
100 ms 以上OTA · 统计 · 后台维护后台任务最低
关键约束:上层算法不能直接打断底层实时控制环。
例:一个复杂的轨迹算法突然占满 CPU,不能影响电流环和过流保护。
实现方式:把实时任务放在中断或高优先级任务里,给上层算法留出明确的 CPU 配额(比如 ≤ 30%)。

2.4 中断与优先级

2.5 内存与临界区

2.6 看门狗

3 · 3电机与功率级驱动

3.1 功率级硬件组成

一体化关节模组的功率级由以下几个部分构成:

3.2 底软需要做的事情

PWM 输出

ADC 采样

栅极驱动状态

保护功能

3.3 标准化接口(上层不碰硬件)

上层控制算法不应该直接操作寄存器,而是通过底软抽象出来的接口。这是最容易混乱的地方,必须把接口设计清楚。

// 上层调用(伪代码)

// 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();             // 清除可恢复故障
    

3.4 实际工程坑

功率级底软的两个硬要求:
① 保护响应时间 ≤ 5 μs(短路 / 硬件过流必须靠硬件触发,软件来不及)
② 采样同步精度 ≤ 1 μs(三相电流必须同一时刻采样,否则 FOC 解算会有旋转误差)

4 · 4编码器与传感器采集

4.1 模组里到底有哪些传感器

一体化关节模组的传感器比普通电机伺服多,因为要做R6 双编码器 + 力矩感知,需要完整观测链:

传感器位置用途
电机侧编码器电机轴端(≥ 19 bit)电机转子角度 · FOC 解算源头
输出侧编码器减速器输出端关节实际位置 · 扭簧解算
扭簧两端角度扭簧前后轴承位置扭簧变形量 → 力矩
母线电流母线侧总功率监控
三相电流U/V/W 相FOC 电流环
电机温度绕组 / 铁芯过温保护 · 温度补偿
壳体温度减速器外壳过温保护
减速器温度润滑相关润滑状态监测
抱闸状态抱闸机构抱闸可靠性监测
振动传感器(可选)壳体 / 减速器异常噪声 / 磨损检测

4.2 采集同步

多源数据的时间对齐是力矩感知的前提。如果各传感器在不同时间采样,扭簧解算会有相位误差。

同步策略

采样时间戳

4.3 R6 双编码器观测链(关键)

这是 R6 力矩感知能不能 work 的物理基础。底软要把这条链的数据质量做好。

电机角度 θm(电机侧编码器)
  ↓
减速器传动比 N
  ↓
理论输出角度 θo_theory = θm / N
  ↓
实际输出角度 θo(输出侧编码器)
  ↓
扭簧变形量 Δθ = θo_theory - θo
  ↓
扭簧特性表 f(Δθ, temperature, speed)
  ↓
输出侧力矩估计 τ = f(Δθ, T, ω)
  ↓
DOB / 自适应 K / 阻抗控制
    

底软需要保证

4.4 传感器预处理

去毛刺

校准

异常值钳位

4.5 传感器冗余

高安全等级应用需要考虑冗余:

R6 力矩感知的物理基础:双编码器精度(≥ 19 bit)+ 采样同步(μs 级)+ 温度补偿(覆盖工况)+ 异常处理(容错)。少一块,R6 就只能停在 demo,不能量产。

5 · 5参数与标定管理

5.1 为什么参数管理重要

一体化关节模组有 4 类参数,每类的访问权限、修改流程、回滚要求都不同。混在一起管理会出现:

5.2 4 类参数

类别典型参数修改权限存放位置
电机参数电阻 · 电感 · 反电动势常数 · 极对数 · 转矩常数 · 最大电流工厂 · 高级用户出厂标定区
减速器参数减速比 · 回差 · 效率 · 摩擦模型 · 温度相关特性工厂出厂标定区
传感器参数零偏 · 增益 · 方向 · 安装角 · 温漂补偿 · 非线性修正工厂 · 现场标定出厂 + 现场标定区
安全参数最大位置 · 最大速度 · 最大力矩 · 最大温度 · 过载时间 · 降额曲线仅认证工程师安全区(独立校验)

5.3 参数区分维度

除了按"类别"分,还需要按生命周期分:

5.4 参数的工程管理

参数存储

权限控制

版本管理

修改记录

回滚

5.5 标定流程示意

工厂标定工位
  ↓
电机参数辨识(电阻 · 电感 · 反电动势)
  ↓
编码器零点标定(机械角度 ↔ 编码器值)
  ↓
扭簧特性表生成(Δθ → 力矩)
  ↓
减速器参数测量(减速比 · 回差 · 摩擦)
  ↓
温度特性测试(多温度点参数)
  ↓
参数写入 + CRC + 签名
  ↓
现场标定(机械安装 · 客户工艺)
  ↓
交付使用
    
参数管理的红线:不能让普通上层应用随意修改安全参数。所有安全参数修改必须走认证通道 + 留操作日志,否则产品出厂后会出现"现场工程师乱调参数导致批次性失效"。

6 · 6诊断、日志与故障记录

6.1 故障等级的 5 档

工程样机阶段,日志可以多;量产阶段,日志必须可控。需要把故障按严重程度分级:

等级处理举例
Warning继续运行,记录 + 上报温度接近上限 · 编码器信号质量下降
Derating限制电流/速度/力矩温度达到降额区间 · 母线电压低
Recoverable Fault进入安全状态,条件满足后恢复通信超时 · 编码器丢帧
Latched Fault必须人工确认或重新上电过流保护 · 编码器断线 · 抱闸异常
Critical Fault立即关断功率级 + 抱闸硬件短路 · 驱动器损坏 · 通信完全中断

6.2 故障上下文记录

光记录「发生了故障」是不够的,必须记录故障时的状态,才能事后复盘。

必记录项

波形记录

6.3 故障处理链

检测异常
  ↓
确认是否真实故障(去抖 · 多源校验)
  ↓
进入降额或安全状态
  ↓
停止输出 / 限制输出 / 抱闸
  ↓
记录故障上下文(波形 · 时间戳 · 上下文)
  ↓
上报上位机(实时告警)
  ↓
等待自动恢复 或 人工确认
    

6.4 安全停机 vs 正常停止

不能把安全停机和正常停止混为一谈:

类型目标允许代价
正常停止减速到 0,动作平滑不能损失轨迹精度
急停保证人和设备安全可以牺牲运动平滑性
机械卡死保护电机和机械不能继续加大电流硬顶
通信断开进入安全姿态不能简单保持最后一个力矩指令无限运行

6.5 日志管理

日志分级

日志存储

6.6 诊断与预测

不只是记录故障,还要预测故障。这部分交给上层算法应用(参见 2-10)。

诊断日志的工程价值:
① 现场可维护:客户工程师能根据故障码快速定位
② 远程诊断:售后团队能远程读取故障波形
③ 质量追溯:批次性问题能在第一周发现
④ 预测性维护:从「坏了再修」变成「快要坏了就提醒客户」

7 · 今天小结 + 下一步

底软 6 块全部展开完了。今天聊的范围:

底层底软「准出门禁」清单:上电 / 自检 / 电机可使能 / 编码器可读 / 电流可采 / PWM 可控 / 故障可关断 / 参数可保存 / 日志可读取。
达到这个标准之后:才能进入 2-7 三层总览 中的「阶段 2:单关节闭环」(电流环 → 速度环 → 位置环),对应 2-9 中层控制详细拆解。

下一步建议:2-9 中层控制详细拆解已 lock(7 节:三环 PID / FOC / 摩擦 / 力矩 / 阻抗 / 状态机 / 多关节)。如果要继续深挖底层,可以挑某一块再展开(比如 R6 双编码器观测链的具体实现)。