淺談優先權,從ARM Cortex-M到FreeRTOS設定
什麼是Exception?
任何讓程式脫離正常的執行流程的事件被稱為Exception。當Exception發生時,程式會停止手邊的工作,然後跳去執行Exception Handler,執行完後再回來繼續執行手邊的工作。
什麼是Interrupt?
在ARM的架構上來說,Interrupt是一種Exception,Interrupt通常是週邊裝置或是外部輸入所產生,也可以透過軟體設定產生。Interrupt的Exception Handler同時也被稱作ISR(Interrupt Service Routine)
Exception對Cortex-M而言有什麼意義?
Cortex-M有幾個不同的exception來源,但都會先交給NVIC處理。NVIC會負責處理Interrupt Request(IRQs)和Non-Maskable Interrupt(NVI) Request。
IRQs和NMI差再哪裡?
- IRQ
- 通常是週邊或外部輸入產生的
- NMI
- 通常是給watchdog timer(看門狗,一定時間處理器沒有回應時會主動打斷處理器)和brownout detector(處理器電壓偵測,當處理器的電壓低於某個水平時會發出警告) 另外還有SysTick,是處理器內部的timer,會週期性的對處理器發出中斷。通常是給embedded-OS使用。
下面這張表圖代表Cortex-M3, M4的exception type 可以觀察到exception number越小,代表事情越大條。而編號16~255總共240個例外都交給Interrupt使用。
雖然處理器提供了高達240個IRQ,但一般實作上並不會全部使用,一般只會使用16~100個Interrupt,好處是簡化設計,同時減少電力消耗。舉例而言,STM32F429的startup.s中 (請參閱Line152~242),只使用到了91個interrupt。
談NVIC,Nested vectored interrupt controller
NVIC是Cortex-M處理器的一部份。負責處理例外和中斷的設定,包括中斷的優先權和遮罩。他有一些很棒的特性
- 彈性的控制和設定
- 每個ISR都可以獨立做啟動與關閉
- 允許巢狀中斷,也就是中斷時,還可 以被中斷
- 每個Exception都有自己的優先權,有些可以自由設定優先權,少數嚴重的例外不可以
- Interrupt可以自由設定,可以改變
- Reset, NMI, HardFault的優先權是固定的,不可改變
- 當例外發生時,NVIC會比較例外的優先權,如果後來發生的exception優先權比較高,那就插隊先執行更優先的例外,也就是preemption。
- 每個Exception都有自己的優先權,有些可以自由設定優先權,少數嚴重的例外不可以
- 可以做中斷遮罩,也就是停用某些中斷
- Cotex-M3, M4提供了幾個遮罩register,例如PRIMASK,你可以停用所有的exception(除了最嚴重的HardFault和NMI不可以停用),好處是當你在執行一些關鍵任務,不可以被打斷(例如看片執行real-time multimedia解碼時)。或是你可以使用BASEPRI register,來停用某個優先權以下的例外。
談優先權
每個Exception都有自己的優先權。對Cortex-M來說,有一件很簡單但重要的事情要記得,那就是
數值越小代表優先權越高
預設上,所有軟體可以設定的優先權預設都是0。優先權可以設定的範圍在0~15之間,背後意含是Reset(-3), NMI(-2), HardFault(-1)的優先權永遠比你設定的例外還高。
優先權的觀念
在ARM Cortex-M裡,設定優先權的register bits被分為兩個欄位
- group priority(靠近MSB這一邊)(或稱為preempt priority)
- subpriority within group(靠近LSB這一邊)
就是遵守幾個簡單的原則
- 如果一個exception handler正在執行,其他例外發生時,如果group priority優先權比你高就可以插隊,如果跟你一樣或比你低,就乖乖等
- 如果有多個相同優先權的例外處理在等待執行(Pending),那麼先比較subpriority,優先權比較高的排前面,如果還是一樣,Exception Number小的優先。
ARM Cortex-M 架構允許0~255個不同的優先權,總共256個。但是實際上各個使用Cortex-M的微處理器並廠商不會讓你自由設定256個優先權。舉例來說,TI Stellaris Cortex-M3 and ARM Cortex-M4 提供3個priority bits,允許你自訂8個優先權。NXP LPC17xx ARM Cortex-M3 提供了5個優先權bits,允許你自訂32個優先權。而STM32F429這塊使用Cortex-M4的板子,提供4個優先權bits。 這4個bits要如何分配給group priority和subpriority呢?透過設定Application interrupt and reset control register (AIRCR)可以改變,你可以設成以下形式,詳情請參閱stm32 programming manual p.213
- GGGG
- GGGS
- GGSS
- GSSS
- SSSS
其中G代表Group priority field,S代表Subpriority field
談CMSIS和NVIC的關係
CMSIS 提供了控制NVIC register的function。你可以透過CMSIS來控制優先權。包括啟用、停用某個exception,設定某個Interrupt的優先權等。
值得一提的是其實每個優先權會佔用8個bits,但是其實只有bits[7:4]有用而已,bits[3:0]是don't care bits。詳情請參閱stm32_programming_manual p.200