假设你现在正在写作业,突然电话响起,你需要停下写作业接电话,挂电话后继续写作业。突然由人按门铃,你需要先去开门,然后继续回来写作业。电话和门铃打断了写作业,能中断写作业的事情有很多,比如身体不舒服,口渴等。被打断后怎么做?身体不舒服就停下写作业休息一会,身体好了继续写作业。口渴就停下写作业喝水,喝完水继续写作业。如果你正在接一个很重要的电话,突然门铃响了,这是会优先处理其中一件事,比如先让按门铃的人等一下,挂电话后再去开门,或者先挂电话,等开门后再打电话过去。这就存在一个中断优先级的问题。
当有事件产生,处理事件之前我们需要记住现在作业写到第几页了,或者在作业上记一个标记,然后取处理事件,电话铃响了需要到放电话的地方去,门铃响了需要到门口去,口渴需要到放饮水机地方去,也就是说,不同的突发事件需要到不同的地方去处理。
嵌入式系统中也有类似的情况。CPU在运行过程中,也会被各种异常打断。
————————————————
版权声明:本文为CSDN博主「韦东山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/thisway_diy/article/details/122475661
以上摘自其他博主,来帮助理解。
中断系统是一个处理器重要的组成部分,中断系统极大的提高了CPU的执行效率。
STM32的中断系统参照
STM32的中断系统主要有以下几个关键点:
、中断向量表。
、NVIC(内嵌向量中断控制器)。
、中断使能。
、中断服务函数。
1、中断向量表
中断向量表是一个表,这个表里面存放的是中断向量。中断服务程序的入口地址或存放中断服务程序的首地址成为中断向量,因此中断向量表是一系列中断服务程序入口地址组成的表。这些中断服务程序(函数)在中断向量表中的位置是由半导体厂商定好的,当某个中断被触发以后就会自动跳转到中断向量表中对应的中断服务程序(函数)入口地址处。中断向量表在整个程序的最前面。
示例代码17.1.1.1 STM32F103中断向量表
1 __Vectors DCD __initial_sp ; Top of Stack
2 DCD Reset_Handler ; Reset Handler
3 DCD NMI_Handler ; NMI Handler
4 DCD HardFault_Handler ; Hard Fault Handler
5 DCD MemManage_Handler ; MPU Fault Handler
6 DCD BusFault_Handler ; Bus Fault Handler
7 DCD UsageFault_Handler ; Usage Fault Handler
8 DCD 0 ; Reserved
9 DCD 0 ; Reserved
10 DCD 0 ; Reserved
11 DCD 0 ; Reserved
12 DCD SVC_Handler ; SVCall Handler
13 DCD DebugMon_Handler ; Debug Monitor Handler
14 DCD 0 ; Reserved
15 DCD PendSV_Handler ; PendSV Handler
16 DCD SysTick_Handler ; SysTick Handler
17
18 ; External Interrupts
19 DCD WWDG_IRQHandler ; Window Watchdog
20 DCD PVD_IRQHandler ; PVD through EXTI Line detect
21 DCD TAMPER_IRQHandler ; Tamper
22 DCD RTC_IRQHandler ; RTC
23 DCD FLASH_IRQHandler ; Flash
24
25 /* 省略掉其它代码 */
26
27 DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & l5
28 __Vectors_End
“示例代码17.1.1.1”就是STM32F103的中断向量表,中断向量表都是链接到代码的最前面,比如一般ARM处理器都是从地址0X00000000开始执行指令的,那么中断向量表就是从0X00000000开始存放的。
“示例代码17.1.1.1”中第1行的“__initial_sp”就是第一条中断向量,存放的是栈顶指针,接下来是第2行复位中断复位函数Reset_Handler的入口地址,依次类推,直到第27行的最后一个中断服务函数DMA2_Channel4_5_IRQHandler的入口地址,这样STM32F103的中断向量表就建好了。
arm处理器都是从地址0X000000000开始运行,所以中断向量表应该存放在0X0000000,如果我们出于某些原因,要将中断向量表存放在其他地址该怎么办?
Cortex-M架构引入了一个新的概念——中断向量表偏移,通过中断向量表偏移就可以将中断向量表存放到任意地址处,中断向量表偏移配置在函数SystemInit中完成,通过向SCB_VTOR寄存器写入新的中断向量表首地址即可,代码如下所示:
示例代码17.1.1.2 STM32F103中断向量表偏移
1 void SystemInit (void)
2 {
3 RCC->CR |= (uint32_t)0x00000001;
4
5 /* 省略其它代码 */
6
7 #ifdef VECT_TAB_SRAM
8 SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
9 #else
10 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
11 #endif
12 }
第8行和第10行就是设置中断向量表偏移,第8行是将中断向量表设置到RAM中,第10行是将中断向量表设置到ROM中,基本都是将中断向量表设置到ROM中,也就是地址0X8000000处。第10行用到了FALSH_BASE和VECT_TAB_OFFSET,这两个都是宏,定义如下所示:
#define FLASH_BASE ((uint32_t)0x08000000)
#define VECT_TAB_OFFSET 0x0
因此第10行的代码就是:SCB->VTOR=0X080000000,中断向量表偏移设置完成。通过上面的讲解我们了解了两个跟STM32中断有关的概念:中断向量表和中断向量表偏移,那么这个跟I.MX6U有什么关系呢?因为I.MX6U所使用的Cortex-A7内核也有中断向量表和中断向量表偏移,而且其含义和STM32是一模一样的!只是用到的寄存器不同而已,概念完全相同!
2、NVIC(内嵌向量中断控制器)
中断系统得有个管理机构,对于STM32这种Cortex-M内核的单片机来说这个管理机构叫做NVIC,全称叫做Nested Vectored Interrupt Controller。既然Cortex-M内核有个中断系统的管理机构—NVIC,那么I.MX6U所使用的Cortex-A7内核是不是也有个中断系统管理机构?答案是肯定的,不过Cortex-A内核的中断管理机构不叫做NVIC,而是叫做GIC,全称是general interrupt controller,
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、中断服务函数
我们使用中断的目的就是为了使用中断服务函数,当中断发生以后中断服务函数就会被调用,我们要处理的工作就可以放到中断服务函数中去完成。同样以STM32F103的PE2为例,其中断服务函数如下所示:
/* 外部中断2服务程序 */
void EXTI2_IRQHandler(void)
{
/* 中断处理代码 */
}
当PE2引脚的中断触发以后就会调用其对应的中断处理函数EXTI2_IRQHandler,我们可以在函数EXTI2_IRQHandler中添加中断处理代码。同理,I.MX6U也有中断服务函数,当某个外设中断发生以后就会调用其对应的中断服务函数。
通过对STM32中断系统的回顾,我们知道了Cortex-M内核的中断处理过程,那么Cortex-A内核的中断处理过程是否是一样的,有什么异同呢?