第6章 内存保护单元MPU
本期教程带领大家学习内存保护单元MPU的使用,在前面的几期教程中曾多次的提到MPU的使用,MPU在RTOS的安全关键设计中也十分的重要,μCOS-III和μCOS-II就有配套的μC/OS-MPU,不过没有对外开源,对于想学习其源代码的人来说有点可惜,而FreeRTOS也支持MPU的配置,有兴趣的可以去学习了解。本期教程主要学习M4内核支持的MPU单元。 6.1 MPU的介绍 6.2实验例程说明 6.3实验总结 6.1 MPU的介绍 关于MPU的基础知识在Cortex-M3权威指南中文版的第14章有非常详细的介绍,或者看Cortex-M4权威指南英文版第11章。如果打算学习MPU,这两章一定要认真的看完。这个是下面几个MPU实验的基础,也是以后学习RTOS中关于MPU的基础。 6.2 实验例程说明 一共为本期教程制作了3个例子,下面就跟大家详细讲解这3个例子。前两个工程都不需要添加额外的文件,将代码都放在了main.c文件中实现,第三个工程专门做了一个驱动文件,方便后面教程配套实验中调用。
6.2.1 实验一:MPU简易使用例子一实验目的: 1.学习MPU的配置 实验内容: 1.初始化串口,LED和MPU 2.主程序实现LED的闪烁 实验现象: 请用USB转串口线连接PC机和 开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象):
进入了硬件异常。 程序设计: 本程序主要分为两个部分: Ø MPU的配置 Ø 主程序 1. MPU的配置 MPU的配置相对比较容易,前提是一定要看权威指南上面对这个的介绍。
- /*
- *******************************************************************************************
- * 函 数 名: mpu_setup
- * 功能说明: mpu配置
- * 形 参:无
- * 返 回 值: 无
- *******************************************************************************************
- */
- static int mpu_setup(void)
- {
- uint32_t i;
-
- uint32_t const mpu_cfg_rbar[4] =
- {
- 0x08000000, // Flash
- 0x20000000, // SRAM
- GPIOF_BASE, // GPIO F base address
- RCC_BASE // Reset Clock CTRL base address
- };
-
- uint32_t const mpu_cfg_rasr[4] =
- {
- (MPU_DEFS_RASR_SIZE_1MB | MPU_DEFS_NORMAL_MEMORY_WT |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // Flash
- (MPU_DEFS_RASR_SIZE_128KB | MPU_DEFS_NORMAL_MEMORY_WT |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // SRAM
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // GPIO D
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk) // RCC
- };
-
- /* 通过读取此寄存器的DREGION位值,够判断芯片中是否配了MPU */
- if (MPU->TYPE==0)
- {
- return 1;
- }
- __DMB(); // Make sure outstanding transfers are done
-
- /* 禁止MPU */
- MPU->CTRL = 0;
-
- /* 配置MPU的4个region */
- for (i=0;i<4;i++)
- {
- MPU->RNR = i; // 选择配置那个region
- MPU->RBAR = mpu_cfg_rbar[i]; // 配置地址
- MPU->RASR = mpu_cfg_rasr[i]; // 配置属性和大小
- }
-
- /* 下面的配置,相当于禁止*/
- for (i=4;i<8;i++)
- {
- MPU->RNR = i;
- MPU->RBAR = 0;
- MPU->RASR = 0;
- }
-
- /* 使能MPU */
- MPU->CTRL = MPU_CTRL_ENABLE_Msk;
- __DSB(); // Ensure MPU settings take effects
- __ISB(); // Sequence instruction fetches using update settings
- }
复制代码
2. 主程序 主程序的功能也比较的简单,就是实现LED的闪烁。
- #define MPU_DEFS_RASR_SIZE_32B (0x04 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64B (0x05 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128B (0x06 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256B (0x07 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512B (0x08 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1KB (0x09 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2KB (0x0A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4KB (0x0B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8KB (0x0C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16KB (0x0D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32KB (0x0E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64KB (0x0F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128KB (0x10 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256KB (0x11 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512KB (0x12 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1MB (0x13 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2MB (0x14 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4MB (0x15 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8MB (0x16 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16MB (0x17 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32MB (0x18 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64MB (0x19 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128MB (0x1A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256MB (0x1B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512MB (0x1C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1GB (0x1D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2GB (0x1E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4GB (0x1F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASE_AP_NO_ACCESS (0x0 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW (0x1 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW_USER_RO (0x2 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_FULL_ACCESS (0x3 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RO (0x5 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_RO (0x6 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_NORMAL_MEMORY_WT (MPU_RASR_C_Msk)
- #define MPU_DEFS_NORMAL_MEMORY_WB (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WT (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WB (MPU_DEFS_NORMAL_MEMORY_WB | MPU_RASR_S_Msk)
- #define MPU_DEFS_SHARED_DEVICE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
-
- #define LOOP_COUNT 0x3FFFFF
-
- /* 仅允许本文件内调用的函数声明 */
- static void PrintfLogo(void);
- static int mpu_setup(void);
- static void Delay(uint32_t nCount);
-
- /*
- *******************************************************************************************
- * 函 数 名: main
- * 功能说明: c程序入口
- * 形 参:无
- * 返 回 值: 错误代码(无需处理)
- *******************************************************************************************
- */
- int main(void)
- {
- //(在Cortex-M3 r1p1中推荐使用, 在Cortex-M3 r2px 和 Cortex-M4中默认支持)
- SCB->CCR |= SCB_CCR_STKALIGN_Msk; // 使能堆栈的双字对齐模式
- SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; // 使能 MemManage fault
-
- bsp_InitUart();
- PrintfLogo();
- bsp_InitLed(); /* 初始LED指示灯端口 */
- mpu_setup();
-
- /* 进入主程序循环体 */
- while (1)
- {
- bsp_LedToggle(1);
- bsp_LedToggle(3);
- Delay(LOOP_COUNT);
- }
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: Delay
- * 功能说明: nCount 延迟
- * 形 参:无
- * 返 回 值: 无
- *******************************************************************************************
- */
- static void Delay(uint32_t nCount)
- {
- while(nCount--)
- {
- __DSB();
- }
- }
复制代码
6.2.2 实验二:MPU简易使用例子二实验目的: 1.学习MPU的配置 实验内容: 1.初始化串口,LED和MPU 2.主程序实现LED的闪烁 3.这个例子和第一个例子基本相同,只是换了一种region的配置方法。 实验现象: 请用USB转串口线连接PC机和开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象):
进入了硬件异常。 程序设计: 本程序主要分为两个部分: Ø MPU的配置 Ø 主程序 1. MPU的配置 MPU的配置相对比较容易,前提是一定要看权威指南上面对这个的介绍。
- /*
- *******************************************************************************************
- * 函 数 名: mpu_setup
- * 功能说明: mpu配置
- * 形 参:无
- * 返 回 值: 无
- *******************************************************************************************
- */
- static int mpu_setup(void)
- {
- uint32_t i;
-
- uint32_t const mpu_cfg_rbar[4] =
- {
- // Flash - region 0
- (0x08000000 | MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 0)),
- // SRAM - region 1
- (0x20000000 | MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 1)),
- // GPIO D base address - region 2
- (GPIOF_BASE | MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2)),
- // Reset Clock CTRL base address - region 3
- (RCC_BASE | MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 3))
- };
-
- uint32_t const mpu_cfg_rasr[4] =
- {
- (MPU_DEFS_RASR_SIZE_1MB | MPU_DEFS_NORMAL_MEMORY_WT |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // Flash
- (MPU_DEFS_RASR_SIZE_128KB | MPU_DEFS_NORMAL_MEMORY_WT |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // SRAM
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk), // GPIO D
- (MPU_DEFS_RASR_SIZE_1KB | MPU_DEFS_SHARED_DEVICE |
- MPU_DEFS_RASE_AP_FULL_ACCESS | MPU_RASR_ENABLE_Msk) // RCC
- };
-
- /* 通过读取此寄存器的DREGION位值,够判断芯片中是否配了MPU */
- if (MPU->TYPE==0)
- {
- return 1;
- }
- __DMB(); // Make sure outstanding transfers are done
-
- /* 禁止MPU */
- MPU->CTRL = 0;
-
- /* 配置MPU的4个region */
- for (i=0;i<4;i++)
- {
- MPU->RNR = i; // 选择配置那个region
- MPU->RBAR = mpu_cfg_rbar[i]; // 配置地址
- MPU->RASR = mpu_cfg_rasr[i]; // 配置属性和大小
- }
-
- /* 下面的配置,相当于禁止其余的4个region */
- for (i=4;i<8;i++)
- {
- MPU->RNR = i;
- MPU->RBAR = 0;
- MPU->RASR = 0;
- }
-
- /* 使能MPU */
- MPU->CTRL = MPU_CTRL_ENABLE_Msk;
- __DSB(); // Ensure MPU settings take effects
- __ISB(); // Sequence instruction fetches using update settings
- }
复制代码
2. 主程序 主程序的功能也比较的简单,就是实现LED的闪烁。
- #define MPU_DEFS_RASR_SIZE_32B (0x04 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64B (0x05 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128B (0x06 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256B (0x07 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512B (0x08 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1KB (0x09 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2KB (0x0A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4KB (0x0B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8KB (0x0C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16KB (0x0D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32KB (0x0E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64KB (0x0F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128KB (0x10 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256KB (0x11 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512KB (0x12 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1MB (0x13 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2MB (0x14 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4MB (0x15 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8MB (0x16 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16MB (0x17 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32MB (0x18 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64MB (0x19 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128MB (0x1A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256MB (0x1B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512MB (0x1C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1GB (0x1D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2GB (0x1E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4GB (0x1F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASE_AP_NO_ACCESS (0x0 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW (0x1 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW_USER_RO (0x2 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_FULL_ACCESS (0x3 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RO (0x5 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_RO (0x6 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_NORMAL_MEMORY_WT (MPU_RASR_C_Msk)
- #define MPU_DEFS_NORMAL_MEMORY_WB (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WT (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WB (MPU_DEFS_NORMAL_MEMORY_WB | MPU_RASR_S_Msk)
- #define MPU_DEFS_SHARED_DEVICE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
-
- #define LOOP_COUNT 0x3FFFFF
-
- /* 仅允许本文件内调用的函数声明 */
- static void PrintfLogo(void);
- static int mpu_setup(void);
- static void Delay(uint32_t nCount);
-
- /*
- *******************************************************************************************
- * 函 数 名: main
- * 功能说明: c程序入口
- * 形 参:无
- * 返 回 值: 错误代码(无需处理)
- *******************************************************************************************
- */
- int main(void)
- {
- //(在Cortex-M3 r1p1中推荐使用, 在Cortex-M3 r2px 和 Cortex-M4中默认支持)
- SCB->CCR |= SCB_CCR_STKALIGN_Msk; // 使能堆栈的双字对齐模式
- SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; // 使能 MemManage fault
-
- bsp_InitUart();
- PrintfLogo();
- bsp_InitLed(); /* 初始LED指示灯端口 */
- mpu_setup();
-
- /* 进入主程序循环体 */
- while (1)
- {
- bsp_LedToggle(1);
- bsp_LedToggle(3);
- Delay(LOOP_COUNT);
- }
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: Delay
- * 功能说明: nCount 延迟
- * 形 参:无
- * 返 回 值: 无
- *******************************************************************************************
- */
- static void Delay(uint32_t nCount)
- {
- while(nCount--)
- {
- __DSB();
- }
- }
复制代码
6.2.3 实验三:MPU的API函数实验目的: 1.学习MPU的配置 实验内容: 1.初始化串口,LED和MPU 2.主程序实现LED的闪烁 3.这个实验相对于前面两个只是重新封装了下,方便调用 实验现象: 请用USB转串口线连接PC机和开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象):
进入了硬件异常。 程序设计: 本程序主要分为两个部分: Ø MPU的配置 Ø 主程序 1. MPU的配置 这里将相关的函数进行了专门的配置,方便用户进行调用。
- #define MPU_DEFS_RASR_SIZE_32B (0x04 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64B (0x05 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128B (0x06 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256B (0x07 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512B (0x08 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1KB (0x09 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2KB (0x0A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4KB (0x0B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8KB (0x0C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16KB (0x0D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32KB (0x0E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64KB (0x0F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128KB (0x10 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256KB (0x11 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512KB (0x12 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1MB (0x13 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2MB (0x14 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4MB (0x15 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_8MB (0x16 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_16MB (0x17 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_32MB (0x18 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_64MB (0x19 << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_128MB (0x1A << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_256MB (0x1B << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_512MB (0x1C << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_1GB (0x1D << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_2GB (0x1E << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASR_SIZE_4GB (0x1F << MPU_RASR_SIZE_Pos)
- #define MPU_DEFS_RASE_AP_NO_ACCESS (0x0 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW (0x1 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RW_USER_RO (0x2 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_FULL_ACCESS (0x3 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_PRIV_RO (0x5 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_RASE_AP_RO (0x6 << MPU_RASR_AP_Pos)
- #define MPU_DEFS_NORMAL_MEMORY_WT (MPU_RASR_C_Msk)
- #define MPU_DEFS_NORMAL_MEMORY_WB (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WT (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_NORMAL_SHARED_MEMORY_WB (MPU_DEFS_NORMAL_MEMORY_WB | MPU_RASR_S_Msk)
- #define MPU_DEFS_SHARED_DEVICE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
- #define MPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
-
- /*************************************************/
- void mpu_region_config(uint32_t region_num, uint32_t addr, uint32_t size, uint32_t attributes);
- void mpu_enable(uint32_t options);
- void mpu_disable(void);
- void mpu_region_disable(uint32_t region_num);
-
- /*
- *******************************************************************************************
- * 函 数 名: bsp_InitMPU
- * 功能说明: 内存保护单元初始化
- * 形 参: 无
- * 返 回 值: 0 表示失败,1 表示成功
- *******************************************************************************************
- */
- uint8_t bsp_InitMPU(void)
- {
- if (MPU->TYPE==0)
- {
- return 0;
- }
- /* 第一步要先禁止MPU再进行相应的设置 */
- mpu_disable();
-
- /* 设置MPU的8个Region */
- /* 配置Region 0 - Flash */
- mpu_region_config(0, 0x08000000, MPU_DEFS_RASR_SIZE_1MB,
- MPU_DEFS_NORMAL_MEMORY_WT | MPU_DEFS_RASE_AP_FULL_ACCESS |
- MPU_RASR_ENABLE_Msk),
- /* 配置Region 1 - SRAM */
- mpu_region_config(1, 0x20000000, MPU_DEFS_RASR_SIZE_128KB,
- MPU_DEFS_NORMAL_MEMORY_WT | MPU_DEFS_RASE_AP_FULL_ACCESS |
- MPU_RASR_ENABLE_Msk),
- /* 配置Region 2 - GPIO D */
- mpu_region_config(2, GPIOF_BASE, MPU_DEFS_RASR_SIZE_1KB,
- MPU_DEFS_SHARED_DEVICE | MPU_DEFS_RASE_AP_FULL_ACCESS |
- MPU_RASR_ENABLE_Msk),
- /* 配置Region 3 - Reset Clock CTRL */
- mpu_region_config(3, RCC_BASE, MPU_DEFS_RASR_SIZE_1KB,
- MPU_DEFS_SHARED_DEVICE | MPU_DEFS_RASE_AP_FULL_ACCESS |
- MPU_RASR_ENABLE_Msk),
- /* 禁止Region 4 */
- mpu_region_disable(4);
- /* 禁止Region 5 */
- mpu_region_disable(5);
- /* 禁止Region 6 */
- mpu_region_disable(6);
- /* 禁止Region 7 */
- mpu_region_disable(7);
-
- /* 使能允许MPU */
- mpu_enable(0);
-
- return 1;
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: mpu_enable
- * 功能说明: mpu使能,mpu控制寄存器有3位,功能分别如下:
- * 位2 PRIVDEFENA 是否为特权级打开缺省存储器映射(即背景
- * region)。
- * 1 = 特权级下打开背景region
- * 0 = 不打开背景region。任何访问违例以及对
- * region外地址区的访问都将引起fault。
- * 位1 HFNMIENA 1=在NMI和硬fault服务例程中不强制除能MPU
- * 0=在NMI和硬fault服务例程中强制除能MPU
- * 位0 ENABLE 使能或者禁止
- * 形 参: options MPU_CTRL_HFNMIENA_Msk或者MPU_CTRL_PRIVDEFENA_Msk
- * 返 回 值: 无
- *******************************************************************************************
- */
- void mpu_enable(uint32_t options)
- {
- MPU->CTRL = MPU_CTRL_ENABLE_Msk | options;
- __DSB(); // Ensure MPU settings take effects
- __ISB(); // Sequence instruction fetches using update settings
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: mpu_disable
- * 功能说明: 禁止mpu
- * 形 参: 无
- * 返 回 值: 无
- *******************************************************************************************
- */
- void mpu_disable(void)
- {
- __DMB(); // Make sure outstanding transfers are done
- MPU->CTRL = 0; // Disable the MPU
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: mpu_region_disable
- * 功能说明: 禁止mpu谋一个region
- * 形 参: region_num 范围0 - 7
- * 返 回 值: 无
- *******************************************************************************************
- */
- void mpu_region_disable(uint32_t region_num)
- {
- MPU->RNR = region_num;
- MPU->RBAR = 0;
- MPU->RASR = 0;
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: mpu_region_config
- * 功能说明: mpu配置
- * 形 参: region_num 范围0 - 7
- * addr 地址
- * size 大小
- * attributes 属性
- * 返 回 值: 无
- *******************************************************************************************
- */
- void mpu_region_config(uint32_t region_num, uint32_t addr, uint32_t size, uint32_t attributes)
- {
- MPU->RNR = region_num;
- MPU->RBAR = addr;
- MPU->RASR = size | attributes;
- }
复制代码
2. 主程序
- /* 仅允许本文件内调用的函数声明 */
- static void PrintfLogo(void);
- static void Delay(uint32_t nCount);
- /*
- *******************************************************************************************
- * 函 数 名: main
- * 功能说明: c程序入口
- * 形 参:无
- * 返 回 值: 错误代码(无需处理)
- *******************************************************************************************
- */
- int main(void)
- {
- //(在Cortex-M3 r1p1中推荐使用, 在Cortex-M3 r2px 和 Cortex-M4中默认支持)
- SCB->CCR |= SCB_CCR_STKALIGN_Msk; // 使能堆栈的双字对齐模式
- SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; // 使能 MemManage fault
-
- bsp_InitUart();
- PrintfLogo();
- bsp_Init(); /* 硬件初始化 */
-
- /* 进入主程序循环体 */
- while (1)
- {
- bsp_LedToggle(1);
- bsp_LedToggle(3);
- Delay(LOOP_COUNT);
- }
- }
-
- /*
- *******************************************************************************************
- * 函 数 名: Delay
- * 功能说明: nCount 延迟
- * 形 参:无
- * 返 回 值: 无
- */
- static void Delay(uint32_t nCount)
- {
- while(nCount--)
- {
- __DSB();
- }
- }
复制代码
6.3 实验总结 本期教程相对来说也比较的重要,希望初学RTOS的同学认真的学习。
参考资料: 1. Patterns fortime-triggered embedded systems英文版和中文版 2. Cortex-M3权威指南中文版 3. TheDefinitive Guide to Arm Cortex-M3 and Cortex-M4 Processors(M4权威指南)
0
|
|
|
|