the watchdog (watchdog) is divided between the hardware watchdog and the software watchdog. Hardware watchdog is the use of a timer circuit, its timing output is connected to the reset end of the circuit, the program in a certain time range to the timer 0 (commonly known as "feed the Dog"), if the program fails, not reset the watchdog during the scheduled period, Causes the watchdog timer overflow to generate a reset signal and restart the system. The software watchdog principle is just the same as the timer on the hardware circuit is replaced by the processor's internal timing device.
1 watchdog three registers
1.1 Watchdog principle
The s3c2410 is internally integrated with the watchdog, providing 3 registers to operate on the watchdog, the 3 registers are WTCON (watchdog control Register), WTDAT (watchdog data Register), and WTCNT (watchdog Count register) The s3c2440 of the watchdog is as follows:
As can be seen, the frequency of the watchdog timer is provided by PCLK, its prescaler maximum value is 255+1, in addition, through the MUX, can further reduce the frequency. The timer is in descending mode, and once it is 0, it can trigger the watchdog interrupt and reset signal. The frequency of the watchdog timer is calculated as follows:
T_watchdog = 1/[pclk/(prescaler value + 1)/division_factor]
1.2 Opening the s3c2410 watchdog
void enable watchdog () { Rwtcon = Wtcon DIV64 | Wtcon RSTEN;//64 crossover, open reset signal Rwtdat = 0x8000;//count target rwtcon |= wtcon enable;//turn on watchdog
1.3 s3c2410 's Watchdog "Feed the dog."
void Feed Dog () {
1.4 Watchdog usage Routines
void Main () { init system (); ... Enable watchdog ();//start watchdog ... while (1) { ... Feed Dog (); Feed the Dog }
2 data knots in the watchdog
One type of device is called a "platform device", and a separate peripheral unit that is typically integrated in the SoC system is treated as a platform device
2.1 Platform_device Structural Body
struct platform device { const char * name;//unit name u32 ID; struct device dev; U32 number of resources used by NUM resources;//devices struct resource * resource;//resources
2.2 Platform devices in the s3c2410
struct platform device *s3c24xx UART devs[];struct platform device s3c device USB;// USB controller struct platform device s3c device LCD; LCD controller struct Platform device s3c device WDT; Watchdog 2 struct platform device s3c Dev Ice i²c; I C controller struct platform device s3c device IIS; IIS struct platform device s3c device RTC; Real Time clock ... the platform device used by the/*SMDK2410 Development Board */static struct platform device *smdk2410 Devic Es[] InitData = {&s3c device USB,//usb &s3c device LCD,//LCD &S3C device WDT,//watchdog &S3C device i²c,//i C &S3C device IIS,//iis};
2.3 s3c2410 watchdog's platform_device structure
struct platform Device s3c device WDT = { . Name = "S3C2410-WDT", //device name . id = -1,. num resources = ARRAY SIZE (s3c WDT Resource), //resource quantity . Resource = s3c WDT resource, //Resources used by the watchdog
2.4 int platform_add_devices () function
int platform add devices (struct platform device **devs, int num) { int i, ret = 0; for (i = 0; i < num; i++) {ret = Platform device register (devs[i]);/* Register Platform Device */ if (ret)/* Registration failed */ { while (-i >= 0) platform device unregister (devs[i]);/* Unregister the registered platform device */break ; } } return ret;
2.5 Platform_driver Structural Body
struct platform driver { int (*probe) (struct platform device *);//Probe int (*remove) (struct platform device *) ;//Remove void (*shutdown) (struct platform device *);//close int (*suspend) (struct platform device *, PM message T State) ;//suspend Int (*resume) (struct platform device *);//restore the struct device driver driver;
2.6 s3c2410 watchdog's platform_driver structure
static struct platform driver S3C2410WDT Driver = { . Probe = S3C2410WDT probe,//s3c2410 watchdog detection . Remove = S3C2410WDT remove,//s3c2410 watchdog removed . Shutdown = S3C2410WDT shutdown,//s3c2410 watchdog off . Suspend = S3C2410WDT suspend,//s3c2410 watchdog hangs. Resume = S3C2410WDT Resume,//s3c2410 watchdog recovery . Driver = { . Owner = This MODULE, . Name = "S3C2410-WDT",//device name },};
Resources used by the 2.7 s3c2410 watchdog
static struct resource s3c WDT resource[] = { [0] = { . start = s3c24xx PA WATCHDOG, //watchdog I/O memory start position
.end = s3c24xx PA WATCHDOG + s3c24xx SZ WATCHDOG-1, //watchdog I/O memory end location . Flags = Ioresource MEM, //i/o memory Resources
}, [1] = { . start = IRQ WDT,//watchdog start IRQ number . end = IRQ WDT,//watchdog end IRQ Number . flags = Ioresource IRQ , //IRQ Resources }
2.8 s3c2410 watchdog-driven miscdevice structural body
static struct Miscdevice S3c2410wdt Miscdev = { . minor = WATCHDOG minor,//secondary device number . Name = " Watchdog ", . FoPs
2.9 s3c2410 watchdog-driven file operation structure
Static struct file operations S3c2410wdt fops = { . Owner = this MODULE, . Llseek = no llseek, //seek
.write = S3c2410wdt Write, //write function . IOCTL = S3C2410WDT ioctl,//ioctl function . Open = S3C2410WDT Open, //Opening function . release
3 Loading and unloading functions
The load and unload functions of the driver module are registered and unregistered with platform_driver_register () and Platform_driver_ unregister () respectively Platform_driver
3.1 s3c2410 watchdog driver
static int __init watchdog__init (void) { printk (banner); Return Platform Driver register (&S3C2410WDT driver);// Register platform driver } static void exit Watchdog exit (void) {platform driver unregister (&S3C2410WDT driver);// injection PIN platform driver
4 Detection and removal functions
4.1 Detection function
static int S3C2410WDT probe (struct platform device *pdev) {struct resource *res; int started = 0; int ret; int size; DBG ("%s:probe=%p\n", _ _function_ _, Pdev); /* Get the memory area of the watchdog */res = platform Get resource (Pdev, Ioresource MEM, 0); if (res = = NULL) {PRINTK (KERN INFO PFX "failed to get memory region resouce\n"); Return-enoent; } size = (Res->end-res->start) + 1; Request I/o memory WDT mem = Request Mem Region (Res->start, size, pdev->name); if (wdt mem = = NULL) {PRINTK (KERN INFO PFX "failed to get memory region\n"); Return-enoent; WDT base = Ioremap (Res->start, size); Device memory, virtual address if (wdt base = = 0) {PRINTK (KERN INFO PFX "failed To Ioremap () region\n "); Return-einval; } DBG ("Probe:mapped wdt base=%p\n", WDT base); /* Get the watchdog interrupt */RES = platform Get resource (Pdev, Ioresource IRQ, 0); if (res = = NULL) {PRINTK (KERN INFO PFX "failed to get IRQ resource\n"); Return-enoent; }//Request interrupt RET = Request IRQ (Res->start, S3C2410WDT IRQ, 0, Pdev->name, Pdev); if (ret! = 0) {PRINTK (KERN INFO PFX "failed to install IRQ (%d) \ n", ret); return ret; WDT Clock = CLK get (&pdev->dev, "watchdog"); Get watchdog clock source if (wdt clock = = NULL) {PRINTK (KERN INFO PFX "failed to fin D watchdog clock source\n "); Return-enoent; } CLK enable (WDT clock); /* See if you can setThe timeout for the timer is the desired value, and if not, use the default value */if (S3C2410WDT set heartbeat (TMR margin)) { started = S3c2410wdt set Heartbeat (CONFIG s3c2410 Watchd OG DEFAULT time); if (started = = 0) {PRINTK (KERN INFO PFX "TMR margin value out of range, defaul T%d used\n ", CONFIG s3c2410 WATCHDOG DEFAULT time); } else {PRINTK (KERN INFO PFX "Default timer value is out of range, cannot start\n "); }}//register miscdevice RET = Misc Register (&S3C2410WDT Miscdev); if (ret) {PRINTK (KERN ERR PFX "Cannot registermiscdev on minor=%d (%d) \ n", WATCHDOG MINOR, ret); return ret; } if (TMR atboot && started = = 0) {PRINTK (KERN INFO PFX "Starting Watchdog Ti Mer\n "); S3C2410WDT start (); } return 0; }
4.2 Detection function
static int S3C2410WDT Remove (struct platform device *dev) { if (WDT mem! = NULL) { release resource (WDT MEM); Release Resource Kfree (WDT mem);//Free memory WDT mem = NULL; } Release Interrupt if (WDT IRQ! = NULL) {free IRQ (WDT irq->start, dev); WDT IRQ = NULL; } //disable clock source if (WDT clock! = NULL) { clk disable (WDT clock); CLK put (WDT clock); WDT Clock = NULL; } Misc deregister (&S3C2410WDT miscdev);//logout Miscdevice return 0;
5 Suspend and Resume functions
5.1 Suspend function
static int S3C2410WDT suspend (struct platform device *dev, PM message T State) {/ * save watchdog status, Stop it * /Wtcon save = READL (WDT base + s3c2410 Wtcon); Wtdat save = READL (WDT base + s3c2410 wtdat); S3c2410wdt stop (); return 0;
5.2 Restore function
static int S3C2410WDT Resume (struct platform device *dev) { /* restore watchdog status * /Writel (Wtdat Save, WDT base + S 3c2410 wtdat); Writel (Wtdat save, WDT base + s3c2410 wtcnt); Writel (Wtcon save, WDT base + s3c2410 Wtcon); PRINTK (KERN INFO PFX "Watchdog%sabled\n", (Wtcon save &s3c2410 wtcon ENABLE)? "en": "dis"); return 0;
6 opening and releasing functions
6.1 Opening functions
static int S3C2410WDT open (struct inode *inode, struct file *file) { if (down Trylock (&open Lock)) //Get Hit Unlock return -ebusy; if (nowayout) { module get (this module); } Else {Allow close = Close state allow; } /* Start watchdog * /S3C2410WDT start (); Return nonseekable open (inode, file);
6.2 Release function
static int S3C2410WDT release (struct inode *inode,struct file *file) {/ * stop watchdog * /if (allow close = = Close S TATE allow) { s3c2410wdt stop (); } else { PRINTK (KERN crit PFX "Unexpected close, not stopping watchdog!\n"); S3C2410WDT keepalive (); } Allow close = Close is not; Up (&open lock); Release Open lock return 0;
7 Start-stop watchdog functions and write functions
7.1 Start-stop watchdog function
/* Stop watchdog */static int s3c2410wdt stop (void) {unsigned long wtcon; Wtcon = Readl (WDT base + s3c2410 Wtcon); Stop watchdog, disable reset Wtcon &= ~ (s3c2410 wtcon ENABLE | s3c2410 Wtcon Rsten); Writel (Wtcon, WDT base + s3c2410 Wtcon); return 0; }/* Turn on Watchdog */static int s3c2410wdt start (void) {unsigned long wtcon; S3c2410wdt Stop (); Wtcon = Readl (WDT base + s3c2410 Wtcon); Enable watchdog, 128-way Wtcon |= s3c2410 Wtcon Enable | s3c2410 Wtcon DIV128; if (soft noboot) {Wtcon |= s3c2410 wtcon inten;//Enable interrupt Wtcon &= ~s3c2410 Wtcon rsten; Disable Reset} else { Wtcon &= ~s3c2410 Wtcon inten; Prohibit interruption Wtcon |= s3c2410 Wtcon rsten; Enable reset} DBG ("%s:wdt count=0x%08x, wtcon=%08lx\n", FUNCTION, WDT count, Wtcon); Writel (WDT count, WDT base + s3c2410 wtdat); Writel (WDT count, WDT base + s3c2410 wtcnt); Writel (Wtcon, WDT base + s3c2410 Wtcon); return 0; }
7.2 Write function
Static Ssize t S3C2410WDT write (struct file *file, const char user *data, size t len, Loff t *ppos) {/ * Refresh Watchdog */ if (len) { if (!nowayout) { size t i; Allow close = Close is not; for (i = 0; I! = Len; i++) { char C; if (get User (c, data + i))//user space, kernel space , return-efault; if (c = = ' V ') //If a ' V ' is written, allow closing allowed close = Close state allows ;} } S3C2410WDT keepalive (); } return Len;
The watchdog device drive of ~linux equipment drive