未定义指令异常
1.1 M3_M4支持哪些异常
从向量表可以看出,M3/M4支持哪些异常:
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
前面几个对应各类错误:
- Hard Fault
- MPU Fault
- Bus Fault
- Usage Fault
这几类错误产生的原因入下图所示,参考:ARM Cortex-M3与Cortex-M4权威指南.pdf
:
以未定义指令为例,它属于"处理器操作相关的错误",如果没有使能"Usage Fault",就会触发"Hard Fault"。
1.2 什么是未定义指令?
未定义指令,即使"还没有定义的指令",也就是CPU不认识的指令。
很多时候,我们故意在代码里插入一些伪造的指令,故意让CPU执行到它时触发错误。
这在调试时很有用,比如想打断点:怎么实现呢?
有很多种方法:硬件监视点(watch point,数量有限)、软件断点(数量无限)。
软件断点就是使用未定义指令
来实现的,比如想让程序执行到某个地址A时停下来,可以这样做:
- 地址A上原来的指令是
xxx
- 我们故意把它改成
yyy
,改成一条CPU无法识别的指令 - 当CPU执行到地址A上的
yyy
指令时,触发异常 - 在异常处理函数里,打印更多调试信息
- 调试完毕后,恢复地址A上的指令为
xxx
- 从地址A重新执行程序
1.3 在汇编代码里插入未定义指令
在代码中插入:
DCD 0xffffffff
看看会发生什么事情。
结果就是程序无法正常执行,执行到DCD 0xffffffff
位置时,就会发生错误,产生一个异常,然后就会中断向量表中,去执行某个异常函数
未定义指令属于处理器相关的错误,当发生错误时,如果Usage Fault
没有使能的话,这个未定义指令异常就会导致硬件错误Hard Fault
。
在上述代码产生错误时,我们还未使能Usage Fault
,于是当cpu执行到这条指令时,就会产生错误,这个错误就会被认为是Hard Fault
,硬件错误。此时就会执行Hard Fault Handler处的函数。
我们可以在此处添加函数,并用C来实现这个函数,以此得到我们想要的打印信息
1.3.1 先不使能"Usage Fault"
会产生异常,被认为是硬件错误异常
; Vector Table Mapped to Address 0 at Reset
IMPORT HardFault_Handler
__Vectors
DCD HardFault_Handler ; Hard Fault Handler
//实现 HardFault_Handler 函数
//exception.c
#include "string.h"
void HardFault_Handler(void)
{
puts("HardFault_Handler\n\r");
while (1);
}
执行程序,输出结果如下:
1.3.2 使能"Usage Fault"
1.定义一个SCB结构体,通过结构体来使能 Usage Fault
//exception.h
typedef struct
{
volatile unsigned int CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
volatile unsigned int ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
volatile unsigned int VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
volatile unsigned int AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
volatile unsigned int SCR; /*!< Offset: 0x010 (R/W) System Control Register */
volatile unsigned int CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
volatile unsigned char SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
volatile unsigned int SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
volatile unsigned int CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
volatile unsigned int HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
volatile unsigned int DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
volatile unsigned int MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
volatile unsigned int BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
volatile unsigned int AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
volatile unsigned int PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
volatile unsigned int DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
volatile unsigned int ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
volatile unsigned int MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
volatile unsigned int ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
unsigned int RESERVED0[5U];
volatile unsigned int CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
} SCB_Type;
/* SCB CPUID Register Definitions */
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
/* SCB Interrupt Control State Register Definitions */
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Vector Table Offset Register Definitions */
#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */
#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */
#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */
#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
#else
#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos)