- 在前面的基础上,实现多按键中断,这里实现2个,k1,k3。
- 通过应用程序,打印出产生中断的key号。
- 代码如下:
- key.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#define GPGCON 0x56000060
#define GPGDAT 0x56000064
struct work_struct *key_work;
struct timer_list key_timer;
unsigned int *gpio_data;
unsigned int key_num;
// 工作队列函数
void key_work_func(struct work_struct *work)
{
mod_timer(&key_timer, jiffies + HZ/10); // 延时100ms
}
// 判断按键是否真正按下
void key_timer_func(unsigned long data)
{
unsigned short key_vall;
key_vall = readw(gpio_data)&0x01;
if (key_vall == 0)
{
printk("key1 down!\n");
key_num = 1;
}
key_vall = readw(gpio_data)&0x20;
if (key_vall == 0)
{
printk("key3 down!\n");
key_num = 3;
}
}
// 中断处理函数
irqreturn_t key_int(int irq, void *dev_id)
{
// 1.检测是否发生了按键中断
// 2.清除已经发生的按键中断
// 3.提交下半部分
schedule_work(key_work);
return 0;
}
// 按键的初始化函数
void key_hw_init()
{
unsigned int *gpio_config;
unsigned int data;
gpio_config = ioremap(GPGCON, 4);
data = readl(gpio_config);
data &= ~0xc03; // 设置GPIO寄存器
data |= 0x802;
writel(data, gpio_config);
gpio_data = ioremap(GPGDAT, 4);
}
int key_open(struct inode *node, struct file *filp)
{
return 0;
}
ssize_t key_read (struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
copy_to_user(buf, &key_num, 4);
return 4;
}
const struct file_operations key_fops =
{
.open = key_open,
.read = key_read,
};
// 初始化miscdevice
struct miscdevice key_miscdev =
{
.minor = 200,
.name = "mykey",
.fops = &key_fops,
};
static int button_init()
{
// 注册miscdevice
misc_register(&key_miscdev);
// 注册中断处理程序
request_irq(IRQ_EINT8, key_int, IRQF_TRIGGER_FALLING, "mykey", 0); // K1
request_irq(IRQ_EINT13, key_int, IRQF_TRIGGER_FALLING, "mykey", 0); // K3
// 按键初始化
key_hw_init();
// 创建工作1
key_work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
INIT_WORK(key_work, key_work_func);
// 初始化定时器
init_timer(&key_timer);
key_timer.function = key_timer_func;
// 注册定时器
add_timer(&key_timer);
return 0;
}
static void button_exit()
{
// 注销miscdevice
misc_deregister(&key_miscdev);
// 注销中断处理程序
free_irq(IRQ_EINT8, 0);
free_irq(IRQ_EINT13, 0);
}
MODULE_LICENSE("GPL");
module_init(button_init);
module_exit(button_exit);
- key_app.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
int key_num;
// 打开设备文件
fd = open("/dev/mini2440key",0);
if (fd < 0)
printf("open device fail!\n");
// 读取设备
read(fd, &key_num, 4);
printf("key is %d\n",key_num);
// 关闭设备
close(fd);
}
- 编译后把key.ko安装到开饭板中,
- #insmod key.ko
- 创建设备文件,由于按键驱动程序可以分成混杂设备,主设备号统一为10,次设备号自己定义,这里为200
- mknod dev/mini2440key c 10 200
- 运行结果