如何開發(fā)嵌入式中斷控制系統(tǒng)?
在嵌入式開發(fā)過程中,中斷處理是一個不可或缺的環(huán)節(jié)。本篇博文將以STM32微控制器為核心案例,深入解析中斷處理在MCU開發(fā)中的關(guān)鍵步驟和策略。
主要有以下幾個關(guān)鍵點:
中斷向量表。
NVIC(內(nèi)嵌向量中斷控制器)。
中斷使能。
中斷服務(wù)函數(shù)。
通過這篇博文,讀者將獲得對STM32 MCU中斷處理流程和邏輯的全面理解。
1
中斷向量表
中斷向量表是關(guān)鍵的數(shù)據(jù)結(jié)構(gòu),用于存儲中斷服務(wù)程序的入口地址,這些地址被稱為中斷向量。具體來說,當(dāng)一個中斷發(fā)生時,系統(tǒng)會自動跳轉(zhuǎn)到中斷向量表中對應(yīng)的地址,從而執(zhí)行相應(yīng)的中斷服務(wù)程序(函數(shù))。這個表由半導(dǎo)體制造商預(yù)先定義,確保每個中斷都有一個唯一的入口地址。
在程序架構(gòu)中,中斷向量表位于最前面,起到了連接硬件中斷信號和相應(yīng)處理程序的橋梁作用。中斷向量表在整個程序的最前面,比如 STM32F103 的中斷向量表如下所示:
中斷向量表都是鏈接到代碼的最前面,比如一般 ARM 處理器都是從地址 0X00000000 開始執(zhí)行指令的,那么中斷向量表就是從 0X00000000 開始存放的。代碼第 1 行的“__initial_sp”就是第一條中斷向量,存放的是棧頂指針,接下來是第 2 行復(fù)位中斷復(fù)位函數(shù) Reset_Handler 的入口地址,依次類推,直到第 27 行的最后一個中斷服務(wù)函數(shù)DMA2_Channel4_5_IRQHandler 的入口地址,這樣 STM32F103 的中斷向量表就建好了。
雖然ARM處理器默認(rèn)從地址0X00000000開始執(zhí)行程序,但在學(xué)習(xí)STM32時,我們通常將代碼下載到從0X8000000地址開始的存儲區(qū)域。這一做法似乎與處理器的初始執(zhí)行地址不符,看起來可能導(dǎo)致錯誤。然而,為了解決這一潛在問題,Cortex-M架構(gòu)引入了中斷向量表偏移的概念。這使得開發(fā)者可以將中斷向量表放置在任何所需的地址位置。中斷向量表的具體偏移配置是在'SystemInit'函數(shù)中完成的,方法是向SCB_VTOR寄存器寫入新的中斷向量表首地址。這種靈活的配置方式有效地克服了初始地址和程序存儲地址之間的潛在沖突,確保了中斷處理的正確進(jìn)行。
代碼如下所示:
第 8 行和第 10 行就是設(shè)置中斷向量表偏移,第 8 行是將中斷向量表設(shè)置到 RAM 中,第10 行是將中斷向量表設(shè)置到 ROM 中,基本都是將中斷向量表設(shè)置到 ROM 中,也就是地址0X8000000 處。第 10 行用到了 FALSH_BASE 和 VECT_TAB_OFFSET,這兩個都是宏,定義如下所示:
#define FLASH_BASE ((uint32_t)0x08000000)#define VECT_TAB_OFFSET 0x0
因此第 10 行的代碼就是:SCB->VTOR=0X080000000,中斷向量表偏移設(shè)置完成。
2
NVIC(內(nèi)嵌向量中斷控制器)
NVIC(Nested Vectored Interrupt Controller)是ARM Cortex-M微控制器的一個關(guān)鍵組件,用于管理中斷。各個芯片廠商在設(shè)計芯片的時候會對Cortex-M內(nèi)核里面的NVIC進(jìn)行裁剪,把不需要的部分去掉,所以說STM32的NVIC是Cortex-M3的NVIC 的一個子集。
其主要功能包括:
中斷優(yōu)先級管理:NVIC允許為每個中斷分配不同的優(yōu)先級。這樣,當(dāng)多個中斷同時發(fā)生時,處理器可以根據(jù)優(yōu)先級來確定處理的順序,確保更重要的任務(wù)得到優(yōu)先處理。
嵌套中斷處理:NVIC支持中斷的嵌套。這意味著一個高優(yōu)先級的中斷可以打斷一個低優(yōu)先級的中斷服務(wù)例程,使得系統(tǒng)能夠及時響應(yīng)更緊急的任務(wù)。
向量化中斷處理:每個中斷都有一個唯一的向量地址,該地址指向相應(yīng)的中斷服務(wù)例程。當(dāng)中斷發(fā)生時,處理器可以直接跳轉(zhuǎn)到相應(yīng)的服務(wù)例程,無需通過傳統(tǒng)的中斷查詢方式,從而提高了處理速度。
中斷屏蔽與啟用:NVIC允許程序動態(tài)地使能或禁用特定中斷。這種靈活性使得系統(tǒng)可以在不同的操作環(huán)境下,根據(jù)需要調(diào)整其中斷響應(yīng)。
中斷掛起與恢復(fù):NVIC能夠掛起正在執(zhí)行的中斷,并在適當(dāng)?shù)臅r候恢復(fù)中斷的處理。這對于管理復(fù)雜的中斷場景尤為重要。
中斷狀態(tài)管理:NVIC提供接口來查詢中斷的狀態(tài),例如檢查哪些中斷處于掛起狀態(tài)或哪些中斷正在被處理。這有助于更好地理解和控制系統(tǒng)的行為。
低功耗模式支持:在低功耗模式下,NVIC可以幫助處理器在接收到中斷信號時喚醒,這對于節(jié)能和延長電池使用壽命至關(guān)重要。
系統(tǒng)復(fù)位管理:NVIC還負(fù)責(zé)處理來自系統(tǒng)的復(fù)位請求,確保系統(tǒng)能夠在出現(xiàn)問題時安全地重新啟動。
通過查看STM32 NVIC寄存器,可以更清晰的解NVIC的主要功能:
/** 中斷 NVIC 結(jié)構(gòu)體定義 */typedef struct{ __IO uint32_t ISER[8]; /*!<offset: 0x000="" 中斷使能寄存器="" *="" uint32_t RESERVED0[24]; __IO uint32_t ICER[8]; /*!<offset: 0x080="" 中斷清除寄存器="" *="" uint32_t RSERVED1[24]; __IO uint32_t ISPR[8]; /*!<offset: 0x100="" 中斷使能懸起寄存器="" *="" uint32_t RESERVED2[24]; __IO uint32_t ICPR[8]; /*!<offset: 0x180="" 中斷清除懸起寄存器="" *="" uint32_t RESERVED3[24]; __IO uint32_t IABR[8]; /*!<offset:0x200 中斷有效位寄存器="" *="" uint32_t RESERVED4[56]; __IO uint8_t IP[240]; /*!< Offset: 0x300 中斷優(yōu)先級寄存器 (8Bit wide) */ uint32_t RESERVED5[644]; __O uint32_t STIR; /*!< Offset: 0xE00 軟件觸發(fā)中斷寄存器 */} NVIC_Type;
3
中斷使能
中斷使能是指允許特定的中斷源向處理器發(fā)出中斷請求的過程。當(dāng)一個中斷被使能后,如果相應(yīng)的事件發(fā)生(如外部信號、定時器溢出等),中斷控制器會捕捉到這個事件,并通知處理器中斷程序需要被執(zhí)行。
中斷使能通常通過設(shè)置特定的控制寄存器來完成。這些寄存器可能是微控制器的一部分,也可能位于外部設(shè)備中。通過編寫特定的值到這些寄存器,可以選擇性地使能或禁用特定的中斷。
要使用某個外設(shè)的中斷,肯定要先使能這個外設(shè)的中斷,以 STM32F103 的 PE2 這個 IO 為例,假如我們要使用 PE2 的輸入中斷肯定要使用如下代碼來使能對應(yīng)的中斷:
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //搶占優(yōu)先級 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子優(yōu)先級 2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道NVIC_Init(&NVIC_InitStructure);
4
中斷服務(wù)函數(shù)
中斷服務(wù)函數(shù)是響應(yīng)中斷的專門函數(shù)。當(dāng)特定的中斷事件發(fā)生時,系統(tǒng)自動調(diào)用對應(yīng)的中斷服務(wù)函數(shù)來處理該事件。
當(dāng)中斷發(fā)生時,處理器暫停當(dāng)前正在執(zhí)行的任務(wù),保存當(dāng)前任務(wù)的上下文(如寄存器狀態(tài)),然后跳轉(zhuǎn)到相應(yīng)的中斷服務(wù)函數(shù)執(zhí)行中斷處理。一旦中斷處理完成,處理器恢復(fù)之前任務(wù)的上下文,并繼續(xù)執(zhí)行被中斷的任務(wù)。
同樣以 STM32F103 的 PE2 為例,其中斷服務(wù)函數(shù)如下所示:
/* 外部中斷 2 服務(wù)程序 */void EXTI2_IRQHandler(void){ /* 中斷處理代碼 */}
當(dāng) PE2 引腳的中斷觸發(fā)以后就會調(diào)用其對應(yīng)的中斷處理函數(shù) EXTI2_IRQHandler,我們可以在函數(shù) EXTI2_IRQHandler 中添加中斷處理代碼。
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。