ARM架构与编程——异常与中断实战:未定义指令异常

未定义指令异常

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)   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值