[STM32F4]

【安富莱STM32F407之uCOS-III教程】第6章 内存保护单元MPU

[复制链接]
8742|17
手机看帖
扫描二维码
随时随地手机跟帖
Eric2013|  楼主 | 2014-12-19 16:26 | 显示全部楼层 |阅读模式
特别说明:
1.  本教程是安富莱电子原创。
2.  安富莱STM32F407开发板资料已经全部开源,开源地址:地址链接
3.  当前共配套300多个实例,4套用户手册。

第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.1.png


6.2.1      实验一:MPU简易使用例子一
实验目的:
    1.学习MPU的配置
实验内容:
    1.初始化串口,LED和MPU
    2.主程序实现LED的闪烁
实验现象:
    请用USB转串口线连接PC机和开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象):
6.2.png

     进入了硬件异常。
程序设计:
本程序主要分为两个部分:
  Ø  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 Printf**(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();
     Printf**();
     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();
     }
}


Eric2013|  楼主 | 2014-12-19 16:32 | 显示全部楼层
6.2.2      实验二:MPU简易使用例子二
实验目的:
    1.学习MPU的配置
实验内容:
    1.初始化串口,LED和MPU
    2.主程序实现LED的闪烁
    3.这个例子和第一个例子基本相同,只是换了一种region的配置方法。
实验现象:
    请用USB转串口线连接PC机和开发板。PC机上运行SecureCRT软件,波特率设置为115200bps,无硬件流控。从PC机的软件界面观察程序执行结果(如果访问MPU范围之外的空间将出现下面现象):
6.3.png

                              
     进入了硬件异常。
程序设计:
本程序主要分为两个部分:
  Ø  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 Printf**(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();
     Printf**();
     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范围之外的空间将出现下面现象):
6.4.png

    进入了硬件异常。
程序设计:
本程序主要分为两个部分:
  Ø  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 Printf**(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();
     Printf**();
     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权威指南)

使用特权

评论回复
mmuuss586| | 2014-12-19 19:02 | 显示全部楼层

不错,谢谢楼主分享;

使用特权

评论回复
Eric2013|  楼主 | 2014-12-19 21:55 | 显示全部楼层
mmuuss586 发表于 2014-12-19 19:02
不错,谢谢楼主分享;

谢谢置酷:handshake

使用特权

评论回复
sgj245609615| | 2014-12-22 10:39 | 显示全部楼层
不错

使用特权

评论回复
hqtdzgs| | 2014-12-22 17:41 | 显示全部楼层
资料很全呀,

使用特权

评论回复
bhkjcg| | 2014-12-24 13:09 | 显示全部楼层
长期供应ST  MCU  STM32F103ZET6  STM32F103C8T6  STM32F103RBT6  STM32F103R8T6  STM32F103VET6  原装正品 进口 环保 需要联系  13316984089   QQ596615307

使用特权

评论回复
Eric2013|  楼主 | 2014-12-27 16:58 | 显示全部楼层
莫要沉了啊~~

使用特权

评论回复
周董| | 2014-12-27 21:20 | 显示全部楼层
不错!!赞一个!!

使用特权

评论回复
mega1702| | 2014-12-28 01:52 | 显示全部楼层
谢谢楼主分享!!!

使用特权

评论回复
白丁野老| | 2014-12-30 21:27 | 显示全部楼层
学习一下

使用特权

评论回复
周董| | 2014-12-30 23:29 | 显示全部楼层
MPU->RNR  = i;  这个选择配置的是哪个个region啊???

使用特权

评论回复
beiyongmail| | 2015-1-9 16:55 | 显示全部楼层
学习下,谢谢了

使用特权

评论回复
鸿盛数控| | 2015-1-16 10:35 | 显示全部楼层
感谢分享。

使用特权

评论回复
鸿盛数控| | 2015-1-16 10:36 | 显示全部楼层
感谢分享。

使用特权

评论回复
permanentk| | 2015-2-28 08:49 | 显示全部楼层
学习一下

使用特权

评论回复
zh113214| | 2015-2-28 15:08 | 显示全部楼层
MPU配置看上去还是比较简单的呀。。

使用特权

评论回复
lskam| | 2015-9-15 15:33 | 显示全部楼层
好像不行的,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:RTX->μCOS-II->FreeRTOS->embOS->μCOS-III μCGUI->emWin->FatFs->DSP 淘宝:armfly.taobao.com

115

主题

639

帖子

34

粉丝