一、异常与中断的概念引入与处理流程
1.1 生活中的中断
假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。 问:这个母亲怎么才能知道这个小孩醒?
- 过一会打开一次房门,看婴儿是否睡醒,然后接着看书
- 一直等到婴儿发出声音以后再过去查看,期间都在读书
第一种方法叫做查询方式:
- 优点:简单
- 缺点: 累
如何写程序?
while(1)
{
1 read book(读书)
2 open door(开门)
if(小孩还在睡)
return(继续读书)
else
照顾小孩
}
第二种方法叫中断方式:
- 优点:不累
- 缺点:复杂
如何写程序:
while(1)
{
read book
}
中断服务程序() //核心问题:如何被调用?
{
处理照顾小孩
}
1.2 母亲如何处理中断
我们还是看看母亲被小孩哭声打断如何照顾小孩?
母亲的处理过程
- 平时看书
- 发生了各种声音,如何处理这些声音
- 有远处的猫叫(听而不闻,忽略)
- 门铃声有快递(开门收快递)
- 小孩哭声(打开房门,照顾小孩)
- 母亲的处理
- 只会处理门铃声和小孩哭声
- 先在书中放入书签,合上书(保存现场)
- 去处理 (调用对应的中断服务程序)
- 继续看书(恢复现场)
- 只会处理门铃声和小孩哭声
不同情况,不同处理
- 对于门铃:开门取快件
- 对于哭声:照顾小孩
1.3 ARM系统中异常与中断处理流程
我们将母亲的处理过程抽象化:
- 母亲的头脑相当于CPU
- 耳朵听到声音会发送信号给脑袋
- 声音来源有很多种
- 有远处的猫叫,门铃声,小孩哭声
- 这些声音传入耳朵,再由耳朵传给大脑
- 除了这些可以中断母亲的看书,还有其他情况,比如:
- 身体不舒服
- 有只蜘蛛掉下来
- 对于特殊情况无法回避,必须立即处理
对于arm系统,异常与中断的硬件框图如下:
所有的中断源(按键、定时器等),它们发出的中断汇聚到中断控制器, 再由中断控制器发信号给CPU,告诉它发生了那些紧急情况。
除了这些中断,还有什么可以打断CPU的运行?
- 指令不对
- 数据访问有问题
- reset信号
- 等等,这些都可以打断断CPU,这些被称为异常
- 中断属于一种异常
ARM系统中如何处理异常与中断?重点在于保存现场以及恢复现场, 处理过程如下:
- 保存现场(各种寄存器)
- 处理异常(中断属于一种异常)
- 恢复现场
细化一下,在ARM系统中如何使用异常(中断)?
初始化
- 设置中断源,让它可以产生中断
- 设置中断控制器(可以屏蔽某个中断,优先级)
- 设置CPU总开关,使能中断
执行其他程序:正常程序
产生中断,举例:按下按键--->中断控制器--->CPU
cpu每执行完一条指令都会检查有无中断/异常产生
发现有中断/异常产生,开始处理:
- 保存现场
- 分辨异常/中断,调用对于异常/中断的处理函数
- 恢复现场
不同的芯片,不同的架构,在这方面的处理稍有差别:
- 保存/恢复现场:cortex M3/M4是硬件实现的,cortex A7是软件实现的
- CPU中止当前执行,跳转去执行处理异常的代码:也有差异
- cortex M3/M4在向量表上放置的是函数地址
- cortex A7在向量表上放置的是跳转指令
二、ARM架构中异常与中断的处理
2.1 处理流程
- 每执行完一条指令都会检查有无中断/异常产生
- 发现有中断/异常产生,开始处理:
- 保存现场
- 分辨异常/中断,调用对应的异常/中断处理函数
- 恢复现场
不同的芯片,不同的架构,在这方面的处理稍有差别:
CPU中止当前执行,跳转去执行处理异常的代码:也有差异
- cortex M3/M4在向量表上放置的是函数地址
- cortex A7在向量表上放置的是跳转指令
保存/恢复现场:cortex M3/M4是硬件实现的,cortex A7是软件实现的
2.2 cortex M3/M4
参考资料:DDI0403E_B_armv7m_arm.pdf
、ARM Cortex-M3与Cortex-M4权威指南.pdf
、PM0056.pdf
要想理解这个处理流程,需要从向量表说起。 向量,在数学定义里是有方向的量,在程序里可以认为向量就是一个数组,里面有多个项。 在ARM架构里,对于异常/中断,它们的处理入口会整齐地排放在一起。
2.2.1 M3/M4的向量表
M3/M4的向量表中,放置的是具体异常/中断的处理函数的地址。 比如发生Reset
异常时,CPU就会从向量表里找到第1项,得到Reset_Handler函数的地址,跳转去执行。 比如发生EXTI Line 0
中断时,CPU就会从向量表里找到第22项,得到EXTI0_IRQHandler函数的地址,跳转去执行。
- 跳转之前,硬件会保存现场(会将寄存器保存在SP栈中)
- 函数执行完毕,返回之后,硬件会恢复现场
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1 & ADC2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
DCD TIM8_BRK_IRQHandler ; TIM8 Break
DCD TIM8_UP_IRQHandler ; TIM8 Update
DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD ADC3_IRQHandler ; ADC3
DCD FSMC_IRQHandler ; FSMC
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_IRQHandler ; TIM6
DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Channel1_IRQHandler ; DMA2 Channel1
DCD DMA2_Channel2_IRQHandler ; DMA2 Channel2
DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3
DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End
2.2.2 M3/M4的异常/中断处理流程
发生异常/中断时,硬件上实现了这些事情:
保存现场:把被中断瞬间的寄存器的值保存进栈里
根据异常/中断号,从向量表中得到函数地址,跳转过去执行
函数执行完后,从栈中恢复现场
保存现场、分辨异常/中断、跳转执行,都是硬件实现的。 我们只需要在向量表中,把处理函数的地址填进去就可以了。
硬件承包了大部分的工作。
M3/M4的向量表中,存放的是函数地址。
2.3 cortex A7
参考资料:ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf
实际上,以前的S3C2440属于ARM9处理器,它的异常/中断处理流程给cortex A7是一样的。
2.3.1 A7的向量表
A7的向量表中,放置的是某类异常的跳转指令。 比如发生Reset
异常时,CPU就会从向量表里找到第0项,得到b reset
指令,执行后就跳转到reset函数。 比如发生任何的中断时,CPU就会从向量表里找到第6项,得到ldr pc, _irq
指令,执行后就跳转到_irq函数。
跳转之前,硬件只会保存CPSR寄存器
跳转之后,软件要保存现场
函数执行完毕,返回之前,软件恢复现场
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
2.3.2 A7的异常/中断处理流程
发生异常/中断时,硬件上实现了这些事情:
CPU切换到对应的异常模式,比如IRQ模式、未定义模式、SVC模式
保存被中断时的CPSR到SPSR
- CPSR:current program status register,当前程序状态寄存器
- SRSR:saved program status register,保存的程序状态寄存器
跳到这个异常的入口地址去,执行指令,这通常是一条跳转指令
软件要做的事情就比较多了:
- 保存现场
- 分辨异常/中断
- 调用对应的处理函数
- 恢复现场
A7的向量表中,存放的是跳转指令。
三、异常处理深入分析_保存现场
3.1 回顾处理流程
点击ARM异常与中断处理(上)查看全文