FreeRTOS 之 在Cortex-M中应用时的中断优先级设置
??由于不同的 Cortex-M 系列,其中斷優先級是不一樣的,所以事先搞清楚所用 MCU 的中斷優先級有幾種。在 CMSIS 庫中的頭文件中可以查看優先級的數量 __NVIC_PRIO_BITS
?? FreeRTOS 的中斷嵌套結構被分為兩組,一組為被屏蔽的一組為不屏蔽的。FreeRTOS Config.h 中的configMAX_SYSCALL_INTERRUPT_PRIORITY 定義了這種分組。而這個最優值取決于上面提到的 MCU 的優先級位數,實際 CMSIS 中只要定義了 __NVIC_PRIO_BITS,移植時需要在 FreeRTOS Config.h 引入即可。
??數以千計的 FreeRTOS 應用運行在 ARM Cortex-M 內核上。令人驚奇的是,RTOS 與 Cortex-M 內核組合使用,使得技術支持請求變得如此的少。大多數的問題點是由不正確的優先級設置引起的。這個問題也是在意料之中的,因為盡管 Cortex-M 內核的中斷模式是非常強大的,但對于那些使用傳統中斷優先級架構的工程師來說, Cortex-M 內核中斷機制也有點笨拙(或者是說使用比較繁瑣),并且違反直覺(這個主要是因為 Cortex-M 優先級數越大代表的優先級反而越小)。
說明:雖然 Cortex-M 內核的優先級方案看上去比較復雜,但每一個官方發布的 FreeRTOS 接口包(在 .\ FreeRTOS \Source\portable文件夾中,一般為 port.c)內都會有正確配置的演示例程,可以以此為參考。
有效優先級
Cortex-M 硬件詳述
??首先需要清楚有效優先級的總數,這取決于微控制器制造商怎么使用 Cortex-M 內核。所以,并不是所有的 Cortex-M 內核微處理器都具有相同的中斷優先級級別。
?? Cortex-M 構架自身最多允許 256 級可編程優先級(優先級配置寄存器最多 8 位,所以優先級范圍從 0x00 ~ 0xFF),但是絕大多數微控制器制造商只是使用其中的一部分優先級。比如,TI Stellaris Cortex-M3 和 Cortex-M4 微控制器使用優先級配置寄存器的 3 個位,能提供 8 級優先級。再比如,NXP LPC17xx Cortex-M3 微控制器使用優先級配置寄存器的 5 個位,能提供 32 級優先級。STM32F1、F4 使用了其中的 4 位,能提供 16 級優先級。
??如果你的工程包含 CMSIS 庫頭文件,則頭文件中的宏 __NVIC_PRIO_BITS 定義使用多少優先級寄存器的位(默認是 4 位)。
應用到 FreeRTOS
??RTOS 中斷嵌套方案將有效的中斷優先級分成兩組:一組可以通過 RTOS 臨界區屏蔽,另一組不受 RTOS 影響,永遠都是使能的。在 FreeRTOS Config.h 中配置的 configMAX_SYSCALL_INTERRUPT_PRIORITY ,定義兩組中斷優先級的邊界。邏輯優先級高于此值的中斷不受 RTOS 影響。最優值取決于微控制器使用的優先級配置寄存器的位數。
與數值相反的優先級值和邏輯優先級設置
Cortex-M 硬件詳述
??有必要先解釋一下優先級值和邏輯優先級:在 Cortex-M 內核中,假如有 8 級優先級,我們說優先級值是 0~7,但數值最大的優先級 7 卻代表著最低的邏輯優先級。很多使用傳統傳統中斷優先級架構的工程師會覺得這樣比較繞,違反直覺。以下內容提到的優先級要仔細區分是優先級數值還是邏輯優先級。
??接下來需要清楚的是,在 Cortex-M 內核中,一個中斷的優先級數值越低,邏輯優先級卻越高。比如,中斷優先級為 2 的中斷可以搶占中斷優先級為 5 的中斷,但反過來就不行。換句話說,中斷優先級 2 比中斷優先級 5 的優先級更高。這是 Cortex-M 內核最容易讓人犯錯之處,因為大多數的非 Cortex-M 內核微控制器的中斷優先級表述是與之相反的。
應用到 FreeRTOS
??以 “FromISR” 結尾的 FreeRTOS 函數是具有中斷調用保護的(執行這些函數會進入臨界區),但是就算是這些函數,也不可以被邏輯優先級高于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的中斷服務函數調用。(宏 configMAX_SYSCALL_INTERRUPT_PRIORITY 定義在頭文件 FreeRTOS Config.h 中)。因此,任何使用 RTOS API 函數的中斷服務例程的中斷優先級數值大于等于 configMAX_SYSCALL_INTERRUPT_PRIORITY 宏的值。這樣就能保證中斷的邏輯優先級等于或低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 。
?? Cortex-M 中斷默認情況下有一個數值為 0 的優先級。大多數情況下 0 代表最高級優先級。因此,絕對不可以在優先級為 0 的中斷服務例程中調用 RTOS API 函數。
Cortex-M 內部優先級概述
Cortex-M 硬件詳述
?? Cortex-M 內核的中斷優先級寄存器是以最高位(MSB)對齊的。比如,如果使用了 3 位來表達優先級,則這 3 個位位于中斷優先級寄存器的 bit5、bit6、bit7 位。剩余的 bit0~bit4 可以設置成任何值,但為了兼容,最好將他們設置成 1.
?? Cortex-M 優先級寄存器最多有 8 位,如果一個微控制器只使用了其中的 3 位,那么這 3 位是以最高位對齊的,見下圖:
??某微控制器只使用了優先級寄存器中的 3 位,下圖展示了優先級數值5(二進制101B)是怎樣在優先級寄存器中存儲的。如果優先級寄存器中未使用的位置 1,下圖也展示了為什么數值 5(二進制0000 0101B)可以看成數值 191(二進制1011 1111)的。
??某微控制器只使用了優先級寄存器中的 4 位,下圖展示了優先級數值 5(二進制101B)是怎樣在優先級寄存器中存儲的。如果優先級寄存器中未使用的位置 1,下圖也展示了為什么數值 5(二進制0000 0101B)可以看成數值 95(二進制0101 1111)的。
原出處,本圖有誤,查找英文出處修訂改過
應用到 FreeRTOS
??上文中已經描述,那些在中斷服務例程中調用 RTOS API 函數的中斷邏輯優先級必須低于或等于configMAX_SYSCALL_INTERRUPT_PRIORITY(低邏輯優先級意味著高優先級數值)。
?? CMSIS 以及不同的微控制器供應商提供了可以設置某個中斷優先級的庫函數。一些庫函數的參數使用最低位對齊,另一些庫函數的參數可能使用最高位對齊,所以,使用時應該查閱庫函數的應用手冊進行正確設置。
??可以在 FreeRTOS Config.h 中設置宏 configMAX_SYSCALL_INTERRUPT_PRIORITY 和 configKERNEL_INTERRUPT_PRIORITY 的值。(關于這兩個宏可以參考參數設置一章,網址:http://open MCU.net/post/kernel-config.html)。這兩個宏需要根據 Cortex-M 內核自身的情況進行設置,要以最高有效位對齊。比如某微控制器使用中斷優先級寄存器中的 3 位,設置 configKERNEL_INTERRUPT_PRIORITY 的值為 5,則代碼為:#define configKERNEL_INTERRUPT_PRIORITY (5<<(8-3))
??對于每一個官方 FreeRTOS 演示例程,這也是在FreeRTOS Config.h中要設置宏 configKERNEL_INTERRUPT_PRIORITY 為最低優先級時,為什么要將它設置為 255(1111 1111B)的原因。使用這種方式指定這個值的原因是: FreeRTOS 內核是直接在 Cortex-M 內核硬件上運行的(沒有使用第三方接口庫函數),要比大多數庫函數先運行。
臨界區
Cortex-M 硬件詳述
??RTOS 內核使用 Cortex-M 內核的 BASEPRI 寄存器來實現臨界區(注:BASEPRI 為優先級屏蔽寄存器,優先級數值大于或等于該寄存器的中斷都會被屏蔽,優先級數值越大,邏輯優先級越低,但是為零時不屏蔽任何中斷)。這允許 RTOS 內核可以只屏蔽一部分中斷,因此可以提供一個靈活的中斷嵌套模式。
??那些需要在中斷調用時保護的 API 函數, FreeRTOS 使用寄存器 BASEPRI 實現中斷保護臨界區。當進入臨界區時,將寄存器BASEPRI 的值設置成 configMAX_SYSCALL_INTERRUPT_PRIORITY,當退出臨界區時,將寄存器 BASEPRI 的值設置成 0。很多 Bug 反饋都提到,當退出臨界區時不應該將寄存器設置成 0,應該恢復它之前的狀態(之前的狀態不一定是 0)。但是 Cortex-M NVIC 決不會允許一個低優先級中斷,去打斷當前正在執行的高優先級中斷,不管 BASEPRI 寄存器中是什么值。與進入臨界區前先保存 BASEPRI 的值,退出臨界區再恢復的方法相比,退出臨界區時將 BASEPRI 寄存器設置成 0 的方法可以獲得更快的執行速度。
應用到RTOS kernel
??RTOS 內核通過寫 configMAX_SYSCALL_INTERRUPT_PRIORITY 的值到 BASEPRI 寄存器的方法創建臨界區。中斷優先級 0(具有最高的邏輯優先級)不能被 BASEPRI 寄存器屏蔽,因此,configMAX_SYSCALL_INTERRUPT_PRIORITY 絕不可以設置成 0。
鳴謝
原文地址:https://www.douban.com/note/548730851/,感謝原作者。轉載時可能有部分改動。
總結
以上是生活随笔為你收集整理的FreeRTOS 之 在Cortex-M中应用时的中断优先级设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LwIP 之三 操作系统隔离接口 sys
- 下一篇: LwIP 之四 超时处理/定时器(tim