ARM异常处理 M33

news2024/12/24 5:31:35

1. ARMv8-M异常类型及其详细解释

ARMv8-M Exception分为两类:预定义系统异常(015)和外部中断(1616+N)。
在这里插入图片描述
各种异常的状态可以通过Status bit查看,获取更信息的异常原因:
在这里插入图片描述

CFSR是由UFSR、BFSR和MMFSR组成:在这里插入图片描述

下面列举HFSR、MMFSR、BFSR、UFSR的详细解释。
1.1 HFSR
在这里插入图片描述
DEBUGEVT, bit [31] Debug event. Indicates when a debug event has occurred.
The possible values of this bit are:
0 No debug event has occurred.
1 Debug event has occurred. The Debug Fault Status Register has been updated.

FORCED, bit [30] Forced. Indicates that a fault with configurable priority has been escalated to a HardFault exception, because
it could not be made active, because of priority, or because it was disabled.
The possible values of this bit are:
0 No priority escalation has occurred.
1 Processor has escalated a configurable-priority exception to HardFault.

VECTTBL, bit [1] Vector table. Indicates when a fault has occurred because of a vector table read error on exception processing.
The possible values of this bit are:
0 No vector table read fault has occurred.
1 Vector table read fault has occurred.

1.2 MMFSR
在这里插入图片描述
MMARVALID, bit [7] MMFAR valid flag. Indicates validity of the MMFAR register.
The possible values of this bit are:
0 MMFAR content not valid.
1 MMFAR content valid.

MLSPERR, bit [5] MemManage lazy state preservation error flag. Records whether a MemManage fault occurred during FP lazy state preservation.
The possible values of this bit are:
0 No MemManage occurred.
1 MemManage occurred.

MSTKERR, bit [4] MemManage stacking error flag. Records whether a derived MemManage fault occurred during exception entry stacking.
The possible values of this bit are:
0 No derived MemManage occurred.
1 Derived MemManage occurred during exception entry.

MUNSTKERR, bit [3] MemManage unstacking error flag. Records whether a derived MemManage fault occurred during exception return unstacking.
The possible values of this bit are:
0 No derived MemManage fault occurred.
1 Derived MemManage fault occurred during excep

DACCVIOL, bit [1] Data access violation flag. Records whether a data access violation has occurred.
The possible values of this bit are:
0 No MemManage fault on data access has occurred.
1 MemManage fault on data access has occurred.

IACCVIOL, bit [0] Instruction access violation. Records whether an instruction related memory access violation has occurred.
The possible values of this bit are:
0 No MemManage fault on instruction access has occurred.
1 MemManage fault on instruction access has occurred.

1.3 BFSR

在这里插入图片描述
BFARVALID, bit [7] BFAR valid. Indicates validity of the contents of the BFAR register.
The possible values of this bit are:
0 BFAR content not valid.
1 BFAR content valid.

LSPERR, bit [5] Lazy state preservation error. Records whether a precise BusFault occurred during FP lazy state preservation.
The possible values of this bit are:
0 No BusFault occurred.
1 BusFault occurred.

STKERR, bit [4] Stack error. Records whether a precise derived BusFault occurred during exception entry stacking.
The possible values of this bit are:
0 No derived BusFault occurred.
1 Derived BusFault occurred during exception entry.

UNSTKERR, bit [3] Unstack error. Records whether a precise derived BusFault occurred during exception return unstacking.
The possible values of this bit are:
0 No derived BusFault occurred.
1 Derived BusFault occurred during exception return.

IMPRECISERR, bit [2] Imprecise error. Records whether an imprecise data access error has occurred.

The possible values of this bit are:
0 No imprecise data access error has occurred.
1 Imprecise data access error has occurred.

PRECISERR, bit [1] Precise error. Records whether a precise data access error has occurred.
The possible values of this bit are:
0 No precise data access error has occurred.
1 Precise data access error has occurred.

IBUSERR, bit [0]
Instruction bus error. Records whether a precise BusFault on an instruction prefetch has occurred.
The possible values of this bit are:
0
No BusFault on instruction prefetch has occurred.
1
A BusFault on an instruction prefetch has occurred.

1.4 UFSR
在这里插入图片描述

DIVBYZERO, bit [9] Divide by zero flag. Sticky flag indicating whether an integer division by zero error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.

UNALIGNED, bit [8] Unaligned access flag. Sticky flag indicating whether an unaligned access error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.

STKOF, bit [4] Stack overflow flag. Sticky flag indicating whether a stack overflow error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.
NOCP, bit [3] No coprocessor flag. Sticky flag indicating whether a coprocessor disabled or not present error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.
INVPC, bit [2] Invalid PC flag. Sticky flag indicating whether an integrity check error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.

INVSTATE, bit [1] Invalid state flag. Sticky flag indicating whether an EPSR.T, EPSR.IT, or FPSCR.LTPSIZE validity error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.

UNDEFINSTR, bit [0] UNDEFINED instruction flag. Sticky flag indicating whether an UNDEFINED instruction error has occurred.
The possible values of this bit are:
0 Error has not occurred.
1 Error has occurred.

2 ARMv8-M ARM中关于异常入口处理和压栈

在ARMv8-M ARM中介绍了异常发生时,硬件所做的一系列操作:
在这里插入图片描述在这里插入图片描述

从中可以看出对R0-R3、R12、LR、XPSR、ReturnAddress进行了压栈操作,最后PC指向异常处理函数。

当异常发生时,压栈的内容和顺序是固定的:XPSR->ReturnAddress->LR->R12->R3->R2->R1->R0。
在这里插入图片描述
这里的LR指的是异常的PC值,是真正的死亡前现场。ReturnAddress是处理器决定的异常后返回地址。

EXC_RETURN
EXC_RETURN代表异常入口时LR的值。
ARMv8-M规格书中关于EXC_RETURN定义如下:
在这里插入图片描述

PREFIX, bits [31:24] Prefix. Indicates that this is an EXC_RETURN value.This field reads as 0b11111111.

S, bit [6] Secure or Non-secure stack.

DCRS, bit [5] Default callee register stacking.

FType, bit [4] Stack frame type. 0 Extended stack frame. 1 Standard stack frame.

Mode, bit [3] Mode. Indicates the Mode that was stacked from. 0 Handler mode. 1 Thread mode.

SPSEL, bit [2] Stack pointer selection. 0 Main stack pointer. 1 Process stack pointer.

ES, bit [0] Exception Secure. 0 Non-secure. 1 Secure.

RETPSR
当异常进入的时候,会将RETPSR的值压栈。
在这里插入图片描述
N, bit [31] Negative condition flag. 0 Result is positive or zero. 1 Result is negative.

Z, bit [30] Zero condition flag.0 Result is nonzero. 1 Result is zero.

C, bit [29] Carry condition flag. 0 No carry occurred, or last bit shifted was clear. 1 Carry occurred, or last bit shifted was set.

V, bit [28] Overflow condition flag. 0 Signed overflow did not occur. 1 Signed overflow occurred.

Q, bit [27] Sticky saturation flag. 0 Saturation or overflow has not occurred since bit was last cleared. 1 Saturation or overflow has occurred since bit was last cleared.

T, bit [24] T32 state. 0 Execution of any instruction generates an INVSTATE UsageFault. 1 Instructions decoded as T32 instructions.

SFPA, bit [20] Secure Floating-point active.

GE, bits [19:16] Greater than or equal flags.

SPREALIGN, bit [9]
0 The stack pointer was 8-byte aligned before exception entry began, no special handling is required on exception return.
1 The stack pointer was only 4-byte aligned before exception entry. The exception entry realigned SP to 8-byte alignment by increasing the stack frame size by 4-bytes.
Exception, bits [8:0] Exception number.

3 异常Handler以及分析

异常的入口是异常向量表,根据异常号调用对应的处理函数:

__isr_vector:
    .long    __StackTop            /* Top of Stack */
    .long    Reset_Handler         /* 1. Reset Handler */
    .long    NMI_Handler           /* 2. NMI Handler */
    .long    HardFault_Handler     /* 3. Hard Fault Handler */
    .long    MemManage_Handler     /* 4. MPU Fault Handler */
    .long    BusFault_Handler      /* 5. Bus Fault Handler */
    .long    UsageFault_Handler    /* 6. Usage Fault Handler */
    .long    0                     /* 7. Reserved */
    .long    0                     /* 8. Reserved */
    .long    0                     /* 9. Reserved */
    .long    0                     /* 10. Reserved */
    .long    SVC_Handler           /* 11. SVCall Handler */
    .long    DebugMon_Handler      /* 12. Debug Monitor Handler */
    .long    0                     /* 13. Reserved */
    .long    PendSV_Handler        /* 14. PendSV Handler */
    .long    SysTick_Handler       /* 15. SysTick Handler */

    /* External interrupts */
    /* The interrupts 0 to 31 */
    .long    Default_IRQHandler /*16. External Interrupt 0*/
    .long    Default_IRQHandler

在进入Handler的时候,异常栈顶为包括R0~R3、R12、LR、ReturnAddress、RETPSR寄存器的内容。

下面的寄存器通过判断EXC_RETURN[2]来决定使用msp还是psp:

asm volatile(
    " tst lr, #4                        \n"--测试EXC_RETURN[2]是否为1,即测试当前StackPointer是MSP(0)还是PSP(1)" ite eq                            \n"--当EXC_RETURN[2]0,则z=1;当EXC_RETURN[2]1,则z=1" mrseq r0, msp                     \n"--当EXC_RETURN[2]0,将msp放入r0。
    " mrsne r0, psp                     \n"--当EXC_RETURN[2]1,将psp放入r0。
    "b common_handler_c             \n"--
    : /* no output */
    : /* no input */
    : "r0" /* clobber */
);

其中B和BL区别:

B Label ;程序无条件跳转到标号 Label 处执行。

BL Label ;当程序无条件跳转到标号 Label 处执行时,同时将当前的 PC 值保存到 R14 中。L ;用来区分 分支是否是有带返回的分支指令。

下面以HardFault为例,介绍代码和分析流程。

void HardFault_Handler(void)
{
    asm volatile(
            " tst lr, #4                        \n"
            " ite eq                            \n"
            " mrseq r0, msp                     \n"
            " mrsne r0, psp                     \n"
            "b hardfault_handler_c             \n"
            : /* no output */
            : /* no input */
            : "r0" /* clobber */
    );
}

void hardfault_handler_c(sContextStateFrame* regs)--传入的参数为msp的值。
{
    unsigned int hfsr = SCB->HFSR;

    star_stack_dump(regs);

    MSG("Cause of Hard Fault:\n");

    if(hfsr & SCB_HFSR_DEBUGEVT_Msk) {
        MSG("Debug event has occurred, ");

        unsigned dfsr = SCB->DFSR;
        if(dfsr & SCB_DFSR_PMU_Msk)
            MSG("PMU event.\n");
        if(dfsr & SCB_DFSR_EXTERNAL_Msk)
            MSG("External event.\n");
        if(dfsr & SCB_DFSR_VCATCH_Msk)
            MSG("Vector Catch event.\n");
        if(dfsr & SCB_DFSR_DWTTRAP_Msk)
            MSG("Watchpoint event.\n");
        if(dfsr & SCB_DFSR_BKPT_Msk)
            MSG("Breakpoint event.\n");
        if(dfsr & SCB_DFSR_HALTED_Msk)
            MSG("Halt or step event.\n");
    }

    if(hfsr & SCB_HFSR_FORCED_Msk) {
        MSG("Processor has escalated a configurable-priority exception to HardFault.\n");
        aon_system_reset();
    }

    if(hfsr & SCB_HFSR_VECTTBL_Msk) {
        MSG("Vector table read fault has occurred.\n");
        aon_system_reset();
    }
}

void star_stack_dump(sContextStateFrame* regs)
{
    unsigned int *stackPtr = NULL;

    MSG("ExceptionStack(%08x):\n", regs);--输出异常入栈信息:R0~R3、R12、LR、ReturnAddress、XPSR。
    MSG("R0 = %08x\n", regs->r0);
    MSG("R1 = %08x\n", regs->r1);
    MSG("R2 = %08x\n", regs->r2);
    MSG("R3 = %08x\n", regs->r3);
    MSG("R12 = %08x\n", regs->r12);
    MSG("LR = %08x\n", regs->lr);
    MSG("ReturnAddr = %08x\n", regs->return_address);
    MSG("PSR = %08x: N(%u) Z(%u) C(%u) V(%u) Q(%u) IT(%u) T(%u) SFPA(%u) GE(%u) SPRealign(%u) ISR(%u) \n", regs->xpsr.w,
        regs->xpsr.b.N,
        regs->xpsr.b.Z,
        regs->xpsr.b.C,
        regs->xpsr.b.V,
        regs->xpsr.b.Q,
        regs->xpsr.b.IT,
        regs->xpsr.b.T,
        regs->xpsr.b.SFPA,
        regs->xpsr.b.GE,
        regs->xpsr.b.SPREALIGN,
        regs->xpsr.b.ISR
        );--RETPSR的几种情况暂未分别分析。

    MSG("\nStack from 0x%08x in [StackTop(0x%08x), MSPLIM(0x%08x)]:\n", regs, &__StackTop,  __get_MSPLIM());
    for(stackPtr = (unsigned int *)regs; stackPtr < &__StackTop; stackPtr++ ) {--遍历输出栈内容,方便后续分析。
        MSG("0x%08x %08x\n", stackPtr, *stackPtr);
    }
}

触发产生异常:

void fault_test_by_trigger(void) {
    MSG("%s\n", __func__);
    SCB->SHCSR |= SCB_SHCSR_HARDFAULTPENDED_Msk;
//    SCB->SHCSR |= SCB_SHCSR_BUSFAULTPENDED_Msk;
//    SCB->SHCSR |= SCB_SHCSR_MEMFAULTPENDED_Msk;
//    SCB->SHCSR |= SCB_SHCSR_USGFAULTPENDED_Msk;
}

结果如下:

fault_test_by_trigger
ExceptionStack(2003FFA8):
R0 = 00000007
R1 = 0000000A
R2 = E000ED00
R3 = 00270000
R12 = 00000000
LR = 000002E7
ReturnAddr = 000002F2
PSR = 69000000: N(0) Z(1) C(1) V(0) Q(1) IT(0) T(1) SFPA(0) GE(0) SPRealign(0) ISR(0) 

Stack from 0x2003FFA8 in [StackTop(0x2003FFF0), MSPLIM(0x2003F3F0)]:
0x2003FFA8 00000007
0x2003FFAC 0000000A
0x2003FFB0 E000ED00
0x2003FFB4 00270000
0x2003FFB8 00000000
0x2003FFBC 000002E7
0x2003FFC0 000002F2
0x2003FFC4 69000000--到此都为异常入栈内容。
0x2003FFC8 0000E4E0
0x2003FFCC 0000E4E0
0x2003FFD0 0000E4E0
0x2003FFD4 0000C0CC
0x2003FFD8 00000000
0x2003FFDC 00000000
0x2003FFE0 00000000
0x2003FFE4 00000000
0x2003FFE8 00000000
0x2003FFEC 0000B6C1
Cause of Hard Fault:

从上述log可知三个地址0x000002E7、0x000002F2、0x0000B6C1。

使用addrline工具分析对应符号表,

arm-linux-gnueabihf-addr2line -e main.elf -a -f 0x000002E7 0x000002F2 0x0000B6C1

结果如下:

0x000002e7
fault_test_by_trigger--异常栈中的LR,对应异常现场PC值。是导致问题产生的原因。
xxx.c:34
0x000002f2
main--这是异常退出后处理器PC指向的地方,即退出异常后将要执行的代码。
xxx.c:66
0x0000b6c1
Reset_Handler--栈回溯部分。
xxx.S:284

基本可以得到函数调用关系。

引用链接:https://www.cnblogs.com/arnoldlu/p/16199437.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2264548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉

遇到问题&#xff1a; 从今年开始&#xff0c;不知道咋回事&#xff0c;电脑上的Unity2017像是变了个人似得&#xff0c;突然特别爱闪退掉&#xff0c;有时候还次次闪退&#xff0c;真是让人无语&#xff0c;一直以来我都怀疑是不是电脑上安装了什么别的软件了&#xff0c;导致…

SpringBoot核心:自动配置

有使用过SSM框架的&#xff0c;还记得曾经在spring-mybatis.xml配置了多少内容吗&#xff1f;数据源、连接池、会话工厂、事务管理&#xff0c;而现在Spring Boot告诉你这些都不需要了&#xff0c;简单的几个注解统统搞定&#xff0c;是不是很方便&#xff01; 前言 SpringBoo…

重温设计模式--享元模式

文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;概述享元模式的结构C 代码示例1应用场景C示例代码2 享元模式&#xff08;Flyweight Pattern&#xff09;概述 定义&#xff1a; 运用共享技术有效地支持大量细粒度的对象。 享元模式是一种结构型设计模式&#xff0…

Taro小程序开发性能优化实践

我们团队在利用Taro进行秒送频道小程序的同时&#xff0c;一直在探索性能优化的最佳实践。随着需求的不断迭代&#xff0c;项目中的性能问题难免日积月累&#xff0c;逐渐暴露出来影响用户体验。适逢双十一大促&#xff0c;我们趁着这个机会统一进行了Taro性能优化实践&#xf…

纯血鸿蒙APP实战开发——textOverflow长文本省略

介绍 本示例实现了回复评论时&#xff0c;当回复人的昵称与被回复人的昵称长度都过长时&#xff0c;使用textOverflow和maxLines()实现昵称的长文本省略展示的功能。 效果图预览 使用说明 点击评论中的"回复"&#xff0c;在输入框中输入回复内容&#xff0c;点击发…

【java面向对象编程】第九弹----抽象类、接口、内部类

笔上得来终觉浅,绝知此事要躬行 &#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;javase &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 一、抽象类 1.1基本介绍 &…

Qt笔记:网络编程UDP

一、铺垫 1.Qt框架使用的网络结构的基础就是Linux学习的网络编程基础&#xff1b;所以使用Qt写客户端&#xff0c;使用Linux写服务端&#xff1b;两者是可以实现互联的 二、UDP 网络编程UDP使用套路&#xff1a; 1.首先在.pro文件中加上network&#xff0c;使Qt可以搭载网络…

Redis存在安全漏洞

Redis是美国Redis公司的一套开源的使用ANSI C编写、支持网络、可基于内存亦可持久化的日志型、键值&#xff08;Key-Value&#xff09;存储数据库&#xff0c;并提供多种语言的API。 Redis存在安全漏洞。攻击者利用该漏洞使用特制的Lua脚本触发堆栈缓冲区溢出漏洞&#xff0c;从…

【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题

目录 背包问题简介 问题描述 输入&#xff1a; 输出&#xff1a; 动态规划解法 动态规划状态转移 代码实现 代码解释 动态规划的时间复杂度 例子解析 输出&#xff1a; 总结 作者我蓝桥杯&#xff1a;2023第十四届蓝桥杯国赛C/C大学B组一等奖&#xff0c;所以请听我…

ReactPress 1.6.0:重塑博客体验,引领内容创新

ReactPress 是一个基于Next.js的博客&CMS系统&#xff0c; Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 体验地址&#xff1a;http://blog.gaoredu.com/ 今天&#xff0c;我们自豪地宣布ReactPress 1.6.0版本的正式发布&#xff0c;…

单元测试-Unittest框架实践

文章目录 1.Unittest简介1.1 自动化测试用例编写步骤1.2 相关概念1.3 用例编写规则1.4 断言方法 2.示例2.1 业务代码2.2 编写测试用例2.3 生成报告2.3.1 方法12.3.2 方法2 1.Unittest简介 Unittest是Python自带的单元测试框架&#xff0c;适用于&#xff1a;单元测试、Web自动…

带有 Elasticsearch 和 Langchain 的 Agentic RAG

作者&#xff1a;来自 Elastic Han Xiang Choong 讨论并实现 Elastic RAG 的代理流程&#xff0c;其中 LLM 选择调用 Elastic KB。 更多阅读&#xff1a;Elasticsearch&#xff1a;基于 Langchain 的 Elasticsearch Agent 对文档的搜索。 简介 代理是将 LLM 应用于实际用例的…

[react 3种方法] 获取ant组件ref用ts如何定义?

获取ant的轮播图组件, 我用ts如何定义? Strongly Type useRef with ElementRef | Total TypeScript import React, { ElementRef } from react; const lunboRef useRef<ElementRef<typeof Carousel>>(null); <Carousel autoplay ref{lunboRef}> 这样就…

stm32制作CAN适配器5--WinUsb上位机编写

上次我们要stm32制作了一个基于winusb有canfd适配器&#xff0c;今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的&#xff0c;只是更改下dll文件。 项目链接器&#xff0c;输入&#xff0c;附加依赖项中增加winusb.lib winusb初始化&#xff1a;#incl…

C/C++圣诞树

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C…

图解HTTP-HTTP报文

参考资料&#xff1a;图解HTTP HTTP报文 用于HTTP协议交互的信息被称为HTTP报文。请求端的HTTP请求报文&#xff0c;响应端&#xff08;服务器端&#xff09;的叫做响应报文。HTTP报文本身是由多行&#xff08;CR LF作为换行符&#xff09;数据行构成的文本。 请求报文及响…

机器学习基础算法 (一)-线性回归

python 环境的配置参考 从零开始&#xff1a;Python 环境搭建与工具配置 线性回归的 Python 实现 线性回归是一种经典的机器学习算法&#xff0c;用于预测连续的目标变量。它假设目标变量和特征之间存在线性关系。本文将详细介绍线性回归的原理、Python 实现、模型评估和调优&…

Java字符串的|分隔符转List实现方案

字符串处理 问题背景代码实现代码优化原因分析实现方案 注意事项异常处理Maven未识别异常 问题背景 在项目组对账流程中&#xff0c;接收对方系统的对账文件&#xff0c;数据以|为分隔符&#xff0c;读取文件内容&#xff0c;分条入库。 代码实现 Java中将字符串转给list&am…

【HarmonyOs学习日志(14)】计算机网络之域名系统DNS

域名系统DNS 域名系统DNS——从域名解析出IP地址 文章目录 域名系统DNS概述域名到IP地址的解析 互联网的域名结构命名标准 域名服务器域名的解析过程 概述 域名系统DNS&#xff08;Domain Name System&#xff09;是互联网使用的命名系统&#xff0c;用来把便于人们使用的机器…

LabVIEW与PLC点位控制及OPC通讯

在工业自动化中&#xff0c;PLC通过标准协议&#xff08;如Modbus、Ethernet/IP等&#xff09;与OPC Server进行数据交换&#xff0c;LabVIEW作为上位机通过OPC客户端读取PLC的数据并进行监控、控制与处理。通过这种方式&#xff0c;LabVIEW能够实现与PLC的实时通信&#xff0c…