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