【经验】灵动微电子MM32F5330系列微控制器内存保护单元详解
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后再进行写访问,仿真观测运行情况。测试代码如下:
void mpu_readwrite(void)
{
volatile uint32_t *temptr = (volatile uint32_t *)0x20006000UL;
MPU_Cmd(MPU, DISABLE); //Disable MPU
*temptr = 0x00;
printf("%x : %x\n", (uint32_t)temptr,*temptr);
*temptr = 0xA5;
printf("%x : %x\n", (uint32_t)temptr,*temptr);
//Enable MPU region0:0x20006000 - 0x20006FFF
//Read-only,Execution not permitted,Device memory
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("Test start:\n");
//After MPU is enabled, check whether the write permission is granted.
printf("%x : %x\n", (uint32_t)temptr,*temptr);
//The hardfault will be triggered when the code is executed here.
*temptr = 0x5A;
printf("%x : %x\n", (uint32_t)temptr,*temptr);
printf("Test over!\n");
}
仿真查看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,测试代码如下:
void mpu_overlap(void)
{
volatile uint32_t *temptr = (volatile uint32_t *)0x20006000UL;
MPU_Cmd(MPU, DISABLE);
*temptr = 0x00;
printf("%x : %x\n", (uint32_t)temptr,*temptr);
*temptr = 0xB9;
printf("%x : %x\n", (uint32_t)temptr,*temptr);
//Configure region0:0x20006000 - 0x20006FFF
//Read/write,Execution not permitted,Device memory
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,Execution not permitted,Device memory
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("Test start:\n");
//The address of the 0x20006000 overlaps in region0 and region1.
//Accessing the address triggers a hard fault.
printf("%x : %x\n", (uint32_t)temptr,*temptr);
printf("Test over!\n");
}
仿真查看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()函数,观察测试情况。测试代码如下:
void func(void) __attribute__((section(".ARM.__AT_0x08007800")));
void func(void)
{
printf("Execute the function!\n");
}
void mpu_xn(void)
{
//Inject code at 0x08007800
typedef void (*test_func_t)(void);
test_func_t test_func = (test_func_t)0x08007801;
test_func();
MPU_Cmd(MPU, DISABLE);
//Enable MPU region0:0x08007800 - 0x080087FF
//Read-only,Execution not permitted,Device memory
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("Test start:\n");
//The test_func of 0x08007800 cannot be executed after MPU is enabled.
//The hardfault will be triggered when the code is executed here.
test_func();
printf("Test over!\n");
}
仿真查看MPU配置情况和代码执行预期一致:
串口调试助手打印情况:
打印Test start之前调用func()函数一次,执行正常。使能MPU之后,再次调用func()函数,就进入了HardFault,该代码不可执行。
6、小结
MPU为存储保护单元,它位于存储器内部的一个可编程的区域,定义了存储器的属性和访问权限,试图访问非法或者不允许的内存地址则会触发HardFault异常。MPU能够提高嵌入式系统的健壮性,使得系统更加安全。实际应用中根据具体的项目需要,选择MPU是默认配置还是需要更改一些配置,这样才能使应用更加符合要求。
- |
- +1 赞 0
- 收藏
- 评论 0
本文由ll转载自灵动MM32MCU公众号,原文标题为:灵动微课堂 (第269讲)|MM32F5330内存保护单元(MPU),本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。
相关推荐
【经验】灵动微电子MM32F0160微控制器开源项目:如何实现一套低成本带RGB灯效的机械键盘
灵动的软件与系统工程SE团队,基于带有 USB 外设模块的 MM32F0160 微控制器,实现了一套低成本带RGB灯效的机械键盘。这里将设计机械键盘的全过程开源出来,感兴趣的开发者,可以向灵动申请 MM32F0160 微控制器的样片,复刻一把自己专属的机械键盘,也可以继续进行二次开发,实现更加有趣的作品。
【经验】单独下载可执行文件到灵动MM32F5系列微控制器的几种简易方法
本文将以下载MicroPython固件文件到灵动MM32F5微控制器为例,总结了几种简单易用的方法,专门针对使用DAP-Link调试器的情况,通过常用图形界面工具,实现单独下载可执行文件的功能。
【经验】如何验证不同Flash对灵动微微控制器执行程序性能的影响
本文通过在QSPI Flash,片内Flash 与片内SRAM中分别运行测试工程Arm CMSIS-DSP FFT、Mbed-TLS RSA1024与Helix MP3 Decoder,获取微控制器性能数据,从而对比在不同Flash位置的执行速度的差异。
基于灵动MM32F0130微控制器的智能插排方案,实现远程开关控制、定时开关、随时了解家电设备的使用状况
智能插座又可以称为WIFI插座,在普通插座的功能基础上延伸了许多功能,如防雷击,防短路,防过载,防漏电,配合智能手机的APP应用,可以实现远程开关控制、定时开关、随时了解家电设备的使用状况。基于灵动MM32F0130微控制器的插排,具有以下特点:-内置Timer进行解码红外输入-通过串口与云端连接,进行远程控制,以及电量监控等-通过I2C与计量芯片通讯,进行异常检测,过流,过/欠压等保护
MM32SPIN023C 基于 ARM® Cortex®-M0 内核的 32 位微控制器数据手册
描述- MM32SPIN023C是一款基于ARM® Cortex®-M0内核的32位微控制器,具备高性能运动控制驱动功能。该产品具有60MHz的最高工作频率,内置32KB Flash存储器和4KB SRAM,支持多种外设,包括ADC、COMP、OPAMP、定时器、USART等。产品适用于电机驱动、照明电路、应急消防设备、玩具等多种应用场合。
型号- MM32SPIN023C
MM32G0001 基于 Arm® Cortex®-M0 内核的 32 位微控制器数据手册
型号- MM32G0001A1T,MM32G0001A6T1V,MM32G0001,MM32G0001A1NV,MM32G0001A6TV,MM32G0001A6T,MM32G0001A6T1,MM32G0001A1TV,MM32G0001A1N
MM32SPIN0280微控制器精准驱动电动自行车的智能核心
MM32SPIN0280微控制器作为电动自行车的主控单元,提供精确的动力控制、电助动与电驱动功能,同时确保骑行安全,满足现代城市出行的需求
MM32F0140 基于 Arm® Cortex®-M0 内核的 32 位微控制器数据手册
描述- 本资料介绍了MM32F0140微控制器,一款基于Arm® Cortex®-M0内核的32位微控制器。该芯片具有64KB闪存、8KB SRAM、丰富的外设接口和多种低功耗模式,适用于各种嵌入式系统。
型号- MM32F0141B1T,MM32F0141C1T,MM32F0144C4PV,MM32F0144C4QV,MM32F0144C1TV,MM32F0144C4P,MM32F0141B6P,MM32F0144C3N,MM32F0144C4N,MM32F0144C6P,MM32F0140,MM32F0144C6PV,MM32F0144C3NV,MM32F0144C1T,MM32F0141B4Q,MM32F0141C4P,MM32F0141C4Q,MM32F0141C4N,MM32F0141C6P,MM32F0141B3N,MM32F0144C4Q,MM32F0141B4P,MM32F0141C3N
灵动Cortex-M0内核微控制器的自诊断库通过IEC 60730-1及IEC 60335-1认证
灵动股份Arm® Cortex®-M0核心微控制器的自诊断库经必维电子电气检测,证明符合IEC 60730-1 Class B附录H&IEC60335-1附录R的功能安全需求规定,获得了VOC认证证书和测试报告。
MM32F0160 基于 Arm® Cortex®-M0 内核的 32 位微控制器数据手册
描述- 本资料为MM32F0160微控制器数据手册,详细介绍了该产品的特性、功能描述、订购信息、引脚定义及复用功能、电气特性、封装特性等。MM32F0160是一款基于Arm® Cortex®-M0内核的32位微控制器,具有128KB Flash存储器、16KB SRAM、多种外设模块和丰富的I/O端口,适用于工业物联网、PC外设、电子门锁控制、医疗保健设备等多种应用场合。
型号- MM32F0163D4QV,MM32F0162DAP,MM32F0163DAP,MM32F0163D7PV,MM32F0163D6PV,MM32F0160,MM32F0162D6P,MM32F0163D6P,MM32F0162D7P,MM32F0163D7P,MM32F0164D3N,MM32F0161D3N,MM32F0162D4Q,MM32F0163D4Q
MM32F0020 基于 Arm® Cortex®-M0 内核的 32 位微控制器数据手册
描述- 本资料介绍了MM32F0020微控制器,一款基于Arm® Cortex®-M0内核的32位产品。该产品具备48MHz的最高工作频率,内置32KB Flash存储器和2KB SRAM,支持多种低功耗模式。它集成了丰富的I/O端口和外设模块,包括ADC、定时器、通信接口等,适用于充电器、通信模块等多种应用场景。
型号- MM32F0020B1NV,MM32F0020,MM32F0020B1T,MM32F0020B1TV,MM32F0020B1N
MM32G0001 基于Arm®Cortex®-M0内核的32位微控制器 用户手册
描述- 本手册详细介绍了基于Arm®Cortex®-M0内核的32位微控制器MM32G0001的用户手册。内容涵盖系统架构、存储器、CRC循环冗余校验计算单元、电源控制、时钟和复位、通用端口、中断和事件、模拟/数字转换器(ADC)、高级控制定时器(TIM1)、通用定时器(TIM3和TIM14)、独立看门狗(IWDG)以及串行外设接口(SPI)等模块的特性和功能描述。还包括了相应的寄存器配置和使用方法。
型号- MM32G0001
基于微控制器MM32F3270的智能监护仪,实现精准监测与高效护理
MM32F3270微控制器为监护仪提供了从信号采集到数字处理的全方位解决方案,确保了医疗监测的高精度和高效率,助力提高护理工作的智能化水平。
MM32F103xx 32 位基于 ARM® Cortex® M3 核心的微控制器数据手册
描述- 本资料为MM32F103xx系列微控制器数据手册,介绍了该系列产品的核心特性、规格说明、引脚定义、存储器映像、电气特性、封装特性和型号命名等内容。该系列产品采用ARM®Cortex®-M3内核,具备高性价比和丰富外设配置,适用于多种应用场合。
型号- MM32F103XX,MM32F103KET,MM32F103KEU,MM32F103KCT,MM32F103VET,MM32F103VCT,MM32F103RET,MM32F103RCT,MM32F103CCT,MM32F103KCU,MM32F103CET,MM32F103RCT6XXX
MM32系列微控制器优化血氧仪性能与用户体验
MM32微控制器的集成LCD控制器和低功耗特性,为便携式血氧仪带来了更优化的性能和更持久的电池寿命,改善了用户的测量体验。
电子商城
现货市场
服务
可定制板装式压力传感器支持产品量程从5inch水柱到100 psi气压;数字输出压力传感器压力范围0.5~60inH2O,温度补偿范围-20~85ºС;模拟和数字低压传感器可以直接与微控制器通信,具备多种小型SIP和DIP封装可选择。
提交需求>
可来图定制均温板VC尺寸50*50mm~600*600 mm,厚度1mm~10mm,最薄0.3mm。当量导热系数可达10000W/M·K,散热量可达10KW, 功率密度可达50W/cm²。项目单次采购额需满足1万元以上,或年需求5万元以上。
提交需求>
登录 | 立即注册
提交评论