1 異常類型
Cortex-M3內(nèi)核具有強大的異常響應(yīng)系統(tǒng)乱陡,它把能夠打斷當前代碼執(zhí)行流程的事件分為異常(exception)和中斷(interrupt),并把它們用一個表管理起來始藕,編號為0~15的稱為內(nèi)核異常,而16以上的則稱為外部中斷氮趋,這個表就稱為中斷向量表伍派。
CM3 內(nèi)核總共支持 256 個中斷,其中包含了 16 個內(nèi)核中斷和 240 個外部中斷剩胁,并且具有 256級的可編程中斷設(shè)置诉植。除了個別異常的優(yōu)先級固定外, 其它異常的優(yōu)先級都是可編程的昵观,這里及下文不在嚴格區(qū)分異常和中斷晾腔。異常類型如下表所示:
偏移 | 異常類型 | 優(yōu)先級 | 描述 |
---|---|---|---|
0 | - | - | 復(fù)位時加載向量表中第一項作為棧頂?shù)刂?/td> |
1 | Reset | -3 (最高) | 電源開啟或熱復(fù)位時調(diào)用,在執(zhí)行第一條指令時索昂,優(yōu)先級下降到最低(Thread模式)建车,異步故障 |
2 | NMI | -2 | 除了復(fù)位扩借,它不能被其他任何中斷搶占椒惨,異步故障 |
3 | Hard Fault | -1 | 如果故障由于優(yōu)先級或可配置的故障處理程序被禁止而不能激活時,此時所有這些故障均為硬故障潮罪,同步故障 |
4 | Memory Management | 可編程 | 存儲包含單元(MPU)不匹配康谆,包括不可訪問和不匹配领斥,同步故障;也用于MPU不可用或不存在的情況沃暗,已至此默認存儲映射的從不執(zhí)行區(qū)域 |
5 | Bus Fault | 可編程 | 預(yù)取出錯月洛,存儲器訪問錯誤,以及其它地址/存儲器相關(guān)的錯誤孽锥;當為精確的總線故障時是同步故障嚼黔,不精確時為異步故障 |
6 | Usage Fault | 可編程 | 應(yīng)用錯誤,如果執(zhí)行未定義的指令或試圖進行非法的狀態(tài)轉(zhuǎn)換惜辑,同步故障 |
7-10 | 保留 | - | 保留 |
11 | SVCall | 可編程 | 使用SVC指令進行系統(tǒng)服務(wù)調(diào)用唬涧,同步故障 |
12 | Debug Monitor | 可編程 | 調(diào)試監(jiān)視異常(當沒有停止時),同步故障盛撑,但只在允許時有效碎节;如果它的優(yōu)先級比當前激活的處理程序優(yōu)先級更低,則它不激活 |
13 | 保留 | - | 保留 |
14 | PendSV | 可編程 | 系統(tǒng)服務(wù)科掛起請求抵卫,異步故障狮荔,只能由軟件掛起 |
15 | PendSV | 可編程 | 用于系統(tǒng)滴答定時器,異步故障 |
16及以上 | External Interrupt | 可編程 | 有核外發(fā)出的中斷介粘,傳遞給NVIC殖氏,都為異步故障 |
2 中斷優(yōu)先級
STM32中有兩種優(yōu)先級:搶占式優(yōu)先級和響應(yīng)優(yōu)先級(也有成“副優(yōu)先級”或“亞優(yōu)先級”的)。所有可編程中斷都需要指定這兩種優(yōu)先級碗短。高搶占式優(yōu)先級的中斷可以中斷低搶占式優(yōu)先級的中斷處理受葛,即中斷嵌套,或者說高搶占式優(yōu)先級的中斷可以嵌套于低搶占式優(yōu)先級的中斷中偎谁。當兩個中斷源的搶占式優(yōu)先級相同時总滩,這兩個中斷將沒有嵌套關(guān)系,當一個中斷到來后巡雨,如果正在處理另一個中斷闰渔,這個后到來的中斷就要等到前一個中斷處理完之后才能被處理。如果這兩個中斷同時到達铐望,則中斷控制器根據(jù)他們的響應(yīng)優(yōu)先級高低來決定先處理哪一個冈涧;如果他們的搶占式優(yōu)先級和響應(yīng)優(yōu)先級都相等,則根據(jù)他們在中斷表中的排位順序決定先處理哪一個正蛙《焦可以總結(jié)為:搶占優(yōu)先級決定是否可以產(chǎn)生中斷嵌套,響應(yīng)優(yōu)先級決定了中斷響應(yīng)順序乒验,如果兩種優(yōu)先級一樣看偏移愚隧,中斷向量表中偏移小的優(yōu)先執(zhí)行。
由于每個中斷源都需要被指定搶占優(yōu)先級和響應(yīng)優(yōu)先級锻全,那么就需要有相應(yīng)的寄存器記錄每個中斷的優(yōu)先級狂塘,在Cortex-M3中定義了8個比特位用于設(shè)置中斷源的優(yōu)先級录煤,這8個比特位可以有8種分配方式,如下:
- 所有8位用于指定響應(yīng)優(yōu)先級
- 最高1位用于指定搶占式優(yōu)先級荞胡,最低7位用于指定響應(yīng)優(yōu)先級
- 最高2位用于指定搶占式優(yōu)先級妈踊,最低6位用于指定響應(yīng)優(yōu)先級
- 最高3位用于指定搶占式優(yōu)先級,最低5位用于指定響應(yīng)優(yōu)先級
- 最高4位用于指定搶占式優(yōu)先級泪漂,最低4位用于指定響應(yīng)優(yōu)先級
- 最高5位用于指定搶占式優(yōu)先級廊营,最低3位用于指定響應(yīng)優(yōu)先級
- 最高6位用于指定搶占式優(yōu)先級,最低2位用于指定響應(yīng)優(yōu)先級
- 最高7位用于指定搶占式優(yōu)先級萝勤,最低1位用于指定響應(yīng)優(yōu)先級
以上即為Cortex-M3優(yōu)先級分組方式赘风,但是Cortex-M3也允許在具有較少中斷源時使用較少的寄存器位指定中斷源的優(yōu)先級。STM32并沒有使用Cortex-M3內(nèi)核嵌套向量中斷的全套東西纵刘,而是使用了它的一部分邀窃,STM32有84個中斷,包括16個內(nèi)核中斷和68個可屏蔽中斷假哎,具有16級可編程的中斷優(yōu)先級瞬捕。我們最常用的是68個可屏蔽中斷,但是STM32的68個可屏蔽中斷舵抹,只有在STM32F107系列才有68個肪虎,其他只有60個。
STM32對中斷進行了編號惧蛹,編號為負的為系統(tǒng)異常扇救,標號為正的外部中斷,有些未定義中斷號(復(fù)位Reset香嗓,不可屏蔽中斷NMI和硬錯誤中斷Hand Fault和一些保留的中斷)的系統(tǒng)異常是不能被設(shè)置優(yōu)先級的迅腔,其他中斷的優(yōu)先級都是用戶可以配置的。STM32中指定中斷優(yōu)先級的寄存器有效位為4位靠娱,因此有一下5種分組方式:
第0組:所有4位用于指定響應(yīng)優(yōu)先級(16種)
第1組:最高1位用于指定搶占式優(yōu)先級沧烈,最低3位用于指定響應(yīng)優(yōu)先級(8種)
第2組:最高2位用于指定搶占式優(yōu)先級,最低2位用于指定響應(yīng)優(yōu)先級(4種)
第3組:最高3位用于指定搶占式優(yōu)先級像云,最低1位用于指定響應(yīng)優(yōu)先級(2種)
第4組:所有4位用于指定搶占式優(yōu)先級
STM32的分組可以使用標準庫函數(shù)void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)設(shè)置锌雀,這個函數(shù)在中斷配置前優(yōu)先調(diào)用以配置中斷優(yōu)先級分組,該函數(shù)的可選參數(shù)對應(yīng)以上5種分組:
- NVIC_PriorityGroup_0: 選擇第0組
- NVIC_PriorityGroup_1: 選擇第1組
- NVIC_PriorityGroup_2:選擇第2組
- NVIC_PriorityGroup_3:選擇第3組
- NVIC_PriorityGroup_4:選擇第4組
3 函數(shù)庫
3.1 數(shù)據(jù)結(jié)構(gòu)
typedef struct
{
uint8_t NVIC_IRQChannel; /*!< 指定中斷號 */
uint8_t NVIC_IRQChannelPreemptionPriority; /*!< 指定中斷搶占優(yōu)先級 */
uint8_t NVIC_IRQChannelSubPriority; /*!< 指定中斷響應(yīng)優(yōu)先級 */
FunctionalState NVIC_IRQChannelCmd; /*!< 指定中斷是否使能 */
} NVIC_InitTypeDef;
3.2 庫函數(shù)
函數(shù)名 | 描述 |
---|---|
NVIC_SetPriorityGrouping | 設(shè)置中斷優(yōu)先級分組(內(nèi)核提供) |
NVIC_GetPriorityGrouping | 獲取中斷優(yōu)先級分組(內(nèi)核提供) |
NVIC_EnableIRQ | 使能外部中斷(內(nèi)核提供) |
NVIC_DisableIRQ | 失能外部中斷(內(nèi)核提供) |
NVIC_GetPendingIRQ | 獲取指定中斷是否掛起(內(nèi)核提供) |
NVIC_SetPendingIRQ | 設(shè)置指定中斷掛起位(內(nèi)核提供) |
NVIC_ClearPendingIRQ | 清除指定掛起中斷(內(nèi)核提供) |
NVIC_GetActive | 獲取指定中斷激活狀態(tài)(內(nèi)核提供) |
NVIC_SetPriority | 設(shè)置指定中斷優(yōu)先級(內(nèi)核提供) |
NVIC_GetPriority | 獲取指定中斷優(yōu)先級(內(nèi)核提供) |
NVIC_EncodePriority | 編碼優(yōu)先級(內(nèi)核提供) |
NVIC_DecodePriority | 解碼優(yōu)先級(內(nèi)核提供) |
NVIC_SystemReset | 系統(tǒng)復(fù)位(內(nèi)核提供) |
NVIC_PriorityGroupConfig | 配置中斷優(yōu)先級分組(STM32提供) |
NVIC_Init | 中斷初始化(STM32提供) |
NVIC_SetVectorTable | 設(shè)置中斷向量表位置和偏移(STM32提供) |
NVIC_SystemLPConfig | 選擇系統(tǒng)進入低功耗模式的條件(STM32提供) |
注意 :上表中迅诬,加粗的函數(shù)為常用庫函數(shù)腋逆。
4 示例說明
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /*!< 中斷分組 */
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn; /*!< 指定中斷號 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0; /*!< 配置搶占優(yōu)先級 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; /*!< 配置響應(yīng)優(yōu)先級 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /*!< 使能中斷*/
NVIC_Init(&NVIC_InitStructure); /*!< 初始化指定中斷 */
NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; /*!< 指定中斷號 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1; /*!< 配置搶占優(yōu)先級 */
NVIC_Init(&NVIC_InitStructure); /*!< 初始化指定中斷 */
}
說明: 示例中,CAN2的搶占優(yōu)先級高于CAN1的搶占優(yōu)先級侈贷,則CAN2中斷可以嵌套CAN1中斷即當CAN1產(chǎn)生接收中斷時惩歉,CAN2中斷可以打斷CAN1中斷執(zhí)行。