Chinaunix首页 | 论坛 | 博客
  • 博客访问: 654839
  • 博文数量: 185
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2107
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(185)

文章存档

2024年(1)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2010-10-25 00:57:58

下面的代码让WatchDog也工作起来。

1.先执行命令"insmod wdt.ko",

2.再让WatchDog工作在reset模式“./app wdt_node”。此时一切正常.
    其中文件wdt_node由命令“sudo mknode wdt_node c 52 0”创建。
3.插入一个故障模块,使上一步中的进程得不到调度。很快,系统重启。

wdt.c代码如下:

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>

#include <asm/io.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zl");

#define WDT_MAGIC    'Y'
#define WDT_ON        _IOW(WDT_MAGIC, 0x00, int)
#define WDT_OFF        _IOW(WDT_MAGIC, 0x01, int)
#define WDT_MODE        _IOW(WDT_MAGIC, 0x02, int)
#define WDT_FEED        _IOW(WDT_MAGIC, 0x03, int)

struct watch_dog {
    unsigned long virt,phys;
    unsigned long wdtcon;
    unsigned long wdtdat;
    unsigned long wdtcnt;

    char name[1024];

    int reset_mode;
    int irq;

    void (*on)(struct watch_dog *);    
    void (*off)(struct watch_dog *);
    void (*mode)(struct watch_dog *, int);

    void (*feed)(struct watch_dog *);
    //----------------

    dev_t no;
    struct cdev dev;
};

void mywdt_on(struct watch_dog* mywdt)
{
    iowrite32(ioread32(mywdt->wdtcon) | (1 << 5), mywdt->wdtcon);
}

void mywdt_off(struct watch_dog* mywdt)
{
    iowrite32(ioread32(mywdt->wdtcon) & ~(1 << 5), mywdt->wdtcon);
}

void mywdt_mode(struct watch_dog* mywdt, int mymode)
{
    unsigned long tmp;
    mywdt->reset_mode = mymode;

    tmp = ioread32(mywdt->wdtcon);
    if(mywdt->wdtcon)
    {
        iowrite32((tmp & ~(1 << 2)) | 1, mywdt->wdtcon);            
    }
    else
    {
        iowrite32((tmp & ~1) | (1 << 2), mywdt->wdtcon);
    }

}
void mywdt_feed(struct watch_dog* mywdt)
{
    iowrite32(0x8000, mywdt->wdtcnt);
}

irqreturn_t mywdt_handle(int irq, struct watch_dog *mywdt)
{
    printk("wdt timer....\n");    
    return IRQ_HANDLED;
}

int init_watch_dog(struct watch_dog *mywdt, const char *name )
{
    int ret = 0;
    strcpy(mywdt->name, name);    
    mywdt->phys = 0x53000000;
    mywdt->irq = IRQ_S3C2440_WDT;
    mywdt->reset_mode = 0;

    ret = request_mem_region(mywdt->phys, SZ_4K, mywdt->name );
    if ((void *)ret == NULL) {
        ret = -EBUSY;
        goto err0;    
    }    
    
    ret = 0;
    mywdt->virt = ioremap(mywdt->phys, SZ_4K);
    if (mywdt->virt == NULL) {
        ret = -EBUSY;    
        goto err1;
    }

    mywdt->wdtcon = mywdt->virt + 0x00;
    mywdt->wdtdat = mywdt->virt + 0x04;
    mywdt->wdtcnt = mywdt->virt + 0x08;

    if (ret) {
        goto err2;    
    }

    mywdt->on = mywdt_on;
    mywdt->off = mywdt_off;
    mywdt->feed = mywdt_feed;
    mywdt->mode = mywdt_mode;

    iowrite32( 0x8004, mywdt->wdtcon);

    return ret;
err2:
    iounmap(mywdt->virt);
err1:
    release_mem_region(mywdt->phys, SZ_4K);    
err0:
    return ret;
}

void destroy_watch_dog(struct watch_dog *mywdt)
{
    iowrite32( 0x0, mywdt->wdtcon);
    iounmap(mywdt->virt);
    release_mem_region(mywdt->phys, SZ_4K);
    free_irq(mywdt->irq, mywdt);
}

//----------------------------------------

int mywdt_ioctl(struct inode *no, struct file *fp, unsigned long cmd, unsigned long arg)
{
    int ret = 0;
    struct watch_dog *mywdt = container_of(no->i_cdev, struct watch_dog, dev);

    switch(cmd) {
        case WDT_ON:
        mywdt->on(mywdt);
        break;

        case WDT_OFF:
        mywdt->off(mywdt);
        break;

        case WDT_MODE:
        mywdt->mode(mywdt, arg);
        break;

        case WDT_FEED:
        mywdt->feed(mywdt);
        break;

        default:
        ret = -EINVAL;
        break;
    }

    return ret;
}

struct watch_dog s3c2440_wdt;
struct file_operations s3c2440_wdt_ops = {
    .ioctl = mywdt_ioctl,
};
int test_init(void)
{
    int ret = 0;
    
    ret = init_watch_dog(&s3c2440_wdt, "s3c2440 watch dog");
    if (ret) {
        goto err0;
    }
    
    s3c2440_wdt.no = MKDEV(52, 0);
    ret = register_chrdev_region(s3c2440_wdt.no, 1, s3c2440_wdt.name);
    if (ret) {
        goto err1;    
    }

    cdev_init(&s3c2440_wdt.dev, &s3c2440_wdt_ops);
    cdev_add(&s3c2440_wdt.dev, s3c2440_wdt.no, 1);        

    return ret;
err1:
    destroy_watch_dog(&s3c2440_wdt);

err0:
    return ret;
}

void test_exit(void)
{
    destroy_watch_dog(&s3c2440_wdt);    
    cdev_del(&s3c2440_wdt.dev);
    unregister_chrdev_region(s3c2440_wdt.no, 1);
}

module_init(test_init);
module_exit(test_exit);


app.c文件代码创建一个守护进程,使WatchDog工作在reset模式。每0.1秒执行一次喂狗,内容如下:


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include "wdt.h"

int main(int argc, char **argv)
{
    int fd;
    unsigned cmd;
    if (argc < 2) {
        printf("Usage: %s \n", argv[0]);
        return 0;
    }

    fd = open(argv[1], O_RDWR);

    chdir("/");
    close(0);close(1);close(2);    

    if (fork()) {
        return 0;    
    }

    ioctl(fd, WDT_MODE, 1);
    ioctl(fd, WDT_ON);

    while(1) {
        ioctl(fd, WDT_FEED);    
        usleep(100 * 1000);
    }

    close(fd);
    return 0;
}


故障模块文件代码bad_module.c禁止内核抢占,然后一个死循环把系统卡死,这样上面的"./app wdt_node"命令启动的守护进程就得不到调度。代码如下:


#include

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zl");

int test_init(void)
{
    preempt_disable();
    while(1);

    return 0;
}

void test_exit(void)
{
}

module_init(test_init);
module_exit(test_exit);

阅读(1286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~