[国嵌攻略][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,[ase, #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!
");
    
    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);
原文地址:https://www.cnblogs.com/d442130165/p/5254789.html