給初學者的STM32(Cortex-M3)中斷原理及編程方法[原創www.cnblogs.com/helesheng]

本人和教研室幾位老師編著的《基於STM32的嵌入式系統原理及應用》(ISBN:9787030697974)剛剛在科學出版社出版。這本書花費了半年以上的時間,凝聚了筆者作爲高校教師和嵌入式工程師的一些經驗,希望對大學生、嵌入式初學者和有一定經驗的工程師都有參考和借鑑作用。在寫作中尤其注意了不做芯片手冊的“搬運工”和“翻譯者”,試圖從開發者和工程師的角度理清知識點之間的邏輯關係,給讀者一條清晰的學習路徑。寫作中儘量做到用生活中的實例來闡述抽象的概念;用工程實例來幫助大家提高嵌入式開發的實踐能力。另外爲幫助讀者理解某些難點,我們在Bilibili上陸續發佈免費的講解的視頻,歡迎大家關注我的B站賬號:“何樂生0”(本文講解點這裏)。高校教師朋友們還可在微信中搜索公衆號“科學EDU”公衆號,申請免費樣書和課程PPT。

下面將該書中關於STM32的Cortex-M3中斷控制器NVIC的一小節發出來供大家拍磚,歡迎大家批評指正。以下內容歡迎轉載,但請註明出處: https://www.cnblogs.com/helesheng

一、中斷機制概述

中斷是計算機系統的一種處理異步事件的重要方法。它的作用是在計算機的CPU運行軟件的同時,監測系統內外有沒有發生需要CPU處理的“緊急事件”:當需要處理的事件發生時,中斷控制器會打斷CPU正在處理的常規事務,轉而插入一段處理該緊急事件的代碼;而該事務處理完成之後,CPU又能正確地返回剛纔被打斷的地方,以繼續運行原來的代碼。中斷可以分爲“中斷響應”、“中斷處理”和“中斷返回”三個階段。

中斷處理事件的異步性是指,緊急事件在什麼時候發生與CPU正在運行的程序完全沒有關係,是無法預測的。既然無法預測,只能隨時查看這些“緊急事件”是否發生,而中斷機制最重要的作用,是將CPU從不斷監測緊急事件是否發生這類繁重工作中解放出來,將這項“相對簡單”的繁重工作交給“中斷控制器”這個硬件來完成。中斷機制的第二個重要作用是判斷哪個或哪些中斷請求更緊急,應該優先被響應和處理,並且尋找不同中斷請求所對應的中斷處理代碼所在的位置。中斷機制的第三個作用是幫助CPU在運行完處理緊急事務的代碼後,正確地返回之前運行被打斷的地方。根據上述中斷處理的過程及其作用,讀者會發現中斷機制既提高了CPU正常運行常規程序的效率,又提高了響應中斷的速度,是幾乎所有現代計算機都配備的一種重要機制。

嵌入式系統是嵌入宿主對象中,幫助宿主對象完成特定任務的計算機系統,其主要工作就是和真實世界打交道。能夠快速、高效地處理來自真實世界的異步事件成爲嵌入式系統的重要標誌,因此中斷對於嵌入式系統而言顯得尤其重要,是學習嵌入式系統的難點和重點。

1.1 中斷的基本概念

這裏通過一個生活實例來解釋中斷機制中涉及的各種概念:某人在家中讀書學習,假設可能有兩件打斷他學習的事情分別是:有人敲門來訪和接聽電話。安靜地讀書學習相當於嵌入式處理器的常規程序,而“有人敲門來訪”和“接聽電話”兩件事就是可能引發中斷的“中斷源”,中斷之前他讀書所達到的頁碼稱爲“斷點”。如圖1所示,中斷源提出要求響應中斷稱爲“中斷請求”;而CPU打斷原來的程序運行,轉而處理開門或接電話等事情稱爲“中斷響應”;爲響應事件而運行的程序稱爲“中斷服務程序”;處理完異步事件,返回的過程稱爲“中斷返回”。中斷響應過程又可以分爲自動保存當前寄存器值的“現場保護”和定位並跳轉到中斷服務程序地址兩個小步驟。中斷返回也相應地分爲恢復寄存器值的“恢復現場”和恢復原來主程序運行的位置的“返回斷點”兩個小步驟。當然,也可以選擇不理睬這些打斷讀書的事情,例如,將手機設置爲靜音狀態,此時就稱爲“中斷屏蔽”。

圖1 中斷示意圖

 如圖2所示,當電話鈴聲和敲門聲同時響起時,只能根據事情的重要性,先響應一件事,而決定孰先孰後的分級機制稱爲“中斷優先級”。顯然圖2中開門迎客的優先級高於接聽電話。

圖2 中斷優先級示意圖

 優先級高可以有兩種體現,一種如圖2所示,兩個中斷同時到來時先響應優先級較高的那個中斷請求,再響應優先級低的那個。優先級高還可以體現爲,即使優先級低的中斷服務程序在運行中,優先級高的中斷也可以打斷優先級低的中斷服務程序,而優先級低的中斷服務程序只有等到優先級高的中斷服務程序運行完成後才能繼續運行。如圖3所示,開門任務能夠打斷接聽電話任務,形成類似“菊花”的嵌套結構,就稱爲“中斷嵌套”。STM32中將能夠被打斷,實現中斷嵌套的優先級稱爲“搶佔優先級”,而不能夠被打斷,只能優先響應的中斷優先級稱爲“子優先級”。

圖3 中斷嵌套示意圖

 中斷機制中還有一個重要概念稱爲“中斷向量表”,中斷向量表是一張由中斷服務程序的入口地址構成的表格,一般佔據代碼空間的起始地址。處理器設計者會將所有可能響應的中斷源所對應的中斷服務程序入口地址按照固定的順序排列在該表格中。當某個中斷源被響應時,處理器會自動跳轉到該中斷源的中斷服務程序入口所在的表格地址,並由該表格位置進一步跳轉到中斷服務程序。

1.2 ARM Cortex-M3的中斷控制器——NVIC

ARM V7架構將處理器分爲應用處理器A型、實時處理器R型和微控制器M型。M型中最重要的ARM Cortex-M3充分考慮了嵌入式應用中對異步事件處理的實時性要求。因而與之前的ARM架構不同,直接在Cortex-M3內核中集成了功能強勁的中斷控制器,並命名爲NVIC。在內核中集成中斷控制器不但防止了不同芯片生產廠商間的不兼容,還大大提高了中斷控制器和Cortex-M3內核的結合緊密度,降低了中斷響應時間,提高了實時性。

NVIC直譯爲嵌套向量中斷控制器,顧名思義,指ARM Cortex-M3的中斷控制器支持中斷嵌套和中斷向量表的自動跳轉功能。典型的NVIC可支持256箇中斷,其中包括16個由內核產生的異常中斷和240個外設中斷。其中,內核異常中斷指由Cortex-M3內核產生的復位、硬件錯誤、SysTick定時器中斷等中斷,而外設中斷則是由管腳電平變化、UART或DMA等外設變化引起的中斷。NVIC還能實現Cortex-M3內核響應中斷請求後的自動現場保護(自動保存處理器狀態寄存器)和中斷返回時的自動現場恢復(自動恢復處理器狀態寄存器)。另外還有一種稱爲“中斷尾鏈(末尾連鎖)”的技術,能夠在從高優先級的中斷服務程序返回時避免多餘的自動現場恢復,即自動進入低優先級的中斷服務程序,從而避免了一輪多餘的自動現場恢復和自動現場保護操作。

二、 STM32的NVIC

STM32的NVIC也只是標準NVIC的一部分,但主要功能都已經包含在其中:STM32的NVIC可支持16個內核異常中斷和68個外設中斷(其中STM32F103系列60個,STM32F107系列68個)。同時,每個中斷源可配置4位優先級控制字PRI_n(ARM Cortex-M3內核定義了8位,STM32微控制器只使用了其中的4位),具有16級可編程中斷優先級。

表1是STM32F103系列的中斷向量表,供讀者查詢。其中灰色部分是內核異常中斷。

表1 STM32F103系列的中斷向量表

 

 

 NVIC通過中斷優先級控制字PRI_n既支持嵌套中斷又支持非嵌套中斷,方法如表2所示,將每個中斷的優先級控制字PRI_n(4位)分爲兩截:前半截用於定義本中斷的搶佔優先級,後半截用於定義子優先級。而分割的具體辦法由優先級組別寄存器定義:若優先級組別定義爲4,則前半截的搶佔優先級佔據全部4位(共可定義24=16中搶佔優先級),而後半截的子優先級佔據0位(無法定義子優先級);若優先級組別定義爲3,則前半截的搶佔優先級佔據全部3位(共可定義23=8種搶佔優先級),而後半截的子優先級佔據1位(共可定義21=2種子優先級);其他優先級組別定義以此類推,表2所示是NVIC的中斷優先級配置。

表2 NVIC的中斷優先級配置

優先級組別

搶佔優先級

子優先級

4

4位/16級

0位/0級

3

3位/8級

1位/2級

2

2位/4級

2位/4級

1

1位/2級

3位/8級

0

0位/0級

4位/16級

值得注意的是,每個中斷源都擁有自己的優先級控制字PRI_n(n爲中斷源編號),但優先級組別寄存器只有一個。即一旦對NVIC定義了優先級控制字的分割方式,則對所有中斷源的所有PRI_n,分割方式都是相同的,並且意法半導體官方不建議在程序中頻繁修改優先級組別寄存器的內容。

與本節關於通用中斷嵌套規則的描述相同,STM32的NVIC的優先級嵌套規則如下:

(1)搶佔優先級高的中斷可以打斷搶佔優先級低的中斷服務,構成中斷嵌套。

(2)當兩個或多個同級別搶佔優先級的中斷出現時,它們不能構成中斷嵌套,但STM32先響應子優先級高的中斷請求。

(3)當兩個或者多個同級別搶佔優先級和同級別子優先級的中斷同時出現時,STM32先響應在中斷向量表中靠前的那個中斷。

通過實際生活的例子類比上述NVIC響應順序原則:在火車站購票時,先比較搶佔優先級,搶佔優先級高(軍人)的中斷優先響應;當搶佔優先級相同時,比較子優先級,子優先級高(軍銜)的中斷優先響應;當上述兩者都相同時,比較它們在中斷向量表中的位置(年齡),位置低(年齡大)的中斷優先響應。

再通過一箇中斷配置實例,說明STM32的NVIC配置和響應順序:假定設置優先級組爲2,然後進行以下設置。

(1)中斷3(RTC中斷)的搶佔優先級爲2,子優先級爲1。

(2)中斷6(外部中斷0)的搶佔優先級爲3,子優先級爲0。

(3)中斷7(外部中斷1)的搶佔優先級爲2,子優先級爲0。

則中斷優先級順序爲:中斷7 >中斷3 >中斷6。其中,中斷3和中斷7的搶佔優先級相同,所以中斷3不能被中斷7打斷,但中斷6可以被中斷3或中斷7打斷。

三、NVIC的配置和使用

STM32的嵌套向量中斷控制器需要和中斷源配合使用,本書將在後續章節中採用標準外設庫提供的庫函數,並結合具體中斷源外設來詳細講解。這裏爲了幫助讀者理解NVIC的工作方式,僅給出基於標準外設庫的NVIC通用配置流程。

(1)配置中斷優先級分組,例如:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//將中斷優先級組別配置爲2

上面代碼調用的函數“void NVIC_PriorityGroupConfig(uint32_t NVIC_Priority Group);”是意法半導體官方提供的標準外設庫函數,其功能是對中斷優先級組別進行配置。而其參數NVIC_PriorityGroup_2是由標準外設庫事先定義的宏,代表將組別設爲2,也就是2位搶佔優先級,2位子優先級。

(2)針對具體需要的中斷源,設置對應的搶佔優先級和子優先級,初始化NVIC,例如: 

NVIC_Init(&NVIC_InitStructure);   //用結構體NVIC_InitStructure中定義的參數初始化NVIC                                  //寄存器

函數“void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);”也是標準外設庫中提供的函數。&NVIC_InitStructure是指向初始化結構體NVIC_InitStructure的指針。結構體NVIC_InitStructure的定義如下,其成員包含了NVIC的主要參數。

typedef struct
{
  uint8_t NVIC_IRQChannel;                  //設置中斷源是哪一個
  uint8_t NVIC_IRQChannelPreemptionPriority;   //搶佔優先級
  uint8_t NVIC_IRQChannelSubPriority;          //子優先級
  FunctionalState NVIC_IRQChannelCmd;        //使能/禁能本中斷源
} NVIC_InitTypeDef;

(3)編寫對應的中斷服務程序。官方提供的標準外設庫已經在文件stm32f10 x_it.c中爲STM32所包含的每一個外設編寫了中斷服務程序的框架。其命名規則爲“void PPP_IRQHandler(void);”,其中PPP代表了具體中斷源的縮寫,如:

void WWDG_IRQHandler(void);   //窗口看門狗中斷服務
void RTC_IRQHandler (void);     //實時時鐘中斷服務
void EXTI0_IRQHandler (void);   //外部中斷0中斷服務
void EXTI1_IRQHandler (void);   //外部中斷1中斷服務
void USART1_IRQHandler(void);  //串口1中斷服務
void SPI1_IRQHandle(void);      //SPI1中斷服務

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章