powerpc平台watchdog总结

1. 硬件原理图

这里使用了ADM706芯片,wdi喂狗引脚与CPUGPIO3相连。

wdo看门狗超时复位信号输出引脚,与/MR手动复位输入相连,也就是会产生一个RESET信号。

原理图如下所示:

powerpc平台watchdog总结_第1张图片

2. uboot中添加watchdog喂狗功能

首先需要在include/configs/xxx.h文件中,添加一个宏定义:

#defineCONFIG_HW_WATCHDOG

启动HW_WATCHDOG功能。

 

因为在include/watchdog.h中有WATCHDOG宏定义如下:

#ifdefCONFIG_HW_WATCHDOG

        #if defined(__ASSEMBLY__)

                #define WATCHDOG_RESET blhw_watchdog_reset

        #else

                extern voidhw_watchdog_reset(void);

 

                #define WATCHDOG_RESEThw_watchdog_reset

        #endif /* __ASSEMBLY__ */

#else

        /*

         * Maybe a software watchdog?

         */

        #if defined(CONFIG_WATCHDOG)

                #if defined(__ASSEMBLY__)

                        #define WATCHDOG_RESETbl watchdog_reset

                #else

                        extern voidwatchdog_reset(void);

 

                        #define WATCHDOG_RESETwatchdog_reset

                #endif

        #else

                /*

                 * No hardware or softwarewatchdog.

                 */

                #if defined(__ASSEMBLY__)

                        #define WATCHDOG_RESET/*XXX DO_NOT_DEL_THIS_COMMENT*/

                #else

                        #defineWATCHDOG_RESET() {}

                #endif /* __ASSEMBLY__ */

        #endif /* CONFIG_WATCHDOG &&!__ASSEMBLY__ */

#endif/* CONFIG_HW_WATCHDOG */

 

在定义了CONFIG_HW_WATCHDOG宏之后,系统就会使用hw_watchdog_reset()函数,二者个函数就定义在arch/powerpc/cpu/mpc85xx/cpu.c文件中,这里使用的是powerpc的P2020芯片,也就是MPC85xx系列芯片。

 

添加watchdog功能代码实现如下:

 

#ifdefCONFIG_HW_WATCHDOG

 

#defineGPIO_REG_BASE   0xFFE0F000

#defineGPIO_REG_GPDIR  (GPIO_REG_BASE + 0x00)

#defineGPIO_REG_GPODR  (GPIO_REG_BASE + 0x04)

#defineGPIO_REG_GPDAT  (GPIO_REG_BASE + 0x08)

#defineGPIO_3_OFFSET   0x10000000

 

void

watchdog_adm_reset(void)

{

        *(volatile unsigned int*)GPIO_REG_GPDIR |= GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPODR &= ~GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPDAT &= ~GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPDAT |= GPIO_3_OFFSET;

}

 

void

hw_watchdog_reset(void)

{

        watchdog_adm_reset();

}

#endif

 

Uboot中基本是到处都使用了一个WATCHDOG_RESET宏,基本上每运行一段时间就会调用这个宏来喂狗,这样实现的一个看门狗伪狗功能。

3. linux驱动中添加一个看门狗喂狗程序

这个驱动很简单,就是添加一个定时器,每隔一段时间就喂狗一次。

代码如下:

/*

 *     Driver for GPIO-controlled ADM706 Hardware Watchdogs.

 *

 */

 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

 

#defineGPIO_REG_BASE   0xFFE0F000

#defineGPIO_REG_GPDIR  (gpio_mem + 0x00)

#defineGPIO_REG_GPODR  (gpio_mem + 0x04)

#defineGPIO_REG_GPDAT  (gpio_mem + 0x08)

#defineGPIO_3_OFFSET   0x10000000

 

staticvoid *gpio_mem;

 

void

watchdog_adm_reset(void)

{

        *(volatile unsigned int *)GPIO_REG_GPDIR|= GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPODR &= ~GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPDAT &= ~GPIO_3_OFFSET;

        *(volatile unsigned int*)GPIO_REG_GPDAT |= GPIO_3_OFFSET;

}

 

staticstruct {

        spinlock_t lock;

        struct timer_list timer;

        int interval;

        int first_interval;

}adm_wdt_device;

 

staticvoid adm_wdt_trigger(unsigned long unused)

{

        spin_lock(&adm_wdt_device.lock);

        watchdog_adm_reset();

        mod_timer(&adm_wdt_device.timer, jiffies+ adm_wdt_device.interval);

        spin_unlock(&adm_wdt_device.lock);

}

 

staticvoid adm_wdt_start(void)

{

        unsigned long flags;

 

       spin_lock_irqsave(&adm_wdt_device.lock, flags);

        mod_timer(&adm_wdt_device.timer,jiffies + adm_wdt_device.first_interval);

       spin_unlock_irqrestore(&adm_wdt_device.lock, flags);

}

 

staticint __init adm_wdt_init(void)

{

        printk(KERN_INFO "ADM706 watchdogstart feeding\n");

 

        spin_lock_init(&adm_wdt_device.lock);

 

        setup_timer(&adm_wdt_device.timer,adm_wdt_trigger, 0L);

        adm_wdt_device.first_interval = 0;

        adm_wdt_device.interval =msecs_to_jiffies(1000);

 

        gpio_mem = ioremap(GPIO_REG_BASE, 100);

        adm_wdt_start();

 

        return 0;

}

arch_initcall(adm_wdt_init);

 

staticvoid __exit adm_wdt_exit(void)

{

        printk(KERN_INFO "ADM706 watchdogstop feeding\n");

        iounmap(gpio_mem);

        del_timer(&adm_wdt_device.timer);

}

module_exit(adm_wdt_exit);

 

MODULE_AUTHOR("XiaohaiXu");

MODULE_DESCRIPTION("Driverfor GPIO controlled ADM706 watchdogs");

MODULE_LICENSE("GPL");

MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

MODULE_ALIAS("adm706gpio-controlled watchdog");

你可能感兴趣的:(watchdog)