一、前言
在之前的STM32的中斷系統理論基礎知識之基本原理及NVIC中,分別中斷的基本原理,中斷的管理機制和中斷的處理流程進行了較為詳細的論述,讀者通過全篇的閱讀了解可以整體上對以圍繞NVIC為管理核心的STM32的中斷系統有一個初步的了解,明白中斷的一些基本概念以及STM32中斷系統的一個大致的工作流程。
這一篇主要對中斷系統相關的寄存器進行相應的分析介紹,適當了解中斷系統寄存器的相關介紹,有助于加深對STM32內核的中斷及異常的認識,明白中斷時的功能都是由哪些寄存器負責完成實現的,同時對后續介紹到的中斷相關配置及API函數的使用有很好的幫助。
二、 寄存器概述
圖1為STM32中斷系統寄存器的概述,總共可以分為3組不同的寄存器組。各個寄存器組下分別又有不同用于中斷控制的寄存器。它們都屬于STM32內核上的寄存器。
(1)、NVIC作為內嵌向量中斷控制器,控制著整個芯片中斷相關的功能,它跟內核緊密耦合,是內核里面的一個外設。但是各個芯片廠商在設計芯片的時候會對 Cortex-M3 內核里面的 NVIC 進行裁剪,把不需要的部分去掉,所以說 STM32的 NVIC 是Cortex-M3的 NVIC 的一個子集。它用于總體管理異常和中斷,因此提供了和中斷系統緊密相關的控制和狀態寄存器;
(2)、SCB為系統控制塊,SCB中包含了一些內核系統控制相關的寄存器,同時也包含了關于中斷相關的,由于本篇主要介紹中斷系統,因此這里就只針對SCB中關于中斷控制的寄存器功能進行分析介紹;
(3)、而為了滿足一些代碼段不允許被中斷打斷,那么這段代碼就必須用關中斷的方式給保護起來的場合,STM32提供了中斷屏蔽寄存器,我們可以一次性把一堆必須要屏蔽的中斷進行屏蔽。
圖1 中斷系統寄存器概述
三、 NVIC****寄存器組
NVIC控制器包含一系列寄存器組,STM32為其定義了如下的結構體:
typedef struct
{
__IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register*/
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register*/
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register*/
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644];
__IO uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register*/
} NVIC_Type;
(1)、中斷使能寄存器ISER
Interrupt Set-Enable Registers,這是一個中斷使能寄存器組。總共有8個uint32類型的寄存器,即ISER[8],上面說了 CM3 內核支持 256 個中斷,這里用 8 個32位寄存器來控制,每個位控制一個中斷。但是例如STM32F103 的可屏蔽中斷只有 60 個,所以對我們來說,有用的就是兩個(ISER[0]和 ISER[1]),總共可以表示 64 個中斷。而 STM32F103 只用了其中的前 60 位。ISER[0]的 bit0 ~ bit31 分別對應中斷 0 ~ 31。ISER[1]的 bit0 ~ 27 對應中斷 32~59;這樣總共 60 個中斷就分別對應上了。你要使能某個中斷,必須設置相應的 ISER 位為 1,使該中斷被使能(這里僅僅是使能,還要配合中斷分組、屏蔽、IO 口映射等設置才算是一個完整的中斷設置)。
圖2 中斷使能和中斷除能寄存器組
(2)、中斷除能寄存器ICER
Interrupt Clear-Enable Registers,是一個中斷除能寄存器組。總共有8個uint32類型的寄存器,即ICER[8],該寄存器組與 ISER 的作用恰好相反,是用來清除某個中斷的使能的。其對應位的功能,也和 ICER 一樣。這里要專門設置一個 ICER 來清除中斷位,而不是向 ISER 寫 0 來清除,是因為NVIC 的這些寄存器都是寫 1 有效的,寫 0 是無效的。
(3)、中斷掛起控制寄存器ISPR
Interrupt Set-Pending Registers,是一個中斷掛起控制寄存器組。總共有8個uint32類型的寄存器,即ISPR[8],每個位對應的中斷和 ISER 是一樣的。通過置 1,可以將正在進行的中斷掛起,暫時停止執行該中斷,而執行同級或更高級別的中斷。寫 0 是無效的。
圖3 中斷掛起和中斷解掛寄存器組
(4) 、中斷解掛控制寄存器ICPR
Interrupt Clear-Pending Registers,是一個中斷解掛控制寄存器組。總共有8個uint32類型的寄存器,即ICPR[8],其作用與 ISPR 相反,將之前暫時停止執行的中斷解掛,對應位也和 ISER 是一樣的。通過設置 1,可以將掛起的中斷解掛。寫 0 無效。
(5)、中斷激活標志位寄存器IABR
Interrupt Active Bit Registers,是一個中斷激活標志位寄存器組。總共有8個uint32類型的寄存器,即IABR[8],對應位所代表的中斷和 ISER 一樣,如果為 1,則表示該位所對應的中斷正在被執行。這是一個只讀寄存器,通過它可以知道當前在執行的中斷是哪一個。在中斷執行完了由硬件自動清零。如果在中斷執行過程中,發生了更高優先級的中斷搶占,那么之前被搶占的中斷該標志位依然是1。
圖4 中斷激活標志位寄存器組
(6)、中斷優先級控制寄存器IP
Interrupt Priority Registers,是一個中斷優先級控制的寄存器組。總共有240個uint8類型的寄存器,即IP[240],這個寄存器組相當重要!STM32 的中斷分組與這個寄存器組密切相關。IP 寄存器組由 240 個 8bit 的寄存器組成,每個可屏蔽中斷占用 8bit,這樣總共可以表示 240 個可屏蔽中斷。而 STM32 只用到了其中的前 60 個。IP[59] ~ IP[0]分別對應中斷 59 ~ 0。而每個可屏蔽中斷占用的 8bit 并沒有全部使用,而是只用了高 4 位。這 4 位,又分為搶占優先級和子優先級。搶占優先級在前,子優先級在后。而這兩個優先級各占幾個位又要根據 SCB->AIRCR 中的中斷分組設置來決定。
圖5 中斷優先級控制寄存器組
(7)、軟件觸發中斷寄存器STIR
這個寄存器是利用軟件設置中斷編號的方式來觸發中斷發生,是一個uint32類型的寄存器,有效位為0~8。比如設置NVIC->STIR=3,則會觸發中斷3,需要注意的是,該寄存器無法觸發系統異常如NMI或Systick的。
圖6 軟件觸發中斷寄存器
四、 SCB****寄存器組
系統控制塊(SCB)是內核外設的主要模塊之一,提供系統控制以及系統執行信息,包括配置,控制,報告系統異常等。而SCB數據結構中也包含了一些常用于中斷控制的寄存器。
(1) 、中斷控制和狀態寄存器ICSR
該寄存器的主要作用為:
a. 設置和清除系統異常的掛起狀態,異常包括Systick、PendSV、NMI。這個功能和NVIC的中斷掛起控制寄存器ISPR和中斷解掛控制寄存器ICPR差不多;
b.通過讀取VECTACTIVE=>Vector Active域,可以確定當前執行的異常/中斷編號,VECTACTIVE域和中斷程序狀態寄存器(IPSR)功能比較類似,IPSR包含了當前正在執行的中斷服務程序(ISR)編號,只不過VECTACTIVE是用來讀Systick、PendSV、NMI這些異常狀態的。
圖7 中斷控制和狀態寄存器
注意:當寫ICSR時,如果:寫1到PENDSVSET位和寫1到PENDSVCLR位;寫1到PENDSTSET位和寫1到PENDSTCLR位;程序執行的效果是不可預測的。該寄存器各個位域可以通過調試器讀取狀態,但多數情況下只有掛起位用于應用開發。
(2) 、向量偏移寄存器VTOR
由于CPU隨時都可能檢測到中斷信息,也就是說,CPU 隨時都可能執行中斷處理程序,所以中斷處理程序必須一直存儲在內存某段空間之中。中斷處理程序在內存中的入口地址稱為中斷向量;而要確定中斷處理程序的入口地址,處理器利用了一種向量表機制:即中斷向量,必須存儲在對應的中斷向量表表項中。采用向量表處理中斷,處理器會從存儲器的向量表中,自動定位中斷的程序入口。
一般來說,程序啟動后,將首先從“中斷向量表”取出復位中斷向量執行復位中斷程序完成啟動。而這張“中斷向量表”的起始地址是0x8000004,當中斷來臨,STM32的內部硬件機制亦會自動將PC指針定位到“中斷向量表”處,并根據中斷源取出對應的中斷向量執行中斷服務程序。不過有些應用可能需要在運行時修改或定義向量表地址。為了進行這種處理,M3/M4處理器實現了一種名為向量表重定位的特性。向量表重定位特性提供了一個名為向量表偏移寄存器(VTOR)的可編程寄存器。該寄存器將正在使用的存儲器的起始地址定義為向量表。
圖8 向量偏移寄存器
中斷向量表里的中斷跳轉地址在編譯后就定下來了,SCB->VTOR向量可動態調整就是讓我們的程序運行后還能改變向量的跳轉地址。方法就是:在RAM重建一個中斷向量表,在想改變的位置重新賦值新的跳轉地址。通過賦值向量表偏移數值SCB->VTOR = (uint32_t)__VECTOR_RAM,這樣下次異常發生時,就直接跳到重新指定的RAM中斷向量表的首地址處,再匹配對應的中斷向量。
(3) 、應用中斷和復位控制寄存器AIRCR
該寄存器用于:
控制異常/中斷優先級管理中的優先級分組
提供系統的端信息(可以被軟件或調試器使用)
提供自復位特性
圖9 應用中斷和復位控制寄存器
SCB->AIRCR的中斷分組決定了如何去理解NVIC中斷優先級控制寄存器IP的高4bit(47bit)。SCB->AIRCR的810位決定了分組的組別,可以分為0到4共5組,不同的組別決定了IP寄存器劃分的搶占優先級和響應優先級各占幾位。
VECTRESET和VECTCLRACTIVE位域是為調試器設計的,盡管軟件可以利用VECTRESET觸發一次處理器復位,不過由于它不會復位外設等系統中的其他部分,因此多數應用程序是不大會用到它的。若想產生一次系統復位,多數情況下(取決于芯片設計和應用復位需求)應該使用SYSRESETREQ。有一點要注意,VECTRESET和VECTCLRACTIVE不應同時置位,非要這么做的話會導致Cortex-M3/M4設備的復位電路出錯。
在Cortex-M3中,有兩種方法能夠進行系統復位:
第一種方法:置位 NVIC 中應用程序中斷與復位控制寄存器(AIRCR)的 VECTRESET 位(位偏移:0)。這種復位的作用為復位Cortex-M3處理器內核,除了調試邏輯之外的所有角落,但是它不會影響到Cortex-M3處理器外部的任何電路,所以STM32上的各片上外設和其它電路都不受影響。
第二種方法:置位 NVIC 中應用程序中斷與復位控制寄存器(AIRCR)的 SYSRESETREQ位(位偏移:2)。系統復位是置位同一個寄存器中的 SYSRESETREQ 位。這種復位則會波及整個芯片上的電路:它會使Cortex-M3/M4處理器把送往系統復位發生器的請求線置為有效。但是系統復位發生器不是Cortex-M3/M4的這一局部,而是由芯片廠商實現,因此不同的芯片對此復位的響應也不同。因此,讀者須要仔細參閱芯片規格書,明白當發生片內復位時,各外設和功能模塊都會回到什么樣的初始狀態,或者有哪些功能模塊不受影響(假如,STM32系列的芯片有后備存儲區,該區就被特殊對待)。大部分情況下,復位發生器在響應SYSRESETREQ 時,它也會同時把Cortex-M3/M4處理器的系統復位信號(SYSRESETn)置為有效。通常,SYSRESETREQ不應復位調試邏輯。這里有一個要注意的問題:從SYSRESETREQ被置為有效到復位發生器執行復位命令,往往會有一個延時。在此延時期間,處理器依然能夠響應中斷請求。但我們的本意往往是要讓此次執行到此為止,不要再做任何其它事情了。所以,最好在發出復位請求前,先把FAULTMASK置位。
這里有一個要注意的問題:從SYSRESETREQ 被置為有效,到復位發生器執行復位命令,往往會有一個延時。在此延時期間,處理器仍然可以響應中斷請求。但我們的本意往往是要讓此次執行到此為止,不要再做任何其它事情了。所以,最好在發出復位請求前,先把FAULTMASK 置位,才萬無一失。即:
void mcuRestart(void)
{
__set_FAULTMASK(1); //關閉所有中斷
NVIC_SystemReset(); //復位
}
(4) 系統處理優先級處理器SHP
SCB->SHP[0]到SCB->SHP[11]的位域定義和NVIC中斷優先級寄存器IP的定義相同,不同之處是SHP是用于系統異常優先級的。這些寄存器并未全部實現,為了編程中斷和異常的優先級,CMSIS提供了函數NVIC_SetPrioriity和NVIC_GetPriority。這兩個函數位于core_cm3.h中。例如:
圖10 系統處理優先級處理器
(5) 、系統處理控制和狀態寄存器SHCSR
使用錯誤、存儲器管理錯誤和總線錯誤異常的使能由該寄存器控制。錯誤的掛起狀態和多數系統異常的活躍狀態也可以從該寄存器中得到。
多數情況下,該寄存器及用于應用代碼使能可配置的錯誤處理(MEMFAULT、 BUSFAULT、USGFAULT)。
圖11 系統處理控制和狀態寄存器
使能位ENA,設置1使能異常,設置0失能異常。
待定位PENDED,如果異常待定讀為1,否則讀為0。我們可以寫這些位改變異常的待定狀態。
活躍位ACT,如果異常活躍讀為1,否則讀為0。我們可以寫這些位改變異常的活躍狀態,但是看這部分的注意事項。
盡管可以寫SCB->SHCSR寄存器的所有位,但建議軟件只寫異常使能位。寫這個寄存器需要小心,確保系統異常的活躍位狀態不會被意外修改,使能異常時,應該使用一次讀修改寫順序的操作。下面的例子用于使能所有非硬Fault(存儲器管理Fault、總線Fault、用法Fault異常):
不然若一個已經被激活的系統異常的活躍狀態被意外清除了,當系統異常處理產生異常退出時就會出現錯誤異常。
五、 中斷屏蔽寄存器組
中斷屏蔽寄存器的目的是讓實時性要求高的任務或者事件能夠順利執行,因此要在需要的時候暫時屏蔽中斷。
圖12 異常和中斷編號表
編號為 0~15 的稱為內核異常,而 16 以上的則稱為核外(外部)中斷。
PRIMASK
PRIMASK雖然是32位的寄存器,但是只有最低位有效,這是一個只有1個bit有效的寄存器。當將寄存器的位置為1時,相當于將當前中斷的優先級設為0,它只響應NMI(優先級為-2更高)和HardFault(優先級為-1更高)異常,關掉其它優先級小于0(即數值比0大)所有可屏蔽的異常或中斷;寄存器的默認值是0,表示沒有關異常或者中斷。
PRIMASK通常用于在處理有實時性要求(time critical)的程序時關閉所有中斷, 實時程序處理完畢后清除PRIMASK,重新開啟中斷。
FAULTMASK
FAULTMASK雖然是32位的寄存器,但是只有最低位有效,這是一個只有1個bit有效的寄存器。當將寄存器的位置為1時,當于將當前中斷的優先級設為-1,它只響應NMI(優先級為-2更高),關掉其它優先級小于-1(即數值比-1大)的可屏蔽的異常或中斷,甚至是HardFault異常也關閉;寄存器的默認值是0,表示沒有關異常或者中斷。
BASEPRI
為了提供靈活的中斷屏蔽機制,內核架構提供了BASEPRI寄存器,可以根據優先級屏蔽中斷或者異常,屏蔽的是搶占優先級(主優先級),它可以由用戶來定義需要屏蔽中斷的優先級的閾值,當設置為具體的閾值時,所有大于該數字值的中斷都被關閉(優先級數字越大,表示優先級越低);這里設置的優先級針對的是搶占優先級;寄存器的默認值是0,表示沒有關異常或者中斷。
比如我們配置寄存器BASEPRI的數值為3,所有優先級數值大于等于3的中斷都會被關閉,優先級數值小于3的中斷不會被關閉。但0比較特殊,對寄存器basepri寄存器賦值0,那么被關閉的中斷會被打開。
寄存器BASEPRI的有效位數受系統中表達優先級的位數影響,如果系統中只使用3個位(5~7bit)來表達優先級,則BASEPRI有意義的值僅為0x00、0x20、0x40、0x60、0x80、0xA0、0xC0和0xE0。
圖12 寄存器BASEPRI
六、總結
本篇對STM32的中斷系統涉及到的的寄存器分別進行了介紹,了解了各個寄存器的功能和對應寄存器位的定義可以更方便的去理解在實際使用中斷配置時的配置功能,下一篇將對中斷配置流程在實際開發中的設計及應用進行詳細的分析。
-
寄存器
+關注
關注
31文章
5317瀏覽量
120002 -
STM32
+關注
關注
2266文章
10871瀏覽量
354787 -
中斷系統
+關注
關注
1文章
96瀏覽量
61006
發布評論請先 登錄
相關推薦
評論