中断的概念和机制
中断与轮询
- 中断: 由硬件判断外部事件并通知CPU;专用的中断服务程序来处理事件
- 处理对响应要求非常高的事件
- 处理持续事件非常短的事件
- 低功耗的应用
- 程序设计复杂
通常把CPU内部的紧急时间叫做异常,比如地址访问越界; 把CPU外部的片上外设产生的紧急时间叫做中断,比如GPIO口引脚的电平变化。 中断和异常都是停下当前任务去执行紧急事件,所以一般统称位中断。
- 轮询:周期/连续检查外部事件是否发生 消耗大量CPU处理时间
在CM3的内核中1~15号是系统异常,16 ~ 256是外部中断,有内核中的NVIC(嵌套向量中断控制器)
中断控制器(NVIC)
作用
- 中断管理
- 支持异常及中断向量化处理
- 支持嵌套中断
中断管理
-
全局中断控制 CRR寄存器中的一个特殊位 在复位和中断后该位置
-
Dedicated IE 在复位后所有中断被禁止
-
中断标志位 IF 中断源对应的标志 引发请求 读写操作清除中断标志位
寄存器AIRCR(中断和复位寄存器) 0-7位:设置抢占优先级和子优先级的级数 8-10位:优先级分组 中断先看抢占优先级,抢占优先级越高越先触发;抢占优先级相同,子优先级高的先触发。 抢占优先级高可以打断低的,即中断的嵌套,实现中断的嵌套
中断优先级特点
- 多个中断同时出现,高优先级中断先得到响应。
- 中断优先级可以是固定的或者是编程指定的 固定优先级:根据中断向量表顺序(比如S12内核) 设定优先级:每个中断都有优先级设置位(比如ARM Cortex M0+支持4个优先级)
每一个部件也有一个自己的中断控制器,而NVIC相当于总管家。
中断和异常向量表
内部异常和外部中断按照优先级进行排列形成一张中断向量表,一般数字越小优先级越高。当发生中断和异常的时候,处理器将PC指向表中的相应地址,这个地址叫做异常向量。
前三个优先级是最高的。
中断向量表的特点:
- 一段连续的存储空间 ;
- 复位后有默认起始位置 ;
- 每个中断在向量表中都有相应的表项,该表项的值为该中断对应的服务程序的地址;
- 中断向量表里的内容赋值给PC指针,程序相应的就会发生跳转 由程序代码确定中断向量表的每个表项;
- 中断向量表的位置是可以通过改写中断向量基址寄存器重新定位的;
在系统上电之后,即缺省情况下,会执行这样一张表,后面会讲到。
工作流程
中断的过程
一个中断的产生可以归纳为打开中断总开关,使能中断,配置发生条件:
- step1 设置自己的控制单元;
- step2 在NVIC里打开总中断;
- step3 中断源送到CPU;
- step4 CPU查找中断向量表,找到处理函数的地址去执行函数。
以GPIO口电平引起的中断为例,有一个EXIT外部中断控制器,管理所有GPIO的中断。EXTI进行使能,将请求通知给NVIC,再通知CPU。
堆栈情况
通过栈结构进行现场恢复的步骤
- step1 主程序执行的时候,发生中断
- step2 压栈保留一个现场执行中断函数
- step3 中断函数没有执行完,又来了一个更高优先级的中断
- step4 再次打断它,在保留一个CPU的现场
- step5 再占一部分堆栈去执行更高优先级的中断
- step6 依次退出
注意点
- 中断的寄存器入栈由CPU硬件自动完成
- 在中断时寄存器在堆栈中的保存顺序是在其手册中指明的。
- 开发者需要手动的把发生变化的寄存器压入堆栈。
中断服务子程
中断服务子程也叫中断服务函数,在一些CPU中,中断服务子程不同于一般的C函数,函数退出时的返回汇编指令有所区别。 在ARM Cortex M0+平台上,中断服务子程与一般C语言写法没有区别,使用同样的汇编返回指令即可
中断子程序函数特点:
- 被CPU硬件自动调用
- 在ISR执行前、后,CPU自动进行了堆栈出入等操作
- 写成C语言的参数和返回值都应该为void