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