0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教大家如何写出一个现场保存函数以及如何调用该函数

冬至子 来源:嵌入式BugMaker 作者:BugMaker 2023-08-10 11:33 次阅读

在进行CortexM系列MCU开发时,大家应该都或多或少触发过不可屏蔽中断,例如人见人爱的Hardfault。

对于嵌入式工程师来说,能够稳定复现的Bug最好解决,再不济挨个打断点也能定位到问题代码位置。

可是异常如果是不定时,无规律的发生在日常的运行中,那打断点的方式无异于守株待兔。

本篇将提供小技巧简述CortexM的异常压栈机制,教大家如何写出一个现场保存函数以及如何调用该函数。

如下图所示,触发中断的时候,CortexM​系列芯片会按照该排列将相关现场数据进行地址偏移压栈,N即此时的SP数值,通过SP中存放的地址,我们可以获取到如图所示的数据。

而要知道触发异常的地址则需要关注LR(Link Register)的数值,它存放着异常触发点的函数地址。

图片

那么按照压栈的排列,我们可以编写一个结构体以及相关的记录现场函数,如下图所示,结构体的成员完全是按照上图的压栈顺序排列,那下一步就是在哪里调用这个接口来获取到案发时的第一手资料

图片

​要想获得第一手数据,就要去中断函数的执行处,很多厂商SDK都会在名为XXX_it.c文件里为开发者们写好各个中断的Handler,由于S文件中都是弱定义(弱定义即在C文件中有同名的函数,则以C文件中的函数优先编译,则可能造成触发中断时并不会运行S文件处的函数)所以建议可以将其屏蔽或者自己重新编写一个新的函数名。

由下图可见,通过IMPORT的形式调用外部现场保存函数,将SP寄存器赋值给R0寄存器是因为R0通常时作为函数的第一个参数进行调用的,可看作是将SP数值作为参数传入StackSave函数,BL的意思是带返回的跳转,即使跳转运行完成StackSave函数后还返回此处。

图片

完成上述函数编写以及调用后,即可进行测试了。本次范例通过SPI初始化时传入错误的外设寄存器地址来触发HardFault中断,由下图可看出,此时记录到的LR数值为0x8000e83

图片

​查询后可知,0x8000e83的位置为SPI初始化函数中,符合预设的异常触发位置。在非仿真环境下可通过map文件找到大致的函数地址。

图片

综上,我们就知道了如何获取到触发异常中断时的程序运行地址,通过将获取到的信息存入到片上Flash指定地址的形式将此时的现场信息进行保存,并通过固件和map一一对应管控。

这样在漫长运行过程中,如果不慎触发异常异常中断,通过对应的map文件即可迅速定位BUG所在大致位置​

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5234

    浏览量

    119000
  • 仿真器
    +关注

    关注

    14

    文章

    1006

    浏览量

    83400
  • 串口中断
    +关注

    关注

    0

    文章

    64

    浏览量

    13777
  • Flash单片机
    +关注

    关注

    0

    文章

    111

    浏览量

    9334
  • MCU芯片
    +关注

    关注

    3

    文章

    241

    浏览量

    11219
收藏 人收藏

    评论

    相关推荐

    C函数调用机制与栈帧原理详解

    C函数调用时,函数的参数如何传递、堆栈指针如何变化、栈帧是如何被建立以及如何被消除的,
    发表于 06-08 10:49 910次阅读
    C<b class='flag-5'>函数</b><b class='flag-5'>调用</b>机制与栈帧原理详解

    文详解python调用函数

    函数被定义后,本身是不会自动执行的,只有在被调用后,函数才会被执行,得到相应的结果。但是在 Python 中我们要注意关键点,就是Pyt
    发表于 10-01 10:45 466次阅读

    如何查看及更改函数/函数块的调用环境

    模块化设计的思想是把些相似的功能(比如电机控制、阀控制)设计成函数函数块,这样就可以反复调用。其优点是:使程序架构更加清晰,避免重复编写相似功能的代码。不过可能会产生
    的头像 发表于 11-17 09:08 628次阅读
    如何查看及更改<b class='flag-5'>函数</b>/<b class='flag-5'>函数</b>块的<b class='flag-5'>调用</b>环境

    如何写出多串口共用printf函数语句呢

    如何写出多串口共用printf函数语句呢?求大神解答
    发表于 11-17 06:37

    C++教程之函数的递归调用

    C++教程之函数的递归调用 在执行函数 f 的过程中,又要调用 f 函数本身,称为函数的递归
    发表于 05-15 18:00 35次下载

    函数执行完毕后,如何返回调用处?

    函数执行完毕后,如何返回调用处呢?由于该函数可能会被多次调用,且每次调用的地方很可能不样,这
    的头像 发表于 09-14 14:27 1.6w次阅读
    当<b class='flag-5'>函数</b>执行完毕后,如何返回<b class='flag-5'>调用</b>处?

    带你了解嵌入式C语言函数调用

    大家都知道函数调用是通过栈来实现的,而且知道在栈中存放着该函数的局部变量。但是对于栈的实现细节可能不定清楚。
    发表于 07-12 17:08 2005次阅读
    带你了解嵌入式C语言<b class='flag-5'>函数</b><b class='flag-5'>调用</b>栈

    C语言函数的回调函数

    ,如果过后再执行,则称之为异步回调。 回调函数就是通过函数指针调用函数。如果你把
    的头像 发表于 09-11 09:57 4002次阅读

    传递函数是怎么定义的以及如何写出传递函数

    本来这期应该讲Buck的尖峰的,不过遇到些问题,所以就往后拖拖吧,这次来个简单点儿的。 来看看传递函数,也就是我们经常看到的H(s)。 传递函数是怎么定义的呢? 百科是这么定义的: 【传递
    的头像 发表于 06-30 11:23 7.6w次阅读
    传递<b class='flag-5'>函数</b>是怎么定义的<b class='flag-5'>以及</b><b class='flag-5'>如何写出</b>传递<b class='flag-5'>函数</b>?

    如何写要被C调用的汇编函数

    问:我该怎么写将被C调用的汇编函数? 答:最简单的学习怎么写汇编的方式是,先用C写这个代
    的头像 发表于 01-22 14:54 1029次阅读

    C语言函数调用的形式及过程

    C语言函数调用时的数据传递 在调用有参函数时,主调函数和被调函数之间有数据传递关系。
    的头像 发表于 03-10 14:28 1460次阅读

    什么是函数调用

    函数调用,就是使用我们已经定义好的函数,或者C语言自带的库函数
    的头像 发表于 04-04 17:21 5071次阅读

    python定义函数调用函数的顺序

    定义函数调用函数的顺序 函数被定义后,本身是不会自动执行的,只有在被调用后,函数才会被执行,得
    的头像 发表于 10-04 17:17 961次阅读

    python函数函数之间的调用

    ) 运行结果: 无结果 分析:因为第9行中的x(f)中的f没有带括号,f只是普通的参数,所以程序只调用执行了x(f)函数,没有调用执行f
    的头像 发表于 10-04 17:17 471次阅读

    OP-TEE的内核初始化函数调用

    init_primary_helper函数来完成系统运行环境的建立 ,如果系统支持ATF,则该函数会返回OP-TEE的处理句柄,该处理句柄主要包含 • 各种安全监控模式调用的处理函数
    的头像 发表于 11-02 18:18 525次阅读
    OP-TEE的内核初始化<b class='flag-5'>函数</b><b class='flag-5'>调用</b>