功能安全(Functional Safety):IEC 61508标准下的软件冗余设计与看门狗(Watchdog)逻辑实现
扫描二维码
随时随地手机看文章
在轨道交通、工业过程控制等SIL(安全完整性等级)要求的系统中,IEC 61508标准是软件设计的红线。仅仅“跑得快”是不够的,必须保证单点故障不导致系统失效。本文将探讨在该标准下,如何通过软件冗余与看门狗逻辑,构建符合SIL2/SIL3等级的嵌入式安全架构。
一、IEC 61508对软件架构的要求
IEC 61508将安全等级分为SIL1至SIL4。对于SIL2及以上等级,标准强制要求容错(Fault Tolerance)。这意味着系统必须具备在出现一个确定故障(Safe Failure)时,仍能维持安全状态的能力。
核心策略:
1. 多样性(Diversity):避免共因失效(Common Cause Failure)。
2. 独立性(Independence):安全相关功能与非安全功能隔离。
3. 自检(Self-Test):周期性检查硬件和软件完整性。
二、软件冗余设计:1oo2D架构
在MCU资源有限的情况下,实现高可靠性通常采用1oo2D(1 out of 2 Diverse)架构。即:两个独立的软件通道并行运行,结果比对一致才输出。
2.1 双通道任务调度
// 安全相关任务状态机
typedef enum {
SAFE_STATE_INIT,
SAFE_STATE_RUNNING,
SAFE_STATE_FAULT,
SAFE_STATE_SHUTDOWN
} SafeState_t;
// 双通道控制块
typedef struct {
SafeState_t state;
uint32_t heartbeat; // 心跳计数器
uint32_t crc; // 程序流CRC
uint32_t last_output; // 上一次输出
} SafetyChannel_t;
// 通道A(主逻辑)
SafetyChannel_t channel_A;
// 通道B(监控/冗余逻辑,使用不同的算法实现)
SafetyChannel_t channel_B;
// 独立看门狗定时器(硬件)
#define WDG_TIMEOUT_MS 100
2.2 表决逻辑(Voting Logic)
表决逻辑必须独立于主循环,通常由高优先级中断或独立的监控核执行。
// 表决函数(必须在安全时间内执行)
bool safety_vote(SafetyChannel_t* chA, SafetyChannel_t* chB) {
// 1. 心跳检查(程序跑飞检测)
if ((chA->heartbeat - chB->heartbeat) > 2) {
return false; // 心跳失步
}
// 2. 输出一致性检查
if (chA->last_output != chB->last_output) {
return false; // 输出分歧
}
// 3. CRC一致性检查(防止程序存储器篡改)
if (chA->crc != calculate_runtime_crc(chA)) {
return false;
}
return true; // 表决通过
}
三、看门狗(Watchdog)的高级实现
简单的喂狗(Kick)是不够的。IEC 61508要求看门狗必须能检测出程序流错误(Program Flow Error)。
3.1 时间窗看门狗(Window Watchdog)
防止程序执行过快或过慢。
// 窗口看门狗配置
typedef struct {
uint32_t min_interval_ticks; // 最小喂狗间隔
uint32_t max_interval_ticks; // 最大喂狗间隔
uint32_t last_kick_tick;
} WindowWdg_t;
// 喂狗函数(必须在规定的时间窗内调用)
bool window_watchdog_kick(WindowWdg_t* wdg) {
uint32_t current_tick = HAL_GetTick();
uint32_t delta = current_tick - wdg->last_kick_tick;
// 过早喂狗(程序跑飞或死循环)
if (delta < wdg->min_interval_ticks) {
safety_enter_fault_state(); // 进入安全状态
return false;
}
// 过晚喂狗(程序阻塞)
if (delta > wdg->max_interval_ticks) {
// 硬件看门狗会自动复位MCU
// 此处仅作记录
safety_log_error("WDG Timeout");
}
wdg->last_kick_tick = current_tick;
HAL_IWDG_Refresh(&hiwdg); // 硬件喂狗
return true;
}
3.2 逻辑看门狗(Logic Watchdog)
不仅看时间,还要看程序执行路径。
// 程序流监控点
typedef enum {
FLOW_START = 0x12345678,
FLOW_MIDDLE = 0x55AA55AA,
FLOW_END = 0xA5A5A5A5
} ProgramFlow_t;
volatile uint32_t expected_flow = FLOW_START;
// 在每个关键函数入口调用
void check_program_flow(ProgramFlow_t current_step) {
if (current_step != expected_flow) {
// 程序执行顺序错误
safety_enter_fault_state();
}
// 更新下一步期望值
switch(current_step) {
case FLOW_START:
expected_flow = FLOW_MIDDLE;
break;
case FLOW_MIDDLE:
expected_flow = FLOW_END;
break;
case FLOW_END:
expected_flow = FLOW_START;
break;
}
}
四、安全状态机(Safety State Machine)
当看门狗或冗余表决失败时,系统必须进入定义好的安全状态。
// 安全状态处理
void safety_enter_fault_state(void) {
// 1. 立即停止危险输出
HAL_GPIO_WritePin(RELAY_GPIO_Port, RELAY_Pin, GPIO_PIN_RESET);
// 2. 记录故障码到非易失存储
EEPROM_Write(FAULT_CODE_ADDR, FAULT_WDG_TRIGGERED);
// 3. 禁用所有中断,防止进一步干扰
__disable_irq();
// 4. 进入死循环,等待硬件看门狗复位
// 或者进入低功耗关机模式
while(1) {
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
}
五、结语
在IEC 61508框架下开发软件,冗余与看门狗不再是“锦上添花”,而是合规的刚需。通过1oo2D软件架构实现故障容忍,结合时间窗+逻辑流的双重看门狗机制,可以有效抵御内存翻转、程序跑飞和共因失效,确保系统在单点故障下依然安全。





