67 wdt
作者:陈媛媛
一、概述
看门狗(Watch Dog Timer,WDT)是一种用于监控嵌入式系统状态的电路,旨在提高系统的可靠性和稳定性。在看门狗电路的帮助下,当系统出现异常,如程序跑飞或死循环时,能够自动复位并重新启动系统。
1.1 各类看门狗的区别
1.1.1. 内部硬件看门狗(Always-On Watchdog Timer)
- 定义:AON WDT,位于芯片"Always-On"电源域的硬件看门狗,即使主芯片休眠仍能工作
- 特点:开机后硬件层面自动开始计数,独立于软件系统运行
- 控制方式:完全由内核固件自动控制,不需要脚本干预
- 工作原理:硬件定时器持续计数,喂狗操作复位计数,超时(计数溢出)触发系统复位
- 可靠性:理论上能复位大部分系统异常,但在极端硬件故障(如 PSRAM 完全死锁)时可能无法正确重启
1.1.2. 软件看门狗
- 定义:基于操作系统任务调度机制的软件层面监控
- 特点:能够检测任务阻塞和软件死锁,依赖操作系统正常运行
- 控制方式:通过 wdt 库函数控制
- 实现原理:基于操作系统定时器机制,FreeRTOS 按 2ms 间隔调用检测函数
- 特殊说明:在 Air6101 中,软件看门狗检测函数同时也会喂硬件看门狗
1.1.3. 外部硬件看门狗
- 定义:独立的看门狗芯片,通过 GPIO/I2C 等接口通信
- 特点:完全独立于主系统,具有独立的电源和时钟,可靠性最高
- 控制方式:不通过 wdt 库,需使用 i2c、gpio 等外设驱动库实现喂狗操作
1.2 wdt 库专门用于控制芯片内部的看门狗:
- 内部硬件看门狗:芯片内部集成的硬件看门狗单元,如 AON WDT(Always-On Watchdog Timer)。
- 软件看门狗:基于操作系统任务调度机制的软件层面看门狗,
注意:外部硬件看门狗通过 GPIO/I2C 等接口控制,不在 wdt 库的控制范围内,需要使用相应的外设驱动库(如 i2c、gpio 库)来实现喂狗操作。
二、核心示例
1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;
2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;
3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/wdt;
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "wdtdemo"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- 定义喂狗任务函数
function wdt_task()
-- 这个demo要求有wdt库
-- wdt库的使用,基本上每个demo的头部都有演示
-- 模组/芯片的内部硬狗, 能解决绝大多数情况下的死机问题
-- 但如果有要求非常高的场景, 依然建议外挂硬件,然后通过gpio/i2c定时喂狗
if wdt == nil then
while 1 do
sys.wait(1000)
log.info("wdt", "this demo need wdt lib")
end
end
-- 注意, 大部分芯片/模块是 2 倍超时时间后才会重启
-- 以下是常规配置, 9秒超时, 3秒喂一次狗
-- 若软件崩溃,死循环,硬件死机,那么 最多 18 秒后,自动复位
-- 注意: 软件bug导致业务失败, 并不能通过wdt解决
wdt.init(9000)
sys.timerLoopStart(wdt.feed, 3000)
end
-- 定义故障模拟任务函数
function fault_task()
log.info("fault_task", "Entering infinite loop to simulate fault.")
while true do
-- 模拟故障场景,真的进入死循环
end
end
-- 启动任务
sys.taskInit(wdt_task)
sys.taskInit(fault_task)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
三、常量详解
核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;
每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;
如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;
wdt 核心库没有常量。
四、函数详解
4.1 wdt.init(timeout)
功能 初始化看门狗并立即启用。具体支持的范围取决于硬件设备。
参数
参数含义:看门狗超时时长
数据类型:number
取值范围:1000-90000毫秒
是否必选:是
注意事项:具体支持的范围取决于硬件设备
参数示例:wdt.init(9000)
注意事项:
- 控制范围:wdt 库仅用于控制产品内部看门狗,外部硬件看门狗需要通过 i2c、gpio 等外设驱动库控制。
- 具体支持的范围取决于硬件设备。
Air8101/Air6101:配置软狗超时时长,然后开启软狗;硬狗是内核固件自动开启的,这个接口只是配置硬狗超时时长。
Air780 系列/Air700 系列及 Air8000 系列:无软件看门狗,硬狗是内核固件自动开启的,硬狗超时时长固定为 20s(无软件看门狗)。 - 超时机制:
Air8101/Air6101:在超时时间后马上重启,如配置 9 秒超时,在第 10 秒自动复位。
Air780 系列/Air700 系列及 Air8000 系列:硬件看门狗超时时间固定为 20 秒,超时后将触发系统复位。
- 失效情况:软件看门狗在操作系统死机时失效,硬件看门狗在 PSRAM 等关键硬件死机时可能无法正确复位。
返回值
local success = wdt.init(9000)
有一个返回值 success;
success
含义说明:看门狗初始化操作是否成功;
数值类型:boolean;
取值范围:true或false;
注意事项:当底层不支持或参数无效时返回false;
初始化成功后看门狗立即开始计时;
返回示例:true;
示例
-- 初始化看门狗,超时时间10秒
local success = wdt.init(10000)
if success then
log.info("wdt", "看门狗初始化成功")
else
log.error("wdt", "看门狗初始化失败")
end
-- 配合定时喂狗使用
wdt.init(9000)
sys.timerLoopStart(wdt.feed, 3000)
4.2 wdt.feed()
功能 喂狗操作,使看门狗超时计时复位,重新开始计时。
参数
无
返回值
local success = wdt.feed()
有一个返回值 success
success
含义说明:喂狗操作是否成功;
数据类型:boolean;
取值范围:true或false;
注意事项:当看门狗未初始化或操作失败时返回false;
喂狗成功后看门狗超时计时器从零开始重新计时;
返回示例:true
注意事项:
- 具体支持的范围取决于硬件设备。
Air8101/Air6101:喂软件看门狗(硬件看门狗由 LuatOS 内核固件按 2ms 间隔自动喂狗)。
Air780 系列/Air700 系列及 Air8000 系列:喂硬件看门狗,无软件看门狗。 - 使用建议:喂狗间隔建议为超时时间的 1/3 以内。
- 高可靠性场景:建议同时使用内部看门狗 + 外部看门狗。
示例
-- 初始化看门狗
wdt.init(9000)
-- 定时喂狗(推荐方式)
sys.timerLoopStart(wdt.feed, 3000)
4.3 wdt.setTimeout(timeout)
功能 重新设置看门狗超时时长(部分设备支持)。
参数
参数含义:新的超时时长,单位为毫秒
数据类型:number
取值范围:正整数
是否必选:是
注意事项:不是所有设备都支持此功能。建议使用定时器定期调用这个函数。
参数示例:wdt.setTimeout(5000)
返回值
local success = wdt.setTimeout(5000)
有一个返回值 success;
success
含义说明:超时时间设置操作是否成功;
数据类型:boolean;
取值范围:true或false;
注意事项:当设备不支持此功能或参数无效时返回false;
设置成功后新的超时时间立即生效;
返回示例:true;
注意事项:
- 具体支持的范围取决于硬件设备。
Air8101/Air6101:配置软件和硬件看门狗超时时间。
Air780系列/Air700系列及 Air8000系列:硬狗超时时长固定为 20s(无软件看门狗),不支持重新配置看门狗超时时长。
- 超时机制:
Air8101/Air6101:在超时时间后马上重启,如配置 9 秒超时,在第 10 秒自动复位。
Air780 系列/Air700 系列及 Air8000 系列:硬件看门狗超时时间固定为 20 秒,超时后将触发系统复位。
示例
-- 初始化看门狗
wdt.init(10000)
sys.timerLoopStart(wdt.feed, 3000)
-- 5秒后调整超时时间
sys.timerStart(function()
local success = wdt.setTimeout(5000)
if success then
log.info("wdt", "超时时间已调整为5秒")
else
log.info("wdt", "设备不支持动态调整超时时间")
end
end, 5000)
4.4 wdt.close()
功能 关闭看门狗(通常不被支持或功能有限)。
参数
无
返回值
local success = wdt.close()
有一个返回值 success;
success
含义说明:看门狗关闭操作是否成功;
数据类型:boolean;
取值范围:true或false;
注意事项:当设备不支持关闭操作或操作失败时返回false;
具体支持的范围取决于硬件设备;
返回示例:false;
注意事项:
- 具体支持的范围取决于硬件设备。 Air8101/Air6101:关闭软件看门狗。 Air780 系列/Air700 系列及 Air8000 系列:无法关闭硬件看门狗,无软件看门狗。
示例
wdt.init(10000)
-- 运行一段时间后尝试关闭(通常不会成功)
sys.timerStart(function()
local success = wdt.close()
if success then
log.info("wdt", "看门狗已关闭")
else
log.info("wdt", "看门狗关闭失败(正常情况)")
end
end, 9000)
五、产品支持说明
支持 LuatOS 开发的所有产品都支持 wdt 核心库。