Linux驱动开发——按键为例介绍Linux内核中断

   日期:2020-12-15     浏览:91    评论:0    
核心提示:Linux内核中断1. 简介2. linux内核中中断的注册与注销3. 代码4. 测试1. 简介     linux的中断处理过程和ARM裸板中的中断处理过程是一致的。不同点在于裸板开始时所有的软件都是自行编程完成的,在linux中很多中断相关的代码内核已经实现完毕了,某个中断产生后应该做什么样的具体工作没有完成,这就需要我们自己编程实现。    ● 中断服务程序有如下特点:(速记:3不快栈–三不沾) (不属于) 1)

Linux内核中断

  • 1. 简介
  • 2. linux内核中中断的注册与注销
  • 3. 代码
  • 4. 测试

1. 简介

     linux的中断处理过程和ARM裸板中的中断处理过程是一致的。不同点在于裸板开始时所有的软件都是自行编程完成的,在linux中很多中断相关的代码内核已经实现完毕了,某个中断产生后应该做什么样的具体工作没有完成,这就需要我们自己编程实现。

    ● 中断服务程序有如下特点

 (不属于)  1)中断处理程序不属于进程,它运行于中断上下文
 (不交换)  2)在中断上下文中不能做用户空间和内核空间的数据交互(linux不允许,STM32中裸板中可以)
 				 copy_to_user/copy_from_user /kmalloc  
 (不阻塞)  3)在中断上下文中不允许执行引起阻塞或者睡眠的函数,如:
             	 sleep //睡眠函数
             	 recv //阻塞函数
 (栈)  	  4)中断使用的栈为独立的栈空间,栈空间为一个4KB的内存页 
 (快)    5)要求对应的处理过程,执行速度越快越好

2. linux内核中中断的注册与注销

● 注册


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)

3. 代码

硬件上使用了四个按键,都是下降沿触发。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/interrupt/h>

MODELE_LICENSE("GPL");

struct btn_desc
{ 
    int irq;  //中断号
    char *name;
} 

struct btn_desc btns[]=
{ 
    { IRQ_GPIO_A_START+28, "K1"},
    { IRQ_GPIO_B_START+30, "K2"},
    { IRQ_GPIO_B_START+31, "K3"}
    { IRQ_GPIO_B_START+9,  "K4"}, 
}


irqreturn_t btn_isr(int irq, void *dev)
{ 
    //int test = *((int *)dev);
    sturct btn_sesc *pdata = (sturct btn_desc *)dev;
    printk("%s press!\n",pdate->name);
    return IRQ_HANDLED;
}

//初始化:注册中断服务函数
int __init btn_drv_init(void) 
{ 
    //int irq = gqio_to_irq(PAD_GPIO_A + 28); //获取终端号 
    for(i=0; i<ARRAY_SIZE(btns); i++))
    { 
	    //注册中断服务函数 约定一下,按键的时候才使用,具体见上文的函数解释
        int ret = request_irq(btns[i].irq, btn_isr, IRQF_RTIGGER_FALLING, btns[i].name, (void *)&(btns[i]));  
        if(ret)
        { 
            printk("request_irq failed!\n");
            return -EAGAIN;
        }
    }
    return 0;
}

//注销中断服务程序
void __exit btn_drv_exit(void)
{ 
	int i = 0;
    for(i=0; i<ARRAY_SIZE(btns); i++)
    { 
        //int irq = gqio_to_irq(PAD_GPIO_A + 28); 
        free_irq(btns[i].irq, (void *)&(btns[i]));
    }
}
...
module_init(btn_drv_init);
module_exit(btn_drv_exit);

4. 测试

向内核加载模块:

insmod btn_drv.ko
insmod: can't insert 'btn_drv.ko': Resource temporarily unavailable
#原因: 内核中自带了按键的驱动程序,在其中通过request_irq的方式注册了K1对应的中断服务程序,导致再次调用request_irq时注册失败

解决方法:

make menuconfig
  Device Drivers  --->
      Input device support  --->
            [*]   Keyboards  --->  
                   < >   SLsiAP push Keypad support
  make uImage  #让开发板使用新内核
  cp arch/arm/boot/uImage /tftpboot/
  tftp 48000000 uImage
  mmc write 48000000 800 3000

重启后,再向内核加载模块:

  insmod btn_drv.ko
  # 按下K1观察实验效果

查看中断信息:

  cat /proc/interrupts
  #中断号 中断产生的次数
  134:          0           GPIO   K1
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服