裸板中中断异常处理,linux中断异常处理 ,linux系统中断处理的API,中断处理函数的要求,内核中登记底半部的方式

1、linux系统中的中断处理
  1.0裸板中中断异常是如何处理的?
     以s5p6818+按键为例
     
     1)按键中断的触发
        中断源级配置
            管脚功能
            中断使能
            中断触发方式
        (如果中断源是uart/i2c 只需要配置中断使能)
        中断级级设置
            中断优先级设置
            中断使能
        ARMcore级设置
            cpsr.I=0
     2) 中断异常触发 硬件自动做4件事
        备份CPSR
        修改CPSR
        保存返回地址到LR
        PC=VECTOR_BASE + 0x18
     3) 软件处理异常
        异常向量表
          0x18: 跳转指令 ldr pc, =irq_handler
          
        irq_handler:
           保护现场//压栈寄存器
           bl c_irq_handler
           恢复现场
        
        c_irq_handler:
           判断哪个硬件中断源触发的中断
           调用对应硬件处理函数hardware_isr
           清空中断源、中断控制器中对应的pending
        hardware_isr:
           执行相应的硬件操作
  1.1 linux中断异常处理
     linux中断异常处理过程和裸板中是一致的
     
     但是linux内核中将大部分的处理代码已经实现完毕了
     实际驱动编程过程中只需要实现   
        1)中断触发方式的配置
        2)hardware_isr
        
     内核中实现的这部分代码 被称作linux中断子系统
     
     百度搜: linux中断子系统   arm
     
  1.3 linux系统中提供的关于中断处理的API
      
      //中断注册
      int __must_check
      request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
              const char *name, void *dev)
         irq, 中断号
              s5p6818中所有中断源的编号s5p6818_irq.h//BSP
         handler, 对应硬件处理函数
                  handler的类型为
                       irqreturn_t (*)(int, void *)
         flags, 中断触发方式的配置 常用的取值
                IRQF_TRIGGER_RISING
                IRQF_TRIGGER_FALLING
                IRQF_TRIGGER_HIGH
                IRQF_TRIGGER_LOW
         name, 名称
         dev,  内核调用handler时传递给handler第二个参数值
         返回值,0 注册成功
                 非0 注册失败
         作用:和内核约定
               1)irq号中断源硬件什么情况下触发中断
               2)irq号中断产生了调用内核handler函数
               3)当内核调用handler函数时传递的第二个参数值
                       
      //中断注销    
      void free_irq(unsigned int irq, void *dev)
         irq, 中断号
         dev, 特别注意 和注册时request_irq(irq, ...,dev)
              给定的最后一个参数保持一致
              否则注销失败
         作用:
              取消和内核的约定    
     
     实验时将内核中自带的按键驱动程序裁剪掉
        cd /home/tarena/driver/kernel
        make menuconfig
           Device Drivers  --->
              Input device support  --->
                  [*]   Keyboards  --->
                      < >   SLsiAP push Keypad support
        make uImage
        
        让开发板使用新内核
        cp arch/arm/boot/uImage /tftpboot
        ...
        
        insmod btn_drv.ko
        cat /proc/interrupts
            
            中断号   中断产生次数  中断来源   name
            134:          0         GPIO      up
        尝试按几次按键
        cat /proc/interrupts
        rmmod btn_drv
        cat /proc/interrupts
   4按键按下触发中断,打印不同的信息出来
      up
      down
      left
      right
   
   注意:xxx_init,只要返回0 就意味着模块安装成功
                           非0 模块安装失败   
   
   16道经典嵌入式笔试题 + 高质量的c/c++笔试题  
       
     判断一个函数是否具有可重入性的标准:
         就是看该函数是否使用了全局变量
         如果全局变量,那么它就是不可重入的
         
   中断处理函数的特点:
       1)最最重要的特点就是执行速度要非常快(裸板/linux/vxworks ...)
       2) linux系统中,中断处理函数工作于中断上下文
          其中不能调用引起阻塞或者睡眠的函数,(中断因为不能参与进程调度,睡眠之后就无法得到再次调用)
       3) 当执行中断处理函数时使用了独立的栈空间
          该栈一般很小 通常为一个物理内存页(4KB)
          在中断处理函数中不能静态分配大数组  
    
   linux系统中要求中断处理执行非常快
   但是往往有些硬件中断处理起来就是耗时
   针对这种情况,
   linux内核人为的将整个中断过程分为两个半部:
      顶半部:top half
              做那些最为紧急的工作
              往往就是一些特殊功能寄存器的读写操作
              中断退出之前,要向内核登记底半部
      底半部: bottom half     
              不紧急且耗时的工作放在底半部中完成
              
2、内核中登记底半部的方式
  2.1 软中断机制
      通过软中机制登记底半部得去修改内核源码
      不能以模块的形式完成底半部的登记
      使用起来不灵活
      硬件驱动编程时很少使用
      
  2.2 tasklet
      如何使用tasklet登记半部?
      
      核心数据结构
          struct tasklet_struct
          {
              //记录底半部函数的地址
              void (*func)(unsigned long);
              //当内核调用func时传递给func的参数值
          unsigned long data;
          ...
          }
      1)定义tasklet变量
         struct tasklet_struct btn_tasklet;
      2) 初始化tasklet变量
         void tasklet_init(struct tasklet_struct *t,
          void (*func)(unsigned long), unsigned long data)
      3)使用tasklet变量完成底半部的登记
         void tasklet_schedule(struct tasklet_struct *t)

猜你喜欢

转载自www.cnblogs.com/DXGG-Bond/p/11851608.html