1
MM32F5330 MPU簡介
靈動微電子發(fā)布了搭載安謀科技“星辰”STAR-MC1處理器的全新高性能 MM32F5 微控制器系列,該系列在內(nèi)核、總線和外設(shè)配置等多個方面進行了創(chuàng)新,內(nèi)核上更是首次搭載了 Armv8-M 架構(gòu)的 “星辰” STAR-MC1 處理器。Armv8-M 架構(gòu)相較于 Armv7-M 架構(gòu),除了性能顯著提升以外,其中一項就是更加安全:Armv8-M 架構(gòu)引入了 TrustZone 技術(shù),并強化了內(nèi)存保護單元(MPU),讓代碼運行在更安全的環(huán)境中。
MPU 在 4GB 地址映射中定義保護區(qū)域。Armv8-M 上的MPU 有8個region,每一個region都有起始地址,結(jié)束地址,訪問權(quán)限和內(nèi)存屬性,每一個region都有單獨的屬性。和以往Armv7-M 的MPU有所不同,Armv8-M的MPU不支持region overlap,如果一個地址同時出現(xiàn)在兩個不同的region中,會導(dǎo)致HardFault。如果程序訪問被MPU禁止的內(nèi)存位置,處理器就會生成一個 MemManage異常。
MPU 本質(zhì)上就是為了保護某一段地址區(qū)域不被非授權(quán)狀態(tài)的程序進行訪問。通常嵌入式操作系統(tǒng)使用MPU進行內(nèi)存保護,內(nèi)核可以根據(jù)進程動態(tài)更新MPU區(qū)域設(shè)置。MPU 可以讓嵌入式系統(tǒng)更加健壯,以及保護一些加密區(qū)域。MPU 具有以下能力可以增加系統(tǒng)的健壯性:
可以阻止用戶去破壞操作系統(tǒng)需要使用的數(shù)據(jù)
可以防止一個任務(wù)去非法訪問其他任務(wù)的數(shù)據(jù),將任務(wù)完全隔離開
可以把關(guān)鍵數(shù)據(jù)區(qū)設(shè)為只讀,從而不被破壞
檢測其他意外訪問,比如堆棧溢出,數(shù)組越界等
2
內(nèi)存類型
Armv8中將內(nèi)存分為兩種類型:Normal memory和Device memory。Normal memory適用于系統(tǒng)中的大部分內(nèi)存,而Device memory則適用于外設(shè)所使用的內(nèi)存。
Normal memory,主要指RAM,ROM,F(xiàn)LASH等,處理器以及編譯器都可以對程序做優(yōu)化,處理器還可以增加repeate,reorder,merge的操作。在強制訪問順序的情況下,需要調(diào)用內(nèi)存屏障指令。
Device memory,通常都是外設(shè)對應(yīng)的內(nèi)存映射。Device類型用于可能有副作用的位置,不可緩存,不允許對標(biāo)記為Device的區(qū)域進行推測性數(shù)據(jù)訪問。
Device memory屬性:
1) G:Gather,多個內(nèi)存訪問可以合并
2) R:Reordering,對內(nèi)存訪問指令進行重排
3) E:Early Write Ack,寫操作的Ack可提前應(yīng)答
四種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內(nèi)存類型和屬性還有很多細節(jié),對MPU region屬性配置會涉及到Cache讀寫策略的內(nèi)容,感興趣的同學(xué)可以先查閱相關(guān)資料,進行詳細了解。本章節(jié)我們著重理解MPU的功能和作用,并進行簡單驗證,關(guān)于Cache內(nèi)容在后續(xù)章節(jié)中再進行說明。
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值對應(yīng)的內(nèi)存屬性編碼。
每一個region屬性MARI_ATTR占8位。
如果MAIR_ATTR[7:4]為0,那么MAIR_ATTR定義如下:
如果MAIR_ATTR[7:4]不為0,那么MAIR_ATTR定義如下:
4
MPU配置
關(guān)于MPU的配置可以參考靈動微電子官網(wǎng)的LibSamples,具體在core_starmc1.h和mpu_armv8.h文件定義了MPU寄存器映射及接口函數(shù),下表中列出部分函數(shù):
5
MPU測試
5.1 region read/write測試
定義一個指針變量指向地址0x20006000位置,在MPU關(guān)閉時,該地址可以正常進行讀寫,通過配置MPU將0x20006000 - 0x20006FFF區(qū)域設(shè)置為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配置和代碼執(zhí)行預(yù)期一致:
串口調(diào)試助手打印情況:
打印Test start之前的數(shù)據(jù)可以進行讀寫,使能MPU之后先打印一次數(shù)據(jù),即可讀,但是運行到賦值語句*temptr = 0x5A,就進入了HardFault,說明該地址不可寫。
修改測試代碼設(shè)置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配置和代碼執(zhí)行預(yù)期一致:
串口調(diào)試助手打印情況:
測試代碼得到全部執(zhí)行,使能MPU之后先打印一次數(shù)據(jù),即可讀,運行賦值語句*temptr = 0x5A后,打印該地址的數(shù)據(jù)是0x5A,說明寫正常。
綜上,MPU可以有效設(shè)置區(qū)域的讀寫權(quán)限。
5.2 region overlap測試
定義一個指針變量指向地址0x20006000位置,在MPU關(guān)閉時,該地址可以正常進行讀寫,通過配置MPU將0x20006000 - 0x20006FFF區(qū)域設(shè)置為region0可讀寫,將0x20005000 - 0x20007FFF區(qū)域設(shè)置為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配置情況和代碼執(zhí)行預(yù)期一致:
串口調(diào)試助手打印情況:
打印Test start之前的數(shù)據(jù)可以進行讀寫,使能MPU之后,因為地址0x20006000位于region0和region1的overlap區(qū)域,運行打印*temptr 的語句,就進入了HardFault,該位置不可訪問,說明MPU不支持region overlap,否則對overlap區(qū)域訪問時會觸發(fā)HardFault。
5.3 region code execute測試
將func()函數(shù)定義在指定地址0x08007800位置,在MPU關(guān)閉時,程序中調(diào)用該函數(shù)可以正常執(zhí)行,通過配置MPU將0x08007800 - 0x080087FF區(qū)域設(shè)置為region0不可執(zhí)行,使能MPU后再次運行func()函數(shù),觀察測試情況。測試代碼如下:
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配置情況和代碼執(zhí)行預(yù)期一致:
串口調(diào)試助手打印情況:
打印Test start之前調(diào)用func()函數(shù)一次,執(zhí)行正常。使能MPU之后,再次調(diào)用func()函數(shù),就進入了HardFault,該代碼不可執(zhí)行。
6
小結(jié)
MPU為存儲保護單元,它位于存儲器內(nèi)部的一個可編程的區(qū)域,定義了存儲器的屬性和訪問權(quán)限,試圖訪問非法或者不允許的內(nèi)存地址則會觸發(fā)HardFault異常。MPU能夠提高嵌入式系統(tǒng)的健壯性,使得系統(tǒng)更加安全。實際應(yīng)用中根據(jù)具體的項目需要,選擇MPU是默認配置還是需要更改一些配置,這樣才能使應(yīng)用更加符合要求。
審核編輯:劉清
-
微控制器
+關(guān)注
關(guān)注
48文章
7542瀏覽量
151316 -
處理器
+關(guān)注
關(guān)注
68文章
19259瀏覽量
229653 -
存儲器
+關(guān)注
關(guān)注
38文章
7484瀏覽量
163764 -
MPU
+關(guān)注
關(guān)注
0文章
357瀏覽量
48775
原文標(biāo)題:靈動微課堂 (第269講)|MM32F5330內(nèi)存保護單元(MPU)
文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論