Cortex M架構(gòu)與Cortex A架構(gòu)中斷系統(tǒng)的區(qū)別
Cortex M架構(gòu),典型就是STM32系列,比如STM32F103(Cortex M3)。
Cortex A架構(gòu),可以細(xì)分為Cortex A7,Cortex A8,Cortex A9,Cortex A15等,比如NXP的IMX6系列,TI的AM335X系列等。
Cortex M主要用在微控制器領(lǐng)域,Cortex R主要用在對(duì)實(shí)時(shí)性要求比較高的領(lǐng)域,Cortex A主要用在高端應(yīng)用領(lǐng)域。

Cortex M架構(gòu)
在Cortex M架構(gòu)中,比如STM32F103,中斷向量表是寫(xiě)在啟動(dòng)文件當(dāng)中,一般為startup_stm32f10x_hd.s或者startup_stm32f10x_md.s中,.s結(jié)尾為匯編文件,這個(gè)匯編語(yǔ)言寫(xiě)的啟動(dòng)文件的作用,是在板子上電后為C語(yǔ)言代碼的運(yùn)行做好初始化工作,比如設(shè)置堆棧大小,設(shè)置中斷向量表等,然后再跳轉(zhuǎn)到main函數(shù)去執(zhí)行你的C代碼。文件內(nèi)容如下(部分省略):
設(shè)置棧大小
- Stack_Size EQU 0x00000400
設(shè)置堆大小
- Heap_Size EQU 0x00000200
; Vector Table Mapped to Address 0 at Reset后面很多 DCD 的就是STM32的中斷向量表,系統(tǒng)所有可用的中斷都寫(xiě)在這里,包括外部中斷、定時(shí)器中斷、DMA中斷、IIC中斷、串口中斷等。
- Stack_Size EQU 0x00000400
- AREA STACK, NOINIT, READWRITE, ALIGN=3
- Stack_Mem SPACE Stack_Size
- __initial_sp
- ; <h> Heap Configuration
- ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
- ; </h>
- Heap_Size EQU 0x00000200
- AREA HEAP, NOINIT, READWRITE, ALIGN=3
- __heap_base
- Heap_Mem SPACE Heap_Size
- __heap_limit
- PRESERVE8
- THUMB
- ; 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
- __Vectors_Size EQU __Vectors_End - __Vectors
- AREA |.text|, CODE, READONLY
其中“__initial_sp”就是第一條中斷向量,存放的是棧頂指針,接下來(lái)是第 2 行復(fù)位中斷復(fù)位函數(shù)Reset_Handler 的入口地址,依次類(lèi)推,直到最后一個(gè)中斷服務(wù)函數(shù)DMA2_Channel4_5_IRQHandler 的入口地址,這樣 STM32F103 的中斷向量表就建好了。
中斷使用方法:
- 1、配置中斷向量表(ST提供)。
- 2、配置NVIC(內(nèi)嵌向量中斷控制器)。
- 3、中斷使能。
- 4、中斷服務(wù)函數(shù)。
先配置好中斷向量表(自動(dòng)),然后配置一下IO口,配置NVIC來(lái)管理中斷,使能中斷,最后編寫(xiě)中斷服務(wù)函數(shù),中斷服務(wù)函數(shù)里是我們真正想做的事情。
這個(gè)思路也適合于Cortex A架構(gòu),只是中斷系統(tǒng)不同,中斷管理器也不同,STM32中的中斷管理器是NVIC,Cortex A架構(gòu)的中斷管理器是GIC控制器。GIC 是 ARM 公司給 Cortex-A/R 內(nèi)核提供的一個(gè)中斷控制器。
Cortex A架構(gòu)
下表為Cortex A架構(gòu)中斷向量表,這個(gè)表也是寫(xiě)在.s結(jié)尾的啟動(dòng)文件當(dāng)中,為C語(yǔ)言代碼的運(yùn)行提供前期的初始化工作,只有做好了初始化,你的C語(yǔ)言代碼才會(huì)運(yùn)行,啟動(dòng)文件中做好初始化以后,會(huì)跳轉(zhuǎn)到你的main函數(shù)。
可以發(fā)現(xiàn)比STM32的中斷少了很多,只有八個(gè)中斷,還有一個(gè)未使用。其中我們最常用的中斷是復(fù)位中斷和 IRQ 中斷。

實(shí)際上Cortex A架構(gòu)是不可能只有這么少的中斷,Cortex-A 內(nèi)核 CPU 的所有外部中斷都屬于IQR 中斷,當(dāng)任意一個(gè)外部中斷發(fā)生的時(shí)候都會(huì)觸發(fā) IRQ 中斷。在 IRQ 中斷服務(wù)函數(shù)里面就可以讀取指定的寄存器來(lái)判斷發(fā)生的具體是什么中斷,進(jìn)而根據(jù)具體的中斷做出相應(yīng)的處理,如下圖:
中斷解釋?zhuān)?/h3>
1、復(fù)位中斷(Rest),CPU 復(fù)位以后就會(huì)進(jìn)入復(fù)位中斷,我們可以在復(fù)位中斷服務(wù)函數(shù)里面做一些初始化工作,比如初始化 SP 指針、DDR 等等。
2、未定義指令中斷(Undefined Instruction),如果指令不能識(shí)別的話(huà)就會(huì)產(chǎn)生此中斷。
3、軟中斷(Software Interrupt,SWI),由 SWI 指令引起的中斷,Linux 的系統(tǒng)調(diào)用會(huì)用 SWI指令來(lái)引起軟中斷,通過(guò)軟中斷來(lái)陷入到內(nèi)核空間。
4、指令預(yù)取中止中斷(Prefetch Abort),預(yù)取指令的出錯(cuò)的時(shí)候會(huì)產(chǎn)生此中斷。
5、數(shù)據(jù)訪(fǎng)問(wèn)中止中斷(Data Abort),訪(fǎng)問(wèn)數(shù)據(jù)出錯(cuò)的時(shí)候會(huì)產(chǎn)生此中斷。
6、IRQ 中斷(IRQ Interrupt),外部中斷,芯片內(nèi)部的外設(shè)中斷都會(huì)引起此中斷的發(fā)生。
7、FIQ 中斷(FIQ Interrupt),快速中斷,如果需要快速處理中斷的話(huà)就可以使用此中。
存放地址
中斷向量表都是鏈接到代碼的最前面,比如一般 ARM 處理器都是從地址 0X0000 0000 開(kāi)始執(zhí)行指令的,那么中斷向量表就是從0X0000 0000 開(kāi)始存放的。
在STM32中,一般代碼是下載到 0X0800 0000開(kāi)始的存儲(chǔ)區(qū)域中。因此中斷向量表是存放到 0X0800 0000 地址處的,而不是 0X00000000。這種是通過(guò)中斷向量表偏移實(shí)現(xiàn)的。