• Linux内核定时器


    Linux使用struct    timer_list来描述一个定时器。
      重要成员:

        expires:定时时长
        *function:超时执行函数名
    使用流程:
      1、定义定时器变量

    /*定义定时器变量结构体*/
    struct timer_list key_timer;

      2、初始化定时器
        a、函数init_timer(timer)
          参数:timer:要初始化的定时器的变量名
        b、设置超时函数

      /*初始化定时器*/
    
        init_timer(&key_timer);
    
        key_timer.function = key_timer_func;

      3、注册定时器
      void    add_timer(struct timer_list *timer)
      参数:timer:要注册定时器变量的地址

    /*注册定时器*/
    add_timer(&key_timer);

      4、启动定时器
      int    mod_timer(struct timer_list *timer, unsigned long expires)
      参数:

        timer:要注册定时器变量的地址
        expires:延时时长

    /*启动定时器*/
    mod_timer(&key_timer,jiffies + (HZ/10));

      jiffies:全局变量,当前时间
      HZ是一秒的时间。

      当计时达到后,会执行成员function指定的函数,这里是key_timer_func

     

    这里将定时器应用到键盘中断驱动程序中,用来延时起到消抖的作用

      key.h:

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <linux/miscdevice.h>
    #include <linux/interrupt.h>
    #include <linux/io.h>
    #define GPGCON 0x56000060
    #define GPGDAT 0x56000064
    unsigned int *gpio_config,*gpio_data;

    /*定义工作项结构体*/
    struct work_struct *work1;
    
    /*定义定时器变量结构体*/
    struct timer_list key_timer;

      驱动程序:

    #include "key.h"
    /********************
    函数名:work1_func
    参数:无
    返回值:无
    函数功能:实现工作项
    结构体中的func成员
    ********************/
    void work1_func()
    {
        /*启动定时器*/
        mod_timer(&key_timer,jiffies + (HZ/10));
    }
    
    /************************
    函数名:que_init
    参数:无
    返回值:无
    函数功能:创建一个工作项
    *************************/
    int que_init()
    {
        /*创建工作*/
        work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
    
        INIT_WORK(work1, work1_func);
    }
    
    /************************
    函数名:key_int
    参数:无
    返回值:0
    函数功能:按键中断处理函数
    *************************/
    irqreturn_t key_int(int irq, void *dev_id)
    {
        /*1、检测设备是否产生中断*/
    
        /*2、清除中断产生标志*/
    
        /*3、提交下半部分工作*/
        schedule_work(work1);
    
        return 0;
    }
    
    /************************
    函数名:key_hw_init
    参数:无
    返回值:无
    函数功能:初始化与按键相关
    的寄存器
    *************************/
    void key_hw_init()
    {
        unsigned int data; 
        gpio_config = ioremap(GPGCON,4);
        gpio_data = ioremap(GPGDAT,4);
        data = readw(gpio_config);
        data &= ((3)|(3<<6)|(3<<10)|(3<<12)|(3<<14)|(3<<22));//~(0b11);
        data |= (2|(2<<6)|(2<<10)|(2<<12)|(2<<14)|(2<<22));//0b10;
        writew(data,gpio_config);
    }
    
    /************************
    函数名:key_timer_func
    参数:无
    返回值:无
    函数功能:定时器超时处理函
    数,达到规定时间执行此函数
    *************************/
    void key_timer_func()
    {
        unsigned int key_val,i;
    
        for(i = 0;i < 15;i++)
        {
            if((i == 0)||(i == 3)||(i == 5)||(i == 6)||(i == 7)||(i == 11))
            {
                key_val = readw(gpio_data) & (1 << i);
                if(key_val == 0)
                    printk("press key%d down
    ",i);
            }
        }
    }
    
    int key_open(struct inode *node, struct file *filp)
    {
        return 0; 
    }
    
    /* 函数映射关系表*/
    struct file_operations key_fops = 
    {
        .open = key_open,
        //.unlocked_ioctl = key_ioctl,
    };
    
    /*字符设备描述结构*/
    struct miscdevice key_miscdev = 
    {
        .minor = 200,
        .name = "key",
        .fops = &key_fops,
    };
    
    static int key_init()
    {
        /*注册设备*/
        misc_register(&key_miscdev);
    
        /*硬件初始化*/
        key_hw_init();
        
        /*注册中断*/
        request_irq(IRQ_EINT8,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
        request_irq(IRQ_EINT11,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
        request_irq(IRQ_EINT13,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
        request_irq(IRQ_EINT14,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
        request_irq(IRQ_EINT15,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
        request_irq(IRQ_EINT19,key_int,IRQF_TRIGGER_FALLING ,"key", 0);
    
        /*工作队列初始化*/
        que_init();
    
        /*初始化定时器*/
    
        init_timer(&key_timer);
    
        key_timer.function = key_timer_func;
    
        /*注册定时器*/
        add_timer(&key_timer);
    
        printk("key.ko is ready
    ");
        return 0;
    }
    
    static void key_exit()
    {
        /*注销设备*/
        misc_deregister(&key_miscdev);
        /*注销中断*/
        free_irq(IRQ_EINT8, 0);
    }
    
    MODULE_LICENSE("GPL");
    module_init(key_init);
    module_exit(key_exit);

     此代码适用mini2440开发板,不同型号开发板IO口和中断号不同。如果有疑问或建议,欢迎指出。

  • 相关阅读:
    35 个 Java 代码性能优化总结
    P4172 [WC2006]水管局长(LCT)
    P4219 [BJOI2014]大融合(LCT)
    P1501 [国家集训队]Tree II(LCT)
    P4381 [IOI2008]Island(基环树+单调队列优化dp)
    P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)
    P3809 【模板】后缀排序
    P3813 [FJOI2017]矩阵填数(组合数学)
    P2147 [SDOI2008]洞穴勘测(LCT)
    P3924 康娜的线段树(期望)
  • 原文地址:https://www.cnblogs.com/51qianrushi/p/4294652.html
Copyright © 2020-2023  润新知