MPU(Memory Protection Unit,內存保護單元)在 Cortex-M內核中是可選模塊,帶MPU的微控制器允許內存映射(包括Flash、RAM和外圍設備)細分為若干區域,分別給每個區域分配不同的訪問權限。
FreeRTOS-MPU是FreeRTOS針對MPU實現的一個安全版本,支持ARMv7-M(Cortex-M3, Cortex-M4 和 Cortex-M7)和ARMv8-M (Cortex-M23和Cortex-M33)內核的微控制器。 針對ARMv7-M的FreeRTOS移植存在兩個版本,一個支持MPU,一個不支持。針對ARMv8-M只有一個移植版本,通過編譯開關控制是否支持MPU。 FreeRTOS通過將任務分為特權和非特權運行模式和限制對RAM、外設、可執行代碼、任務堆棧內存的訪問,使得應用更健壯和安全。例如,防止代碼從RAM中執行可以獲得巨大的好處,因為這樣做可以防止許多攻擊向量,如緩沖區溢出漏洞或加載到RAM中的惡意代碼的執行。 使用MPU必然會使應用程序設計更加復雜,首先必須確定MPU的內存區域限制并向RTOS進行描述,其次MPU限制應用程序任務可以做什么和不能做什么。MPU的策略
創建一個將每個任務限制在其自己的內存區域的應用程序可能是最安全的,但它也是設計和實現最復雜的。通常最好使用一個MPU來創建一個偽進程和線程模型——允許線程組共享內存空間。例如,創建一個可被可信的第一方代碼訪問的內存空間,以及一個僅可被不可信的第三方代碼訪問的內存空間。
FreeRTOS-MPU特性
兼容ARM Cortex-M3和Cortex-M4F標準移植。
可以創建以特權模式或非特權模式運行的任務。非特權任務只能訪問它們自己的堆棧和最多三個用戶可定義的內存區域(每個任務三個)。用戶可定義內存區域是在創建任務時分配給任務的,如果需要,可以在運行時重新配置。
用戶可定義的內存區域可以單獨參數化。例如,一些區域可能被設置為只讀,而另一些區域可能被設置為不可執行(在ARM術語中簡稱為XN),等等。
非特權任務之間不共享數據內存,但非特權任務可以使用標準隊列和信號量機制相互傳遞消息。可以通過使用用戶可定義的內存區域顯式地創建共享內存區域,但是不建議這樣做。
特權模式任務可以將自己設置為非特權模式,但一旦進入非特權模式,它就不能再將自己設置為特權模式。
FreeRTOS API位于Flash的一個區域,該區域只能在微控制器處于特權模式(調用API函數導致臨時切換到特權模式)時訪問。
內核維護的數據位于RAM的一個區域,只有在微控制器處于特權模式時才能訪問。
系統外設只能在微控制器處于特權模式時訪問。任何代碼都可以訪問標準外設(UART等),但是可以使用可定義的內存區域顯式地對其進行保護。
FreeRTOS-MPU可以創建兩種類型的任務:
特權任務:特權任務可以訪問整個內存映射。特權任務可以使用xTaskCreate()或xTaskCreateRestricted() API函數來創建。
非特權任務:非特權任務只能訪問它的堆棧。此外,可以授予它最多三個用戶可定義內存區域的訪問權限(每個任務三個)。非特權任務只能使用xTaskCreateRestricted()創建。注意,xTaskCreate()不能用于創建非特權任務。
如果一個任務想要使用MPU,那么必須提供以下附加信息:
任務堆棧的地址。
最多三個用戶可定義內存區域的開始、大小和訪問參數。
因此,創建任務所需的參數總數非常大。為了使創建MPU任務更容易, xTaskCreateRestricted()使用了一個名為xTaskParameters的參數結構體,通常定義為結構常量存儲在Flash中,并將該結構地址作為單個參數傳遞給xTaskCreateRestricted()。
typedef struct xTASK_PARAMTERS
{
TaskFunction_t pvTaskCode;
const signed char * const pcName;
unsigned short usStackDepth;
void * pvParameters;
UBaseType_t uxPriority;
portSTACK_TYPE * puxStackBuffer;
MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
} TaskParameters_t;
typedef struct xMEMORY_REGION
{
void *pvBaseAddress; /* 起始地址 */
unsigned long ulLengthInBytes; /* 長度 */
unsigned long ulParameters; /* 訪問屬性 */
} MemoryRegion_t;
分配給任務的內存區域可以使用vTaskAllocateMPURegions()來更改。
預定義區域和用戶可定義區域
區域0~4被內核配置為可用的運行環境,其中:
運行狀態的任務可以訪問它自己的棧,但是所有其他的RAM只有當運行在特權模式時才可以訪問。
只有當在特權模式下運行時,才能訪問內核和系統外設所在的Flash內存區域。
Flash內存(除了內核所在的內存)和所有非系統外設(例如UART和模擬輸入)都可以被特權和用戶模式任務訪問。
內核在每次上下文切換期間都會重新配置MPU,因此每個任務可以不同地定義其余三個區域。
區域起始地址和大小限制
MPU硬件強加了兩個規則,區域起始地址和大小定義必須遵守:
1、區域大小必須是32字節到4G(包括)之間的二進制的2次方。例如,32字節、64字節、128字節、256字節等等都是有效的區域大小。
2、起始地址必須是區域大小的倍數。例如,一個配置為65536字節長的區域必須從能被65536整除的地址開始。
FreeRTOS-MPUAPI
1、xTaskCreateRestricted()是xTaskCreate()的擴展版本,用于創建執行權限受限或者內存訪問權限受限的任務。
xTaskCreateRestricted()需要xTaskCreate()使用的所有參數,加上四個額外的參數來定義三個任務特定的MPU區域和一個堆棧緩沖區。如果在普通函數參數列表中使用這個數量的參數會很麻煩,而且可能會大量使用堆棧空間。xTaskCreateRestricted()將一個指向xTaskParameters結構的指針作為其兩個參數之一,第二個參數用于向創建的任務傳遞句柄,與xTaskCreate()參數相同。如果不需要任務句柄, pxCreatedTask可以設置為NULL。
portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition,
xTaskHandle *pxCreatedTask );
2、vTaskAllocateMPURegions()定義一組內存保護單元(MPU)區域,供受MPU限制的任務使用。如果創建任務時沒有分配MPU區域,可以在運行時使用vTaskAllocateMPURegions()函數重新分配。
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
const MemoryRegion_t * const xRegions );
3、特權模式任務可以調用portSWITCH_TO_USER_MODE()將自己設置為非特權模式。在非特權模式下運行的任務不能設置為特權模式。
原文標題:FreeRTOS MPU使系統更健壯!
文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
-
微控制器
+關注
關注
48文章
7542瀏覽量
151316 -
MPU
+關注
關注
0文章
357瀏覽量
48775 -
FreeRTOS
+關注
關注
12文章
484瀏覽量
62140 -
Cortex-M3
+關注
關注
9文章
269瀏覽量
59463
原文標題:FreeRTOS MPU使系統更健壯!
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論