Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
MPU_PMP_内存保护
开源之夏
开源之夏2023项目进展(MPU抽象层设计)
发布于 2023-09-02 11:58:16 浏览:605
订阅该版
[tocm] # 项目背景 [开源之夏](https://summer-ospp.ac.cn/) 是由中科院软件所“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护。今年的开源之夏RT-Thread社区的项目之一是[MPU抽象层设计](https://summer-ospp.ac.cn/org/prodetail/238bc0122?lang=zh&list=pro)。项目的目标是为不同处理器架构的内存保护单元提供一套通用的框架,让用户能使用这套框架解决一些常见的内存问题。 # 内存保护单元 内存保护单元是一个可编程的设备,用来指定一块特定内存区域的访问权限,比如读,写,和从该区域执行代码的权限。内存保护单元可以增加系统的健壮性,预防一些黑客的攻击。ARMV7-M和ARMV8-M都提供了内存保护单元,简称MPU(Memory Protection Unit)。[论坛里的这篇文章](https://club.rt-thread.org/ask/article/610305c1379b9e5e.html)提供了ARM MPU更详细的介绍。RISC-V也提供了相似的功能,简称PMP(Physical Memory Protection),具体可参考[RISC-V架构手册](https://riscv.org/wp-content/uploads/2017/05/riscv-privileged-v1.10.pdf)。 # 项目进展 目前对ARMV7-M和ARMV8-M架构实现了初步的支持,代码存放在[https://github.com/tangzz98/rt-thread/tree/mpu](https://github.com/tangzz98/rt-thread/tree/mpu)。框架通用的代码在[components/mp](https://github.com/tangzz98/rt-thread/tree/mpu/components/mp)目录下,硬件相关的代码存放在[libcpu](https://github.com/tangzz98/rt-thread/tree/mpu/libcpu/arm/cortex-m7),并提供了两个简单的[例程](https://github.com/tangzz98/rt-thread/tree/mpu/bsp/stm32/stm32u575-st-nucleo/applications)。 # 功能简介 RT-Thread操作系统的任务和内核使用同一个地址空间,全部运行在特权级。所有代码默认对任何内存都有读,写,和执行的权限。使用MPU框架可以给特定的内存区域设置更低的权限,如只读权限。MPU框架可以被用来实现以下的功能: - 把关键数据或代码设置成只读,防止它们被破坏 - 任务隔离,设定特定地址只能由特定的任务访问 - 检测栈溢出 - 把数据区域设置为不可执行,防止栈溢出攻击 # 使用方法 ## Menuconfig配置 通过`menuconfig`进入`RT-Thread Components->Memory Protection`配置相关选项 - `RT_USING_MEM_PROTECTION`:开启MPU抽象层 - `RT_USING_HW_STACK_GUARD`:使用MPU检测栈溢出。具体实现原理是在任务栈顶和栈底各设置一个MPU区域,权限设置为不可访问。如果发生栈溢出,代码访问了MPU保护的地址,会触发异常 - `NUM_MEM_REGIONS`:硬件支持的MPU区域数量 - `NUM_EXCLUSIVE_REGIONS`:使用`rt_mem_protection_add_exclusive_region`函数配置的内存区域数量 - `NUM_CONFIGURABLE_REGIONS`:各任务可以通过`rt_mem_protection_add_region`函数配置的内存区域数量 ## 内存区域配置 MPU抽象层提供了以下的API来配置任务对内存区域的权限: - `rt_err_t rt_mem_protection_add_region(rt_thread_t thread, rt_mem_region_t *region)`:添加内存区域 - `rt_err_t rt_mem_protection_delete_region(rt_thread_t thread, rt_mem_region_t *region)`:删除内存区域 - `rt_err_t rt_mem_protection_update_region(rt_thread_t thread, rt_mem_region_t *region)`:更新内存区域配置 内存区域的特性由`rt_mem_region_t`结构体定义: ``` typedef struct { void *start; /* 起始地址 */ rt_size_t size; /* 区域大小 */ rt_mem_attr_t attr; /* 区域特性 */ } rt_mem_region_t; ``` 其中`attr`可通过以下宏来定义,使用这样定义的代码在任何处理器架构下都是通用的: - `RT_MEM_REGION_P_RW_U_RW`:可读写 - `RT_MEM_REGION_P_RO_U_RO`: 只读 - `RT_MEM_REGION_P_NA_U_NA`:不可访问 - `RT_MEM_REGION_P_RWX_U_RWX`:可读写,执行 - `RT_MEM_REGION_P_RX_U_RX`:只读,可执行 通常程序需要定义一块内存区域只能由一个特定的任务访问。允许访问该内存区域的任务可以调用以下函数实现这个功能: - `rt_err_t rt_mem_protection_add_exclusive_region(void *start, rt_size_t size)`:添加内存区域 - `rt_err_t rt_mem_protection_delete_exclusive_region(void *start, rt_size_t size)`:删除内存区域 ## 初始化 使用MPU抽象层之前需要在`board.h`文件定义固定的MPU区域数量: ``` #define NUM_STATIC_REGIONS 2 ``` 在`board.c`文件定义固定的MPU区域特性: ``` rt_mem_region_t static_regions[NUM_STATIC_REGIONS] = { /* Flash region, read only */ { .start = (void *)STM32_FLASH_START_ADRESS, .size = (rt_size_t)STM32_FLASH_SIZE, .attr = RT_MEM_REGION_P_RX_U_RX, }, /* SRAM regin, no execute */ { .start = (void *)STM32_SRAM_START_ADDRESS, .size = (rt_size_t)STM32_SRAM_SIZE, .attr = RT_MEM_REGION_P_RW_U_RW, }, }; ``` 任何代码进行内存访问,都要遵守这些区域的配置。可以用固定的MPU区域,把代码段配置为只读,可执行,把数据段配置成可读写,不可执行。 另外必须确保配置的MPU区域数量满足以下的关系: - 如果开启了`RT_USING_HW_STACK_GUARD`:`NUM_STATIC_REGIONS` + `NUM_CONFIGURABLE_REGIONS` + `NUM_EXCLUSIVE_REGIONS` + 2 <= `NUM_MEM_REGIONS` - 如果没有开启`RT_USING_HW_STACK_GUARD`:`NUM_STATIC_REGIONS` + `NUM_CONFIGURABLE_REGIONS` + `NUM_EXCLUSIVE_REGIONS` <= `NUM_MEM_REGIONS` ## 异常检测 程序可以注册钩子函数,用来检测内存异常: ``` rt_err_t rt_hw_mp_exception_set_hook(rt_hw_mp_exception_hook_t hook) ``` `hook`函数会在发生内存异常时被调用。函数声明如下: ``` typedef void (*rt_hw_mp_exception_hook_t)(rt_mem_exception_info_t *) ``` `rt_mem_exception_info_t`结构体根据处理器机构定义,对于ARM架构,提供以下用来诊断内存异常的信息: ``` typedef struct { rt_thread_t thread; /* 触发异常的线程 */ void *addr; /* 发生异常的地址 */ rt_mem_region_t region; /* 地址对应的内存区域 */ rt_uint8_t mmfsr; /* MemManage Status寄存器的值 */ } rt_mem_exception_info_t; ```
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
半亩方塘8067
这家伙很懒,什么也没写!
文章
2
回答
0
被采纳
0
关注TA
发私信
相关文章
1
RT-Thread内核什么时候考虑加入MPU功能?
2
在使用motion_driver时,编译报错
3
关于mpu驱动的问题
4
RT-Thread支持MPU功能、特权线程与非特权线程吗?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部