[原创]Blackfin ADSP BF561 Watch Dog定时器精析
0赞BF561这个强大地ADSP处理芯片中,有一个非常重要的看门狗定时器,针对我在Linux对这个部件的使用情况,给大家做个分析。使用这个部件主要用Visual DSP++这个工具.
实现:设计一个WatchDog驱动与应用程序,每10秒去喂狗一次,watchdog timeout时间小于1分钟。
1 WatchDog驱动程序需要的库文件
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/watchdog.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
2 WatchDog初始参数的设置
//WTCON
#define BLACKFIN_WTCON_PRESCALER(x) (x <<8) // x= 0 - 255
#define BLACKFIN_WTCON_ENABLE 0x0020
#define BLACKFIN_WTCON_CLOCK(x) (x<<3) // x = 0, 1, 2, 3
#define BLACKFIN_WTCON_INTEN 0x0004
#define BLACKFIN_WTCON_RESET 0x0001
//WTDAT
#define BLACKFIN_WTDAT_COUNT 0xFFFF
//WTCNT
#define BLACKFIN_WTCNT_COUNT 0xFFFF
static int timer_alive;
static u8 soft_margin = 44; // in seconds timeout value (0, 44) seconds
3 WatchDog设置函数
void Blackfin_wdt_config(void)
{
//_reg_CRM_PCCR1 |= 0x01000000; //enable clk gate to watchdog
WTCON &= ~BLACKFIN_WTCON_ENABLE;
WTDAT = BLACKFIN_WTDAT_COUNT;
WTCNT = BLACKFIN_WTCNT_COUNT;
WTCON = BLACKFIN_WTCON_PRESCALER(255) | // set prescaler value
BLACKFIN_WTCON_ENABLE | // watchdog timer enable
BLACKFIN_WTCON_CLOCK(3) | // set clock divider value
BLACKFIN_WTCON_INTEN | // watchdog timer interrupt enable
BLACKFIN_WTCON_RESET; // watchdog timer reset enable
}
4 Watchdog的read函数
static ssize_t Blackfin_wdt_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
{
//Refresh the timer.
if (len) {
Blackfin_wdt_config();
return 1;
}
return 0;
}
5 Watchdog的ioctl 函数
static int Blackfin_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int new_margin;
switch(cmd) {
case WDIOC_KEEPALIVE:
Blackfin_wdt_config();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, (int *)arg))
return -EFAULT;
if (new_margin < 0)
return -EINVAL;
if (new_margin > 44)
new_margin = 44;
//soft_margin = new_margin;
return 0;
case WDIOC_GETTIMEOUT:
return put_user(soft_margin, (int *)arg);
default:
return -ENOTTY;
}
}
6 Watchdog的open 函数
static int Blackfin_wdt_open(struct inode *inode, struct file *file)
{
int ret;
if (timer_alive)
return -EBUSY;
ret = request_irq(IRQ_WDT, Blackfin_wdt_interrupt, SA_INTERRUPT, "Blackfin-watchdog", NULL);
if (ret) {
printk(KERN_ERR "watchdog: can't request irq: %d \n", INT_WDOG);
return ret;
}
Blackfin_wdt_config();
MOD_INC_USE_COUNT;
timer_alive = 1;
return 0;
}
6 Watchdog的release 函数
static int Blackfin_wdt_release(struct inode *inode, struct file *file)
{
lock_kernel();
free_irq(INT_WDOG, NULL);
timer_alive = 0;
unlock_kernel();
MOD_DEC_USE_COUNT;
return 0;
}
7 Watchdog的fops结构体
static struct file_operations Blackfin_wdt_fops = {
owner: THIS_MODULE,
write: Blackfin_wdt_write,
ioctl: Blackfin_wdt_ioctl,
open: Blackfin_wdt_open,
release: Blackfin_wdt_release,
};
掌握了这些我们在使用看门狗的时候才会得心应手,堪称ADI利器。