之前我们完成了关于通过查询的方式获取按键键值的驱动程序,可以参考:嵌入式Linux开发——裸板程序之中断控制器。
虽然读取键值没有什么问题,但是测试程序占用CPU过高,一直在不断的查询,资源消耗过大,这个问题非常严重,我们必须要来解决一下。但是在解决这个问题之前,我们先来思考一个问题,除了不断的这样 read,是不是还有其他的方法可以获取按键的键值呢?自然是有的,这个方式就是通过终端的方式来获取键值。
如果举一个例子,小明在家等小华给他送东西,有什么方式不会错过呢?他可以不断的去门口查看,其实这就是我们之前的方式,不断的让应用程序去read,这时候自然小明大量的精力都消耗在了不断的查看过程中,他想做别的事的时间和精力也会被不断的查看而占用。
为了这个解决这个问题,方法很多,我们先来说其中一个普通的,就是小明家安装一个门铃,小华到了,按下门铃,这时候小明去开门就可以了。这时候,小明在家做其他事,也就不会被打扰了,节省了大量的资源。
其实上面的故事很平常,但是实际上,第一种方式就是不断查询的方式,虽然不会错过小华,但是消耗了大量资源,一定是不可以采用的。而第二种方式有点类似于今天要说的——中断模式。
当发生了某件事,这件事作为一个中断,处理完了这个中断后,在恢复去执行另外一件事。
简单总结一下:
- 单片机程序处理中断的过程
- 按键按下,中断发生
- CPU发生中断,跳转到异常向量入口进行执
a. 保存被中断的现场(寄存器的值)
b. 判断中断的来源,执行中断处理函数,清中断
c. 恢复被中断的现场,继续执行
那么对于Linux嵌入式来说,处理中断是不是相同呢?
对于Linux来说,处理流程也是相同的,肯定需要先设置异常向量,不然都不知道该调用谁来处理。同样也需要分辨 异常的来源,毕竟按下每个键都应该执行不同的任务。同样,不能因为按下按键,恢复以后之前的程序就不继续执行了(reset除外)。所以,裸板程序中处理异常事件的流程在Linux下都是成立的,只是这些代码都是由系统帮我们实现的,不需要我们自己来实现。那么我们就需要使用好。那么,我们可以来思考一下,对于以上流程,哪一个对于系统来说没办法帮我们代劳,必须我们自己来完成呢?那么这个过程对我们来说肯定是需要关注的了。
其实,不难想到,以上的处理流程里面,分析中断源、中断处理函数这些部分一定是系统没办法帮我们代劳的。不但这些内容和硬件相关性比较高,同时,我们想要如何处理,也都不一定相同。
ARM架构下的Linux的异常处理原理如下图:


- 按下按键
- CPU进入异常模式
b vector_irq + stubs_offset
,vector_irq是使用宏来定义的。在这个宏中调用__irq_xxxx
的列表,其中会做对现场进行相应的保存的工作 - 最终会调用到
asm_do_IRQ
- 其中调用
desc_handle_irq(irq, desc)
- 调用
desc->handle_irq(irq, desc)
以中断号为下标取出handle_irq,在其中调用irq_desc[irq] -> handle_irq
,irq_desc
实际是一个结构体数组
- 其中调用
-
handle_irq 就等于<