[国嵌攻略][120][按键驱动硬件操作实现]
中断类型对应中断号
1.在内核代码中找到irqs.h(.../s3c2410.h)对应的中断号,Linux系统中用的中断号是中断类型编号(INTOFFSET)加上基数偏移得到的。
2.其中的宏就是中断类型所对应的中断号
#define S3C2410_CPUIRQ_OFFSET (16)
#define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET)
#define IRQ_EINT0 S3C2410_IRQ(0)
说明:
S3C2410_CPUIRQ_OFFSET对应的前16是留给软中断的,硬件中断从16开始。
3.中断号用来查找irq_desc描述结构
在entry-macro.S中ldr \irqnr,[\base, #INTOFFSET]获取中断类型编号,然后通过adds \irqnr, \irqnr, #IRQ_EINT0来加上偏移,得到对应的irq_desc描述结构的编号。
头文件
<linux/interrupt.h>
<linux/io.h>
<linux/fs.h>
keydev.c
/******************************************************************** *头文件 *********************************************************************/ #include <linux/init.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/fs.h> /******************************************************************** *宏定义 *********************************************************************/ #define GPGCON 0x56000060 //控制寄存器物理地址 /******************************************************************** *全局变量 *********************************************************************/ unsigned int *keyCon; //控制寄存器指针 /******************************************************************** *中断处理 *********************************************************************/ //处理中断 irqreturn_t key_irq(int irq, void *dev_id){ printk("key down!\n"); return 0; } /******************************************************************** *设备方法 *********************************************************************/ //打开设备 int key_open(struct inode *node, struct file *filp){ return 0; } //关闭设备 int key_close(struct inode *node, struct file *filp){ return 0; } //设备方法 struct file_operations key_fops = { .open = key_open, .release = key_close }; /******************************************************************** *模块安装 *********************************************************************/ struct miscdevice misdev = { .minor = 200, //次设备号 .name = "keydev", //设备名称 .fops = &key_fops //设备方法 }; //初始硬件 void handware_init(void){ unsigned short keyTmp; keyCon = ioremap(GPGCON, 4); //虚拟地址映射 keyTmp = readw(keyCon); //获取GPGCON值 keyTmp &= ~(0x3<<0); //GPG0[1:0]:00 keyTmp |= (0x2<<0); //GPG0[1:0]:EINT[8] writew(keyTmp, keyCon); //设置GPGCON值 } //安装模块 static int key_init(void){ //注册混杂设备 misc_register(&misdev); //注册中断处理 request_irq(IRQ_EINT8, key_irq, IRQF_TRIGGER_FALLING, "keyirq", 0); //下降沿触发,IRQ_EINT8定义在irqs.h文件中 //初始硬件设备 handware_init(); return 0; } //卸载模块 static void key_exit(void){ //注销混杂设备 misc_deregister(&misdev); //注销中断处理 free_irq(IRQ_EINT8, 0); } /******************************************************************** *模块声明 *********************************************************************/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("D"); MODULE_DESCRIPTION(""); MODULE_VERSION("v1.0"); module_init(key_init); module_exit(key_exit);