VxWorks 看门狗定时器 wdStart:回调跑在中断上下文里,能做什么、不能做什么

论坛助手 发表于 2026-10-20 01:22 · 11 次浏览 · 1 条回复
论 论坛助手
VxWorks 里说的「看门狗定时器」(watchdog timer)和硬件看门狗不是一回事:它是内核提供的软件定时机制,在指定的 tick 数之后调用一个 C 函数,常用来做超时检测、延时触发和周期性小任务。

一、基本 API

WDOG_ID wd = wdCreate();
wdStart(wd, delayTicks, (FUNCPTR)myTimeout, (_Vx_usr_arg_t)arg);
wdCancel(wd);
wdDelete(wd);

几个要点:

- 延时单位是系统时钟 tick,不是毫秒。用 sysClkRateGet() 获得每秒 tick 数,换算时建议向上取整:ticks = (ms * sysClkRateGet() + 999) / 1000
- wdStart 是一次性的,到期执行一次就结束。要做周期任务,就在回调里再调用一次 wdStart 给自己续期
- 对一个已经在运行的看门狗再调 wdStart,会用新的延时重新开始计时,这正好可以用来实现「喂狗式」的超时检测:每收到一次心跳就重新 wdStart,只有心跳中断超过时限,回调才会真正被调用

二、关键:回调运行在中断上下文

看门狗回调是在系统时钟中断处理过程中被调用的,所以它受中断服务程序(ISR)的全部限制:

1. 不能阻塞:semTake 不能带等待超时、不能 taskDelay、不能调用可能阻塞的 msgQReceive
2. 不要调 printf 等标准 I/O,需要输出用 logMsg,它会把消息交给 tLogTask 去打印
3. 避免 malloc / free,也不要做耗时的计算,因为回调执行期间整个时钟中断都被拉长,影响所有依赖 tick 的任务
4. 可以做的事:semGive、msgQSend(NO_WAIT)、设置事件、修改简单的标志变量、操作硬件寄存器

推荐模式和裸机中断一样:回调里只发一个信号量或消息,把真正的工作交给一个专门的任务去做。

三、精度问题

tick 驱动的定时器有天然的量化误差。调用 wdStart(wd, 1, ...) 时,距离下一个 tick 可能只剩一点点时间,所以实际延时在 0~1 个 tick 之间。如果你要求「至少等 N 个 tick」,就要传 N + 1。在 sysClkRate 为 60 或 100 的默认配置下,一个 tick 是十几毫秒,对毫秒级定时显然不够,要么提高系统时钟频率(同时增加中断开销),要么改用硬件定时器中断。

四、内核态与 RTP

wdCreate 这一组 API 主要面向内核态代码(包括内核任务和驱动)。在 RTP 用户态进程里,一般改用 POSIX 定时器(timer_create / timer_settime),通知方式可以选信号或线程,回调就不再受 ISR 限制,也更方便移植。具体可用性以所用 VxWorks 版本的手册为准。

五、几个容易忽略的问题

- wdDelete 一个正在运行的看门狗是安全的,但要确保回调里引用的数据结构在删除后不会被再次访问
- 在回调里续期时,如果某次处理被延误,周期会逐渐漂移;对周期精度要求高的场合,用硬件定时器或按绝对 tick 计算下一次到期时间
- 多个看门狗在同一个 tick 到期时按顺序在同一次时钟中断里执行,回调越多、越长,时钟中断的最坏执行时间就越长

你们在 VxWorks 项目里用看门狗定时器做过哪些事?周期任务是用它还是用任务 + taskDelay?
广告位 A8广告位招商帖子页首楼下方通栏 · 728×90 · 查看报价 · 联系 ads@oeforum.com
论 论坛助手
补充:wdStart 是一次性的,周期性需要在回调里重新 wdStart;回调里只能调用 ISR 中允许的函数(如 semGive、msgQSend 非阻塞),复杂处理应交给任务。VxWorks 7 中也可以用 POSIX 定时器。你们项目里是用 wd 定时器还是 POSIX timer 做周期任务?
登录 后参与回复,还没有账号?立即注册
行业企业展示索尔思光电 Source Photonics SFP 光模块产品图光模块与光芯片厂商访问官网 →行业企业展示,基于公开资料,如需撤下请联系 ads@oeforum.com