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:中断标志

Linux中断按键检测_linux

name:中断名

dev:传递给中断服务函数的参数

释放中断

void free_irq(unsigned int irq, void *dev_id)

形参: dev_id:request_irq 填写的最后一个参数

2.等待队列

直到某一条件成立才可以继续运行 →条件如果不成立,阻塞

1. 初始化等待队列头

Linux中断按键检测_#include_02

2. 等待事件发生

Linux中断按键检测_#include_03

condition:条件 (整数) 为真不阻塞,为假阻塞

3. 唤醒等待队列

Linux中断按键检测_linux_04

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;
}