0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MM32F5330内存保护单元(MPU)设计

灵动MM32MCU 来源:灵动MM32MCU 2023-09-07 18:29 次阅读

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,主要指RAMROM,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属性。

e8e3478c-4d5e-11ee-a25d-92fbcf53809c.png

Armv8内存类型和属性还有很多细节,对MPU region属性配置会涉及到Cache读写策略的内容,感兴趣的同学可以先查阅相关资料,进行详细了解。本章节我们着重理解MPU的功能和作用,并进行简单验证,关于Cache内容在后续章节中再进行说明。

3

MPU寄存器模组

3.1 MPU主要有以下寄存器

e9168cfa-4d5e-11ee-a25d-92fbcf53809c.png

3.2 MPU_TYPE

MPU_TYPE寄存器用来表示MPU是否存在以及它支持多少个region。

e927ead6-4d5e-11ee-a25d-92fbcf53809c.png

3.3 MPU_CTRL

MPU_CTRL用来使能MPU、使能backgroup map、使能NMI中MPU是否有效。

e9552fd2-4d5e-11ee-a25d-92fbcf53809c.png

3.4 MPU_RNR

MPU_RNR用来选择region,在访问MPU_RBAR和MPU_RLAR之前,必须先写入MPU_RNR来选择region。

e97777ae-4d5e-11ee-a25d-92fbcf53809c.png

3.5 MPU_RBAR

MPU_RBAR定义了region的起始地址。

e9990fea-4d5e-11ee-a25d-92fbcf53809c.pnge9c59254-4d5e-11ee-a25d-92fbcf53809c.png

3.6 MPU_RLAR

MPU_RLAR定义了region的上限地址以及region属性选择。

e9e76eb0-4d5e-11ee-a25d-92fbcf53809c.png

3.7 MPU_MAIR0和MPU_MAIR1

MPU_MAIR0和MPU_MAIR1提供与AttrIndex值对应的内存属性编码。

e9fc768e-4d5e-11ee-a25d-92fbcf53809c.png

每一个region属性MARI_ATTR占8位。

如果MAIR_ATTR[7:4]为0,那么MAIR_ATTR定义如下:

ea49a238-4d5e-11ee-a25d-92fbcf53809c.png

如果MAIR_ATTR[7:4]不为0,那么MAIR_ATTR定义如下:

ea88bd42-4d5e-11ee-a25d-92fbcf53809c.png

4

MPU配置

关于MPU的配置可以参考灵动微电子官网的LibSamples,具体在core_starmc1.h和mpu_armv8.h文件定义了MPU寄存器映射及接口函数,下表中列出部分函数:

ea9f1880-4d5e-11ee-a25d-92fbcf53809c.png

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配置和代码执行预期一致:

eab30dea-4d5e-11ee-a25d-92fbcf53809c.png

串口调试助手打印情况:

eaf6c99a-4d5e-11ee-a25d-92fbcf53809c.png

打印Test start之前的数据可以进行读写,使能MPU之后先打印一次数据,即可读,但是运行到赋值语句*temptr = 0x5A,就进入了HardFault,说明该地址不可写。

eb051a0e-4d5e-11ee-a25d-92fbcf53809c.png

修改测试代码设置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配置和代码执行预期一致:

eb4f7860-4d5e-11ee-a25d-92fbcf53809c.png

串口调试助手打印情况:

eb861122-4d5e-11ee-a25d-92fbcf53809c.png

测试代码得到全部执行,使能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配置情况和代码执行预期一致:

eb97d09c-4d5e-11ee-a25d-92fbcf53809c.png

串口调试助手打印情况:

ebbdea16-4d5e-11ee-a25d-92fbcf53809c.png

打印Test start之前的数据可以进行读写,使能MPU之后,因为地址0x20006000位于region0和region1的overlap区域,运行打印*temptr 的语句,就进入了HardFault,该位置不可访问,说明MPU不支持region overlap,否则对overlap区域访问时会触发HardFault。

ebcb514c-4d5e-11ee-a25d-92fbcf53809c.png

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配置情况和代码执行预期一致:

ebfd74f6-4d5e-11ee-a25d-92fbcf53809c.png

串口调试助手打印情况:

ec53a59c-4d5e-11ee-a25d-92fbcf53809c.png

打印Test start之前调用func()函数一次,执行正常。使能MPU之后,再次调用func()函数,就进入了HardFault,该代码不可执行。

ec604914-4d5e-11ee-a25d-92fbcf53809c.png

6

小结

MPU为存储保护单元,它位于存储器内部的一个可编程的区域,定义了存储器的属性和访问权限,试图访问非法或者不允许的内存地址则会触发HardFault异常。MPU能够提高嵌入式系统的健壮性,使得系统更加安全。实际应用中根据具体的项目需要,选择MPU是默认配置还是需要更改一些配置,这样才能使应用更加符合要求。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    6812

    浏览量

    147648
  • 处理器
    +关注

    关注

    68

    文章

    18288

    浏览量

    222175
  • 存储器
    +关注

    关注

    38

    文章

    7151

    浏览量

    162001
  • MPU
    MPU
    +关注

    关注

    0

    文章

    298

    浏览量

    48374

原文标题:灵动微课堂 (第269讲)|MM32F5330内存保护单元(MPU)

文章出处:【微信号:MindMotion-MMCU,微信公众号:灵动MM32MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    管理STM32 MCU中的内存保护单元

    本应用笔记介绍如何管理 STM32 产品中的内存保护单元MPU)。MPU 是用于存储器保护的可选组件。STM32 微控制器(MCU)中嵌入
    发表于 12-23 11:04 810次阅读

    【安富莱】【μCOS-III教程】第6章 内存保护单元MPU

    第6章内存保护单元MPU本期教程带领大家学习内存保护单元MPU的使用,在前面的几期教程中曾多次的
    发表于 01-08 18:04

    主要讲armv7-m架构下的MPU内存保护单元

    简介MPU(Memory Protection Unit) 内存保护单元。 本文主要讲 armv7-m 架构 架构下的 MPU。在 armv7-m 架构下,Cortex-M3 和 Co
    发表于 04-08 11:00

    如何为MPC5744P配置内存保护单元

    我想知道更多关于如何为 MPC5744P 配置内存保护单元,我需要知道如何使用这个配置器。
    发表于 04-04 09:03

    Armv8-M内存模型与内存保护用户指南

    本指南概述了Armv8-M内存模型和内存保护单元(MPU)在Cortex-M处理器中实现。本指南使用示例来帮助解释这些概念 它介绍了。 本章概述以下主题: •
    发表于 08-02 08:12

    如何管理STM32产品中的内存保护单元MPU

    本应用笔记介绍如何管理 STM32 产品中的内存保护单元MPU)。MPU 是用于存储器保护的可选组件。STM32 微控制器(MCU)中嵌入
    发表于 09-07 06:23

    Cortex-M内核的MPU内存保护单元

    讲讲Cortex-M内核的MPU内存保护单元
    的头像 发表于 03-04 11:17 3290次阅读
    Cortex-M内核的<b class='flag-5'>MPU</b><b class='flag-5'>内存保护</b><b class='flag-5'>单元</b>

    Cortex-M内核的MPU内存保护单元

    的选配件,拿STM32F1来说,STM32F10X_XL系列的芯片才具有这个MPU存储保护单元,而其他STM32F1芯片没有。可能很多人都处于简单知道,或认识MPU的阶段,今天就写点关
    发表于 12-01 12:21 9次下载
    Cortex-M内核的<b class='flag-5'>MPU</b><b class='flag-5'>内存保护</b><b class='flag-5'>单元</b>

    为什么要使用MPUMPU如何实现内存保护

    如果你开发的嵌入式项目,因内存溢出,或者内存故障等一些原因,造成了重大经济损失,或者造成了重大事故,你就能体会为什么要使用内存保护单元MPU
    的头像 发表于 07-05 17:38 6282次阅读
    为什么要使用<b class='flag-5'>MPU</b>?<b class='flag-5'>MPU</b>如何实现<b class='flag-5'>内存保护</b>?

    管理 STM32 MCU 中的内存保护单元

    管理 STM32 MCU 中的内存保护单元
    发表于 11-21 08:11 3次下载
    管理 STM32 MCU 中的<b class='flag-5'>内存保护</b><b class='flag-5'>单元</b>

    AN4838 管理STM32 MCU中的内存保护单元

    AN4838 管理STM32 MCU中的内存保护单元
    发表于 11-21 17:07 0次下载
    AN4838 管理STM32 MCU中的<b class='flag-5'>内存保护</b><b class='flag-5'>单元</b>

    应用笔记|管理STM32 MCU中的内存保护单元

    中的内存保护单元MPU)。MPU 是用于存储器保护的可选组件。STM32 微控制器(MCU)中嵌入 M
    的头像 发表于 12-21 21:05 668次阅读

    为什么要使用MPUMPU如何实现内存保护

    如果你开发的嵌入式项目,因内存溢出,或者内存故障等一些原因,造成了重大经济损失,或者造成了重大事故,你就能体会为什么要使用内存保护单元MPU
    的头像 发表于 02-24 11:59 2105次阅读

    什么是MPUMPU在哪些方面保护内存安全?

    内存保护单元(MPU)是一种硬件机制,通过只允许代码访问需要的内存和外设来提高嵌入式设备的安全性。
    的头像 发表于 06-12 09:06 7195次阅读
    什么是<b class='flag-5'>MPU</b>?<b class='flag-5'>MPU</b>在哪些方面<b class='flag-5'>保护</b><b class='flag-5'>内存</b>安全?

    如何管理STM32产品中的内存保护单元(MPU)

    电子发烧友网站提供《如何管理STM32产品中的内存保护单元(MPU).pdf》资料免费下载
    发表于 08-01 09:15 0次下载
    如何管理STM32产品中的<b class='flag-5'>内存保护</b><b class='flag-5'>单元</b>(<b class='flag-5'>MPU</b>)