3.1 Fault异常的控制寄存器 在这里有必要介绍一下系统控制模块寄存器组(SCB)的成员,这个寄存器组的定义可以在core_cm3.h文件中,该文件属于CMSIS Cortex-M3 内核外设接口抽象层的一部分(关于不清楚CMSIS的,可以自行查找资料)。定义如下: 1.定义系统控制寄存器组结构体
/** @brief System Control Block (SCB) register structure definition */
typedef struct
{
__I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register*/
__IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register*/
__IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register*/
__IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register*/
__IO uint32_t SCR; /*!< Offset: 0x10 System Control Register*/
__IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register*/
__IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
__IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */
__IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register*/
__IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register*/
__IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */
__IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register*/
__IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register*/
__IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register*/
__I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register*/
__I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register*/
__I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register*/
__I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register*/
__I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature Register*/
} SCB_Type;
2. 定义系统控制寄存器组物理空间基地址 #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
3. 定义指向系统控制寄存器组的指针 #define SCB ((SCB_Type *)SCB_BASE) /*!< SCB configuration struct * /
通过以上三步,我们就可以使用结构体指针SCB来访问系统控制寄存器组的寄存器了,比如给系统控制寄存器SCR赋值:SCB->SCR=0xFF;
SCB->CCR寄存器控制除数为零和未对齐内存访问是否触发用法Fault。 SCB->SHCSR寄存器可用来使能非硬Fault异常。如果一个非硬Fault异常被禁能并且相关Fault发生,这时异常会升级为硬Fault。SCB->SHP寄存器组控制异常的优先级。 Fault异常控制寄存器列表: 地址/访问 | 寄存器 | 复位值 | 描述 | 0xE000ED14 RW 特权级 | SCB->CCR | 0x00000000 | 配置和控制寄存器:包含控制除数为零和未对齐内存访问是否触发用法Fault的使能位。 | 0xE000ED18 RW 特权级 | SCB->SHP[12] | 0x00 | 系统处理程序优先级寄存器:控制异常处理程序的优先级 | 0xE000ED24 RW特权级 | SCB->SHCSR | 0x00000000 | 系统处理程序控制和状态寄存器 |
3.1.1 SCB->CCR 寄存器 蓝色部分控制是否使能相应的用法Fault 位 | 名称 | 描述 | [31:10] | - | 保留 | [9] | STKALIGN | 表示进入异常时的堆栈对齐。 0:4字节对齐 1:8字节对齐 进入异常时,处理器使用压入堆栈的PSR位[9]来指示堆栈对齐。从异常返回时,这个堆栈位被用来恢复正确的堆栈对齐。 | [8] | BFHFNMIGN | 使能时,使得以优先级位-1或-2运行的处理程序忽略加载和存储指令引起的数据总线故障。它用于硬故障、NMI和FAULTMASK升级处理程序中: 0:加载和存储指令引起的数据总线故障会引起锁定。 1:以优先级-1或-2运行的处理程序忽略加载和存储指令引起的数据总线故障。 仅在处理程序和其数据处于绝对安全的存储器时将该位设为1。一般将该位用于探测系统设备和桥接器以检测并纠正控制路径问题。 | [7:5] | - | 保留 | [4] | DIV_0_TRP | 当处理器进行除0操作(SDIV或UDIV指令)时,会导致故障或停止。 0:不捕获除以零故障 1:捕获除以零故障。 当该位设为0时,除以零返回的商数为0。 | [3] | UNALIGN_TRP | 使能非对齐访问捕获: 0:不捕获非对齐半字和字访问 1:捕获非对齐半字和字访问。 如果该位设为1,非对齐访问产生一个使用故障。无论UNALIGN_TRP是否设为1,非对齐的LDM、STM、LDRD和STRD指令总是出错。 | [2] | - | 保留 | [1] | USERSETM PEND
| 使能对STIR的无特权软件访问。 0:禁能 1:使能 | [0] | NONEBASE THRDENA
| 指示处理器如何进入线程模式: 0:处理器仅在没有有效异常时才能够进入线程模式。 1:处理器可以从EXC_RETURN值控制下的任何级别进入线程模式 |
3.1.2 SCB->SHP 寄存器组 以下SCB->SHP 寄存器组的寄存器用来设置异常处理程序的优先级: SCB->SHP[0]:存储器管理Fault的优先级 SCB->SHP[1]:总线Fault的优先级 SCB->SHP[2]:用法Fault的优先级 为了编程中断和异常的优先级,CMSIS提供了函数NVIC_SetPrioriity和NVIC_GetPriority。这两个函数也位于core_cm3.h中,源码为:
/** \brief Set Interrupt Priority
This function sets the priority for the specified interrupt. The interrupt number can be positive
to specify an external (device specific) interrupt, or negative to specify an internal (core)
interrupt.
Note: The priority cannot be set for every core interrupt.
\param [in] IRQn Number of the interrupt for set priority
\param [in] priority Priority to set
*/
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
/* set Priority for Cortex-M System Interrupts */
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); }
else {
/* set Priority for device specific Interrupts */
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); }
}
/** \brief Get Interrupt Priority
This function reads the priority for the specified interrupt. The interrupt number can be positive
to specify an external (device specific) interrupt, or negative to specify an internal (core)
interrupt.
The returned priority value is automatically aligned to the implemented priority bits of the
microcontroller.
\param [in] IRQn Number of the interrupt for get priority
\return Interrupt Priority
*/
static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{
if(IRQn < 0) {
/* get priority for Cortex-M system interrupts */
return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); }
else {
/* get priority for device specific interrupts */
return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); }
}
可以通过下面的示例代码更改异常优先级:
:
:
NVIC_SetPriority (MemoryManagement_IRQn, 0xF0);
NVIC_SetPri ority (BusFault_IRQn, 0x80);
NVIC_SetPriority ( UsageFault_IRQn, 0x10);
:
UsageFault_prio = NVIC_GetPriority ( UsageFault_IRQn);
:
:
3.1.3 SCB->SHCSR寄存器 与Fault异常相关位见下表的蓝色部分 位 | 名称 | 描述 | [31:19] | - | 保留 | [18] | USGFAULTENA | 用法Fault使能位,设为1时使能 | [17] | BUSFAULTENA | 总线Fault使能位,设为1时使能 | [16] | MEMFAULTENA | 存储器管理Fault使能位,设为1使能 | [15] | SVCALLPENDED | SVC调用挂起位,如果异常挂起,该位读为1 | [14] | BUSFAULTPENDED | 总线Fault异常挂起位,如果异常挂起,该位读为1 | [13] | MEMFAULTPENDED | 存储器Fault故障异常挂起位,如果异常挂起,该位读为1 | [12] | USGFAULTPENDED | 用法Fault异常挂起位,如果异常挂起,该位读为1 | [11] | SYSTICKACT | SysTick 异常有效位,如果异常有效,该位读为1 | [10] | PENDSVACT | PendSV异常有效位,如果异常有效,该位读为1 | [9] | - | 保留 | [8] | MONITORACT | 调试监控有效位,如果调试监控有效,该位读为1 | [7] | SVCALLACT | SVC调用有效位,如果SVC调用有效,该位读为1 | [6:4] | - | 保留 | [3] | USGFAULTACT | 用法Fault异常有效位,如果异常有效,该位读为1 | [2] | - | 保留 | [1] | BUSFAULTACT | 总线Fault异常有效位,如果异常有效,该位读为1 | [0] | MEMFAULTACT | 存储器管理Fault异常有效位,如果异常有效,该位读为1 |
尽管可以写SCB->SHCSR寄存器的所有位,但建议软件只写异常使能位。下面的例子用于使能所有非硬Fault(存储器管理Fault、总线Fault、用法Fault异常): SCB - >SHCSR |= 0x00007000; /*enable Usage Fault, Bus Fault, and MMU Fault*/
注:要包含core_cm3.h头文件。
|