Embedded Linux in my line--s3c2440 watchdog Driver Development Example explain __linux

Source: Internet
Author: User
Tags error handling goto
Http://blog.chinaunix.net/uid-22174347-id-1786939.html

Embedded Linux in my line, mainly narrated and summed up in my study of embedded Linux in each step. One for summing up experience, two want to be able to get into embedded Linux friends to provide convenience. If there is any mistake, please correct me. Share resources, Welcome to reprint: http://hbhuanggang.cublog.cn

first, development environment Host: Vmware--fedora 9 Development Board: MINI2440--64MB Nand, kernel:2.6.30.4 compiler: arm-linux-gcc-4.3.2

Ii. Related Concepts

1, platform equipment and platform equipment driver:
This is in front of: s3c2440 on the RTC clock-driven Development example explained in the explanation. Here we only need to know the system for us to define the watchdog (watchdog) Platform equipment and resource situation, in ARCH/ARM/PLAT-S3C24XX/DEVS.C, as follows:

* Watchdog * *

/* Defines the resources used by the watchdog platform device, which uses the */
Static struct resource s3c_wdt_resource[in the driver = {
     [0] = {/*watchdog used IO Port resource range */
        .start = S3c24xx_pa_ Watchdog,
        .end   = S3c24xx_pa_watchdog + s3c24xx_sz_ WATCHDOG-1,
        .flags = Ioresource_mem,
    &NBSP},
    [1] = { /*watchdog Interrupt resource */
         .start = IRQ_WDT,
        .end   = IRQ_WDT,
         .flags = Ioresource_irq,
    
};

/* Defines the watchdog platform equipment * *
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,/* Refer to the resource defined above * *
};

Export_symbol (S3C_DEVICE_WDT);

2. Miscellaneous equipment (Misc equipment)
The misc device is a special character device defined by Linux as the main device Number 10, because it does not conform to the category of character devices, so it is summed up as a misc device, there are many such devices in Linux, such as: LED devices, watchdog devices, etc. The system distinguishes which device is based on the device's secondary unit number, which is usually defined in include/linux/miscdevice.h. In Linux, the Miscdevice structure is used to describe a misc device, which means that the interface function in the structure body is to be implemented in the driver of the misc device. The structure is also defined in Miscdevice.h, as follows:

struct Miscdevice {
int minor;
const char *name;
const struct File_operations *fops;
struct List_head list;
struct device *parent;
struct device *this_device;
};

Third, the example explanation

1, watchdog hardware structure diagram analysis:

We know from the structure diagram and the data manual that watchdog watchdog mainly realizes the system automatically resets the function, he is utilizes the chip internal timer, the timing output connects to the circuit the reset end, the program in a certain time range to the timer clear 0 (commonly known as "feeds the dog"), therefore the procedure in the normal work, The timer always cannot overflow, also cannot produce the reset signal, if the program error, does not reset the watchdog in the timer cycle, then the timer will overflow and produces the reset signal to cause the system to reset.

The s3c2440 watchdog module provides three registers to operate the watchdog, which are: Timer control register Wtcon, timer data register Wtdat and timer count register wtcnt. Note: In the Timer data register Wtdat operation must be in the Timer control register before the Wtcon can be written to a count target value, when the watchdog can be opened, Wtdat value will automatically be loaded into the count register wtcnt, The watchdog then obtains a work cycle from the CPU's internal clock frequency divider and the clock divisor factor, when the value in the Count register wtcnt at the end of each cycle is 1 until decremented to 0 o'clock, if the new count target value (i.e. "Feed dog") is not written back to the wtcnt. Then the watchdog produces a reset signal to reset the system. Please refer to the data manual for the function of these registers and the operation values of each bit of register.

2, watchdog driver specific implementation steps (build driver file my2440_watchdog.c):

Note: In each step, in order to make the code logic more organized and easy to understand, the order of the Code is not considered, such as when the function is first defined and then called. If you want to compile this code, adjust the order of your code strictly according to the C language specification.

①, still the most basic structure of the driver: watchdog-driven initialization and uninstall section and other, as follows:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>

/*watchdog platform-driven structure, the platform-driven structure is defined in platform_device.h, and the interface function of the structure is realized in ② and ④ step.
static struct Platform_driver Watchdog_driver =
{
. Probe = Watchdog_probe,/*watchdog probe function, implemented in step ②
. remove = __devexit_p (watchdog_remove),/*watchdog remove function, implemented in step ④
. Shutdown = Watchdog_shutdown,/*watchdog close function, implemented in step ④
. Suspend = watchdog_suspend,/*watchdog suspend function, implemented in step ④
. Resume = Watchdog_resume,/*watchdog recovery function, implemented in step ④
. Driver =
{
/* Note that the name must be consistent with the system's definition of the platform device so that the platform device can be associated with the driver of the platform device.
. Name = "S3C2410-WDT",
. Owner = This_module,
},
};

static int __init watchdog_init (void)
{
* * Register watchdog as a platform device driver/*
Return Platform_driver_register (&watchdog_driver);
}

static void __exit watchdog_exit (void)
{
/* Unregister watchdog Platform device driver * *
Platform_driver_unregister (&watchdog_driver);
}

Module_init (Watchdog_init);
Module_exit (Watchdog_exit);

/* Driver module parameters, if these parameters are not set when the drive module is loaded, they will take the default values.
These parameters will be used in the next step in one by one, and the specific effect of the parameters will be explained in each step.
Module_param (tmr_margin, int, 0);
Module_param (tmr_atboot, int, 0);
Module_param (nowayout, int, 0);
Module_param (soft_noboot,int, 0);

Module_license ("GPL");
Module_author ("Huang Gang");
Module_description ("My2440 watchdog Driver");


②,The realization of detection function watchdog_probe in watchdog platform driving structure. Detection means detecting the presence of the device in the system bus, and then obtaining relevant resource information that is useful for the device so that we can use that information. The code is as follows:

#include <linux/irq.h>
#include <asm/io.h>
#include <linux/clk.h>
#include <linux/ioport.h>
#include <plat/regs-watchdog.h>
#include <linux/miscdevice.h>

/* Defines an IO space used to hold the watchdog IO port and a virtual mapped memory address.
static struct resource *wdt_mem;
static void __iomem *wdt_base;

/* Save watchdog interrupt number, NO_IRQ macro definition in Irq.h * *
static int wdt_irqno = NO_IRQ;

/* Save the watchdog clock from the platform clock queue * *
static struct CLK *wdt_clock;

#define CONFIG_WATCHDOG_ATBOOT (0)
#define CONFIG_WATCHDOG_DEFAULT_TIME (15)
static int tmr_atboot = Config_watchdog_atboot;
static int tmr_margin = Config_watchdog_default_time;
static int soft_noboot;
The static unsigned int wdt_count;/* is used to hold the count value of the counted register wtcnt computed.

/* Declare and initialize a spin lock wdt_pie_lock, mutually exclusive access to watchdog Resources * *
Static Define_spinlock (Wdt_pie_lock);

static int __devinit watchdog_probe (struct platform_device *pdev)
{
int ret;
int started = 0;
struct Resource *res;/* defines a resource that is used to hold the IO resource of the acquired watchdog.

/* Get watchdog interrupt number in the system-defined watchdog platform device
PLATFORM_GET_IRQ definition in Platform_device.h * *
Wdt_irqno = PLATFORM_GET_IRQ (Pdev, 0);
if (Wdt_irqno < 0)
{
/* Get watchdog Interrupt no success error handling
Dev_err is defined in device.h and is already referenced in platform_device.h, so there is no need to quote it here.
Dev_err (&pdev->dev, "No IRQ for watchdog\n");
Return-enoent;
}

/* Request watchdog interrupt service, here is a quick interrupt: irqf_disabled.
Interrupt Service Program is: WDT_IRQ, watchdog platform equipment Pdev to pass through the past * *
ret = REQUEST_IRQ (wdt_irqno, WDT_IRQ, irqf_disabled, Pdev->name, Pdev);
if (ret)
{
/* ERROR Handling * *
Dev_err (Dev, "irq%d error%d\n", wdt_irqno, ret);
return ret;
}

/* Obtain the IO port resource used by the watchdog platform device, and note that this IORESOURCE_MEM logo and watchdog platform device definition are consistent/*
res = Platform_get_resource (Pdev, Ioresource_mem, 0);
if (res = = NULL)
{
/* ERROR Handling * *
Dev_err (&pdev->dev, "failed to get memory region resource\n");
Return-enoent;
}

/* Get the watchdog clock from the platform clock queue, why do you want to get this clock, because the watchdog timer's work cycle is made up of this
The clock and the clock divisor factor are obtained. Note that the watchdog parameters here are consistent with the name of the clock defined in the system to obtain the
said that the system must first be defined with watchdog. Some of the system's clocks are defined in ARCH/ARM/PLAT-S3C24XX/S3C2410-CLOCK.C.
Wdt_clock = Clk_get (&pdev->dev, "watchdog");
if (Is_err (Wdt_clock))
{
/* ERROR Handling * *
Dev_err (&pdev->dev, "failed to find watchdog clock source\n");
Return Ptr_err (Wdt_clock);
}

* * Clock after the acquisition to enable the use, clk_enable definition in the ARCH/ARM/PLAT-S3C/CLOCK.C * *
Clk_enable (Wdt_clock);

/* Request IO Space occupied by IO port resources for watchdog (be aware of the difference between IO space and memory space)
Request_mem_region definition in Ioport.h * *
Wdt_mem = Request_mem_region (Res->start, Res->end-res->start + 1, pdev->name);
if (Wdt_mem = NULL)
{
/* ERROR Handling * *
Dev_err (&pdev->dev, "failed to reserve memory region\n");
ret =-enoent;
Goto ERR_NOCLK;
}

/* The IO space occupied by the watchdog IO Port is mapped to the virtual address of the memory, Ioremap defined in io.h.
Note: Io space to be mapped before use, the operation of the virtual address is the operation of IO space, * *
Wdt_base = Ioremap (Res->start, Res->end-res->start + 1);
if (wdt_base = NULL)
{
/* ERROR Handling * *
Dev_err (&pdev->dev, "failed Ioremap () \ n");
ret =-einval;
Goto Err_noreq

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.