什么是Cortex-M内核的MPU?
关注+星标公众号,不错过精彩内容
作者 | strongerHuang
微信公众号 | 嵌入式专栏
估计大家经常听说MCU、MPU、MMU等这类专业名词,但你们了解MPU吗?
MPU在嵌入式领域,通常有两种不同的意思:1. Microprocessor Unit(微处理器);2.Memory Protection Unit(内存保护单元)。
而我们本文说的Cortex-M内核的MPU就是指的内存保护单元。
不知道大家有关注过Cortex-M内核的一些内容,比如在STM32大部分型号中都有MPU。
1
关于MPU及作用阻止用户应用程序破坏操作系统使用的数据。 阻止一个任务访问其它任务的数据区,从而把任务隔开。 可以把关键数据区设置为只读,从根本上消除了被破坏的可能。 检测意外的存储访问,如,堆栈溢出,数组越界。 此外,还可以通过MPU设置存储器regions的其它访问属性,比如,是否缓区,是否缓冲等。
2
了解野指针回顾一下, 什么是指针?指针在内存中实际上是一个无符号整数(unsigned int),但是它的值被赋予特殊的解释:表示变量或函数的地址。所以才被形象地称为“指针”,就好像指向谁家似的。在使用指针前, 都必须先让它指向有意义的, 并且允许由程序使用的实体——数据和代码。而所谓“野指针”, 就是指某个指针变量的值因故超出合法的范围, 使其“枪口” 乱指。程序逻辑错误、 数组越界、 堆栈溢出、 指针未经初始化、 对缓存与缓冲的处理不当、 多任务环境中的紊乱条件, 甚至是恶意地破坏等, 都可以制造出野指针。如果使用野指针去读取或修改内存, 则被读取或修改的位置是不可预料的。前者导致读回来的都是乱掉的数据, 后者则会破坏未知用途的数据。这常常导致系统发生莫名其妙的功能紊乱, 严重时会使系统毫无征兆,没有理由地失控、死机。
野指针就像“肉里的刺, 酱里的蛆” 一般:一个野指针就足以毁掉整个系统, 而且极其隐蔽, 很难通过症状来找出是哪里存在野指针, 甚至都不能判定症状是否因野指针造成(程序大了其它 bug 也很多,并且也能导致相同的症状)。对于通常的单片机系统,是没有任何办法来防止野指针的破坏的, 完全靠程序员的素质和自律。但智者千虑, 必有一失。尤其是当程序规模变得很大时,复杂度会呈指数上升,千头万绪纠缠不清, 就算是谨慎如诸葛亮,聪明如比尔·盖茨的天才,也不敢保证没有漏网之鱼。
---来自CM3内核翻译作者
3
进一步认识MPU4
MPU学习资料上面只是进一步让大家了解了MPU内存保护单元,对于想要深入理解的朋友就需要参看更多相关资料。
对学习MPU编程,就需要对MPU相关寄存器进行掌握,MPU的寄存器其实相对来说也不多,这里再Cotex-M内核技术参考手册,以及STM32应用笔记Managing memory protection unit (MPU) in STM32 MCUs、编程手册中都有讲述关于MPU的知识。
1.STM32内存映射
2.MPU 的寄存器组
特权级的程序代码(如OS内核和异常服务例程)
用户级的程序代码
特权级程序的数据存储器,位于代码区中(data_stack)
用户级程序的数据存储器,位于代码区中(data_stack)
通用的数据存储器,位于其它存储器区域中(如, SRAM)
系统设备区,只允许特权级访问,如NVIC和MPU的寄存器所有的地址区间
常规外设区,如UART, ADC等
3.Cube HAL配置MPU例子
void MPU_RegionConfig(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* Disable MPU */
HAL_MPU_Disable();
/* Configure RAM region as Region N°0, 8kB of size and R/W region */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_8KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Configure FLASH region as REGION N°1, 1MB of size and R/W region */
MPU_InitStruct.BaseAddress = 0x08000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_1MB;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Configure FMC region as REGION N°2, 0.5GB of size, R/W region */
MPU_InitStruct.BaseAddress = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512MB;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enable MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
------------ END ------------
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。