OpenHarmony喂狗源码解读之内核态源码 原创 精华
民之码农
发布于 2022-1-17 09:24
浏览
9收藏
春节不停更,此文正在参加「星光计划-春节更帖活动」https://harmonyos.51cto.com/posts/9923
@[toc](OpenHarmony3.1Beta喂狗内核源码解读
一、喂狗的芯片手册资料
1.概述
看门狗 WatchDog 用于系统异常情况下,一定时间内发出复位信号,以复位整个系统。系统提供 2 个 WatchDog 模块。
2.特点
WatchDog 具备以下特点:
内部具有一个 32bit 减法计数器。
支持超时时间间隔(即计数初值)可配置。
支持寄存器锁定,防止寄存器被误改。
支持超时中断产生。
支持复位信号产生。
支持调试模式
3.DG 寄存器概览
具体详细的内核请查看附件芯片手册
二、内核态代码分析
1.定义喂狗IO地址
- 代码位置
device\hisilicon\hispark_taurus\sdk_linux\soc\src\interdrv\common\wtdg\arch\hi3516cv500\hi_wtdg_hal.h
#define HIWDT_BASE 0x12051000 /* define watchdog IO */
2.代码函数接口分析
-
设置超时函数代码
static void hidog_set_timeout(unsigned int nr)
{
unsigned int cnt_0 = ~0x0;
unsigned int cnt = cnt_0 / g_rate; /* max cnt */
unsigned long flags;
osal_spin_lock_irqsave(&g_hidog_lock, &flags);
if ((nr == 0) || (nr > cnt)) {
cnt = ~0x0;
} else {
cnt = nr * g_rate;
}
/* unlock watchdog registers */
hiwdt_writel(HIWDT_UNLOCK_VAL, HIWDT_LOCK);
hiwdt_writel(cnt, HIWDT_LOAD);
hiwdt_writel(cnt, HIWDT_VALUE);
/* lock watchdog registers */
hiwdt_writel(0, HIWDT_LOCK);
osal_spin_unlock_irqrestore(&g_hidog_lock, &flags);
}
-
喂狗函数代码:
static void hidog_feed(void)
{
unsigned long flags;
/* read the RIS state of current wdg */
unsigned int v = (unsigned int)hiwdt_readl(HIWDT_RIS);
v &= 0x1; /* 0x1: get INT bit [1] */
if (v == 0) { /* no INT on current wdg */
return;
}
osal_spin_lock_irqsave(&g_hidog_lock, &flags);
/* unlock watchdog registers */
hiwdt_writel(HIWDT_UNLOCK_VAL, HIWDT_LOCK);
/* clear watchdog */
hiwdt_writel(0x00, HIWDT_INTCLR);
/* lock watchdog registers */
hiwdt_writel(0, HIWDT_LOCK);
osal_spin_unlock_irqrestore(&g_hidog_lock, &flags);
}
-
喂狗开始函数
static void hidog_start(void)
{
unsigned long flags;
osal_spin_lock_irqsave(&g_hidog_lock, &flags);
/* unlock watchdog registers */
hiwdt_writel(HIWDT_UNLOCK_VAL, HIWDT_LOCK);
hiwdt_writel(0x00, HIWDT_CTRL); /* 0x00: disable watch dog reset signal and interrupt */
hiwdt_writel(0x00, HIWDT_INTCLR); /* 0x00: clear interrupt */
hiwdt_writel(0x03, HIWDT_CTRL); /* 0x03: enable watch dog reset signal and interrupt */
/* lock watchdog registers */
hiwdt_writel(0, HIWDT_LOCK);
osal_spin_unlock_irqrestore(&g_hidog_lock, &flags);
g_options = WDIOS_ENABLECARD;
}
-
内核接口函数
/* Kernel Interfaces */
static struct osal_fileops g_hidog_fops = {
.unlocked_ioctl = hidog_ioctl,
.open = hidog_open,
.release = hidog_release,
};
hidog_open 是用户态句柄代码开始喂狗
hidog_release是用户态停止喂狗,设置喂狗超时时间,并喂一次狗;
hidog_ioctl是设置喂狗参数,获取喂狗参数或者喂狗的函数接口;
-
寄存器的读写
g_wtdg_reg_base = (volatile void *)osal_ioremap(HIWDT_BASE, 0x1000); /* 0x1000: watch dog reg length */
#define hiwdt_io_address(x) ((uintptr_t)g_wtdg_reg_base + (x) - HIWDT_BASE)
#define hiwdt_readl(x) osal_readl(hiwdt_io_address(hiwdt_reg(x)))
#define hiwdt_writel(v, x) osal_writel(v, hiwdt_io_address(hiwdt_reg(x)))
寄存器的读写是寄存器的物理地址通过ioremap转换成虚拟内存地址再进行读写的,程序退出需要对ioremap的地址进行iounmap。
-
watchdog_init函数中创建字符设备接口和接口函数进行注册
g_hidog_miscdev = osal_createdev("watchdog");
g_hidog_miscdev->minor = WATCHDOG_MINOR;
g_hidog_miscdev->fops = &g_hidog_fops;
if (osal_registerdevice(g_hidog_miscdev) != 0) {
-
内核线程喂狗
dog = osal_kthread_create(hidog_deamon, NULL, "hidog");
喂狗模块watchdog_init初始化之后开始喂狗,先有内核喂狗,内核是慢喂狗 30.01s喂一次狗;而用户态(watchdog_service 10 2)接管喂狗是重新设置的了超时时间12s,快于内核的喂狗时间,只要用户态设置的时间超过30s那么用户态停止喂狗,将继续有内核态喂狗。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
Hi3516DV300 专业型 Smart IP Camera SoC .pdf 12.07M 74次下载
已于2022-1-20 15:49:09修改
赞
13
收藏 9
回复
相关推荐
结合大佬之前的文章食用更佳
OpenHarmony喂狗源码解读之启动喂狗服务
https://harmonyos.51cto.com/posts/9945
OpenHarmony喂狗源码解读之用户态源码
https://harmonyos.51cto.com/posts/9967
配合以下阅读,效果更佳
1、OpenHarmony喂狗源码解读之启动喂狗服务
https://harmonyos.51cto.com/posts/9945
2、OpenHarmony喂狗源码解读之内核态源码
https://harmonyos.51cto.com/posts/9966
3、OpenHarmony喂狗源码解读之用户态源码
https://harmonyos.51cto.com/posts/9967
4、OpenHarmony喂狗源码解读之Linux内核原生喂狗配置
https://harmonyos.51cto.com/posts/9969