当前位置:网站首页>armv8m(cortex m33) MPU实战
armv8m(cortex m33) MPU实战
2022-04-23 06:13:00 【MyeDy】
1 MPU
armv8m 上的MPU 有8个region,每一个region都有起始地址,结束地址,访问权限和内存属性。每一个region都有单独的属性。
本文仅以secure MPU为例讲解MPU。
armv8m 上的MPU和armv7m的MPU有一点不同, v8m的MPU不支持overlap,如果一个地址同时出现在两个不同的region中,会导致bus fault。
1.1 Memory attributes summary
Memory Type | Shareability | Other attributes | Description |
---|---|---|---|
Device-nGnRnE | Sharable | - | Used to access memory mapped peripherals.All accesses to DevicenGnRnE memory occur in program order. All regions are assumed to be shared |
Device-nGnRE | Sharable | - | Used to access memory mapped peripherals.Weaker ordering thanDevice-nGnRnE. |
Device-nGRE | Sharable | - | Used to access memory mapped peripherals.Weaker ordering thanDevice-nGnRE. |
Device-GRE | Sharable | - | Used to access memory mapped peripherals.Weaker ordering thanDevice-nGRE. |
Normal | Sharable | Non-cacheable Write-Through Cacheable Write-Back Cacheable | Normal memory that is shared between several processors. |
Normal | Non-Shareable | Non-cacheable Write-Through Cacheable Write-Back Cacheable | Normal memory that only a single processor uses. |
1.2 MPU寄存器
Address | Name | Access Type | Reset Value |
---|---|---|---|
0xE000ED90 | MPU_TYPE | RO | 该寄存器的值是固定的,取决于SOC实现 |
0xE000ED94 | MPU_CTRL | RW | 0x00000000 |
0xE000ED98 | MPU_RNR | RW | 未知 |
0xE000ED9C | MPU_RBAR | RW | 未知 |
0xE000EDA0 | MPU_RLAR | RW | 未知 |
0xE000EDA4 | MPU_RBAR_A<n> | RW | 未知 |
0xE000EDA8 | MPU_RBAR_A<n> | RW | 未知 |
0xE000EDC0 | MPU_MAIR0 | RW | 未知 |
0xE000EDC4 | MPU_MAIR1 | RW | 未知 |
1.2.1 MPU Type Register
MPU_TYPE寄存器用来表示MPU是否存在以及它支持多少个region。
Bits | Name | Function |
---|---|---|
[31:16] | - | 保留位 |
[15:8] | REGION | 0x0-MPU没有region支持 0x8当前MPU 支持8个REGION |
[7:1] | - | 保留位 |
[0] | SEPARATE | 0 |
1.2.2 MPU Control Register
MPU_CTRL用来
- 使能MPU
- 使能backgroup map
- 使能NMI中MPU是否有效
Bits | Name | Function |
---|---|---|
[31:3] | - | 保留位 |
[2] | PRIVDEFENA | 使能特权级软件使用default memory map 0 - 关闭default memory map。任何访问没有在region中描述的都会产生bus fault。 1 - 使能default memory map,当它使能后,访问没有在region中memory会使用默认的memory map |
[1] | HFNMIENA | 使HardFault和NMI时能MPU在 0 - 在HardFault和NMI时, MPU无效 1 - 在HardFault和NMI时, MPU仍然有效 |
[0] | ENABLE | 使能MPU 0 - 关闭MPU 1 - 打开MPU |
1.2.3 MPU Region Number Register
MPU_RNR用来选择region,在访问MPU_RBAR和MPU_RLAR之前,必须先写入MPU_RNR来选择region
Bits | Name | Function |
---|---|---|
[31:8] | - | 保留位 |
[7:0]REGION | REGION索引,如果选择REGION1, 则设为1 |
1.2.4 MPU Region Base Address Register
MPU_RBAR定义了MPU region的起始地址
Bits | Name | Function |
---|---|---|
[31:5] | BASE | REGION 基地址 |
[4:3] | SH | 定义了Normal的Shareability属性 0b00 Non-shareable. 0b01 UNPREDICATABLE 0b10 Outer shareable. 0b11 Inner shareable |
[2:1] | AP | 访问属性 0b00 特权级代码可读写. 0b01 特权级代码可读写 0b10 特权级代码只读. 0b11 所有代码只读 |
[0] | XN | 0 可执行Memory 1 不可执行Memory |
1.2.5 MPU Region Limit Address Register
MPU_RLAR定义了REGION的上限地址以及REGION属性选择
Bits | Name | Function |
---|---|---|
[31:5] | LIMIT | REGION 上限地址 |
[4] | - | 保留位 |
[3:1] | AttrIndx | 属性索引号 |
[0] | EN | 0 不使能REGION 1 使能REGION |
1.2.6 MPU Memory Attribute Indirection Registers 0 and 1
MPU_MAIR0
Bits | Name | Function |
---|---|---|
[31:24] | Attr3 | REGION3属性 |
[23:16] | Attr2 | REGION2属性 |
[15:8] | Attr1 | REGION1属性 |
[7:0] | Attr0 | REGION0属性 |
MPU_MAIR1
Bits | Name | Function |
---|---|---|
[31:24] | Attr7 | REGION7属性 |
[23:16] | Attr6 | REGION6属性 |
[15:8] | Attr5 | REGION5属性 |
[7:0] | Attr4 | REGION4属性 |
每一个REGION属性MARI_ATTR占8位,如果MAIR_ATTR[7:4]为0:那MAIR_ATTR定义如下:
Bits | Name | Function |
---|---|---|
[3:2] | Device | 0b00 Device-nGnRnE 0b01 Device-nGnRE 0b10 Device-nGRE 0b11 Device-GRE |
如果MAIR_ATTR[7:4]不为0, 那么MAIR_ATTR定义如下
Bits | Name | Function |
---|---|---|
[7:4] | Outer | Outer attributes. Specifies the Outer memory attributes. The possible values of this field are: 0b0000 -Device memory. 00RW -Normal memory, Outer write-through transient (RW is not 00). 0b0100 -Normal memory, Outer non-cacheable. 01RW-Normal memory, Outer write-back transient (RW is not 00).10RW Normal memory, Outer write-through non-transient. 11RW -Normal memory, Outer write-back non-transient. R and W specify the outer read and write allocation policy: 0 = do not allocate, 1 = allocate. |
[3:0] | Inner | Inner attributes. Specifies the Inner memory attributes. The possible values of this field are: 0b0000 -UNPREDICTABLE. 00RW- Normal memory, Inner write-through transient (RW is not 00). 0b0100- Normal memory, Inner non-cacheable. 01RW -Normal memory, Inner write-back transient (RW is not 00). 10RW -Normal memory, Inner write-through non-transient. 11RW -Normal memory, Inner write-back non-transient. R and W specify the outer read and write allocation policy: 0 = do not allocate, 1 = allocate. |
2 MPU 代码
2.1环境搭建
安装qemu-system-arm, 确保该版本下有cortex m33的仿真板
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33
安装工具链armv8l-linux-gnueabihf-
运行命令:
make;make qemu
log:
qemu-system-arm -machine mps2-an505 -cpu cortex-m33 \
-m 4096 \
-nographic \
-kernel kernel.elf
qemu-system-arm: invalid accelerator kvm
qemu-system-arm: falling back to tcg
hello cortex m33
test_func_print entry
test_armv8m_xn:mpu setup done
default_exception_handler entry
2.2 MPU 源码
2.2.1 armv8m_mpu.h
#ifndef _ARMV8M_MPU_H_
#define _ARMV8M_MPU_H_
#include <stdint.h>
#include <stdbool.h>
typedef struct armv8m_mpu_tag {
volatile uint32_t mpu_type;
volatile uint32_t mpu_ctrl;
volatile uint32_t mpu_rnr;
volatile uint32_t mpu_rbar;
volatile uint32_t mpu_rlar;
volatile uint32_t reserved[7];
volatile uint32_t mpu_mair0;
volatile uint32_t mpu_mair1;
} armv8m_mpu_t;
#define MPU_CTRL_ENABLE_SHITF 0UL
#define MPU_CTRL_ENABLE_MASK (1UL << MPU_CTRL_ENABLE_SHITF)
#define MPU_CTRL_HFNMIENA_SHIFT 1UL
#define MPU_CTRL_HFNMIENA_MASK (1UL << MPU_CTRL_HFNMIENA_SHIFT)
#define MPU_CTRL_PRIVDEFENA_SHIFT 2UL
#define MPU_CTRL_PRIVDEFENA_MASK (1UL << MPU_CTRL_PRIVDEFENA_SHIFT)
#define MPU_RNR_REGION_SHIFT 0UL
#define MPU_RNR_REGION_MASK (0xFFUL << MPU_RNR_REGION_SHIFT)
#define MPU_CTRL_RBAR_BASE_SHIFT 0x5UL
#define MPU_CTRL_RBAR_BASE_MASK 0xFFFFFFE0UL
#define MPU_CTRL_RBAR_SH_SHIFT 3UL
#define MPU_CTRL_RBAR_SH_MASK (0x3UL << MPU_CTRL_RBAR_SH_SHIFT)
#define MPU_CTRL_RBAR_AP_SHIFT 1UL
#define MPU_CTRL_RBAR_AP_MASK (0x3UL << MPU_CTRL_RBAR_AP_SHIFT)
#define MPU_CTRL_RBAR_XN_SHIFT 0UL
#define MPU_CTRL_RBAR_XN_MASK (1UL << MPU_CTRL_RBAR_XN_SHIFT)
#define MPU_CTRL_RLAR_LIMIT_SHIFT 5UL
#define MPU_CTRL_RLAR_LIMIT_MASK 0xFFFFFFE0UL
#define MPU_CTRL_RLAR_ATTRIDX_SHIFT 1UL
#define MPU_CTRL_RLAR_ATTRIDX_MASK (0x7UL << MPU_CTRL_RLAR_ATTRIDX_SHIFT)
#define MPU_CTRL_RLAR_EN_SHIFT 0UL
#define MPU_CTRL_RLAR_EN_MASK (1UL << MPU_CTRL_RLAR_EN_SHIFT)
#define REGION_NON_SHAREABLE 0
#define REGION_UNPREDICTABLE 1
#define REGION_OUTER_SHAREABLE 2
#define REGION_INNER_SHAREABLE 3
#define REGION_RW_PRIV_ONLY 0
#define REGION_RW_ANY 1
#define REGION_RO_PRIV_ONLY 2
#define REGION_RO_ANY 3
#define REGION_X 0
#define REGION_XN 1
#define REGION_DISABLE 0
#define REGION_EN 1
static inline void mpu_disable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl &= ~MPU_CTRL_ENABLE_MASK;
__asm("dsb");
__asm("isb");
}
static inline void mpu_enable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl |= MPU_CTRL_ENABLE_MASK;
__asm("dsb");
__asm("isb");
}
static inline void mpu_hfnmiena_enable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl |= MPU_CTRL_HFNMIENA_MASK;
}
static inline void mpu_hfnmiena_disable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl &= ~MPU_CTRL_HFNMIENA_MASK;
}
static inline void mpu_privdefena_enable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl |= MPU_CTRL_PRIVDEFENA_MASK;
}
static inline void mpu_privdefena_disable(armv8m_mpu_t *mpu)
{
mpu->mpu_ctrl &= ~MPU_CTRL_PRIVDEFENA_MASK;
}
static inline void mpu_select_region(armv8m_mpu_t *mpu, uint8_t region)
{
mpu->mpu_rnr |= ((region << MPU_RNR_REGION_SHIFT) & MPU_RNR_REGION_MASK);
}
static inline void mpu_set_region_base(armv8m_mpu_t *mpu, uint32_t base,
uint8_t share_att, uint8_t ap_att, uint32_t is_xn)
{
mpu->mpu_rbar = 0;
mpu->mpu_rbar = (base & MPU_CTRL_RBAR_BASE_MASK) |
((share_att << MPU_CTRL_RBAR_SH_SHIFT) & MPU_CTRL_RBAR_SH_MASK) |
((ap_att << MPU_CTRL_RBAR_AP_SHIFT) & MPU_CTRL_RBAR_AP_MASK) |
(is_xn & MPU_CTRL_RBAR_XN_MASK);
}
static inline void mpu_set_region_limit(armv8m_mpu_t *mpu, uint32_t limit,
uint8_t att_idx, uint8_t en)
{
mpu->mpu_rlar = 0;
mpu->mpu_rlar = (limit & MPU_CTRL_RLAR_LIMIT_MASK) |
((att_idx << MPU_CTRL_RLAR_ATTRIDX_SHIFT) & MPU_CTRL_RLAR_ATTRIDX_MASK) |
(en & MPU_CTRL_RLAR_EN_MASK);
}
mpu->mpu_mair1 &= ~(0xFF << ((idx - 4) * 8));
mpu->mpu_mair1 |= (attr << ((idx - 4) * 8));
}
}
#endif
2.2.2 只读region测试
//测试MPU是否关闭region写权限
void test_armv8m_mpu_write()
{
volatile uint32_t *temp_addr = (volatile uint32_t *)0x30001000UL;
//关闭MPU前可以在Memory进行读写
easy_printf("0x30001000:%x\n", *temp_addr);
*temp_addr = 0x1;
easy_printf("0x30001000:%x\n", *temp_addr);
armv8m_mpu_t *mpu = (armv8m_mpu_t *)0xE000ED90;
mpu_disable(mpu); //关闭MPU
mpu_select_region(mpu, 0); //设置region0
//设置region0基地址0x30000000,只读不可执行
mpu_set_region_base(mpu, 0x30000000UL, REGION_NON_SHAREABLE, REGION_RO_PRIV_ONLY, REGION_XN);
//设置region0上限为0x30001FFFF, region0使用attr0,并且使能region
mpu_set_region_limit(mpu, 0x30001FFFUL, 0, REGION_EN);
//设置region0属性为device memory
mpu_set_region_attr(mpu, 0, 0); /*device memory*/
//打开MPU
mpu_hfnmiena_disable(mpu);
mpu_privdefena_enable(mpu);
mpu_enable(mpu);
easy_printf("%s:mpu setup done\n", __func__);
//打开MPU后测试是否具有写权限
easy_printf("0x30001000:%x\n", *temp_addr);
//程序执行到这会触发hard fault
*temp_addr = 0x2;
easy_printf("0x30001000:%x\n", *temp_addr);
easy_printf("%s done\n", __func__);
}
执行log:
qemu-system-arm: invalid accelerator kvm
qemu-system-arm: falling back to tcg
hello cortex m33
0x30001000:00000000
0x30001000:00000001
test_armv8m_mpu_write:mpu setup done
0x30001000:00000001
default_exception_handler entry
2.2.3 地址overlap测试
oid test_armv8m_mpu_overlap()
{
volatile uint32_t *temp_addr = (volatile uint32_t *)0x30001000UL;
easy_printf("0x30001000:%x\n", *temp_addr);
*temp_addr = 0x1;
easy_printf("0x30001000:%x\n", *temp_addr);
armv8m_mpu_t *mpu = (armv8m_mpu_t *)0xE000ED90;
mpu_disable(mpu);
//设置region0:0x30000000 - 0x30001FFF
//可读可写,不可执行,device memory
mpu_select_region(mpu, 0);
mpu_set_region_base(mpu, 0x30000000UL, REGION_NON_SHAREABLE, REGION_RW_PRIV_ONLY, REGION_XN);
mpu_set_region_limit(mpu, 0x30001FFFUL, 0, REGION_EN);
mpu_set_region_attr(mpu, 0, 0); /*device memory*/
//设置region1:0x30001000 - 0x30001FFF
//可读可写,不可执行,device memory
mpu_select_region(mpu, 1);
mpu_set_region_base(mpu, 0x30001000UL, REGION_NON_SHAREABLE, REGION_RW_PRIV_ONLY, REGION_XN);
mpu_set_region_limit(mpu, 0x30001FFFUL, 1, REGION_EN);
mpu_set_region_attr(mpu, 0, 1); /*device memory*/
//打开MPU
mpu_hfnmiena_disable(mpu);
mpu_privdefena_enable(mpu);
mpu_enable(mpu);
easy_printf("%s:mpu setup done\n", __func__);
//打开MPU后,由于0x30001000的地址在region0和region1中重叠了,访问该地址会触发hard fault
//代码执行到这一句的时候会触发异常
easy_printf("0x30001000:%x\n", *temp_addr);
easy_printf("%s done\n", __func__);
}
qemu-system-arm: invalid accelerator kvm
qemu-system-arm: falling back to tcg
hello cortex m33
0x30001000:00000000
0x30001000:00000001
test_armv8m_mpu_overlap:mpu setup done
default_exception_handler entry
2.2.4 执行权限测试
void test_func_print()
{
easy_printf("%s entry\n", __func__);
}
void test_armv8m_xn()
{
/* Inject code at 0x30001000 */
//在0x300001000地址注入代码test_func
typedef void (*test_func_t)(void);
volatile uint32_t *temp_addr = (volatile uint32_t *)0x30001000UL;
test_func_t test_f = (test_func_t )0x30001001;//Thumb指令集,所以函数call的时候地址要加1
/* 1000041c <test_func>: 1000041c: b500 push {lr} 1000041e: 4801 ldr r0, [pc, #4] ; (10000424 <test_func+0x8>) 10000420: 4780 blx r0 10000422: bd00 pop {pc} 10000424: 100005eb andne r0, r0, fp, ror #11 //100005eb是test_func_print的地址 */
*temp_addr++ = 0x4801b500;
*temp_addr++ = 0xbd004780;
*temp_addr++ = 0x100005eb;
//使能MPU前可以执行在0x30001000处的test_func
test_f();
//使能MPU region0:0x30000000 - 0x300010000
//只读,不可执行,device memory
armv8m_mpu_t *mpu = (armv8m_mpu_t *)0xE000ED90;
mpu_disable(mpu);
mpu_select_region(mpu, 0);
mpu_set_region_base(mpu, 0x30000100UL, REGION_NON_SHAREABLE, REGION_RO_PRIV_ONLY, REGION_XN);
mpu_set_region_limit(mpu, 0x30001FFFUL, 0, REGION_EN);
mpu_set_region_attr(mpu, 0, 0); /*device memory*/
mpu_hfnmiena_disable(mpu);
mpu_privdefena_enable(mpu);
mpu_enable(mpu);
easy_printf("%s:mpu setup done\n", __func__);
//使能MPU后不可执行0x30001000的test_func,因此代码执行到这里的时候会触发hardfault
test_f();
}
log
qemu-system-arm: invalid accelerator kvm
qemu-system-arm: falling back to tcg
hello cortex m33
test_func_print entry
test_armv8m_xn:mpu setup done
default_exception_handler entry
版权声明
本文为[MyeDy]所创,转载请带上原文链接,感谢
https://blog.csdn.net/u011280717/article/details/103893441
边栏推荐
- 【動態規劃】不同路徑2
- PyTorch 20. PyTorch技巧(持续更新)
- EasyUI combobox determines whether the input item exists in the drop-down list
- PyTorch 21. PyTorch中nn.Embedding模块
- Paddleocr image text extraction
- [point cloud series] sg-gan: advantageous self attention GCN for point cloud topological parts generation
- 图像分类白盒对抗攻击技术总结
- torch.mm() torch.sparse.mm() torch.bmm() torch.mul() torch.matmul()的区别
- [8] Assertion failed: dims.nbDims == 4 || dims.nbDims == 5
- Chapter 3 pytoch neural network toolbox
猜你喜欢
ARMCC/GCC下的stack protector
Wechat applet uses wxml2canvas plug-in to generate some problem records of pictures
红外传感器控制开关
【期刊会议系列】IEEE系列模板下载指南
GEE配置本地开发环境
【点云系列】Fully-Convolutional geometric features
Chapter 3 pytoch neural network toolbox
Use originpro express for free
【点云系列】SG-GAN: Adversarial Self-Attention GCN for Point Cloud Topological Parts Generation
PyTorch 10. 学习率
随机推荐
Modifying a column with the 'identity' pattern is not supported
“Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated
pth 转 onnx 时出现的 gather、unsqueeze 等算子
WinForm scroll bar beautification
Pytorch best practices and coding style guide
Android exposed components - ignored component security
Wechat applet uses wxml2canvas plug-in to generate some problem records of pictures
【点云系列】PnP-3D: A Plug-and-Play for 3D Point Clouds
5种方法获取Torch网络模型参数量计算量等信息
PyTorch 17. GPU并发
[point cloud series] sg-gan: advantageous self attention GCN for point cloud topological parts generation
torch.where能否传递梯度
树莓派:双色LED灯实验
【3D形状重建系列】Implicit Functions in Feature Space for 3D Shape Reconstruction and Completion
RISCV MMU 概述
MySQL的安装与配置——详细教程
使用 trt 的int8 量化和推断 onnx 模型
Thanos. SH kill bully script, easily delete half of the files in the system at random
[dynamic programming] different paths 2
PyTorch 14. module类