没有合适的资源?快使用搜索试试~ 我知道了~
嵌入式linux系统看门狗实现原理
4星 · 超过85%的资源 需积分: 35 39 下载量 32 浏览量
2011-07-23
17:43:02
上传
评论
收藏 73KB DOCX 举报
温馨提示
试读
13页
看门狗实现原理 看门狗实现原理 看门狗实现原理 看门狗实现原理 看门狗实现原理
资源推荐
资源详情
资源评论
首先,咱们先看看有关 S3C2440 上看门狗的硬件电路:
从结构图和数据手册得知,看门狗 Watchdog 主要是实现系统自动复位的功能,它是利用
芯片内部的定时器,定时输出连接到电路的复位端,程序在一定时间范围内对定时器清零(俗称
“喂狗”),当程序在正常工作时,定时器总是不能溢出,也就不能产生复位信号;一旦程序出现
错误,可能就无法在定时周期内复位看门狗,那么定时器就会溢出而产生复位信号使系统复位。
S3C2440 的 Watchdog 模块提供了三个寄存器来对 Watchdog 进行操作,他们分别是:
定时器控制寄存器 WTCON、定时器数据寄存器 WTDAT 和定时器计数寄存器 WTCNT。注意:
在对定时器数据寄存器 WTDAT 进行操作时必须在定时器控制寄存器 WTCON 使能之前写入一
个计数目标值,当 Watchdog 使能开启后,WTDAT 中的值会自动被加载到计数寄存器
WTCNT 中,然后 Watchdog 从 CPU 内部的时钟分频和时钟除数因子得到一个工作周期,当
每个周期结束时计数寄存器 WTCNT 中的值会 1,直到递减为 0 时,如果还不重新往 WTCNT
中写入新的计数目标值(即“喂狗”),则 Watchdog 就产生复位信号使系统复位。
了解了大致的硬件原理后,咱们就开始结合驱动程序源代码,来讲解有关看门狗驱动程序的
写法。
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <mach/map.h>
#include <plat/regs-watchdog.h>
#dene S3C_VA_WATCHDOG (0)
#dene PFX "s3c2410-wdt:"
#dene CONFIG_S3C2410_WATCHDOG_ATBOOT (0)
#dene CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
static int nowayout = WATCHDOG_NOWAYOUT;
//nowayout 与 CONFIG_WATCHDOG_NOWAYOUT 配置相关,其一旦配置应用层调用
close 函数将不能关闭看门狗
static int tmr_margin =
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;//默认的喂狗时间
static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT;
//关于 tmr_atboot,要想系统一上电自动使能看门狗,就为 1。最好使用 0,由于我们想通过
open 函数来打开看门狗
static int soft_noboot;
//soft_noboot 为 1 时看门狗将作为一般的中断定时器使用,为 0 时作为可复位电路的看门狗,
默认为 0
static int debug; ////调式模式
/*驱动程序模块参数,如果在加载驱动模块时没有设定这些参数,则这些参数将采用默认值,
这些参数在接下来的步骤中将被一一用到,参数具体作用也将在各步骤中来说明*/
module_param(tmr_margin, int, 0);
module_param(tmr_atboot, int, 0);
module_param(nowayout, int, 0);
module_param(soft_noboot, int, 0);
module_param(debug, int, 0);
//下面的这些没什么大的作用,就是为了做参数描述
MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds.
default="
__MODULE_STRING(CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME)
")");
MODULE_PARM_DESC(tmr_atboot, "Watchdog is started at boot time if set
to 1, default="
__MODULE_STRING(CONFIG_S3C2410_WATCHDOG_ATBOOT));
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once
started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore
reboots, "
"0 to reboot (default depends on ONLY_TESTING)");
MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug,
(default 0)");
static unsigned long open_lock;
static struct device *wdt_dev; /* platform device attached to */
//用来保存 watchdog 的 IO 端口占用的 IO 空间和经过虚拟映射后的内存地址
static struct resource *wdt_mem;
static void __iomem *wdt_base;
static struct resource *wdt_irq;
//保存从平台时钟队列中获取 watchdog 的时钟
static struct clk *wdt_clock;
//用于保存经计算后得到的计数寄存器 WTCNT 的计数值
static unsigned int wdt_count;
static char expect_close;
static DEFINE_SPINLOCK(wdt_lock);
/* watchdog control routines */
#dene DBG(msg...) do { \ //打印调试信息
if (debug) \
printk(KERN_INFO msg); \
} while (0)
/* functions */
static void s3c2410wdt_keepalive(void) //喂狗
{
spin_lock(&wdt_lock);//获取自旋锁保护临界区资源
writel(wdt_count, wdt_base + S3C2410_WTCNT);//往计数寄存器
WTCNT 重新写入计数值
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);
}
static void s3c2410wdt_stop(void)
{
spin_lock(&wdt_lock);//获取自旋锁保护临界区资源
__s3c2410wdt_stop();
spin_unlock(&wdt_lock);//释放自旋锁,即解锁
}
static void s3c2410wdt_start(void)
{
unsigned long wtcon;
spin_lock(&wdt_lock);
剩余12页未读,继续阅读
资源评论
- xiaoqiu10172012-11-27感觉还可以,对于刚开始的人比较有用。
easyme
- 粉丝: 4
- 资源: 23
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功