1.查看OK6410的原理图,看到GPN0-GPN5分别对应中断XEINT0-XEINT5
2.简单的按键中断驱动程序button_irq.c代码如下所示
-
//moudle.h 包含了大量加载模块需要的函数和符号的定义
-
#include <linux/module.h>
-
//kernel.h以便使用printk()等函数
-
#include <linux/kernel.h>
-
//fs.h包含常用的数据结构,如struct file等
-
#include <linux/fs.h>
-
//uaccess.h 包含copy_to_user(),copy_from_user()等函数
-
#include <linux/uaccess.h>
-
//io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
-
#include <linux/io.h>
-
#include <linux/miscdevice.h>
-
#include <linux/pci.h>
-
//init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
-
#include <linux/init.h>
-
#include <linux/delay.h>
-
#include <linux/device.h>
-
#include <linux/cdev.h>
-
#include <linux/gpio.h>
-
#include <linux/irq.h>
-
#include <linux/sched.h>
-
#include <linux/interrupt.h>
-
#include <linux/poll.h>
-
//irq.h中断与并发请求事件
-
#include <asm/irq.h>
-
//下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
-
//#include <mach/gpio.h>
-
#include <mach/regs-gpio.h>
-
#include <plat/gpio-cfg.h>
-
#include <mach/hardware.h>
-
#include <mach/map.h>
-
-
-
static struct class *button_irq_class;
-
static int major;
-
-
-
/*中断服务函数*/
-
static irqreturn_t button_irq(int irq, void *dev_id)
-
{
-
printk("irq = %d\n",irq );//打印中断号
-
return IRQ_HANDLED;
-
}
-
-
static int button_irq_open(struct inode *inode, struct file *file)
-
{
-
int ret;
-
-
/*request_irq注册中断
-
*第一个参数是中断号,也是中断处理函数button_irq的第一个参数
-
*第二个参数是中断处理函数
-
*第三个参数是中断触发方式
-
*第四个参数是设备名称
-
*第五个参数是设备ID,也是中断处理函数button_irq的第二个参数
-
*/
-
ret = request_irq(IRQ_EINT(0), button_irq, IRQ_TYPE_EDGE_BOTH, "k1", 1);
-
if (ret){
-
printk("request IRQ_EINT(0) error!\n");
-
free_irq(IRQ_EINT(0), 1);
-
}
-
ret = request_irq(IRQ_EINT(1), button_irq, IRQ_TYPE_EDGE_BOTH, "k2", 1);
-
if (ret){
-
printk("request IRQ_EINT(1) error!\n");
-
free_irq(IRQ_EINT(1), 1);
-
}
-
-
ret = request_irq(IRQ_EINT(2), button_irq, IRQ_TYPE_EDGE_BOTH, "k3", 1);
-
if (ret){
-
printk("request IRQ_EINT(2) error!\n");
-
free_irq(IRQ_EINT(2), 1);
-
}
-
-
ret = request_irq(IRQ_EINT(3), button_irq, IRQ_TYPE_EDGE_BOTH, "k4", 1);
-
if (ret){
-
printk("request IRQ_EINT(3) error!\n");
-
free_irq(IRQ_EINT(3), 1);
-
}
-
-
ret = request_irq(IRQ_EINT(4), button_irq, IRQ_TYPE_EDGE_BOTH, "k5", 1);
-
if (ret){
-
printk("request IRQ_EINT(4) error!\n");
-
free_irq(IRQ_EINT(4), 1);
-
}
-
-
ret = request_irq(IRQ_EINT(5), button_irq, IRQ_TYPE_EDGE_BOTH, "k6", 1);
-
if (ret){
-
printk("request IRQ_EINT(5) error!\n");
-
free_irq(IRQ_EINT(5), 1);
-
}
-
return 0;
-
}
-
-
static ssize_t button_irq_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
-
{
-
return 0;
-
}
-
-
static ssize_t button_irq_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
-
{
-
return 0;
-
}
-
-
static int button_irq_release(struct inode *inode, struct file *file)
-
-
{
-
free_irq(IRQ_EINT(0), 1);
-
free_irq(IRQ_EINT(1), 1);
-
free_irq(IRQ_EINT(2), 1);
-
free_irq(IRQ_EINT(3), 1);
-
free_irq(IRQ_EINT(4), 1);
-
free_irq(IRQ_EINT(5), 1);
-
-
return 0;
-
}
-
-
static struct file_operations button_irq_fops = {
-
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
-
.open = button_irq_open,
-
.read = button_irq_read,
-
.write = button_irq_write,
-
.release = button_irq_release,
-
};
-
-
static int button_irq_init(void)
-
{
-
major = register_chrdev(0, "button_irq_dev", &button_irq_fops);//注册,告诉内核
-
button_irq_class = class_create(THIS_MODULE, "button_irq_cls");
-
device_create(button_irq_class, NULL, MKDEV(major, 0), NULL, "button_irq");/* /dev/button_irq */
-
-
return 0;
-
}
-
-
static void button_irq_exit(void)
-
{
-
unregister_chrdev(major, "button_irq_cls");
-
device_destroy(button_irq_class, MKDEV(major, 0));
-
class_destroy(button_irq_class);
-
}
-
-
module_init(button_irq_init);
-
module_exit(button_irq_exit);
-
-
MODULE_LICENSE("GPL");
3.把编译出的button_irq.ko拷贝到开发板,分别执行以下命令
insmod button_irq.ko 加载驱动
exec 5/dev/button_irq读入到fd5中
ps 查看-/bin/sh的进程号,这里为963
ls -l /proc/963/fd 看到fd5指向
/dev/button_irq
cat /proc/interrupts 看到k1-k5,中断已经注册成功了
按下按键就能打印出中断号了
exec 5<&- 关闭fb5
rmmod button_irq 卸载驱动
阅读(912) | 评论(0) | 转发(0) |