见鬼,过年回来后板子就 hardfault 了?

2023-12-26 14:59

本文主要是介绍见鬼,过年回来后板子就 hardfault 了?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

来源:公众号【鱼鹰谈单片机】

作者:鱼鹰Osprey

ID   :emOsprey

快一个月没有更新了,回家之前给自己安排了很多任务,然后回到家之后电脑就没有打开过,啥也没干,不知道有多少人回家后的状态和鱼鹰是一样的~~

回来之后,准备搞个脚本,自动读取芯片 ID、修改头文件 ID、自动编译、下载。

折腾了一晚上,读取 ID 是搞定了,但是发现有个板子读取 ID 后下载进去发现直接 hardfault 了,可自己年前的时候明明代码没动、板子没动,年前都是没问题的啊。

想不通,反正还有其他板子,直接换一块,下载进去,完全运行正常。因为太晚了,就暂时不管它。

第二天晚上,还是没想明白,本想不管的,想想反正没事情,不如深入研究一下,万一下次遇到这种问题,那不是很快就能定位了嘛。

第一步,打开错误窗口(怎么打开的,自己看往期系列文章吧):

85fafa4cdabb3554cc6f2f2ef250ad03.png

可以看出,总线错误,IMPRECISERR 、STKERR 置位(下面的是 BKPT 是人为给出, FORCED 是因为本来是总线错误,但因为没有开启该中断,直接上访成了 Hardfault,所以真正来说,这次异常应该由总线异常中断处理的)。

突然想起年前好像也发生类似的事情,因为当时程序能正常运行,换板子后不能运行,立马就想到了是芯片差异导致,改了代码就好了;而现在时间过去太久,把这事情忘记了,就闹了这一出(当时解决问题太快,也没深入研究,就没有多少印象了)。

其实这种事情很多工程师估计都遇到过,本来一个程序需要内存 RAM 40 K,在一块板子运行的好好的,换一块就不行,然后发现芯片实际只有 20K。

一般建工程选芯片型号的时候,就会规定好 ROM、RAM大小,只要能正常编译通过,问题都不大,但万一搞错了,就可能遇到鱼鹰的情况了。

a5d4c842863ac2e8ca131092f6f2b511.png

工程选择 STM32F103RET6,实际芯片 STM32F103RCT6,内存一个 64 K,一个 48K,偏偏我这个工程内存用量接近满了(如果 RAM 在 48  K 以内即使下载了也是没有问题的),程序也能正常下载,但运行之后立刻 Hardfault 伺候。

很多人遇到这个错误,束手无策,实际上掌握方法,并不是很难的事情。今天鱼鹰教大家一步步排查定位这个错误,大家遇到了其他错误,也可以按鱼鹰的思路解决。

首先,《权威指南》肯定要有,然后就是在线调试了。

从前面的错误信息可以了解到这是一个总线错误,但是我们看到地址这一栏,发现并不像有效地址(是否有效可以看 BFARVALID 是否置位),所以先不管它:

3130a54736572875f102d5edccce5199.png

就看那两个打钩的位置啥意思了。看看《Cortex-M3 权威指南》咋说的:

df29da03a8332a033fb8035bcd2c989b.png

了解这些就差不多了。

此时,我们就要通过在线调试的方式定位错误代码的位置了,毕竟上面的内容只是给我们一个排查方向,但具体怎么解决还看代码情况。

通过单步运行(代码量大的话,可以用二分法排查),并且追踪到汇编级别的代码发现,在即将运行下面代码时 LDR,[pc, #76],直接跳转到了 Hardfault:

PUSH {r4,lr}   // 执行完成
LDR,[pc, #76]  // 未执行

执行 PUSH {r4,lr}  前,未报错(黄色光标位置代表即将执行但未执行的代码):

865787a760d45099ab5b0818fe7e002e.png

执行后报错,但是还没有运行到 hard fault (单步调试,芯片可能还没反应过来 -_-):

58e91e5b168ef3700fae267cc060720b.png

当想单步执行 LDR,[pc, #76] 时,直接进入了 Hardfault 中断:

fc1be36c02b068d0972b91018d181a8e.png

这样问题就很明确了,PUSH {r4,lr}  执行有问题,这个和前面从权威指南中得到的信息是一致的。

那么为什么压栈操作会导致问题?

此时我们可以看左边的寄存器,压栈前 0x2000F338 ,压栈后 0x2000F330。

如果对这个数据不敏感,可能不知道这个值超出了 48 K (49152,0xC000)范围,没那么快定位。

没关系,我们可以继续看右边鱼鹰给出的内存窗口,压榨后 0x2000F330 和 0x2000F334 的值应该和 R4、LR 值一一对应,实际上并没有(先减 4,再赋值,图片打开后很清晰,认真分析)。

于是很容易可以得出压栈失败的结论,进而得出内存访问问题,从而发现芯片型号不对导致。

后面鱼鹰又查了英文版《Cortex M3与M4权威指南.pdf》,更详细了一些:

66aac2d78ff005e714bd26fa12faef30.png

IMPRECISERR   bit 解释了:访问无效内存空间。

49c870d6d9f39063cf14a02b655b9593.png

如此一来,hardfault 问题就顺利解决了 ^_^ ^_^

工作时间久了,这种问题很容易遇到,那么我们的代码是否能自动根据某个寄存器来识别芯片型号,从而确定大小,继而拒绝运行呢?

鱼鹰发现在用 MDK 更新  ST-LINK 固件的时候,它居然知道我芯片型号的准确容量大小(RAM 不行),从而拒绝下载,ST-LINK Utility 也是,就不知道它是通过读取哪个寄存器得到这些信息的了,有知道的道友不如留言分享一下。

362fae4df36510a3458aa35b0657ab06.png

另外上面提到的两本手册如果没有,可以公众号后台回复:“权威指南”  自行领取。也可以自己人为制造该错误,自行分析、研究、学习。

推荐阅读:

KEIL 调试经验总结

佛祖保佑,永无 BUG,永不修改 | KEIL 调试系列总结篇

更多关于调试的技术请参考鱼鹰历史文章和 MDK 官方文档。安富莱最近也出了一个视频教程,可以研究看看,鱼鹰看完了,感觉还不错,推荐大家看一看(B 站 1.5倍速看效果更好)。

这篇关于见鬼,过年回来后板子就 hardfault 了?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/539860

相关文章

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

在嵌入式板子上搭建和自定义live555服务器---编译问题和方法整理

live555 官方网站 点我直达,live555是一个简单的专注于实现RTSP服务器的开源库。它自带解析H264 H265 mp3等源的API,有一个简单的推流文件参考RTSP服务器例程testH264VideoStreamer也有官方实现的LIVE555 Media Server。无论是命令行使用还是用API实现定制需求是很方便的。 图龙宝刀点击下载 文章目录 live555

Infosys面试回来,我想和Java程序员谈一谈

http://toutiao.com/a6332993280045924610/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=5367969992&utm_medium=toutiao_ios

新换了电脑,电脑里常用的6款软件,下载回来继续用

新换了电脑,准备把之前电脑里常用的几款软件都下载回来继续用,独乐乐不如众乐乐,分享一下~ 1、Listen 1 一款开源、免费的音乐播放器,它能够整合多个主流音乐平台的资源,包括网易云音乐、QQ音乐、酷狗音乐、酷我音乐、Bilibili和咪咕音乐等,可以在一个应用中搜索和播放来自不同平台的音乐。 支持Windows、macOS、Linux,以及Chrome和Firefox浏览器插件版,还有安卓

TX2板子opencv安装

在TX2板子上安装opencv有两种方式,一种是你使用cmake直接在TX2上编译源码,第二种是使用你已编译好的opencv在TX2上进行配置,第二种方式需要注意你编译的版本也是在ARM平台编译的才能生效。 第一种方式可见我之前的博文《Linux下使用cmake编译opencv库》。本文主要介绍第二种方式,编译opencv比较耗时,有时候直接使用已编译好的版本进行配置省很多时间。 注:本文的配

人生应该要有梦想,万一见鬼了呢?!

时间终归是奇妙的,我们还在强调2015刚刚过去的时候,2016年第一个月已经消失不见。这些年里,一直在找寻,甚至于自己都不清楚自己在找寻什么。09年开始学会反思,明确的知道当下的生活不是我想要的,却茫然,毫无头绪;13年本科毕业,期间挣扎了不少东西,有两世人生的体验,也在为钱而奔波,多了点人生经历,却依旧茫然;15年自己拿到第一份技能,可以保住自己生存,也在应用思维导图的基础上,让很多东西有了一

为什么生成设备号过后,还要去板子mknod /dev/led c 11 0来生成设备文件呢?

在Linux系统中,生成设备号(通过MKDEV宏或类似方式)和创建设备文件(如使用mknod命令)是两个不同的步骤,它们各自承担着不同的职责。 为什么需要生成设备号? 设备号是内核用来唯一标识和管理设备的。每个设备都有一个主设备号和次设备号,其中主设备号标识了设备的类型(如硬盘、字符设备等),而次设备号则用于在同一类型的设备中区分不同的设备实例。生成设备号是在内核层面进行的,它确保了设备在内核

关于keil卡在systeminit中,然后出现void HardFault_Handler(void)的几个问题详解

版权声明:本文为博主原创文章,未经博主允许不得转载。    https://blog.csdn.net/u013184273/article/details/83860802 相信很多程序员在用keil的时候都会遇到在仿真调试时,一直停在SystemInit()中的等待晶振中,怎么也出不来。出现HardFault时,可能不是因为内存溢出,访问越界或是堆栈溢出,有可能仅仅只是自己一些最基本的规则没

给ESP32板子下载MicroPython固件(图形化界面)

新手上路,第一篇博客多多指教   1.准备板子 我的是乐鑫的 ESP32-DevKitC,刚出来时买的模组型号都没有后缀 2.下载工具 flash_download_tools https://wiki.ai-thinker.com/_media/tools/flash_download_tools_v3.6.6.zip 或者 https://www.espressif.com/sit

时隔多年,我胡汉三又回来了

最近一直在写论文愁毕业 但是方向还是要尽早定下来 在测试,前端,产品,交互里 我还是初步选择了前端 所以,我胡汉三又打开了这个blog 言简意赅,我是来列计划的 七月要发论文,大部分时间都花在论文上 之后要帮老师做项目 所以我初步对前端的计划是: 七月初步掌握JavaScript,途径imooc 一个星期看一个课,这个月可以看3-4个js的课 八月开始学习node.j