1
MM32F5330 MPU簡介
靈動微電子發布了搭載安謀科技“星辰”STAR-MC1處理器的全新高性能 MM32F5 微控制器系列,該系列在內核、總線和外設配置等多個方面進行了創新,內核上更是首次搭載了 Armv8-M 架構的 “星辰” STAR-MC1 處理器。Armv8-M 架構相較于 Armv7-M 架構,除了性能顯著提升以外,其中一項就是更加安全:Armv8-M 架構引入了 TrustZone 技術,并強化了內存保護單元(MPU),讓代碼運行在更安全的環境中。
MPU 在 4GB 地址映射中定義保護區域。Armv8-M 上的MPU 有8個region,每一個region都有起始地址,結束地址,訪問權限和內存屬性,每一個region都有單獨的屬性。和以往Armv7-M 的MPU有所不同,Armv8-M的MPU不支持region overlap,如果一個地址同時出現在兩個不同的region中,會導致HardFault。如果程序訪問被MPU禁止的內存位置,處理器就會生成一個 MemManage異常。
MPU 本質上就是為了保護某一段地址區域不被非授權狀態的程序進行訪問。通常嵌入式操作系統使用MPU進行內存保護,內核可以根據進程動態更新MPU區域設置。MPU 可以讓嵌入式系統更加健壯,以及保護一些加密區域。MPU 具有以下能力可以增加系統的健壯性:
可以阻止用戶去破壞操作系統需要使用的數據
可以防止一個任務去非法訪問其他任務的數據,將任務完全隔離開
可以把關鍵數據區設為只讀,從而不被破壞
檢測其他意外訪問,比如堆棧溢出,數組越界等
2
內存類型
Armv8中將內存分為兩種類型:Normal memory和Device memory。Normal memory適用于系統中的大部分內存,而Device memory則適用于外設所使用的內存。
Normal memory,主要指RAM,ROM,FLASH等,處理器以及編譯器都可以對程序做優化,處理器還可以增加repeate,reorder,merge的操作。在強制訪問順序的情況下,需要調用內存屏障指令。
Device memory,通常都是外設對應的內存映射。Device類型用于可能有副作用的位置,不可緩存,不允許對標記為Device的區域進行推測性數據訪問。
Device memory屬性:
1) G:Gather,多個內存訪問可以合并
2) R:Reordering,對內存訪問指令進行重排
3) E:Early Write Ack,寫操作的Ack可提前應答
四種Device memory:
1) Device nGnRnE,不允許gather、reorder、early
2) Device nGnRE,允許early
3) Device nGRE,允許reorder、early
4) Device GRE,允許gather、reorder、early
下表顯示了可能的MPU region屬性,包括Shareable和Cacheable屬性。
Armv8內存類型和屬性還有很多細節,對MPU region屬性配置會涉及到Cache讀寫策略的內容,感興趣的同學可以先查閱相關資料,進行詳細了解。本章節我們著重理解MPU的功能和作用,并進行簡單驗證,關于Cache內容在后續章節中再進行說明。
3
MPU寄存器模組
3.1 MPU主要有以下寄存器
3.2 MPU_TYPE
MPU_TYPE寄存器用來表示MPU是否存在以及它支持多少個region。
3.3 MPU_CTRL
MPU_CTRL用來使能MPU、使能backgroup map、使能NMI中MPU是否有效。
3.4 MPU_RNR
MPU_RNR用來選擇region,在訪問MPU_RBAR和MPU_RLAR之前,必須先寫入MPU_RNR來選擇region。
3.5 MPU_RBAR
MPU_RBAR定義了region的起始地址。
3.6 MPU_RLAR
MPU_RLAR定義了region的上限地址以及region屬性選擇。
3.7 MPU_MAIR0和MPU_MAIR1
MPU_MAIR0和MPU_MAIR1提供與AttrIndex值對應的內存屬性編碼。
每一個region屬性MARI_ATTR占8位。
如果MAIR_ATTR[7:4]為0,那么MAIR_ATTR定義如下:
如果MAIR_ATTR[7:4]不為0,那么MAIR_ATTR定義如下:
4
MPU配置
關于MPU的配置可以參考靈動微電子官網的LibSamples,具體在core_starmc1.h和mpu_armv8.h文件定義了MPU寄存器映射及接口函數,下表中列出部分函數:
5
MPU測試
5.1 region read/write測試
定義一個指針變量指向地址0x20006000位置,在MPU關閉時,該地址可以正常進行讀寫,通過配置MPU將0x20006000 - 0x20006FFF區域設置為region0只讀,使能MPU后再進行寫訪問,仿真觀測運行情況。測試代碼如下:
voidmpu_readwrite(void) { volatileuint32_t*temptr=(volatileuint32_t*)0x20006000UL; MPU_Cmd(MPU,DISABLE);//DisableMPU *temptr=0x00; printf("%x:%x ",(uint32_t)temptr,*temptr); *temptr=0xA5; printf("%x:%x ",(uint32_t)temptr,*temptr); //Enable MPU region0:0x20006000-0x20006FFF //Read-only,Executionnotpermitted,Devicememory MPU_SelectRegion(MPU,0); MPU_SetRegionBase(MPU,0x20006000UL,REGION_NON_SHAREABLE,REGION_RO_ANY,REGION_XN); MPU_SetRegionLimit(MPU,0x20006FFFUL,0,REGION_EN); MPU_SetRegionAttr(MPU,0,0); MPU_HfnmienaCmd(MPU,ENABLE); MPU_PrivdefenaCmd(MPU,ENABLE); MPU_Cmd(MPU,ENABLE); printf("Teststart: "); //AfterMPUisenabled,checkwhetherthewritepermissionisgranted. printf("%x:%x ",(uint32_t)temptr,*temptr); //Thehardfaultwillbetriggeredwhenthecodeisexecutedhere. *temptr=0x5A; printf("%x:%x ",(uint32_t)temptr,*temptr); printf("Testover! "); }
仿真查看MPU配置和代碼執行預期一致:
串口調試助手打印情況:
打印Test start之前的數據可以進行讀寫,使能MPU之后先打印一次數據,即可讀,但是運行到賦值語句*temptr = 0x5A,就進入了HardFault,說明該地址不可寫。
修改測試代碼設置region0為可讀寫:
MPU_SelectRegion(MPU,0); MPU_SetRegionBase(MPU,0x20006000UL,REGION_NON_SHAREABLE,REGION_RW_ANY,REGION_XN); MPU_SetRegionLimit(MPU,0x20006FFFUL,0,REGION_EN); MPU_SetRegionAttr(MPU,0,0);
仿真查看MPU配置和代碼執行預期一致:
串口調試助手打印情況:
測試代碼得到全部執行,使能MPU之后先打印一次數據,即可讀,運行賦值語句*temptr = 0x5A后,打印該地址的數據是0x5A,說明寫正常。
綜上,MPU可以有效設置區域的讀寫權限。
5.2 region overlap測試
定義一個指針變量指向地址0x20006000位置,在MPU關閉時,該地址可以正常進行讀寫,通過配置MPU將0x20006000 - 0x20006FFF區域設置為region0可讀寫,將0x20005000 - 0x20007FFF區域設置為region1可讀寫,使能MPU后再訪問地址0x20006000,測試代碼如下:
voidmpu_overlap(void) { volatileuint32_t*temptr=(volatileuint32_t*)0x20006000UL; MPU_Cmd(MPU,DISABLE); *temptr=0x00; printf("%x:%x ",(uint32_t)temptr,*temptr); *temptr=0xB9; printf("%x:%x ",(uint32_t)temptr,*temptr); //Configure region0:0x20006000-0x20006FFF //Read/write,Executionnotpermitted,Devicememory MPU_SelectRegion(MPU,0); MPU_SetRegionBase(MPU,0x20006000UL,REGION_NON_SHAREABLE,REGION_RW_PRIV_ONLY,REGION_XN); MPU_SetRegionLimit(MPU,0x20006FFFUL,0,REGION_EN); MPU_SetRegionAttr(MPU,0,0); //Configure region1:0x20005000-0x20007FFF //Read/write,Executionnotpermitted,Devicememory MPU_SelectRegion(MPU,1); MPU_SetRegionBase(MPU,0x20005000UL,REGION_NON_SHAREABLE,REGION_RW_PRIV_ONLY,REGION_XN); MPU_SetRegionLimit(MPU,0x20007FFFUL,1,REGION_EN); MPU_SetRegionAttr(MPU,0,1); MPU_HfnmienaCmd(MPU,ENABLE); MPU_PrivdefenaCmd(MPU,ENABLE); MPU_Cmd(MPU,ENABLE); printf("Teststart: "); //Theaddressofthe0x20006000overlapsinregion0andregion1. //Accessingtheaddresstriggersahardfault. printf("%x:%x ",(uint32_t)temptr,*temptr); printf("Testover! "); }
仿真查看MPU配置情況和代碼執行預期一致:
串口調試助手打印情況:
打印Test start之前的數據可以進行讀寫,使能MPU之后,因為地址0x20006000位于region0和region1的overlap區域,運行打印*temptr 的語句,就進入了HardFault,該位置不可訪問,說明MPU不支持region overlap,否則對overlap區域訪問時會觸發HardFault。
5.3 region code execute測試
將func()函數定義在指定地址0x08007800位置,在MPU關閉時,程序中調用該函數可以正常執行,通過配置MPU將0x08007800 - 0x080087FF區域設置為region0不可執行,使能MPU后再次運行func()函數,觀察測試情況。測試代碼如下:
voidfunc(void)__attribute__((section(".ARM.__AT_0x08007800"))); voidfunc(void) { printf("Executethefunction! "); } voidmpu_xn(void) { //Injectcodeat0x08007800 typedefvoid(*test_func_t)(void); test_func_ttest_func=(test_func_t)0x08007801; test_func(); MPU_Cmd(MPU,DISABLE); //Enable MPU region0:0x08007800-0x080087FF //Read-only,Executionnotpermitted,Devicememory MPU_SelectRegion(MPU,0); MPU_SetRegionBase(MPU,0x08007800UL,REGION_NON_SHAREABLE,REGION_RO_PRIV_ONLY,REGION_XN); MPU_SetRegionLimit(MPU,0x080087FFUL,0,REGION_EN); MPU_SetRegionAttr(MPU,0,0); MPU_HfnmienaCmd(MPU,ENABLE); MPU_PrivdefenaCmd(MPU,ENABLE); MPU_Cmd(MPU,ENABLE); printf("Teststart: "); //Thetest_funcof0x08007800cannotbeexecutedafterMPUisenabled. //Thehardfaultwillbetriggeredwhenthecodeisexecutedhere. test_func(); printf("Testover! "); }
仿真查看MPU配置情況和代碼執行預期一致:
串口調試助手打印情況:
打印Test start之前調用func()函數一次,執行正常。使能MPU之后,再次調用func()函數,就進入了HardFault,該代碼不可執行。
6
小結
MPU為存儲保護單元,它位于存儲器內部的一個可編程的區域,定義了存儲器的屬性和訪問權限,試圖訪問非法或者不允許的內存地址則會觸發HardFault異常。MPU能夠提高嵌入式系統的健壯性,使得系統更加安全。實際應用中根據具體的項目需要,選擇MPU是默認配置還是需要更改一些配置,這樣才能使應用更加符合要求。
審核編輯:劉清
-
微控制器
+關注
關注
48文章
7487瀏覽量
151042 -
處理器
+關注
關注
68文章
19159瀏覽量
229112 -
存儲器
+關注
關注
38文章
7452瀏覽量
163598 -
MPU
+關注
關注
0文章
346瀏覽量
48735
原文標題:靈動微課堂 (第269講)|MM32F5330內存保護單元(MPU)
文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論