3. 样机阶段核心任务
样机阶段是 MCU 项目从“能跑起来”走向“可验证、可复现、可交接”的关键窗口。这个阶段的目标不是把功能堆完,而是建立一套可观测、可定位、可回归的工程基线。功能验证回答“做对了没有”,外设驱动开发回答“底层是否稳定”,调试接口使用回答“出问题时能否进入现场”,日志与断言机制回答“问题是否留下证据”。四者构成一个闭环:验证驱动开发,调试支撑验证,日志与断言把一次性的调试经验固化为长期资产。
一、核心原理:四类任务构成可观测闭环
样机阶段最容易被低估的是“可观测性”。很多团队把时间花在写业务逻辑上,等到量产测试才发现某个 I²C 从机偶发 NACK、某路 ADC 在低温下漂移、某次看门狗复位后现场丢失。根因往往不是功能没写,而是样机阶段没有把观测手段建起来。功能验证需要明确的输入、预期输出和判定条件;外设驱动需要分层,把寄存器操作、时序控制、错误恢复与业务解耦;调试接口需要保留 SWD/JTAG、串口 shell、RTT 等通道;日志与断言需要在编译期和运行期同时控制成本与信息量。
样机阶段的核心判据:任何一个功能点,都应能回答“怎么触发、怎么观察、怎么判定通过、失败时留下什么证据”。如果四个问题中有任何一个答不上来,这个功能点就还没有真正进入可验证状态。
二、方法流程:从功能清单到可回归基线
建议按以下顺序推进,避免“先写业务、后补驱动”的倒置。第一步,冻结样机功能清单,把每个功能拆成可独立触发的测试项,标注优先级和依赖外设。第二步,先打通最小系统:时钟、复位、电源、调试接口、串口日志,确保“能下载、能打印、能复位”。第三步,按外设逐个开发驱动,每个驱动配套一个自测命令或测试桩。第四步,接入日志分级与断言策略,把关键状态、错误码、时序打点输出到串口或 RTT。第五步,形成冒烟测试脚本,每次提交后自动跑一遍核心路径。
- 功能验证:为每个功能定义输入条件、预期输出、边界条件和失败判据,优先覆盖上电、复位、异常恢复三类场景。
- 外设驱动开发:按“寄存器层—时序层—设备层—业务层”分层,驱动内部处理超时、重试和错误码,不把硬件细节泄漏到业务代码。
- 调试接口使用:保留 SWD 下载与单步、串口 shell 交互、RTT 实时打印;量产固件可通过选项字节或引脚状态关闭调试口,但样机阶段必须开放。
- 日志与断言机制:日志分 ERROR/WARN/INFO/DEBUG 四级,断言区分“开发期致命”和“量产期降级”,避免断言本身成为复位源。
三、外设驱动与调试接口的配合
外设驱动开发最忌讳“只写成功路径”。以 SPI 驱动为例,除了正常收发,还要处理忙等待超时、DMA 传输错误、从机无响应、时钟极性配置错误等情况。驱动应返回统一错误码,并允许上层决定重试或降级。调试接口方面,SWD 适合断点与寄存器查看,串口 shell 适合运行时改参数和触发测试,RTT 适合高频打点且不占用 UART。三者不是替代关系,而是不同时间尺度的观测手段。
/* 驱动层错误码示例 */
typedef enum {
DRV_OK = 0,
DRV_TIMEOUT = 1,
DRV_BUSY = 2,
DRV_PARAM_ERR = 3,
DRV_HW_FAULT = 4
} drv_status_t;
/* 日志分级与断言宏 */
#define LOG_E(fmt, ...) log_printf(LOG_ERROR, fmt, ##__VA_ARGS__)
#define LOG_W(fmt, ...) log_printf(LOG_WARN, fmt, ##__VA_ARGS__)
#define LOG_I(fmt, ...) log_printf(LOG_INFO, fmt, ##__VA_ARGS__)
#define ASSERT_DEV(cond) do { \
if (!(cond)) { \
LOG_E("assert fail: %s, line %d", #cond, __LINE__); \
while (1) { } \
} \
} while (0)
四、日志与断言:把调试经验固化为资产
日志不是越多越好,而是“关键路径必有、高频路径可关”。建议在样机阶段默认打开 INFO,量产固件默认只保留 ERROR 和必要 WARN。断言要区分场景:开发期断言失败可以直接停机并打印现场;量产期断言失败应记录错误码并尝试恢复,避免设备变砖。日志输出通道也要做缓冲和限流,防止高频打印拖慢主循环或阻塞中断。
| 任务 | 关键动作 | 典型工具/接口 | 交付物 |
|---|---|---|---|
| 功能验证 | 拆分测试项、定义判据、覆盖复位与异常 | 串口 shell、测试桩、冒烟脚本 | 功能验证清单与通过记录 |
| 外设驱动开发 | 分层设计、超时重试、统一错误码 | 寄存器手册、逻辑分析仪、示波器 | 驱动接口文档与自测命令 |
| 调试接口使用 | 保留 SWD、串口、RTT,支持运行时干预 | J-Link/ST-Link、串口终端、RTT Viewer | 调试连接说明与常用命令集 |
| 日志与断言 | 分级、限流、区分开发期与量产期策略 | UART、RTT、Flash 日志区 | 日志分级规范与断言策略 |
五、案例与场景:一次 I²C 偶发失败复盘
某样机在老化测试中间歇性出现传感器读取失败,复位后恢复。初期排查怀疑传感器本身,更换后仍复现。后来在 I²C 驱动中加入超时计数和错误码日志,发现失败集中在总线被从机拉低超过 3 ms 的场景。进一步用逻辑分析仪抓取波形,确认是某次从机时钟拉伸后主机未正确处理。修复方式是在驱动层增加超时恢复:检测到 SCL 被拉低超时后,发送 9 个时钟脉冲并重新初始化总线。这个案例说明,如果样机阶段没有日志和错误码,问题会被误判为“传感器不稳定”,量产阶段将付出更大代价。
常见误区:把“功能能跑”当成“功能验证完成”;驱动只写成功路径;调试口在样机阶段就关闭;日志用 printf 直接阻塞主循环;断言在量产固件中仍然停机。这些做法会让问题在量产阶段集中爆发,且现场无法定位。
六、样机阶段的最小交付基线
建议在样机阶段结束时,至少交付以下内容:一份功能验证清单,记录每个测试项的输入、预期、实测结果和失败原因;一套外设驱动接口,包含错误码定义和超时策略;一份调试接口说明,明确 SWD、串口、RTT 的用途和连接方式;一套日志分级规范,明确各级别开关方式和输出通道;一份断言策略,区分开发期与量产期行为。完成这些,样机才具备进入小批量试产的条件。
把样机阶段当作“建立可观测基线”的过程,而不是“把功能写完”的过程,后续的小批量试产和量产导入才会顺畅。功能验证、外设驱动、调试接口、日志与断言四件事做扎实,样机才真正具备可交接、可复现、可回归的工程价值。