在和STM32F103战斗了1个多星期之后,终于搞定error
122 AGDI: memory read failed问题。其中过程曲折,而结果却出人意料的简单。特别整理出来,希望对各位同仁有所帮助。
症状描述:
程序下载正常,但启动仿真模式运行后,程序就进入HardFault_Handler中断。复位后,进行单步跟踪,发现程序在执行完第二步BX R0后就进入HardFault_Handler中断。
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
系统配置:
ARM芯片: STM32F103C6
固件库版本: 3.0
操作系统: UCOS_II V2.8
仿真器: J-Link V8
开发环境: RealView 4.1
调试过程:
首先怀疑程序有问题,将它烧入开发板中调试,一切正常;而烧入自己的板子,就出现问题。所以排除程序问题。
怀疑芯片焊接问题,重新点焊加固后,调试,问题依旧。
怀疑芯片问题,拆掉原芯片,换上新的,问题依旧。
怀疑电路问题,于是将自己的板子和开发板电路一一比对,没有发现错误的地方。
调试陷入困境,洗洗睡吧。
一觉醒来,突然想起,应该查查晶振的信号。马上行动,开示波器,上电。一看晶振的两个管脚都没有信号。于是,拆晶振,拆电容,换上新的。上电调试,问题依旧。
上网查关于晶振不起振的问题,资料显示,STM32F103芯片要求晶振必须是5pF,匹配电容为10pF,云云。将信将疑。就把开发板上的晶振和电容拆下,换上;再调试,问题依旧。
调试再次陷入困境。
经过几次折腾之后,感觉单纯的从硬件入手查找问题,已进入了死胡同。可不可以根据软件线索来查问题呢?
最先想到的是利用RealView的Peripherals,查看Hard Fault寄存器。发现Imprecise和Stkerr两个标志位总是置位。Google了一下这两个标志位的信息,均不知所云。此路不通。
又怀疑可能是某种原因,芯片被加密导致仿真器不能运行。于是用Flash命令将芯片擦除后,再下载程序。仿真运行,问题依然存在。又擦除了一次,再下载程序,下载完后,RealView的信息框中蹦出error 122 AGDI: memory read failed (0xFFFFFFFE)。当然了,还是Google了该错误信息。也有不少朋友遇到了该问题,答案有两个:1. 芯片的BOOT0脚配置不当,没有正确接地;2. 无解。按答案1查找问题,用万用表将BOOT0与地导通测试,接地良好;上电后测量出BOOT0的电压为0。BOOT0配置正常,此路又不通。
但它提供了新的思路,就是通过RealView的输出信息,来查找问题。当下,就仔细的查看了所有的输出信息,发现了一条异常:“Core Locked-up!”。再将仿真器连到开发板,下载、仿真、运行,整个过程中没有Core Locked-up!输出信息。
没二话,再Google “Core Locked-up”,搜索出的解决办法是,用Unlock工具,Unlock后就可以了。只是我的RealView中没有网上所说的Unlock.exe工具。不过意外的发现了Segger文件夹中JLinkSTM32.exe就是Unlock工具。运行该工具之后,输出Unlock OK。再重新下载程序仿真,问题仍然存在,且仍然有Core
Locked-up!输出信息。尝试多次,依然如此。
继续Google “Core Locked-up”,其中有一贴子,楼主Tony大侠提供了一条信息:flash和ram的地址设置重复也会导致该问题。见http://www.cevx.com/bbs/thread-26004-1-1.html。查看自己工程中有关flash和ram配置,果然发现了诸多问题。打开project->option for target ‘XX’,在对话框的Target页中,修改正IROM1和IRAM1的地址,与103C6相符;点Utilities页中的Settings按钮,配置Flash算法,与103C6相符。
重新配置后,下载程序,发现确实没有Core Locked-up消息输出。点击运行后,再停止,却发现程序仍然在HardFault_Handler中。且消息框中又出现了该死的Core locked-up!到目前为止,基本可以肯定是flash或ram配置不对引起的,那么哪里还可能影响flash和ram配置呢?是不是scat文件?调出scat文件,如下:
LR_IROM1 0x08000000 0x00020000
{
ER_IROM1 0x08000000 0x08020000
{
*.o
(RESET, +First)
*(InRoot$$Sections)
.ANY
(+RO)
}
RW_IRAM1 0x20000000 0x00004C00
{
* (+RW,+ZI)
}
ARM_LIB_HEAP 0x20004700
EMPTY 0x00000200 {}
ARM_LIB_STACK 0x20004B00 EMPTY -0x00000200 {}
}
终于找出问题了,最该死的就是这一句:
ARM_LIB_STACK
0x20004B00 EMPTY -0x00000200 {}
把堆栈放在0x20004B00地址上,而STM32F103C6数据存储器最大仅为0x20002800。程序运行时,堆栈指针指向了错误地址,就出现HardFault错误。而且错误正好为ImpreciseData和stkerr。赶紧修改scat文件如下:
LR_IROM1 0x08000000 0x00004000 {
ER_IROM1 0x08000000 0x00004000 {
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00002800 {
.ANY (+RW +ZI)
}
ARM_LIB_HEAP 0x20002000
EMPTY 0x00000200 {}
ARM_LIB_STACK 0x20002400 EMPTY -0x00000200 {}
}
重新编译后,下载运行,一切正常。问题解决。
后记
至于为什么会想起scat文件,主要是因为曾经和scat文件也战斗过一次。自已建的Realview工程,插入官网下载的基于Stm32F103的UCOS-II操作系统代码,编译时老不通过,原因是ARM_LIB_HEAP没有定义。在scat文件中写了ARM_LIB_HEAP定义后,再编还是不通过,再打开scat文件,发现ARM_LIB_HEAP定义没了。
多次查找后,才发现Realview默认自动生成scat文件。所以即使修改了scat文件,也会被自动生成的覆盖。如要改成手动配置scat文件,需要将Option对话框中Link页上的Used Memory Layout From Target
Dialog选项去掉即可,如图。
用户377235 2015-7-3 15:09
用户377235 2015-1-22 14:32