linux-wdt 原理和任意超時時間設定的解決方法
Watchdog Timer的縮寫字母,也就是看門狗,是一個定時器電路。這個電路的功能是維護系統的正常執行,如果遇到系統卡死的情況可以自動的從硬體上覆位系統。簡單來說是用軟體發現問題,用硬體操作解決問題。
可以看到整個模組是內部一個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);
} else
pr_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重啟
} else
pr_crit("keepalive missed, machine will reset\n");停止喂狗
}
總結
用軟體方法解決硬體的侷限
相關文章
- axios請求超時,設定重新請求的完美解決方法iOS
- Linux時間設定系統時間、硬體時間和時間服務Linux
- MyBatis自動設定建立時間和更新時間MyBatis
- Linux設定和修改時間與時區Linux
- 使用requests庫解決Session物件設定超時的問題Session物件
- win10 點選自動設定時間時間快1小時怎麼解決Win10
- 優雅的快取解決方案--設定過期時間快取
- MongoDB 超時設定MongoDB
- SSH 超時設定
- pip安裝selenium超時解決方法
- php 和 nginx 的幾個超時時間PHPNginx
- dubbo 超時設定和原始碼分析原始碼
- 解決代理超時問題的三種方法
- win10怎麼控制孩子玩電腦的時間 設定每日開放時段和允許時間的方法Win10
- **java設定一段程式碼執行超時時間(轉)**Java
- 設定mysql 事務鎖超時時間 innodb_lock_wait_timeoutMySqlAI
- python之為函式執行設定超時時間(允許函式執行的最大時間)Python函式
- win10 自動設定時間無法開啟怎麼解決_win10自動設定時間打不開解決步驟Win10
- Nodered學習記錄-時間戳和時區設定時間戳
- CSocket設定超時(轉)
- MSSQL資料庫超時的原因與解決方法SQL資料庫
- 解決studio 3T時間到期方法
- Win10系統怎麼設定回滾時間 win10系統設定回滾時間的方法Win10
- win10電腦怎麼設定英國時間_win10系統設定英國時間的方法Win10
- Windows10系統下鎖定螢幕超時的設定方法Windows
- 記一次.net core 非同步執行緒設定超時時間非同步執行緒
- PHP CURL 業務呼叫第三方介面設定超時時間PHP
- 包管理工具 NPM 和 yarn 下載超時解決方法NPMYarn
- Selenium爬蟲遇到超時TimeOut問題的解決方法爬蟲
- 2.6.7 設定DDL鎖超時
- win10鎖屏時間太短怎麼辦 設定鎖屏以及睡眠時間的方法Win10
- windows10系統設定時間自動更新的方法Windows
- Ubuntu 時間不準,怎麼設定NTP時間同步?Ubuntu
- WinAppDriver 等待時間設定技巧APP
- localStorage設定過期時間
- linux系統時間設定Linux
- js時間顯示設定JS
- localStorage設定儲存時間