前面两篇一篇分析了看门狗定时器的驱动架构,另一篇分析了平台设备对应的probe函数,虽然对应的remove函数没分析,其实和别的平台设备驱动一样,做和probe函数相反的工作。这一篇要说点啥呢?
S3c2410_wdt.c (linux2.6.28driverswatchdog)在这个文件中还有很多函数,我们都没有分析过,这一篇就找些重要的函数分析下。
1、那就先从s3c2410wdt_start函数开始,此函数开启看门狗,源码如下:
static void s3c2410wdt_start(void)
{
unsigned long wtcon;
spin_lock(&wdt_lock);
__s3c2410wdt_stop();先停止看门狗便于设置
wtcon = readl(wdt_base + S3C2410_WTCON);读控制寄存器WTCON
wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;
这里的定义:
#define S3C2410_WTCON_ENABLE (1<<5)
#define S3C2410_WTCON_DIV128 (3<<3)
对照下面的寄存器图,更直观:
if (soft_noboot) { 这个标志第一篇中说明了它的作用,不明的可以回过去查看。等于1,作为定时器使用。
wtcon |= S3C2410_WTCON_INTEN;使能中断
wtcon &= ~S3C2410_WTCON_RSTEN;不允许发出复位信号
} else {等于0,看门狗做复位电路使用
wtcon &= ~S3C2410_WTCON_INTEN;禁止中断
wtcon |= S3C2410_WTCON_RSTEN;允许复位
}
DBG("%s: wdt_count=0x%08x, wtcon=%08lxn",
__func__, wdt_count, wtcon);
writel(wdt_count, wdt_base + S3C2410_WTDAT);写数据寄存器
writel(wdt_count, wdt_base + S3C2410_WTCNT);写计数器寄存器
writel(wtcon, wdt_base + S3C2410_WTCON);写控制寄存器
spin_unlock(&wdt_lock);
}
2、接着说s3c2410wdt_stop函数,停止看门狗工作。
static void s3c2410wdt_stop(void)
{
spin_lock(&wdt_lock);
__s3c2410wdt_stop();
spin_unlock(&wdt_lock);
}
static void __s3c2410wdt_stop(void)
{
unsigned long wtcon;
wtcon = readl(wdt_base + S3C2410_WTCON);
wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);使看门狗不工作,不发出复位信号
writel(wtcon, wdt_base + S3C2410_WTCON);
}
3、s3c2410wdt_shutdown此函数用于停止看门狗
static void s3c2410wdt_shutdown(struct platform_device *dev)
{
s3c2410wdt_stop();
}
4、s3c2410wdt_suspend该函数用于电源管理,挂起设备
static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state)
{
/* Save watchdog state, and turn it off. */保存看门狗当前状态
wtcon_save = readl(wdt_base + S3C2410_WTCON);
wtdat_save = readl(wdt_base + S3C2410_WTDAT);
/* Note that WTCNT doesn't need to be saved. */
s3c2410wdt_stop();关闭看门狗
return 0;
}
5、s3c2410wdt_resume也与电源管理有关,挂起后的恢复
static int s3c2410wdt_resume(struct platform_device *dev)
{
/* Restore watchdog state. */恢复各寄存器的设置
writel(wtdat_save, wdt_base + S3C2410_WTDAT);
writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
writel(wtcon_save, wdt_base + S3C2410_WTCON);
printk(KERN_INFO PFX "watchdog %sabledn",
(wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
return 0;
}
6、再来看s3c2410wdt_fops结构体中的函数:
static const struct file_operations s3c2410wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = s3c2410wdt_write,
.unlocked_ioctl= s3c2410wdt_ioctl,
.open = s3c2410wdt_open,
.release = s3c2410wdt_release,
};
6.1、先看s3c2410wdt_open函数:在用户调用open函数时被调用。源码如下:
/*
* /dev/watchdog handling
*/
static int s3c2410wdt_open(struct inode *inode, struct file *file)
{
printk("s3c2410wdt_open.n");
if (test_and_set_bit(0, &open_lock))
return -EBUSY;
调用此函数测试open_lock的第0位。为0则表示此函数返回0,表示设备没有被另外的程序打开。如果第0位为1,则表示设备已经被打开,返回EBUSY
if (nowayout)不为0,表示看门狗不允许关闭,则增加看门狗模块的引用计数。
__module_get(THIS_MODULE);
allow_close = CLOSE_STATE_NOT;设为不允许关闭
/* start the timer */
s3c2410wdt_start();打开设备
return nonseekable_open(inode, file);不允许调用seek函数,即不允许对设备进行定位。
}
6.2、接着看s3c2410wdt_release函数,在close函数中被调用。函数源码如下:
static int s3c2410wdt_release(struct inode *inode, struct file *file)
{
/*
* Shut off the timer.
* Lock it in if it's a module and we set nowayout
*/
if (allow_close == CLOSE_STATE_ALLOW)看门狗为允许关闭
s3c2410wdt_stop();关闭看门狗
else {
dev_err(wdt_dev, "Unexpected close, not stopping watchdogn");
s3c2410wdt_keepalive();使看门狗为活动状态
}
其中s3c2410wdt_keepalive函数源码如下:
static void s3c2410wdt_keepalive(void)
{
spin_lock(&wdt_lock);
writel(wdt_count, wdt_base + S3C2410_WTCNT);重新写计数寄存器
spin_unlock(&wdt_lock);
}
allow_close = CLOSE_STATE_NOT;设为不允许关闭
clear_bit(0, &open_lock);将open_lock的第0位设为0,允许打开
return 0;
}
6.3、再来看s3c2410wdt_write函数,该函数主要用来设置allow_close变量为允许关闭状态。如果向设备中写入V,那么就允许关闭设备。源码如下:
static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
/*
* Refresh the timer.
*/
printk("s3c2410wdt_write.n");
if (len) {
if (!nowayout) { 允许关闭
size_t i;
/* In case it was set long ago */
allow_close = CLOSE_STATE_NOT 不允许关闭
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
allow_close = CLOSE_STATE_ALLOW;
}如果往看门狗设备中写入V,允许关闭
}
s3c2410wdt_keepalive();
}
return len;
}
6.4、现在来看一个比较重要的函数,s3c2410wdt_ioctl函数用来接受系统的命令,设置看门狗的状态。
static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
int new_margin;
printk("s3c2410wdt_ioctl.n");
switch (cmd) {
case WDIOC_GETSUPPORT:获取看门狗的信息
return copy_to_user(argp, &s3c2410_wdt_ident,
sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
其中有定义:
#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE
static const struct watchdog_info s3c2410_wdt_ident = {
.options = OPTIONS,
.firmware_version = 0,
.identity = "S3C2410 Watchdog",
};
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS: 获得看门狗状态
return put_user(0, p);
case WDIOC_KEEPALIVE: 对看门狗进行喂狗
s3c2410wdt_keepalive();
return 0;
case WDIOC_SETTIMEOUT:设置新的超时时间
if (get_user(new_margin, p))
return -EFAULT;
if (s3c2410wdt_set_heartbeat(new_margin))
return -EINVAL;
s3c2410wdt_keepalive();
return put_user(tmr_margin, p);
case WDIOC_GETTIMEOUT:获得看门狗的当前超时时间
return put_user(tmr_margin, p);
default:
return -ENOTTY;
}
}
6.5、不知道你还记得吗?我们在probe函数中,申请的中断,并设置中断处理函数是s3c2410wdt_irq,现在来说这个函数,源码如下:
/* interrupt handler code */
static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
{
dev_info(wdt_dev, "watchdog timer expired (irq)n");
s3c2410wdt_keepalive();
return IRQ_HANDLED;
}
其实就是喂狗。
————————————————
版权声明:本文为CSDN博主「tianxiawuzhei」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tianxiawuzhei/article/details/7588824
上一篇:s3c6410在linux下的WATCHDOG TIMER(看门狗定时器)驱动(1)
下一篇:s3c6410的RTC在linux中的驱动(2)
推荐阅读最新更新时间:2024-11-10 19:15
设计资源 培训 开发板 精华推荐
- ch9350验证板
- DC1211A-C,使用 LTC3528EDDB-2 1A、1MHz 同步升压转换器的演示板,在 DFN 自动突发模式下具有输出断开连接
- OP484ESZ-REEL 高端负载电流监控器的典型应用
- 适用于 ADP1196、5V、3A 逻辑控制高端或低端负载开关的典型高端负载应用电路
- MSOP 中 LTC1661IMS8 微功率双路 10 位 DAC 的典型应用电路
- AD8659ARZ 4 mA至20 mA电流环路变送器的典型应用电路
- LT1072HVCT 具有外部电流限制的高效开关稳压器的典型应用
- AD8618ARUZ-REEL高速光电二极管前置放大器典型应用电路
- LDK120PU-R ADJ低压降稳压器典型应用固定电路
- LTC3441 的典型应用 - 大电流微功率同步降压-升压型 DC/DC 转换器
- 有奖直播:Keysight World Tech Day 2024 汽车分论坛|汽车自动驾驶与新能源
- 【温故喝新之单片机版块】温2016年MCUs,喝2017年版块新篇章
- 恩智浦LPC2000系列全套资料!
- 仲夏狂欢,TI 博文学习季再度热力来袭!
- 汽车VCU知识问答第一站:了解VCU系统框图和功能清单
- 了解 TE Connectivity 无创想,不奇迹 精彩专题,答题送好礼!
- 有奖评测+DIY:玩转新版1.3元单片机CH554,赢以太网分析仪器/USB分析仪
- TE 福利月|有奖调查、技术干货、限时折扣
- TI有奖直播|精密 ADC 在变送器中的应用
- 剁手不如玩板,这个双11免费好板等你来玩!