snifer

[原创]Blackfin ADSP BF561 Watch Dog定时器精析

0
阅读(3910)

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利器。