1、中断系统是一个处理器重要的组成部分,中断系统极大的提高了
CPU
的执行效率,在学习
STM32
的时候就经常用到中断。
本章就通过与
STM32
的对比来学习一下
Cortex-A7(I.MX6U) 中断系统和 Cortex-M(STM32)
中断系统的异同。
2、
STM32
中断系统回顾
STM32
的中断系统主要有以下几个关键点:
①、中断向量表。
②、NVIC(内嵌向量中断控制器)。
③、中断使能。
④、中断服务函数
。
中断向量表是一个表,
这个表里面存放的是中断向量
。
中断服务程序的入口地址或存放中
断服务程序的首地址成为中断向量,因此中断向量表是一系列中断服务程序入口地址组成的表
。
编写中断程序就是 填写这些中断 服务程序 对应的 地址 函数指针。
这些中断服务程序
(
函数
)
在中断向量表中的位置是由半导体厂商定好的,当某个中断被触发以
后就会自动跳转到中断向量表中对应的中断服务程序
(
函数
)
入口地址处。
中断向量表都是链接到代码的最 前面,比如一般 ARM
处理器都是从地址
0X00000000
开始执行指令的,那么中断向量表就是 从
0X00000000
开始
存放的
。
因此中断向量表是存放到
0X8000000
地址处 的,而不是 0X00000000
,这样不是就出错了吗?为了解决这个问题,
Cortex-M
架构引入了一 个新的概念——中断向量表偏移,通过中断向量表偏移就可以将中断向量表存放到任意地址 处,中断向量表偏移配置在函数 SystemInit
中完成,通过向
SCB_VTOR
寄存器写入新的中断 向量表首地址
即可。
中断向量表
和
中断向量表偏移。
中断系统得有个管理机构,对于
STM32
这种
Cortex-M
内核的单片机来说这个管理机构叫
做
NVIC
,全称叫做
Nested Vectored Interrupt Controller
。
不过
Cortex-A
内核的中断管理机构不叫做
NVIC
,而是叫做
GIC
,全称是
general interrupt controller
,后面我们会详细的讲解
Cortex-A
内 核的。
3、中断使能
要使用某个外设的中断,肯定要先使能这个外设的中断,以
STM32F103
的
PE2
这个
IO
为
例,假如我们要使用
PE2
的输入中断肯定要使用如下代码来使能对应的中断:
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
//抢占优先级 2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
//子优先级 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
码就是使能
PE2
对应的
EXTI2
中断,同理,如果要使用
I.MX6U
的某个中断的话也
需要使能其对应的中断。
4、
中断服务函数
我们使用中断的目的就是为了使用中断服务函数,当中断发生以后中断服务函数就会被调
用,我们要处理的工作就可以放到中断服务函数中去完成。
/*
外部中断
2
服务程序
*/
void EXTI2_IRQHandler(void)
{
/* 中断处理代码 */
}
5、Cortex A7 也有 8个异常中断
0X00
复位中断
(Rest)
特权模式
(SVC)
0X04
未定义指令中断
(Undefined Instruction)
未定义指令中止模式
(Undef)
0X08
软中断
(Software Interrupt,SWI)
特权模式
(SVC)
0X0C
指令预取中止中断
(Prefetch Abort)
中止模式
0X10
数据访问中止中断
(Data Abort)
中止模式
0X14
未使用
(Not Used)
未使用
0X18
IRQ
中断
(IRQ Interrupt)
外部中断模式
(IRQ)
0X1C
FIQ
中断
(FIQ Interrupt)
快速中断模式
(FIQ)
Cortex-A
内核
CPU
的所有外部中 断都属于这个 IQR
中断,当
任意一个外部中断发生的时候
都会触发
IRQ
中断。在
IRQ
中断服 务函数里面
就可以
读取指定的寄存器来判断发生的具体是什么中断
,进而根据
具体的中断做出 相应的处理
。
我们实际需要 编写的只有复位中断服务函数 Reset_Handler
和
IRQ
中断服务函数
IRQ_Handler
,其它的中断本 教程没有用到,所以都是死循环。在编写复位中断复位函数和 IRQ
中断服务函数之前我们还需 要了解一些其它的知识,否则的话就没法编写。
中断源有很多,为了区分这些不同的中断源肯定要给他们分配一个唯一
ID
,这些
ID
就是 中断 ID
。
6、中断优先级
GIC_Init
初始化 GIC。
GIC_EnableIRQ
使能指定的外设中断。
GIC_DisableIRQ
关闭指定的外设中断。
GIC_AcknowledgeIRQ
返回中断号。
GIC_DeactivateIRQ
无效化指定中断。
GIC_GetRunningPriority
获取当前正在运行的中断优先级。
GIC_SetPriorityGrouping
设置抢占优先级位数。
GIC_GetPriorityGrouping
获取抢占优先级位数。
GIC_SetPriority
设置指定中断的优先级。
GIC_GetPriority
获取指定中断的优先级。
7、GIC 逻辑分块
GIC
架构分为了两个逻辑块:
Distributor
和
CPU Interface
,也就是分发器端和
CPU
接口端。
这两个逻辑块的含义如下:
Distributor(
分发器端
)
:
从图
17.1.3.2
可以看出,此逻辑块负责处理各个中断事件的分发问
题,也就是中断事件应该发送到哪个
CPU Interface
上去。分发器收集所有的中断源,可以控制
每个中断的优先级,它总是将优先级最高的中断事件发送到
CPU
接口端。分发器端要做的主要
工作如下
①、全局中断使能控制。
②、控制每一个中断的使能或者关闭。
③、设置每个中断的优先级。
④、设置每个中断的目标处理器列表。
⑤、设置每个外部中断的触发模式:电平触发或边沿触发。
⑥、设置每个中断属于组 0 还是组 1。
CPU Interface(CPU
接口端
)
:CPU
接口端主要工作如下:
①、使能或者关闭发送到 CPU Core 的中断请求信号。
②、应答中断。
③、通知中断处理完成。
④、设置优先级掩码,通过掩码来设置哪些中断不需要上报给 CPU Core。
⑤、定义抢占策略。
⑥、当多个中断到来的时候,选择优先级最高的中断通知给 CPU Core。