這里優先級分組選擇的是將優先級的4位控制位全部用作搶占優先級的配置,響應優先級都一樣,即不做特別配置。那么上圖中SYSTICK/TIM2/TIM3/TIM4的中斷的搶占優先級數據0、2、3、4其實是站在中斷優先級寄存器的高4位而言的,那么放到整個8位優先級寄存器來看的話,他們的優先級應該是0x00,0x20,0x30,0x40【其實,低4位值是多少無關緊要,反正無效位】。
前面提過了,現在BASEPRI寄存器也只用到高4位,低4位保留。顯然,如果在給BASEPRI寄存器賦值時按照基于高4位得到數字往里面寫的話肯定都是無效的。
比方,我們期望在主程序里將上面TIM2/TIM3/TIM4的幾個中斷都屏蔽掉,若代碼像下面截圖里這樣寫肯定達不到目的。我這里開啟了TIM2/TIM3/TIM4的周期性更新中斷。【本文代碼編譯、調試基于ARM
MDK IDE】
經過測試也的確沒有達到目的。我寫__set_BASEPRI(2)的本意是想屏蔽掉那幾個定時器的中斷響應,結果發現根本沒作用。BASEPRI寄存器也沒正確寫入,因為數據2只能寫到BASEPRI寄存器的低4位,這幾位恰好是無效位。不難理解,當我們改寫成__set_BASEPRI(0x20)時就可以達到目的了。
此時,BASEPRI被正確寫入,TIM2/TIM3/TIM4的中斷不能得到響應,倒是SYSTICK中斷可以不被影響地得到響應,因為它的優先級是0,BASEPRI的配置屏蔽不了它。也就是說,通過配置BASEPRI寄存器來設置中斷響應門檻的話,是阻止不了優先級為0或更高優先級的中斷的響應的。如果對BASEPRI寫0表示放棄其設置的中斷門檻的功能。
如果希望對包括0優先級在內的所有可配置中斷進行關閉或屏蔽,能否做得到呢?若可以,如何操作?
STM32芯片里的中斷如果按中斷源是來自ST外設還是ARM核處理器可以分為異常和中斷,比方下圖中灰色部分的就是異常,其它為中斷。【截圖來自STM32G4系列參考手冊】
平常我們統稱二者為中斷,不做區分。如果說把所有中斷按其優先級是否可以配置,又可以將中斷分為優先級固定和優先級可配置的中斷。其中,優先級固定的中斷在上面表格中都明確標示了fixed字樣,優先級可配置的都加注了settable字樣。結合前面提到的優先級寄存器的特性,可配置的優先級是不會高于0級,即配置的數字不會小于0的。
若我們期望對所有可配置中斷進行關閉或屏蔽,可以操作另一個叫PRIMASK的寄存器,它只有1位有效控制位。
我們通過對PARMASK寫1,令CPU對所有優先級可配置的中斷不做響應;若對其寫0表示放棄屏蔽功能。比方,我們還是接著前面的演示代碼來看看效果。
這時,前面提到的4個定時器中斷都不能得到響應了,雖打了斷點但過不去。我們還可以借助調試工具看到這幾個中斷的響應情況【SYSTICK位置離得遠,單獨截取后插進圖中的】。
對于上圖的部分信息我這里稍微解釋下。
圖形上方的字母E、P、A是下方Eable/Pending/Active單詞的首字母。Enable表示相應中斷是否在NVIC端得到響應允許;Pending表示中斷等待CPU的執行;Active表示中斷服務程序正在被執行。從圖中可以看出,SYSTICK/TIM2/TIM3/TIM4的中斷響應都雖得到允許,但都處于Pending期待執行狀態。既然沒有得到執行,Active位自然也是0。
上圖中優先級的數字顯然是按照高4位結合優先級分組后來看的,那個S表示SubPriority的意思。為了看得更清晰點,我不妨將優先級分組采用下面的做法重新配置下,保持原搶占優先級都不動,增加1位響應優先級【即子優先級】配置。目前4位優先級配置位拆分為3位搶占優先級配置位和1位響應優先級配置位。當前測試代碼也保持不動。
顯然,上圖中的搶占優先級編號2、3、4是站在分組后的高3位單獨來看的,響應優先級是站在分組后剩下的1位單獨來看的。如果我們把兩類優先級的配置合在高4位一起看,優先級數字應該分別是十進制數1、5、6、9。【這個地方要弄清楚,否則下面調試結果看不明白。】
基于前面測試代碼和現有配置,我們看看運行后的中斷響應情況。
剛才雖然調整了優先級的分組配置,但這幾個中斷的搶占優先級都沒改變,所以在PRIMASK為1的情況下都不能得到響應。我們可以發現這幾個中斷的優先級站在高4位的角度來看而得出的優先級數字跟我上面分析的基本一致,除了SYSTICK的。
按理此時此處SYSTICK的優先級應該是1而不是0。為什么會這樣呢?原因就在于我基于CubeMx組織的代碼,這個過程中如果使用SYSTICK做庫代碼的TICK時鐘,其中斷優先級的配置使用默認配置,沒有理睬CubeMx這邊針對它子優先級的配置。Cube庫在配置SYSTICK優先級時,默認使用全部4位用作搶占優先級的配置,同時將子優先級配置為0。當然,我們可以針對性地調整來適應我們的需求。主要是下面這個weak特性的初始函數,我們可以手動修改這個函數里關于中斷優先級的配置。
關于使用PRIMASK屏蔽所有可配置中斷的做法還有其它等效動作,比如使用CPSID指令和CPSIE指令或調用相關CMSIS函數。【參見下圖】
它們的作用一樣,也就是我們平常所說的開、關總中斷,準確點說是屏蔽所有優先級可配置中斷的響應或者放棄屏蔽功能。對于開、關總中斷的說法,從實現屏蔽效果來看勉強可以說能關總中斷。但整體上講,個人覺得這個說法不太合適,還很容易給人帶來誤解,頗具誤導性。其實,不論是操作PRIMASK還是BASEPRI寄存器,并沒有對被屏蔽中斷的原有參數和配置做任何改變。即那些暫時被屏蔽的中斷的中斷響應允許位、中斷請求使能位、中斷觸發事件等都不會因為暫時的被屏蔽而發生改變。打個形象而不是特別貼切的比方。當你開著豪車愉快地跑在某條道上,聽著歌哼著曲。突然前方有交警在對道路做臨時管制,你和其它一干人車都被攔停下來。原因是有一行高級別的人物要保障優先通行。你等雖被攔停下來,既沒人說你無證駕駛、也沒人告知你無權走這條道,證照都在,行路權也有,就是此刻級別不夠。一旦放行,你依然可以一如既往地行使。
我倒覺得ARM技術手冊提到的優先級提升更好理解和接受些。即通過對BASEPRI、PRIMASK這些寄存器編程提升當前執行程序的優先級,使得低于當前優先級的中斷暫時得不到響應。適當時候放棄優先級升級功能,恢復原狀。
可能有人知道,還有個可以關閉或屏蔽優先級高至-1級的HardFault異常的控制寄存器,就是FAULTMASK,也是1位有效位,操作跟PRIMASK類似。有興趣的話,可以自行進一步研究下。
-
STM32
+關注
關注
2270文章
10910瀏覽量
356605 -
控制
+關注
關注
4文章
1013瀏覽量
122694
發布評論請先 登錄
相關推薦
評論