linux-wdt 原理和任意超时时间设置的解决方法

2023-10-12 13:20

本文主要是介绍linux-wdt 原理和任意超时时间设置的解决方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Watchdog Timer的缩写字母,也就是看门狗,是一个定时器电路。这个电路的功能是维护系统的正常运行,如果遇到系统卡死的情况可以自动的从硬件上复位系统。简单来说是用软件发现问题,用硬件操作解决问题。
wdt 描述
可以看到整个模块是内部一个timer计数器,外部输入一个timer 的复位信号,输出一个中断信号和一个复位信号。
流程是:
1.设置复位超时时间
2.内部计数器进行减数计时,减到0 输出中断,数据又更新到复位超时时间,然后再减数运行,再次减到0 输出硬件的复位信号,系统复位。也有不产生中断直接第一次减数到0就输出复位信号,直接系统复位的。
3.软件在复位时间内复位timer ,保证timer 内部的数不到0.
内部计数寄存器
通过调整输入时钟可以改变reset 的时间,达到自动控制系统死机重启的功能。
可以看到这个寄存器的设置档位只有7:4,也就只能设置16个不同的时间周期,并且这个周期是以2的n次方的方式,并不是通常理解的线性时间设置,16个档位肯定不能满足需求,目标必须是任意时间都可以设置,硬件如此就只能通过软件解决了。
解决办法:
1.将硬件wdt 重启时间设置成为0.5秒,这样一般也就满足了日常应用的最小时间设置。
在open 函数就启动wdt,
···
static int fh_wdt_open(struct inode *inode, struct file *filp)
{
if (test_and_set_bit(0, &fh_wdt.in_use))
return -EBUSY;

/* Make sure we don't get unloaded. */
__module_get(THIS_MODULE);spin_lock(&fh_wdt.lock);if(fh_wdt.plat_data && fh_wdt.plat_data->resume)fh_wdt.plat_data->resume();fh_wdt_set_top(WDT_HW_TIMEOUT);///3000);
if (!fh_wdt_is_enabled())
{/** The watchdog is not currently enabled. Set the timeout to* the maximum and then start it.*/u32 value;value = WDOG_CONTROL_REG_WDT_EN_MASK;writel(value, fh_wdt.regs + WDOG_CONTROL_REG_OFFSET);//设置硬件最小的超时时间fh_wdt_keepalive();
}fh_wdt_set_next_heartbeat();spin_unlock(&fh_wdt.lock);return nonseekable_open(inode, filp);

}
···
2.驱动中起一个timer 定时器,定时时间小于硬件wdt重启时间,进行软件喂狗。放置硬件定时器重启。

	setup_timer(&fh_wdt.timer, fh_wdt_ping, 0);mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);
static void fh_wdt_ping(unsigned long data)
{if (time_before(jiffies, fh_wdt.next_heartbeat) ||(!nowayout && !fh_wdt.in_use)) {fh_wdt_keepalive();mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);} elsepr_crit("keepalive missed, machine will reset\n");
}

3.驱动解析应用设置的重启时间,接收应用喂狗的信息。

应用调用ioctl 配置一个全局变量用来记录软件任意时间的超时时间heartbeat。

	case WDIOC_SETTIMEOUT:if (get_user(val, (int __user *)arg))return -EFAULT;pr_debug("[wdt] settime value %lu", val);heartbeat =  val;fh_wdt_keepalive();fh_wdt_set_next_heartbeat();return put_user(val , (int __user *)arg);

驱动把超时时间记录在fh_wdt.next_heartbeat中

static inline void fh_wdt_set_next_heartbeat(void)
{fh_wdt.next_heartbeat = jiffies + heartbeat * HZ;
}

也可以通过write 来写

ssize_t fh_wdt_write(struct file *filp, const char __user *buf, size_t len,loff_t *offset)
{if (!len)return 0;if (!nowayout) {size_t i;fh_wdt.expect_close = 0;for (i = 0; i < len; ++i) {char c;if (get_user(c, buf + i))return -EFAULT;if (c == 'V') {fh_wdt.expect_close = 1;break;}}}fh_wdt_set_next_heartbeat();mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);//启动下一次的超时时间return len;
}

4.如若应用在自己设置的超时时间之内喂狗,则一直维护这个timer。如果应用在自己设置的超时时间内没有喂狗,这个timer 调用的硬件喂狗停止,放任硬件wdt 重启系统。
每0.5s timer循环进行调用fh_wdt_ping 进行时间比对,当前时间jffies 是否超过了应用预设时间fh_wdt_next_hearbeat,没超过硬件喂狗,超过不喂狗。

static void fh_wdt_ping(unsigned long data)
{if (time_before(jiffies, fh_wdt.next_heartbeat) ||(!nowayout && !fh_wdt.in_use)) {fh_wdt_keepalive();mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);继续喂狗,设置0.5s重启} elsepr_crit("keepalive missed, machine will reset\n");停止喂狗
}

总结

用软件方法解决硬件的局限

这篇关于linux-wdt 原理和任意超时时间设置的解决方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/xuweiwei1860/article/details/86346013
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/196111

相关文章

Python将字符串转换为小写字母的几种常用方法

《Python将字符串转换为小写字母的几种常用方法》:本文主要介绍Python中将字符串大写字母转小写的四种方法:lower()方法简洁高效,手动ASCII转换灵活可控,str.translate... 目录一、使用内置方法 lower()(最简单)二、手动遍历 + ASCII 码转换三、使用 str.tr

Python处理超大规模数据的4大方法详解

《Python处理超大规模数据的4大方法详解》在数据的奇妙世界里,数据量就像滚雪球一样,越变越大,从最初的GB级别的小数据堆,逐渐演变成TB级别的数据大山,所以本文我们就来看看Python处理... 目录1. Mars:数据处理界的 “变形金刚”2. Dask:分布式计算的 “指挥家”3. CuPy:GPU

解决Java异常报错:java.nio.channels.UnresolvedAddressException问题

《解决Java异常报错:java.nio.channels.UnresolvedAddressException问题》:本文主要介绍解决Java异常报错:java.nio.channels.Unr... 目录异常含义可能出现的场景1. 错误的 IP 地址格式2. DNS 解析失败3. 未初始化的地址对象解决

Java中的StringUtils.isBlank()方法解读

《Java中的StringUtils.isBlank()方法解读》:本文主要介绍Java中的StringUtils.isBlank()方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录所在库及依赖引入方法签名方法功能示例代码代码解释与其他方法的对比总结StringUtils.isBl

springboot+vue项目怎么解决跨域问题详解

《springboot+vue项目怎么解决跨域问题详解》:本文主要介绍springboot+vue项目怎么解决跨域问题的相关资料,包括前端代理、后端全局配置CORS、注解配置和Nginx反向代理,... 目录1. 前端代理(开发环境推荐)2. 后端全局配置 CORS(生产环境推荐)3. 后端注解配置(按接口

CentOS7增加Swap空间的两种方法

《CentOS7增加Swap空间的两种方法》当服务器物理内存不足时,增加Swap空间可以作为虚拟内存使用,帮助系统处理内存压力,本文给大家介绍了CentOS7增加Swap空间的两种方法:创建新的Swa... 目录在Centos 7上增加Swap空间的方法方法一:创建新的Swap文件(推荐)方法二:调整Sww

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

Python日期和时间完全指南与实战

《Python日期和时间完全指南与实战》在软件开发领域,‌日期时间处理‌是贯穿系统设计全生命周期的重要基础能力,本文将深入解析Python日期时间的‌七大核心模块‌,通过‌企业级代码案例‌揭示最佳实践... 目录一、背景与核心价值二、核心模块详解与实战2.1 datetime模块四剑客2.2 时区处理黄金法

macOS Sequoia 15.5 发布: 改进邮件和屏幕使用时间功能

《macOSSequoia15.5发布:改进邮件和屏幕使用时间功能》经过常规Beta测试后,新的macOSSequoia15.5现已公开发布,但重要的新功能将被保留到WWDC和... MACOS Sequoia 15.5 正式发布!本次更新为 Mac 用户带来了一系列功能强化、错误修复和安全性提升,进一步增

Oracle 通过 ROWID 批量更新表的方法

《Oracle通过ROWID批量更新表的方法》在Oracle数据库中,使用ROWID进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销,下面给大家介绍Orac... 目录oracle 通过 ROWID 批量更新表ROWID 基本概念性能优化建议性能UoTrFPH优化建议注