看门狗 驱动程序

  • 格式:doc
  • 大小:184.00 KB
  • 文档页数:10

看门狗是当CPU进入错误状态后,无法恢复的情况下,使计算机重新启动有两种办法来处理这种情况:一是:采用人工复位的方法

二是:依赖于某种硬件来执行这个复位工作。这种硬件通常叫做看门狗(Watch Dog,WD)

看门狗实际上是一个定时器,其硬件内部维护了一个定时器,每当时钟信号到来时,计数寄存器减1。如果减到0,则系统重启.

如果在减到0之前,系统又设置计数寄存器一个较大的值,那么系统永远不会重启。系统的这种设置能力表示系统一直处于一种正常运行状态。反之,如果计算机系统崩溃,那么就无法重新设置计数寄存器的值。当计数寄存器为0,系统重启

看门狗的工作原理很简单,处理器内部一般都集成了一个看门狗硬件。其提供了三个寄存器

看门狗控制寄存器(WTCON)

看门狗数据寄存器(WTDAT)

看门狗计数寄存器(WTCNT)

结合上图可知,看门狗从一个PCLK频率到产生一个RESET复位信号的过程如下:

1,处理器向看门狗提供一个PCLK时钟信号。其通过一个8位预分频器(8-bit Prescaler)使频率降低

2,8位预分频器由控制寄存器WTCON的第8~15位决定。分频后的频率就相当于PCLK除以(WTCON[15:8]+1).

3,然后再通过一个4相分频器,分成4种大小的频率。这4种频率系数分别是16,32,64,128.看门狗可以通过寄存器的3,4位决定使用哪种频率 4,当选择的时钟频率到达计数器(Down Counter)时,会按照工作频率将WTCNT减1.当达到0时,就会产生一个中断信号或者复位信号

5,如果控制寄存器WTCOON的第二位为1,则发出一个中断信号;如果控制寄存器WTCON第0位为1,则输出一个复位信号,使系统重新启动

看门狗驱动涉及两种设备模型,分别是平台设备和混杂设备

平台设备模型:

从Linux2.6起引入了一套新的驱动管理和注册模型,即平台设备platform_device和平台驱动platform_driver.Linux中大部分的设备驱动,都可以使用这套机制,设备用platform_device表示,驱动用platform_driver表示

平台设备模型与传统的device和driver模型相比,一个十分明显的优势在于平台设备模型将设备本身的资源注册进内核,由内核统一管理。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性。通过平台设备模型开发底层驱动的大致流程为下图:

平台设备是指处理器上集成的额外功能的附加设备,如Watch

Dog,IIC,IIS,RTC,ADC等设备。这些额外功能设备是为了节约硬件成本、减少产品功耗、缩小产品形状而集成到处理器内部的。需要注意的是,平台设备并不是与字符设备、块设备和网络设备并列的概念,而是一种平行的概念,其从另一个角度对设备进行了概括。如果从内核开发者的角度来看,平台设备的引入,是为了更容易开发字符设备、块设备和网络设备驱动

平台设备结构体(platform_device)

struct platform_device

{

const char *name; //平台设备的名字,与驱动的

名字对应

int id; //与驱动绑定有关,一般为-1

struct device dev; //设备结构体说明platform_device派生于device

u32 num_resources; //设备使用的资源数量

struct resource *resource; //指向资源的数组,数量由num_resources指定

};

看门狗的平台设备为:

struct platform_device s3c_device_wdt = {

.name = "s3c2410-wdt",

.id = -1,

.num_resources = ARRAY_SIZE(s3c_wdt_resource),

.resource = s3c_wdt_resource,

};

为了统一管理平台设备的资源,在platform_device机构体中定义了平台设备所使用的资源。

看门狗的资源如下:

static struct resource s3c_wdt_resource[] = {

[0] = { // I/O资源指向看门狗的寄存器

.start = S3C24XX_PA_WATCHDOG, //看门狗I/O内存开始位置,被定义为WTCON的地址0x53000000

.end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, //1M的地址空间

.flags = IORESOURCE_MEM,

//I/O内存资源

},

[1] = { //IRQ资源

.start = IRQ_WDT, //看门狗的开始中断号,被定义为80

.end = IRQ_WDT,

//看门狗的结束中断号 .flags = IORESOURCE_IRQ,

//中断的IRQ资源 }

}; struct resource

{ resource_size_t start; //资源的开始地址,resource_size是32位或者64位的无符号整数

resource_size_t end; //资源的结束地址 const char *name; //资源名

unsigned long flags; //资源的类型 (IORESOURCE_IO,IORESOURCE_MEM,IORESOURCE_IRQ,IORESOURCE_DMA等)

struct resource *parent,*sibling,*child; //用于构建资源的树形结构 };

通过platfrom_add_devices()函数可以将一组设备添加到系统中,其主要完成以下两个功能:

1,分配平台设备所使用的资源,并将这些资源挂接到资源树中

2,初始化device设备,并将设备注册到系统中

第一个参数是平台设备数组的指针,第2个参数是平台设备的数量

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]); if (ret) {

while (--i >= 0) platform_device_unregister(devs[i]);

break; }

} return ret;

}

通过platform_get_resource()函数可以获得平台设备的resource资源:

第一个参数dev是平台设备的指针,第2个参数type是资源的类型,这些类型可以是(IORESOURCE_IO,IORESOURCE_MEM,IORESOURCE_IRQ,IORESOURCE_DMA等),第3个参数num是同种资源的索引。例如一个平台设备有3哥IORESOURCE_MEM资源,如果要获得第2个资源,那么需要使num等于1

struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)

{ int i;

for (i = 0; i < dev->num_resources; i++) {

struct resource *r = &dev->resource[i];

if (type == resource_type(r) && num-- == 0)

return r;

}

return NULL;

}

平台设备驱动 :

每一个平台设备都对应一个平台设备驱动,这个驱动用来对平台设备进行探测、移除、关闭和电源管理等操作。

struct platform_driver {

int (*probe)(struct platform_device *); //探测函数

int (*remove)(struct platform_device *); //移除函数

void (*shutdown)(struct platform_device *); //关闭设备时调用该函数

int (*suspend)(struct platform_device *, pm_message_t state); //挂起函数

int (*suspend_late)(struct platform_device *, pm_message_t state); //挂起之后调用的函数

int (*resume_early)(struct platform_device *); //恢复正常状态之前调用的函数

int (*resume)(struct platform_device *); //恢复正常状态的函数