• Cortex-M3如何跳出BusFault,跳过出错代码,程序往下执行


    为了方便演示如何实现该方法,采用构造触发BusFault,方便分析

    1. 首先需要对系统Handler控制及状态寄存器SHCSR.MEMFAULTENA使能
      在这里插入图片描述

    2. 往SRAM reserved写入数据,触发BusFault

    在这里插入图片描述

    如上图所示,可以看到触发BusFault前BFSR寄存器第7为高,表示BFAR寄存器有效,且BFAR与MMAR寄存器一致,都为0xE000EDF8

    在这里插入图片描述

    此时,需要注意SP指针为0x2000A208,并且存储内容为0x2000A20C,这有助于找到触发BusFault,压栈前的SP指针

    在这里插入图片描述

    进入中断前PC指针为0x77B4,这个有利于分析压栈地址正确与否

    在这里插入图片描述

    1. 进入中断,如下图所示:
      在这里插入图片描述

    可以看到BFSR寄存器为14,为不精确的数据访问违例(violation,本来应该时精确的数据访问违例,不知道为啥后来变成这样了),LR寄存器赋值解释如下

    在这里插入图片描述

    并且SP指针为0x2000A1E8(这个很重要)。根据入栈顺序以及入栈后堆栈中的内容表可反推出旧的SP位置为新的SP+32

    在这里插入图片描述
    在这里插入图片描述

    可以发现,通过新SP+32的方式找到的旧SP与原来的SP一致

    在这里插入图片描述

    此时,新的SP+24就可以得到压栈前PC指针

    在这里插入图片描述

    通过对比可以发现此时0x77B4就是进入BusFault前,PC指针

    在这里插入图片描述

    也就是说假如清除中断标志位后退出中断,或者说出栈后PC指针就是该值。但是BusFault清除中断后退出中断,PC指针指向为该地址,并不会自动+4。因此还是会再次进入BusFault。这里就解释了为什么MemMange Fault, Bus Fault, Usage Fault清除中断标记位后还是出不来的原因

    因此,只需要在该地址上,给0x77B4+4,这样清除中断标记位后,就能使程序不再进入BusFault。

    1. 但是当程序往下运行时,可以程序又执行了一次压栈,SP指针由0x2000A1E8变成0x2000A1E0,SP指针减了8,故在采用SP指针修改PC指针的时候,一定要注意压栈的次数,SP改变次数,反推进入Handler时候的SP指针 我这里一共改变了12

    在这里插入图片描述

    1. 对BFSR寄存器清空,也就是清除中断标记位 注:USFR BFSR MFSR合称 CFSR

    在这里插入图片描述

    在这里插入图片描述

    1. 获取当前SP值,并进入Handler时候的SP指针,其中 24表示压栈后PC偏移地址,+24表示找到压栈后的PC地址,4*6表示压栈前的PC指针(这里指针同地址),可以看到修改后的PC值为0x77B8。此时程序往下执行便不会再次触发BusFault,程序往下继续执行。

    在这里插入图片描述

    便不会再次触发BusFault,程序往下继续执行。
    在这里插入图片描述

    注意:采用修改PC值跳出BusFault,最好在进入BusFault后不在有程序跳转,防止PC值改变,另外程序也应该尽量简短,防止压栈出栈次数太多破坏各寄存器值。并且触发BusFault的整体函数也应该减少程序调用。总之,通过修改PC值,在代码中不是一种好的方法。

  • 相关阅读:
    用了那么久的Vue,你了解Vue的报错机制吗?
    国产域控TSN协议栈首发量产,理想汽车+映驰科技「抢先」
    java毕业设计滴答拍摄影项目(附源码、数据库)
    Java IO流(下)
    Topaz Video AI:一键提升视频品质,智能重塑影像魅力 mac/win版
    内网搭建在线文档服务
    【电气介数】电气介数及考虑HVDC和FACTS元件的电气介数计算
    排序算法简述
    面向对象-01我的世界
    docker-compose部署单节点rocketmq-server
  • 原文地址:https://blog.csdn.net/qq_37619128/article/details/132741991