华清远见嵌入式学习day37——中断、内核延时机制

【1】、复习

    IO模型:
    
    阻塞 非阻塞

    1. IO多路复用实现 
    
        poll接口 --->>> poll_wait
        
    2. 异步通知 
    
        fasync接口 --->>> fasync_helper
        
        kill_fasync
        
        
    ----------------------------------------


    3. gpio子系统
    
        gpionum
    
        out 
        in
    


【一】、中断


    irqreturn_t (*irq_handler_t)(int, void *);
    
    irqreturn_t xxx(int irq, void *arg)
    {
        return;
    }

    IRQ_NONE        没有处理
    IRQ_HANDLED     处理中断
    
   /*******************************************************************************
    *功能: 
    *参数: 
    *        @irq        中断号  --->>> gpio_to_irq()
    *        @handler    中断处理函数指针
    *        @flags        中断的标志 
    *                    IRQF_SHARED    共享中断标志
    *                    IRQF_DISABLED  屏蔽其他中断
    *                    IRQF_TRIGGER_RISING        上升沿
    *                    IRQF_TRIGGER_FALLING    下降沿
    *                    IRQF_TRIGGER_HIGH        高电平 
    *                    IRQF_TRIGGER_LOW        低电平
    *        @name       名字
    *        @dev        私有数据
    *返回值:成功返回0,失败返回负数错误码
    ******************************************************************************/
    int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
        const char *name, void *dev)
    
    void free_irq(unsigned int irq, void *dev_id)
    
===========================================================================================

    cat /proc/interrupts 
    
     1. cat /proc/interruptes 
     
        nxp-keypad
        
     2. 内核源码中搜索是哪一个驱动使用了这个名字在注册中断

        grep "nxp-keypad" -nR ./*

        ./arch/arm/mach-s5p6818/include/mach/devices.h:48:#define DEV_NAME_KEYPAD         "nxp-keypad"
        
     3. 在内核源码中搜索DEV_NAME_KEYPAD
     
        grep "DEV_NAME_KEYPAD" -nR ./*
        
        ./arch/arm/plat-s5p6818/fs6818/device.c:534:    .name    = DEV_NAME_KEYPAD,
        
     4. 查看device.c的时候,确定device.c是platform平台总线设备端
     
     5. 应该在驱动端查找相应的驱动程序
     
        cd /drivers
        
        grep "DEV_NAME_KEYPAD" -nR  ./*
        
        ./input/keyboard/nxp_io_key.c:324:        .name    = DEV_NAME_KEYPAD,
        
     6. 确定是在nxp_io_key.c里使用的按键中断,所以不编译该驱动,就可以。
     
     7. 在nxp_io_key.c目录下打开Makefile文件,找nxp_io_key.o 
     
        obj-$(CONFIG_KEYBOARD_NXP_KEY)      += nxp_io_key.o
        
     8. 查看当前目录下的Kconfig文件,找config KEYBOARD_NXP_KEY
     
         config KEYBOARD_NXP_KEY
            tristate "SLsiAP push Keypad support"
            depends on ARCH_CPU_SLSI
            help
            Say Y here to enable the gpio keypad on SLsiAP SoC based board.
            
      9. 执行make menuconfig ,搜索 KEYBOARD_NXP_KEY
            
            
            Location:                                                                                            │  
  │     -> Device Drivers                                                                                        │  
  │       -> Input device support                                                                                │  
  │         -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])                                │  
  │           -> Keyboards (INPUT_KEYBOARD [=y])
            
    
    学完platform平台总线后回来再看
=========================================================================================    
    
【二】、中断底半部

    1. 软中断  --->>> 可以被中断顶半部打断,不可以被底半部和进程打断 --->>> 
    
            实现耗时操作,不能有进程调度相关函数
            
      /**********************************************************************
       *功能: 注册软中断
       *参数: 
       *            @nr      软中断编号(枚举变量)
       *            @action  函数指针
       *返回值: void
       *********************************************************************/
       void open_softirq(int nr, void (*action)(struct softirq_action *))
       
       void raise_softirq(unsigned int nr)  //调度软中断
    
    2. tasklet  --->>> 基于软中断实现的
    
        可以被中断顶半部打断,不可以被底半部和进程打断 --->>> 
    
            实现耗时操作,不能有进程调度相关函数
            
        ----------软中断 、 tasklet------------
        
          
       /***********************************************************
        *功能:初始化tasklet
        *参数: 
        *            @t            tasklet结构体指针
        *            @func       tasklet底半部处理函数
        *            @data        私有数据
        *返回值:void
        **********************************************************/
        void tasklet_init(struct tasklet_struct *t,
             void (*func)(unsigned long), unsigned long data);
        /* 调度软中断底半部 */
        void tasklet_schedule(struct tasklet_struct *t)
    
    3. 工作队列    --->>> 可以被中断顶半部打断,也可以被底半部和进程打断(参与进程调度)
    
        --->>> 可以有进程调度函数出现(copy_to_user / copy_from_user)
    
        /******************************************
         *功能:初始化工作队列
         *参数: 
         *            @_work    工作队列结构体指针
         *            @_func  work_func_t
         *****************************************/
         INIT_WORK(struct work_struct * _work, _func)
        
         typedef void (*work_func_t)(struct work_struct *work);
        
        
         int schedule_work(struct work_struct *work);
        
【三】、定时器


    /****************************************************************
     *功能:定义并初始化
     *参数: 
     *            @_name            变量名
     *            @_function         定时器处理函数指针
     *            @_expires         定时器定时时间(计数值)
     *            @_data             私有数据
     ***************************************************************/
     #define DEFINE_TIMER(_name, _function, _expires, _data)        \
     struct timer_list _name =    {                                \
         .entry = { .prev = TIMER_ENTRY_STATIC },                \
         .function = (_function),                                \
         .expires = (_expires),                                    \
         .data = (_data),                                        \
         .base = &boot_tvec_bases,                                \
         .slack = -1,                                            \
         __TIMER_LOCKDEP_MAP_INITIALIZER(                        \
             __FILE__ ":" __stringify(__LINE__))                    \
     }
    
    
     jiffies   计数值 
    
     HZ
     
     _expires = jiffies + n 
     
     _expires = jiffies + n * HZ      //延时n秒
     
     _expires = jiffies +  HZ / n    //延时1/n秒
     
    
    #define INIT_TIMER(timer, func, duration, extra_delay)    \
    do {                   \
        init_timer(timer); \
        timer->function = func; \
        timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
        timer->data = (unsigned long) wl; \
        add_timer(timer); \
    } while (0);
    
    
    
    变量名.expires = xxx;
    变量名.function =xxx ;
     
    init_timer(struct timer_list *timer)
    
    //开启定时器
    void add_timer(struct timer_list *timer);
    //删除定时器
    int del_timer(struct timer_list * timer);
    //修改定时器时间
    int mod_timer(struct timer_list *timer, unsigned long expires);
    
    
【四】、按键消抖

    使用定时器定时,推后执行按键事件。
    
    定时时间是20-30ms之间,跳出按键抖动时间,然后在定时器中断处理函数中判断是否是按键
    事件,如果是按键事件,进行相应的处理。

【五】、内核延时机制

    1. 中断底半部
    2. 定时器 
    3. 延时/睡眠函数
    
        void ndelay(unsigned long x)
        mdelay(n)
        udelay(DIV_ROUND_UP(x, 1000));
        
        void msleep(unsigned int msecs);
        unsigned long msleep_interruptible(unsigned int msecs);
        void ssleep(unsigned int seconds)


    

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值