进入了硬件异常。
程序设计:
本程序主要分为两个部分:
Ø MPU的配置
Ø 主程序
1. MPU的配置
这里将相关的函数进行了专门的配置,方便用户进行调用。
#defineMPU_DEFS_RASR_SIZE_32B (0x04 <<MPU_RASR_SIZE_Pos)
#define MPU_DEFS_RASR_SIZE_64B (0x05 << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_128B (0x06 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_256B (0x07 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_512B (0x08 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_1KB (0x09 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_2KB (0x0A <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_4KB (0x0B <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_8KB (0x0C <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_16KB (0x0D <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_32KB (0x0E <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_64KB (0x0F <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_128KB (0x10 << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_256KB (0x11 << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_512KB (0x12 << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_1MB (0x13 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_2MB (0x14 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_4MB (0x15 << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_8MB (0x16 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_16MB (0x17 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_32MB (0x18 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_64MB (0x19 <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_128MB (0x1A << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_256MB (0x1B << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_512MB (0x1C << MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_1GB (0x1D <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_2GB (0x1E <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASR_SIZE_4GB (0x1F <<MPU_RASR_SIZE_Pos)
#defineMPU_DEFS_RASE_AP_NO_ACCESS (0x0<< MPU_RASR_AP_Pos)
#defineMPU_DEFS_RASE_AP_PRIV_RW (0x1<< MPU_RASR_AP_Pos)
#defineMPU_DEFS_RASE_AP_PRIV_RW_USER_RO (0x2 << MPU_RASR_AP_Pos)
#defineMPU_DEFS_RASE_AP_FULL_ACCESS (0x3<< MPU_RASR_AP_Pos)
#defineMPU_DEFS_RASE_AP_PRIV_RO (0x5<< MPU_RASR_AP_Pos)
#defineMPU_DEFS_RASE_AP_RO (0x6<< MPU_RASR_AP_Pos)
#defineMPU_DEFS_NORMAL_MEMORY_WT (MPU_RASR_C_Msk)
#defineMPU_DEFS_NORMAL_MEMORY_WB (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
#defineMPU_DEFS_NORMAL_SHARED_MEMORY_WT (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
#defineMPU_DEFS_NORMAL_SHARED_MEMORY_WB (MPU_DEFS_NORMAL_MEMORY_WB | MPU_RASR_S_Msk)
#defineMPU_DEFS_SHARED_DEVICE (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
#defineMPU_DEFS_STRONGLY_ORDERED_DEVICE (0x0)
/*************************************************/
voidmpu_region_config(uint32_t region_num, uint32_t addr, uint32_t size, uint32_tattributes);
voidmpu_enable(uint32_t options);
voidmpu_disable(void);
voidmpu_region_disable(uint32_t region_num);
/*
*******************************************************************************************
* 函 数 名: bsp_InitMPU
* 功能说明: 内存保护单元初始化
* 形 参: 无
* 返 回 值: 0 表示失败,1 表示成功
*******************************************************************************************
*/
uint8_tbsp_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 - GPIOD */
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 - ResetClock 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
* 返 回 值: 无
*******************************************************************************************
*/
voidmpu_enable(uint32_t options)
{
MPU->CTRL = MPU_CTRL_ENABLE_Msk |options;
__DSB(); // Ensure MPU settings take effects
__ISB(); // Sequence instruction fetches using updatesettings
}
/*
*******************************************************************************************
* 函 数 名: mpu_disable
* 功能说明: 禁止mpu
* 形 参: 无
* 返 回 值: 无
*******************************************************************************************
*/
voidmpu_disable(void)
{
__DMB(); // Make sure outstanding transfersare done
MPU->CTRL = 0; // Disable the MPU
}
/*
*******************************************************************************************
* 函 数 名:mpu_region_disable
* 功能说明: 禁止mpu谋一个region
* 形 参:region_num 范围0 - 7
* 返 回 值: 无
*******************************************************************************************
*/
voidmpu_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_tregion_num, uint32_t addr, uint32_t size, uint32_t attributes)
{
MPU->RNR = region_num;
MPU->RBAR = addr;
MPU->RASR = size | attributes;
}
2. 主程序
/* 仅允许本文件内调用的函数声明 */
static voidPrintfLogo(void);
static voidDelay(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 voidDelay(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权威指南)