[linux字符驱动]Watchdog如何躲过linux的启动时间

Watchdog做过项目的同学应该不会陌生,主要是启动程序守护作用,程序跑飞后能够让MCU重新复位,让设备进入正常工作模式,通常所说的看门狗,普通的看门狗喂狗的周期是1.6S,只要在1.6S的时间内,让看门狗的喂狗电平进行反转一次,看门狗内部的计数器就会清0,如果超过1.6S周期没有反转喂狗信号,则会发出一个下降沿的电平给MCU的RST引脚,MCU从而复位。
普通单片机的操作是这样的,如果换成了ARM系统,1.6S周期对于Linux来说,启动时间是不够的,先从bootstrap->uboot->kernel->文件系统->应用程序;这个过程下来大概要10S时间,已经算是非常快了。
我接触的Linux系统方案有以下两种:

1、看门狗的Rst引脚和ARM的Rst脚之间加一个使能芯片,就像是一个开关一样,默认是关闭的,复位信号过不来,系统起来后,应用程序把开关打开,让复位信号导通;

缺点就是无法保证复位信号是不是导通的,也不能很清晰的知道硬件的开关是否正常。

在这里插入图片描述

2、ARM的外侧加一个单片机用来喂狗,ARM与单片机使用串口通讯,在系统启动之前喂狗权在单片机上面,系统启动后双机能够正常通讯喂狗权交给ARM。

缺点成本较高,通讯复杂。

3、基于以上两种呢,都不是很优的方案,后面找了一款超长时间的比较器,也能输出RST信号,用作看门狗比较好,并且还能输出提醒喂狗信号,ARM端可以做是否焊接看门狗芯片的逻辑;

在这里插入图片描述

下面主要介绍一下Linux下的字符驱动编写:

上期有小伙伴提了疑问,为什么IO的配置不放在设备树里面呢,你把IO配置还写在字符驱动的头文件当中是不是很Low,感觉不是很方便啊,工作和项目中难道是这么用的吗?

设备树里面放对应字符驱动IO配置当然没有问题,我现在目前的字符驱动都是模块驱动,就是不用更改内核的情况下可以随意更改驱动,就像是个应用程序一样,编译好的文件放入文件系统中,然后使用命令加载就可以了,如果IO的配置放在设备树里面,管脚有改动的话还要重新烧录设备树问题,根本做不到远程升级字符驱动,不利于应付工作中的突发需求。

关注微信公众号,回复“看门狗字符驱动”,下载源代码。

字符驱动的模型还是套用gpio系统;

1、模块的入口函数


module_init(at91_watdog_init);
module_exit(at91_watdog_cleanup);


MODULE_DESCRIPTION ("AT91 watdog detect DRIVER"); 
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR ("Jack"); 
MODULE_LICENSE ("GPL");
调用insmod和rmmod的时候会调用这两个函数;

2、创建init和cleanup函数
定义初始化信息,喂狗信号和捕捉提醒喂狗信号

struct watdog_pin
{
   
    ulong wdgfree_pin;  //
    ulong wdgdete_pin;  //
};

struct St_watdog
{
   
    dev_t dev_major;
    int sys_irq;
    int hard_irq;

    atomic_t open_count;
    int detect_flag;// 断电检查标志
    struct watdog_pin st_pin;
    struct mutex watdog_mudex;//互斥锁
    spinlock_t watdog_spinlock;
    wait_queue_head_t watdog_poll_head;
    struct cdev watdog_dev;//
    struct class *watdog_class;
    struct device *watdog_device;
};

3、注册及注销驱动流程

static int __init at91_watdog_init(void)
{
    
    int retval = -1;
    dev_t dev_id;

    // 分配一个结构
    pwdg = (struct St_watdog *)kzalloc(sizeof (struct St_watdog),GFP_KERNEL);
    if(!pwdg)
    {
   
        printk("%s:kzalloc failded from:%s\n", __func__,WATCHDOG_NAME);
        return -ENOMEM;
    }

    //需要减去偏移量

    pwdg->st_pin.wdgfree_pin = WATCHDOG_PIN;
    pwdg->st_pin.wdgdete_pin = WATDETECT_PIN;

    mutex_init(&(pwdg->watdog_mudex));
    spin_lock_init(&(pwdg->watdog_spinlock));
    //init_timer
    init_waitqueue_head(&pwdg->watdog_poll_head);
    pwdg->detect_flag =0;

    //分配主设备号
    if (watdog_major) {
   
        dev_id = MKDEV(watdog_major, 0);
        retval = register_chrdev_region(dev_id, MAX_WATDOG_NB,
                        WATCHDOG_NAME);
    } else {
   
        retval = alloc_chrdev_region(&dev_id, 0, MAX_WATDOG_NB,
                         WATCHDOG_NAME);
        watdog_major = MAJOR(dev_id);
    }
    if(retval<0)
    {
   
        printk("watdog: register error!\n");
        goto error_malloc
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值