一 MPU介绍
MPU,即内存保护单元,可以设置不同存储区域的存储器访问特性(如只支持特权访问或全访问)和存储器属性(如可缓存、可缓冲、可共享),对存储器(主要是内存和外设)提供保护,从而提高系统可靠性:
阻止用户应用程序破坏操作系统使用的数据
阻止一个任务访问其他任务的数据区,从而隔离任务
可以把关键数据区域设置为只读,从根本上解决被破坏的可能
检测意外的存储访问,如堆栈溢出,数组越界等
将SRAM或者RAM空间定义为不可执行(用不执行,XN),防止代码注入攻击。
注意,MPU不仅可以保护内存区域(SRAM区),还可以保护外设区(比如FMC)。我们可以通过MPU设置存储器的访问权限,当存储器访问和MPU定义的访问权限相冲突的时候,则访问会被阻止,并且触发一次错误异常(一般是MemManage异常)。然后,在异常处理的时候,就可以确定系统是否应该复位或者执行其他操作。
STM32H5的MPU手册里的介绍
Cortex-m33的MPU寄存器列表
二 MPU配置
STM32H5的MPU配置
配置成portMPU_REGION_PRIVILEGED_READ_ONLY模式
保护的地址是ARRAY_ADDRESS_START开始即0x20002000UL的MPU_REGION_NUMBER3
HAL_MPU_Disable();
/* Define cacheable memory via MPU */
MPU_AttributesInit.Number = ARRAY_ATTRIBUTE_NUMBER;
MPU_AttributesInit.Attributes = MPU_NOT_CACHEABLE;
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = ARRAY_ADDRESS_START;
MPU_InitStruct.LimitAddress = ARRAY_ADDRESS_START + ARRAY_SIZE - 1;
MPU_InitStruct.AccessPermission = portMPU_REGION_PRIVILEGED_READ_ONLY;
MPU_InitStruct.AttributesIndex = ARRAY_ATTRIBUTE_NUMBER;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = ARRAY_REGION_NUMBER;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable MPU (any access not covered by any enabled region will cause a fault) */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
那现在我们开始操作这个0x20002000UL地址的RAM空间
首先attribute一个数组到这个地址
uint8_t mpudata[128] __attribute__((section(".ARM.__at_0x20002000")));
三 测试
第一个测试:
如果不对这个数组进行操作,
程序运行到while(1)里面 LED1一直闪烁
测试二:
然后对这个数据进行操作,随便赋值
发现进入到NMI中断,LED3开始亮了