Transplantation of Linux-3.6.6 Based on S3C2440 -- Application of watchdog timer

Source: Internet
Author: User

In Linux, for the S3C2440 Development Board, the watchdog timer has been configured by default, for example:

Devicedrivers --->

[*] Watchdog timer support --->

<*> S3C2410 Watchdog

However, the watchdog timer is not enabled, so we will see the following message when starting the system:

S3c2410-wdts3c2410-wdt: watchdoginactive, reset disabled, IRQ disabled

 

The following is a detailed analysis of the watchdog timer.

The watchdog timer platform device has been added to the Mach-zhaocj2440.c file:

Static struct platform_device * zhaocj2440_devices [] _ initdata = {

......

& Amp; cloud_device_wdt,

......

};

The specific definition of this platform device is given in the Devs. c file under the arch/ARM/Plat-Samsung directory:

Struct platform_device initi_device_wdt = {

. Name = "s3c2410-wdt ",

. ID =-1,

. Num_resources = array_size (maid ),

. Resource = maid,

};

The Platform driver corresponding to the platform device is defined in the s3c2410_wdt.c file under the drivers/watchdog directory:

Static struct platform_driver s3c2410wdt_driver = {

. Probe = s3c2410wdt_probe,

. Remove = _ devexit_p (s3c2410wdt_remove ),

. Shutdown = s3c2410wdt_shutdown,

. Suspend = s3c2410wdt_suspend,

. Resume = s3c2410wdt_resume,

. Driver = {

. Owner = this_module,

. Name = "s3c2410-wdt ",

. Of_match_table = of_match_ptr (s3c2410_wdt_match ),

},

};

 

At the beginning of the s3c2410_wdt.c file, several important variables are defined:

# Define config_s3c2410_watchdog_atboot (0)

# Define config_s3c2410_watchdog_default_time (15)

 

Static bool nowayout = watchdog_nowayout;

Static int tmr_margin = config_s3c2410_watchdog_default_time;

Static int tmr_atboot = config_s3c2410_watchdog_atboot;

Static int soft_noboot;

Static int debug;

The nowayout variable indicates whether the watchdog timer is allowed to be disabled. 1 indicates no, and 0 indicates yes. The variable tmr_margin indicates the longest time interval for dog feeding. The default power-on time is config_s3c2410_watchdog_default_time, that is, it takes at least 15 seconds to assign a value to the watchdog timer. Otherwise, the timer will overflow and the system will reset. The variable tmr_atboot indicates whether to enable the watchdog after the system starts, 1 indicates enabling, and 0 indicates disabling, because config_s3c2410_watchdog_atboot is 0, the dog does not open after the system starts. Therefore, even if the dog is configured during compilation, no dog needs to be fed; the variable soft_noboot indicates whether to use the watchdog as a general timer.

 

In the s3c2410_wdt.c file, an important structure is also defined:

Static struct watchdog_device s3c2410_wdd = {

. Info = & s3c2410_wdt_ident,

. Ops = & s3c2410wdt_ops,

};

 

Where. Ops points to the s3c2410wdt_ops structure:

Static struct watchdog_ops s3c2410wdt_ops = {

. Owner = this_module,

. Start = s3c2410wdt_start,

. Stop = s3c2410wdt_stop,

. Ping = s3c2410wdt_keepalive,

. Set_timeout = s3c2410wdt_set_heartbeat,

};

The s3c2410wdt_start function is used to enable the dog guard. The s3c2410wdt_keepalive function is used to feed the dog. The s3c2410wdt_set_heartbeat function is used to set the timed interval of the dog guard.

 

The following describes the s3c2410wdt_probe function:

Static int _ devinit s3c2410wdt_probe (struct platform_device * pdev)

{

Structdevice * dev;

Unsignedint wtcon;

Intstarted = 0;

Intret;

Intsize;

 

Dbg ("% s: Probe = % P \ n", _ FUNC __, pdev );

 

Dev = & pdev-> dev;

Wdt_dev = & pdev-> dev;

 

// Obtain the memory ing space used by the watchdog platform device

Wdt_mem = platform_get_resource (pdev, ioresource_mem, 0 );

If (wdt_mem = NULL ){

Dev_err (Dev, "no memory resource specified \ n ");

Return-enoent;

}

 

// Obtain the interrupt number used by the watchdog platform device

Wdt_irq = platform_get_resource (pdev, ioresource_irq, 0 );

If (wdt_irq = NULL ){

Dev_err (Dev, "No IRQ resource specified \ n ");

Ret =-enoent;

Gotoerr;

}

 

/* Get the memory region for the watchdog timer */

 

// Obtain the memory size

Size = resource_size (wdt_mem );

If (! Request_mem_region (wdt_mem-> Start, size, pdev-> name )){

Dev_err (Dev, "failed to get memory region \ n ");

Ret =-ebusy;

Gotoerr;

}

 

// Obtain the memory base address

Wdt_base = ioremap (wdt_mem-> Start, size );

If (wdt_base = NULL ){

Dev_err (Dev, "failed to ioremap () region \ n ");

Ret =-einval;

Gotoerr_req;

}

 

Dbg ("probe: mapped wdt_base = % P \ n", wdt_base );

 

// Obtain the watchdog clock from the platform clock queue

Wdt_clock = clk_get (& pdev-> Dev, "Watchdog ");

If (is_err (wdt_clock )){

Dev_err (Dev, "failed to find watchdog clock source \ n ");

Ret = ptr_err (wdt_clock );

Gotoerr_map;

}

 

// Enable the watchdog clock

Clk_enable (wdt_clock );

 

// Register the CPU frequency

Ret = s3c2410wdt_cpufreq_register ();

If (Ret <0 ){

Pr_err ("failedto register cpufreq \ n ");

Gotoerr_clk;

}

 

/* See if we can actually set the requested timer margin, and if

* Not, try the default value */

// Set the overflow interval of the watchdog timer

If (s3c2410wdt_set_heartbeat (& s3c2410_wdd, tmr_margin )){

Started = s3c2410wdt_set_heartbeat (& s3c2410_wdd,

Config_s3c2410_watchdog_default_time );

 

If (started = 0)

Dev_info (Dev,

"Tmr_margin value out of range, default % d used \ n ",

Config_s3c2410_watchdog_default_time );

Else

Dev_info (Dev, "Default timer value is out of range ,"

"Cannotstart \ n ");

}

 

// Apply for timed interruption of the watchdog, because the watchdog timer can also be used when the general timer is interrupted.

Ret = request_irq (wdt_irq-> Start, s3c2410wdt_irq, 0, pdev-> name, pdev );

If (Ret! = 0 ){

Dev_err (Dev, "failed to install IRQ (% d) \ n", RET );

Gotoerr_cpufreq;

}

 

// Set the watchdog attribute by the value of nowayout

Watchdog_set_nowayout (& s3c2410_wdd, nowayout );

 

// Register the watchdog Device

Ret = watchdog_register_device (& s3c2410_wdd );

If (RET ){

Dev_err (Dev, "cannot register watchdog (% d) \ n", RET );

Gotoerr_irq;

}

 

// The tmr_atboot value determines whether to enable the watchdog timer.

If (tmr_atboot & started = 0 ){

Dev_info (Dev, "Starting watchdog timer \ n ");

S3c2410wdt_start (& s3c2410_wdd );

} Else if (! Tmr_atboot ){

/* If we're not enabling the watchdog, then ensure it is

* Disabled if it has been left running fromthe bootloader

* Or other source */

 

S3c2410wdt_stop (& s3c2410_wdd );

}

 

/* Print out a Statement of readiness */

// Print the status information of the watchdog, that is, the watchdog information displayed when the system starts.

Wtcon = readl (wdt_base + s3c2410_wtcon );

 

Dev_info (Dev, "watchdog % sactive, reset % sabled, IRQ % sabled \ n ",

(Wtcon & s3c2410_wtcon_enable )? "": "In ",

(Wtcon & s3c2410_wtcon_rsten )? "EN": "dis ",

(Wtcon & s3c2410_wtcon_inten )? "EN": "dis ");

 

Return0;

// Handle error exceptions

Err_irq:

Free_irq (wdt_irq-> Start, pdev );

 

Err_cpufreq:

S3c2410wdt_cpufreq_deregister ();

 

Err_clk:

Clk_disable (wdt_clock );

Clk_put (wdt_clock );

Wdt_clock = NULL;

 

Err_map:

Iounmap (wdt_base );

 

Err_req:

Release_mem_region (wdt_mem-> Start, size );

 

Err:

Wdt_irq = NULL;

Wdt_mem = NULL;

Returnret;

}

 

From the above introduction, we can see that the most important part of the s3c2410wdt_probe function is to call the watchdog_register_device function to register the watchdog. The watchdog_register_device function is in the watchdog_core.c file under the drivers/watchdog directory. The most important function of the watchdog_register_device function is to call the watchdog_dev_register function. It is registered as a miscellaneous device in the watchdog_dev.c file under the drivers/watchdog directory.

The miscellaneous device structure of the watchdog timer is as follows:

Static struct miscdevice watchdog_miscdev = {

. Minor = watchdog_minor,

. Name = "Watchdog ",

. Fops = & watchdog_fops,

};

 

The structure of watchdog_fops is:

Static const struct file_operationswatchdog_fops = {

. Owner = this_module,

. Write = watchdog_write,

. Unlocked_ioctl = watchdog_ioctl,

. Open = watchdog_open,

. Release = watchdog_release,

};

 

In watchdog_open, The watchdog_start function is called. In the watchdog_start function, the s3c2410wdt_start function in the s3c2410_wdt.c file is called to enable the watchdog. In watchdog_write, The watchdog_ping function is called. In the watchdog_ping function, the s3c2410wdt_keepalive function in the s3c2410_wdt.c file is called to feed the dog. In watchdog_ioctl, different operations on the watchdog are implemented, such as writing the watchdog, obtaining the status of the watchdog, and setting the timer time of the watchdog.

 

Next we will enable the dog guard function, and write an application to implement dog feeding to prevent system reset.

It is easy to enable the watchdog. You only need to change config_s3c2410_watchdog_atboot to 1 in the s3c2410_wdt.c file:

# Define config_s3c2410_watchdog_atboot (1)

 

After Linux is re-compiled, the following information is printed during system startup:

S3c2410-wdt s3c2410-wdt: Starting watchdog timer

S3c2410-wdt s3c2410-wdt: watchdog active, reset enabled, irqdisabled

 

At this time, if we do not implement the dog Feed function, the system will continue to reset and restart.

 

The following is the dog feeding application:

# Include <stdio. h>

# Include <unistd. h>

# Include <sys/STAT. h>

# Include <sys/types. h>

# Include <fcntl. h>

# Include <stdlib. h>

# Include <errno. h>

# Include <Linux/watchdog. h>

Intmain (INT argc, char ** argv ){

Int FD;

FD = open ("/dev/watchdog", o_rdonly );

If (FD <0 ){

Perror ("/dev/watchdog ");

Return-1;

}

For (;;){

IOCTL (FD, wdioc_keepalive );

Sleep (5 );

}

Close (FD );

Return 0;

}

 

We compile the above program into a wdt file, copy it to the bin directory of the root file system, and then modify the etc/init of the root file system. d/RCS file. Add wdt & at the end of the file to implement the dog feeding function in the background. The following is the content of the RCS file:

Mount-

Mkdir/dev/PTS

Mount-tdevpts devpts/dev/PTS

Echo/sbin/mdev>/proc/sys/kernel/hotplug

Mdev-S

Wdt &

Finally, recompile the root file system and write it to the Development Board. At this time, although the system has enabled the watchdog function, the system can still run normally because the backend is continuously feeding the dog.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.