1中断
中断分为:软中断 共享中断 私有中断
Linux 中断不需要设置优先级
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
形参:irq:中断号 可以通过 gpio_to_irq 获取
handler:中断服务函数
typedef irqreturn_t (*irq_handler_t)(int, void *);
flags:中断标志
name:中断名
dev:传递给中断服务函数的参数
释放中断
void free_irq(unsigned int irq, void *dev_id)
形参: dev_id:request_irq 填写的最后一个参数
2.等待队列
直到某一条件成立才可以继续运行 →条件如果不成立,阻塞
1. 初始化等待队列头
2. 等待事件发生
condition:条件 (整数) 为真不阻塞,为假阻塞
3. 唤醒等待队列
x 类型是 wait_queue_head_t * 跳进去看一下就晓得了
中断要求 快进快出
Linux 内核将中断分为两部分,中断上文(中断顶半部)和中断下文(中断底半部) 中断上文: 中断服务函数 处理要紧的内容 中断下文: 小任务/工作队列 处理非要紧的 可以延后处理的事情
自旋锁:锁已经处于上锁状态,此时再加锁,任务会不间断判断锁的状态,直到锁可用
互斥锁:锁已经处于上锁状态, 此时再加锁,任务会挂起,直到锁释放
Makefile
obj-m += irq_key.o
all:
make -C /home/fuck/桌面/linux-3.5 M=${PWD} modules
arm-linux-gcc app.c -o app
clean:
make -C /home/fuck/桌面/linux-3.5 M=${PWD} modules clean
rm app
irq_key.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
int irq1,irq2,irq3,irq4;
int condition = 0;
DECLARE_WAIT_QUEUE_HEAD(wait);
ssize_t key_read (struct file *f, char __user *buf, size_t s, loff_t *l)
{
int value1,value2,value3,value4;
wait_event_interruptible(wait,condition);
value1 = gpio_get_value(EXYNOS4_GPX3(2));
if(value1 == 0)
{
value1 = 1;
copy_to_user(buf,&value1,sizeof(value1));
}
value2 = gpio_get_value(EXYNOS4_GPX3(3));
if(value2 == 0)
{
value2 = 2;
copy_to_user(buf,&value2,sizeof(value2));
}
value3 = gpio_get_value(EXYNOS4_GPX3(4));
if(value3 == 0)
{
value3 = 3;
copy_to_user(buf,&value3,sizeof(value3));
}
value4 = gpio_get_value(EXYNOS4_GPX3(5));
if(value4 == 0)
{
value4 = 4;
copy_to_user(buf,&value4,sizeof(value4));
}
condition = 0;
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.read = key_read
};
struct miscdevice misc = {
.minor = 255,
.name = "my_key",
.fops = &fops
};
irqreturn_t key_irq_handler(int irqnum, void *arg)
{
//printk("key 1 被按下\n");
condition = 1;
wake_up_interruptible(&wait);
return IRQ_HANDLED;
}
static int __init my_irq_init(void)
{
int ret;
//申请四个按键的gpio
gpio_request(EXYNOS4_GPX3(2),"lable1");
gpio_request(EXYNOS4_GPX3(3),"lable2");
gpio_request(EXYNOS4_GPX3(4),"lable3");
gpio_request(EXYNOS4_GPX3(5),"lable4");
//中断工作模式
gpio_direction_input(EXYNOS4_GPX3(2));
gpio_direction_input(EXYNOS4_GPX3(3));
gpio_direction_input(EXYNOS4_GPX3(4));
gpio_direction_input(EXYNOS4_GPX3(5));
irq1 = gpio_to_irq(EXYNOS4_GPX3(2));
irq2 = gpio_to_irq(EXYNOS4_GPX3(3));
irq3 = gpio_to_irq(EXYNOS4_GPX3(4));
irq4 = gpio_to_irq(EXYNOS4_GPX3(5));
ret = request_irq(irq1,key_irq_handler,IRQ_TYPE_EDGE_FALLING,"my_key",NULL);
if(ret == 0)
printk("申请中断1成功\n");
else
printk("申请中断1失败\n");
ret = request_irq(irq2,key_irq_handler,IRQ_TYPE_EDGE_FALLING,"my_key",NULL);
if(ret == 0)
printk("申请2中断成功\n");
else
printk("申请2中断失败\n");
ret = request_irq(irq3,key_irq_handler,IRQ_TYPE_EDGE_FALLING,"my_key",NULL);
if(ret == 0)
printk("申请3中断成功\n");
else
printk("申请3中断失败\n");
ret = request_irq(irq4,key_irq_handler,IRQ_TYPE_EDGE_FALLING,"my_key",NULL);
if(ret == 0)
printk("申请4中断成功\n");
else
printk("申请4中断失败\n");
ret = misc_register(&misc);
if(ret == 0)
printk("注册成功\n");
else
printk("注册失败\n");
return ret;
}
static void __exit my_irq_exit(void)
{
misc_deregister(&misc);
free_irq(irq1,NULL);
free_irq(irq2,NULL);
free_irq(irq3,NULL);
free_irq(irq4,NULL);
}
module_init(my_irq_init);
module_exit(my_irq_exit);
MODULE_LICENSE("GPL");
app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/my_key",O_RDWR);
int data,ret;
while(1){
ret = read(fd,&data,sizeof(data));
printf("按键%d被按下\n",data);
}
return 0;
}