Note06_Key按键驱动_中断方式

 

 

  • KEY 硬件原理图

如下图所示,按键共有4个,K1——K4,对应的中断号为 XEINT26——29(并非与硬件实际的中断号对应),其对应的GPIO 引脚为GPX3_2——5。

 

  • KEY 相关寄存器

1)GPX3CON:GPIO PIN 模式设置寄存器

GPX3_2,对应的中断模式需设置为0xF,GPX3_2——5 ==》EXT_INT43[5——2]

......

2)EXT_INT43_CON中断触发方式设置寄存器

EXT_INT43[5——2],中断触发方式,设置为0x4,上下边沿都触发;

......

......

从如下图,可知EXT_INT43,对应的中断ID 为64.

 

  • 中断简介

1)中断源分类1:

中断包含内部中断和外部中断:内部中断:如若中断由控制器或者SOC 上的完整的设备产生的;比如 触摸屏、串口等中断方式;

外部中断:即只连接到GPIO 引脚上,中断信号通过SOC引脚从SOC外部得到的中断,没有其他外部的设备类控制其中断的发生,只能通过设置SFR 来配置中断模式、触发方式等;4412外部中断共计32个:

外部中断

中断ID

中断号

中断 0—15

48——63

EINT[0:15]

中断16—31

64

EINT[16:31]

2)中断源分类2:

共享外部中断:公共的外接中断,中断源ID号: SPI[127:0]

私有中断:私有外设中断 中断源ID号: PPI[15:0]

软中断:由软件设置的中断源 中断源ID号: SGI[15:0]

3)中断处理流程:

首先保存断点 ==》查找中断入口函数 ==》中断处理 ==》返回断点;

  1. 中断源触发中断;
  2. 首先确认GIC是否接收到中断;然后确认是否将中断转给CPU;
  3. 首先确认CPU是否接收到中断;然后确认接受的中断号的权限及优先级;

3)exynos4412中断简介:

中断控制器 gic 作用是进行中断时间的接收和转发;其资源共160个中断源(软中断16个、私有16个、外部128个),而CPU只识别中断号,所以中断处理的第一步就是获取硬件触发的中断源,并转化为CPU可识别的中断号,该过程由gic完成。

4)中断体系结构

略;待补充后补全;

【遗留】exynos 4412芯片如何将中断和中断号对应

  • 中断资源注册函数

1)编写驱动中断模块是,利用内核的如下函数接口注册中断:

int request_irq(

    unsigned int irq,     //中断号

    irq_handler_t handler,  //中断处理函数

    unsigned long flags,     //中断注册的触发方式

    const char *name,    //中断的名字

    void *dev        //给中断处理函数传入的参数

);

2)中断参数解释:

irq: //中断号

1> 对于内部中断号

         arch/arm/mach-exynos/include/mach/irqs.h

    2> 对于外部中断对应的中断号的获取

        a. IRQ_EINT(eint);  

        b. 在知道gpio编号的情况下,可以通过gpio的编号,得到对应注册的中断号

           gpio_to_irq(gpionum); //通过gpio编号返回中断号

handler: //中断处理函数

typedef irqreturn_t (*irq_handler_t)(int,  void *); 

中断处理函数的形参:(发生中断的中断号, 注册中断时为其传入的参数)

中断处理函数返回值:

    IRQ_NONE   //中断处理失败

    IRQ_HANDLED //中断成功处理

flags: //中断注册的触发方式

#define IRQF_TRIGGER_RISING  0x00000001

#define IRQF_TRIGGER_FALLING 0x00000002

#define IRQF_TRIGGER_HIGH    0x00000004

#define IRQF_TRIGGER_LOW     0x00000008

#define IRQF_SHARED      0x00000080

name:  //中断的名字

dev: //中断处理函数传入的参数

中断发生后,由内核调用处理函数时传给处理函数的第二实参

  • 驱动程序代码

1)按键中断初始化:

 5 // KEY 中断初始化: 中断号、按键名、按键计数

  6 struct millkey{

  7     int irqnum;

  8     char *name;

  9     int keycnt;

 10 }keys[] = {

 11     { IRQ_EINT(26), "KEY1", 0 },

 12     { IRQ_EINT(27), "KEY2", 0 },

 13     { IRQ_EINT(28), "KEY3", 0 },

 14     { IRQ_EINT(29), "KEY4", 0 },

 15 };

2)注册中断函数:

 71 /*

 72 **  driver init call func  

 73 */

 74 static int __init demo_init(void)

 75 {

 76     return register_keys();

 77 }

 

 30 /*

 31 **  register key irq devices  

 32 */

 33 static int register_keys(void)

 34 {

 35     int i;

 36     int ret;

 37 

 38     for (i = 0; i < ARRAY_SIZE(keys); ++i) {

 39         ret = request_irq(

 40             keys[i].irqnum,

 41             do_key_handler,

 42             IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

 43             keys[i].name,

 44             &keys[i]    // irq handler's arg

 45         );

 46 

 47         if (ret < 0) {

 48             goto error0;

 49         }

 50     }

 51 

 52     return 0;

 53 

 54 error0:

 55     while (i--) {

 56         free_irq(keys[i].irqnum, &keys[i]);

 57     }

 58 

 59     return ret;

 60 }

3)中断处理函数:

 17 static irqreturn_t do_key_handler(int irqnum, void *data)

 18 {

 19     struct millkey *pdev = data;

 20 

 21     printk();

 22     pdev->keycnt++;

 23 

 24     printk("%s is %s, keycnt = %d\n", pdev->name,

 25         pdev->keycnt%2?"press down":"release up", pdev->keycnt);

 26 

 27     return IRQ_HANDLED;

 28 }

 

4)中断注销函数:

 62 static void unregister_keys(void)

 63 {

 64     int i;

 65 

 66     for (i = 0; i < ARRAY_SIZE(keys); ++i) {

 67         free_irq(keys[i].irqnum, &keys[i]);

 68     }

 69 }

 70 

 

 79 module_init(demo_init);

 80 

 81 static void __exit demo_exit(void)

 82 {

 83     unregister_keys();

 84 }

 

  • 测试程序代码

中断是由硬件触发,故无应用层的测试程序;

  • 测试结果

1插入驱动模块

[root@millet0923_interrupt]# 

[root@millet0923_interrupt]# insmod demo.ko 

[root@millet0923_interrupt]# 

[root@millet0923_interrupt]# 

[root@millet0923_interrupt]# 

[root@millet0923_interrupt]# find / -name KEY*

/proc/irq/445/KEY4

/proc/irq/444/KEY3

/proc/irq/443/KEY2

/proc/irq/442/KEY1

[root@millet0923_interrupt]# 

[root@millet0923_interrupt]# 

2)查看当前已注册的中断,及其发生的情况

[root@millet0926_03_interrupt]# cat /proc/interrupts

           CPU0       CPU1

28:      63591        472       GIC  MCT 

67:          0          0       GIC  dma-pl330.0

68:          0          0       GIC  dma-pl330.1

75:          0          0       GIC  abc4412-wdt

......

......

442:          0          0  exynos-eint  KEY1                                         

443:          0          0  exynos-eint  KEY2

444:          0          0  exynos-eint  KEY3

445:          0          0  exynos-eint  KEY4

3)按下按键,触发中断,可看到内核打印的日志;

   中断设置双边沿触发,因按键有抖动,故实际按下1次,但弹道多次触发打印

[root@millet0923_interrupt]#

[root@millet0923_interrupt]#

[root@millet0923_interrupt]# [ 7945.490000] KEY1 is release up

[ 7945.625000] KEY1 is press down

[ 7945.625000] KEY1 is release up

[ 7946.225000] KEY2 is release up

[ 7946.350000] KEY2 is press down

[ 7946.940000] KEY3 is release up

[ 7947.110000] KEY3 is press down

[ 7947.665000] KEY4 is press down

[ 7947.665000] KEY4 is release up

[ 7947.665000] KEY4 is press down

[ 7947.665000] KEY4 is release up

[ 7947.790000] KEY4 is press down

[root@millet0923_interrupt]#

 

  • 总结:

  • 遗留问题

 ret = request_irq(

 40             keys[i].irqnum,

 41             do_key_handler,

 42             IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

 43             keys[i].name,

 44             &keys[i]    // irq handler's arg

 45         );

1)如上中断注册函数,中断号 keys[i].irqnum 是如何和内核内核注册的硬件中断ID联系起来的?可参考如下文档,待分析;

https://blog.csdn.net/zqixiao_09/article/details/50926677

https://blog.csdn.net/zqixiao_09/article/details/50908125?locationNum=5&fps=1

https://blog.csdn.net/zqixiao_09/article/details/50916212

https://www.cnblogs.com/wang_yb/archive/2013/04/19/3030345.html《linux 内核设计与实现阅读笔记

2)代码没有消抖,故设置双边沿触发时,会检测到多次中断,增加消抖处理机制;

定时器定时检测消抖、delay(ms)死等延时消抖、中断电平检测消抖? 分析优缺点;

  1. 若应用程序需根据按键功能实现需求,则它如何知晓哪个按键被按下了呢?

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值