简介:面向IEC60730/IEC60335 ClassB认证的STM32安全软件包整理资料,适合嵌入式功能安全工程师、测试与认证相关开发者。内容整合ST官方三套ClassB方案:STM8-SafeCLASSB、STM32-CLASSB-SPL与X-CUBE-CLASSB,附说明文档和使用介绍,覆盖自检库、编译工程及认证指引。资源共1406个文件,压缩包28.41MB,以C/H源文件、汇编、工程配置、PDF/CHM文档和批处理脚本为主,目录完整、便于检索。其中还包含CRC生成脚本及STM32G474示例,支持Keil、IAR、GCC等常用工具链,可快速开展上电自检、CPU/存储器测试等ClassB相关验证。需要注意的是,因上传大小限制,包内已移除Drivers/HAL及CMSIS库,手动添加对应目录后即可编译。当前已有2000人学习下载,适合产品在做ClassB认证评估、或希望复用官方自检方案的团队参考。
1. 我为什么要折腾Class B:家电安全认证不是闹着玩的
第一次接到带"Class B"字样的需求时,我还以为只是给某个产品加个B版本固件。后来翻到客户发来的技术协议,里面写着"需要符合IEC 60730-1 Annex H相关要求",才意识到这压根不是软件版本号的问题,而是关系到家电产品能不能合法出货的安全认证。如果你也在做洗衣机、电饭煲、洗碗机这类家电控制板,或者做工业控制里对人的安全有影响的设备,那么STM32的Class B安全运行认证软件库,就是你迟早要面对的东西。
简单说,IEC 60730是家用电器的自动电气控制标准,里面把控制器的安全等级分成了Class A、B、C三档。Class B属于"防止设备本身发生危险故障"的等级,比如电饭煲在加热管短路时不能一直烧下去,燃气灶的电磁阀在探测到异常时必须可靠关断。问题在于,现在家电主控几乎都是MCU,而MCU是时序逻辑器件,一旦程序跑飞、RAM数据被破坏、Flash内容发生跳变,设备的保护功能就可能失效。认证机构不会相信"我们的代码很稳定"这种口头保证,他们要看到的是:MCU在运行过程中到底有没有自我检查的手段,以及这些检查有没有覆盖到所有可能引发危险故障的环节。
STMicroelectronics为此专门提供了一套软件解决方案,就是标题里说的"STM32 CLASSB安全运行认证软件库",在官方生态里叫X-CUBE-CLASSB扩展包。它干的事,是帮你把MCU运行时的自检逻辑全部搭好,包括CPU内核测试、RAM测试、Flash完整性校验、时钟检测等,并提供一组API让这些自检可以周期性地嵌进你的主循环里。同时它还附带一整套文档,用来支撑IEC 60730 Class B认证过程中最繁琐的"证据链"环节。
如果你只是写业务逻辑,可能一辈子用不上它;但如果你正在给家电或安全相关产品做嵌入式开发,这个库就是你从"能用"走向"能过认证"最省力的一条路。
2. X-CUBE-CLASSB软件库里到底装了什么:不只是代码,是整套证据
刚开始用的时候,我犯了个经验主义错误:以为这库就是个静态库,调几个函数就完事。真打开X-CUBE-CLASSB的包结构才发现,ST把这件事做得很重,里面至少分了三层东西。
第一层是运行时自检库。这部分以预编译库文件或者源码形式提供,根据你用的MCU系列对应不同的文件路径。它内部实现了ARM Cortex-M内核自检库(Cortex-M Self Test Library,简称STL)、RAM的March测试算法、Flash的CRC校验逻辑以及时钟监控逻辑。这一层直接面对硬件,是Class B功能的核心执行者。官方在出厂前已经对这套自检序列做过故障注入测试,你不需要自己去发明轮子。
第二层是应用层接口。库不可能自己跑起来,它需要你告诉它"什么时候跑、跑哪些项目、跑完怎么处理故障"。因此扩展包里会给出CLASSB_Init、CLASSB_SystemInit、CLASSB_ApplicationInit、CLASSB_SelfTest_Schedule这些API,以及配套的示例工程。你在主循环里周期性调用自检调度函数,库内部就会分时地把CPU、RAM、Flash、时钟逐项过一遍。
第三层也是最容易被忽略的一层,是文档套件。包括:
- 说明库怎么用的用户手册(比如UM2262系列)
- 说明安全概念和故障处理策略的安全手册
- 用于证明库本身可靠性的失效模式与影响分析(FMEA)文档
- 给测试工程师用的自检覆盖率和测试报告模板
这个第三层,在认证过程中往往比代码本身还值钱。因为认证机构审核时,最常问的问题就是:"你这个自检覆盖率是多少?怎么证明的?RAM测试算法是什么?遇到测试失败后软件怎么处理?"如果你自己写一段自检代码,可能功能上有九成把握,但证明不了覆盖率,认证就是过不了;而ST官方库附带的安全文档已经把故障模式列表、诊断覆盖率和测试方法写清楚了,你只需要把应用层对应的部分填上自己的实现细节,认证材料的完成度会高出一大截。
我见过不止一个团队,拿到X-CUBE-CLASSB以后只盯着源代码看,把整个包翻了个底朝天,却漏掉了文档目录。等到认证机构问起"安全手册在哪里"时才反应过来。所以拿到这个库的第一件事,我建议先把docs目录里所有PDF按编号通读一遍,再决定改代码。
3. 自检机制核心原理:CPU、RAM、Flash、时钟,一个都不能漏
Class B自检不是跑一遍"软件看门狗"那么简单。IEC 60730 Annex H里要求对影响安全功能的每个部件都做周期性的诊断。放到MCU层面,就是CPU、RAM、Flash、时钟这四大件。
CPU自检。CPU内部执行单元如果出了问题,比如某个指令解码错误、ALU运算不对,那你写的所有保护逻辑都可能变成笑话。ARM针对这个问题提供了一套标准的Cortex-M Self Test Library(Cortex-M STL),X-CUBE-CLASSB直接把这套东西装进去了。它的做法很朴素但很有效:执行一组精心设计的指令序列,对已知的输入计算得到已知的输出,然后比对结果是否一致。比如对一组特殊值做加法、乘法、逻辑运算、移位操作,跑完以后检查寄存器值和内存标志位是否符合预期。这套测试覆盖了大部分整数运算指令和部分控制流指令,能在极短时间内发现CPU核心运算单元的永久性故障或瞬时扰动。
RAM自检。RAM的典型失效是某个存储单元卡在固定电平,或者相邻位互相影响,导致数据读到错误值。Class B库用的是March类测试算法,常见是March C。March测试的思路是逐步遍历整个RAM空间,每一步对每个单元做特定操作,比如先写入0x00再读出来验证,再写入0xFF再读出来验证,同时配合地址方向交替,能检测出绝大部分固定型故障、跳变型故障和部分耦合故障。
这里有个容易被误解的地方:March测试会覆盖整片RAM区域吗?不是的。它需要你在配置阶段明确划分出自检区域,而且自检区域在测试期间不能同时被程序使用,否则自检操作本身就会破坏正在使用的数据。因此正经做Class B的工程,都会把RAM分成"安全相关数据区"和"自检覆盖区",自检区是预先划分好的,数据区在自检时被临时旁路。这个边界不画清楚,后面各种诡异现象全会冒出来。
Flash自检。Flash的问题主要是内容被意外改写,比如电压跌落、位翻转、程序区被野指针踩踏。最常见的可靠手段是CRC校验。启动时对固定区域做一次CRC,算出一个基准值存下来;运行期间周期性重新计算这部分区域的CRC,和基准值比对。不一样就说明Flash被改了,要么尝试恢复,要么进入安全状态。X-CUBE-CLASSB里对这一块的配置要注意CRC多项式、初始值和覆盖范围的匹配,ST文档里写得比较细,但工程里稍不注意就会把CRC区域算错。
时钟自检。时钟的重要性往往被低估。如果HSE晶振频率漂移了,CPU运行频率变快变慢,串口波特率、PWM周期、看门狗超时全都会偏,保护动作也可能提前或滞后。Class B的做法通常是同时用两个独立时钟源互相对比,比如拿LSI和HSE做频率比对,在一定窗口内数主时钟的脉冲数,再和参考时钟的计数结果比较,超差就判定时钟异常。
理解了这四项自检的原理,你才能真正明白为什么Class B自检代码跑起来会占用CPU时间和RAM空间。它不是像看门狗那样只在后台溜一圈,而是实打实地在CPU上执行密集型测试。这也就引出了下面最关键的集成问题:怎么把它合理地塞进你的实时系统里。
4. 把Class B库集成进真实工程:一次完整的融合实践
4.1 环境准备与工程生成
我用STM32CubeMX配合STM32CubeIDE做过一遍完整的集成,也用过Keil,流程大同小异。CubeMX的好处是可以直接勾选X-CUBE-CLASSB。打开软件包管理器,找到对应STM32系列的X-CUBE-CLASSB并安装。要注意,这个扩展包对不同系列(F0、F1、F3、F4、G0、G4、L0、L4、H7等)都有对应版本,选错系列连编译都过不去。
新建工程时,先在CubeMX里配好时钟树、GPIO、外设,确认能正常编译以后,再打开Software Packs选X-CUBE-CLASSB。启用后需要配置几个关键参数:自检RAM区域大小、自检周期模式、系统时钟检测源、CRС覆盖起始地址等。这些参数在不同项目里必须按实际情况调整,不能照抄官方默认值。
生成代码后,CubeMX会把Class B库的源文件和头文件一并导入项目,同时在main.c里生成调用入口的注释位置。你需要在合适的位置调用CLASSB_Init和CLASSB_SystemInit,完成启动阶段的自检。
4.2 核心API的调用顺序
一套典型的调用流程是这样的:
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); /* 其他外设初始化 */ CLASSB_Init(); /* 启动时必须做的完整自检初始化 */ CLASSB_SystemInit(); /* 启动时对系统进行自检 */ /* 启动自检通过后,才允许进入业务逻辑 */ APP_Init(); /* 你的业务初始化 */ while (1) { /* 应用周期任务 */ APP_Task(); /* 调用Class B调度,内部会分时执行非破坏性自检 */ CLASSB_SelfTest_Schedule(); } }CLASSB_Init会把自检涉及的数据结构、标志位准备好;CLASSB_SystemInit会执行第一轮完整的自检,包括CPU、RAM、Flash和时钟。如果这一轮失败,说明硬件初始状态就有问题,绝对不能继续执行业务。CLASSB_SelfTest_Schedule则是在运行期间反复调用,它按预先配置的周期把各项自检分散到不同时间片执行,避免某一瞬间CPU被长时间占用。
4.3 自检周期的取舍逻辑
这里有一个工程上非常核心的问题:自检多久跑一次?跑太频繁,CPU负载升高,实时性变差;跑太少,出错到发现的时间窗口拉长,安全响应可能来不及。IEC 60730要求的是"诊断覆盖率"和"诊断测试间隔"要匹配风险评估。比如你的设备在2秒内必须对某个危险状态做出保护响应,那这一项相关自检的间隔就不能大于2秒。
我实际做过的项目里,把CPU自检拆成多个小块,每个主循环周期只跑一小块,全部跑完需要几十毫秒;RAM自检按Bank分别进行,Flash CRC可以拉长到秒级。关键是要算清楚最坏情况下的自检总耗时,和你的安全响应时间做对比,把这个计算结果写进文档,这就是认证审核时要看的"安全论证"。
5. 实测最容易踩的坑:从报错到静默崩溃的排查记录
5.1 "no stm32 target found":连接层面的第一道坎
很多人装了Class B库以后第一次下载程序,Keil或者STM32CubeProgrammer直接弹一句"No STM32 target found",然后程序烧不进去。这个问题和Class B本身关系不大,但在集成阶段特别容易遇到,因为Class B工程通常会启用调试保护或读保护选项。如果你在CubeMX里开了RDP(读保护)等级到Level 1或者Level 2,并且开启了Debug Authentication(调试认证),普通调试器就不再能直接访问目标芯片了。
排查链路是这样的:第一,确认连接线SWDIO、SWCLK、GND、3.3V没有反接,尤其注意SWDIO和SWCLK顺序,线序出错是最高频原因。第二,检查复位电路是否正常,有些板卡RC复位电容异常会把SWD信号拉死。第三,用STM32CubeProgrammer做连接测试,读取芯片ID,如果读不到,再检查调试认证配置。如果之前已经开了Level 2读保护,那是永久性的,芯片只有通过Boot引脚配合全擦除才能恢复,这也是在Class B调试阶段必须绕开的坑。
经验做法:Class B开发调试阶段,先把Debug Authentication和读保护全部关掉,等到产品定型、准备做安全测试时再打开。否则你每改一次代码都要处理一次调试锁死,心态很容易崩。
5.2 堆栈溢出:Class B自检吃掉的资源比你想的多
Class B库的自检函数,尤其是RAM March测试和CPU自检,都有比较深的调用栈和临时变量需求。我在第一次集成后,程序跑一会儿就进入HardFault,一开始还以为是时序问题,后来发现是任务的栈空间不够了。
我最初在FreeRTOS里给Class B调度单独开了个任务,栈大小给1KB,跑完一轮RAM自检直接爆栈。后来在Class B的官方文档里找到说明,它对栈的需求在某些系列上会到几百字节甚至更多,需要额外预留。请务必检查你运行CLASSB_Init和CLASSB_SelfTest_Schedule的那个上下文,RTOS任务就加大任务的栈,裸机就把主栈加大。另外要注意,RAM自检和CPU自检有自己的临时缓冲区,别把缓冲区放置的位置和自检覆盖区域重叠。
排查思路是:先关掉自检调度,程序长跑稳定;打开自检后短时间HardFault,优先怀疑栈。用调试器在HardFault_Handler里断住,查一下LR和调用栈,几乎每次都指向自检函数内部,这时候别怀疑官方库代码,先给自己的栈扩容。
5.3 自检与看门狗打架:千万不要双保险变双杀
还有一个非常隐蔽的坑:Class B自检执行期间CPU被占住,如果这段时间超过独立看门狗IWDG的超时时间,看门狗会直接复位系统。表面上表现为"程序周期性重启",而且周期完全对不上业务逻辑。
我在项目里设了IWDG超时500ms,RAM March测试在最坏情况下跑掉600ms,于是系统每轮自检都会被看门狗打断。解决办法有两种,要么自检分片得更碎,让每一片都能在看门狗时间内完成;要么在看门狗喂狗逻辑里加标志位,让Class B自检和喂狗节奏错开,确保喂狗调用不会被自检长期阻塞。
我最终选择了分片方案,把自检调度放到一个5ms的定时器中,每个tick执行一部分自检操作,然后在下一个tick之前把窗口让出来,这样既不影响看门狗,也不阻塞主业务。这种"分时片"思路,在带Class B认证要求的实时系统里是最稳的。
5.4 Flash CRC覆盖范围:算错一个地址,认证被退回
Flash自检的覆盖范围配置错误,是最难发现的暗坑。它不会崩溃,也不会报错,就是某些Flash区域不在CRC覆盖范围内。等到认证机构做故障注入测试,往覆盖范围外的Flash区域写坏数据,设备毫无反应,测试直接Fail。
我的教训是:CRC覆盖区域必须从项目链接脚本里确认,而不是凭头文件里的宏定义猜。官方库有时默认覆盖整个代码段,但如果你用了Bootloader+App的结构,或者把常量数据放在了特殊段,宏定义的默认范围就可能偏了。检查方法很直接,用链接脚本里实际分配的Flash起始地址和长度去覆盖CRC配置,再跑一轮故障注入测试验证。
6. 认证文档怎么准备:报告不光是给认证机构看的
代码能跑只是第一步,Class B产品认证的深水区在文档。X-CUBE-CLASSB的文档套件提供了一套模板,但里面的数据需要你根据自己的项目去填写。我建议把以下材料作为主线来准备。
第一,安全需求和风险评估表。明确你的设备哪些功能是安全功能,每项安全功能对应的危险故障模式是什么,检测方法是什么,响应措施是什么。比如"加热管驱动电路异常"对应"切断加热输出",检测方法可能是"周期性检查MCU输出引脚状态和实际硬件反馈",这些都列成表格后,就会变成Class B自检项和业务保护逻辑的映射关系。
第二,自检覆盖率和测试间隔的计算表。把CPU、RAM、Flash、时钟的自检项分别列出来,标明对应的执行周期、执行耗时、覆盖率,然后和上一条的风险评估一一对照。这个表是认证机构查看的重点,也是你自己判断自检配置是否合理的依据。
第三,故障注入测试报告。官方库里会提供一份测试方法说明,指导你怎么人为制造故障,验证自检程序确实能检测到故障并进入安全状态。最常见的做法是通过调试器修改RAM单元的数值、篡改Flash内容、强制停振晶振,然后观察系统的反应。把这些测试的过程、结果截图、日志都整理成报告,认证现场会非常有说服力。
我在准备文档时最大的体会是:别把文档当"应付检查"的负担。因为每次改版固件,只要影响到自检配置、RAM布局、Flash区域划分,文档就必须同步更新。如果平时就维护好这张映射表,产品做认证周期会快很多;临时抱佛脚的话,光是补测试记录就能补到你怀疑人生。
最后分享一个技巧:库里的示例工程中往往自带一份已经填好大半的文档,绝大多数系列的主流程、覆盖率数据、测试方法都是现成的,你需要改的,只是和具体应用相关的参数。先照着示例改,再逐步替换成自己项目的细节,比从零开始写文档要省力得多。我前后两个项目都这么干,第二次做认证时,文档部分只花了第一次三分之一的时间。
本文还有配套的精品资源,点击获取