在shell中执行完一套基于AT指令封装的MQTT消息发布程序后,程序运行结果是正常的,但是会出现hard fault,请大家给点分析意见,谢谢!
[D/AT] send: 0000-0020: 41 54 2B 51 4D 54 53 55 42 3D 30 2C 30 2C 22 64 65 76 31 22 2C 30 AT+QMTSUB=0,0,"dev1",0
[D/AT] recvline: 0000-0020: 0D 0A ..
[D/AT] recvline: 0000-0020: 4F 4B 0D 0A OK..
[D/AT] recvline: 0000-0020: 0D 0A ..
[D/AT] recvline: 0000-0020: 2B 51 4D 54 53 55 42 3A 20 30 2C 30 2C 30 2C 30 0D 0A +QMTSUB: 0,0,0,0..
[D/AT] send: 0000-0020: 41 54 2B 51 4D 54 50 55 42 45 58 3D 30 2C 30 2C 30 2C 30 2C 22 74 65 73 74 22 2C 35 31 31 AT+QMTPUBEX=0,0,0,0,"test",511
[D/AT] recvline: 0000-0020: 0D 0A ..
[D/AT] recvline: 0000-0020: 3E >
[D/AT] send: 0000-0020: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0020-0040: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0040-0060: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0060-0080: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0080-00A0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 00A0-00C0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 00C0-00E0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 00E0-0100: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0100-0120: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0120-0140: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0140-0160: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0160-0180: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 0180-01A0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 01A0-01C0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 01C0-01E0: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11111111111111111111111111111111
[D/AT] send: 01E0-0200: 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 1111111111111111111111111111111
psr: 0x40000000
r00: 0x000001ff
r01: 0x200007cc
r02: 0x200007b8
r03: 0xffffffff
r04: 0x0000000b
r05: 0x200048ac
r06: 0x00006271
r07: 0x20006188
r08: 0x00000001
r09: 0x0000000b
r10: 0xdeadbeef
r11: 0xdeadbeef
r12: 0x0000d3e7
lr: 0x00000d87
pc: 0x00010000
hard fault on thread: tshell
thread pri status sp stack size max used left tick error
-------- --- ------- ---------- ---------- ------ ---------- ---
ec20_lin 30 suspend 0x00000094 0x00000400 33% 0x0000000c 000
eth 10 suspend 0x00000070 0x00000200 21% 0x00000001 000
wdt 10 suspend 0x00000070 0x00000200 21% 0x00000001 000
pin 10 suspend 0x00000070 0x00000100 43% 0x00000004 000
at_clnt 9 suspend 0x000000b8 0x00000600 20% 0x00000002 000
tshell 20 ready 0x00000180 0x00001800 09% 0x00000004 000
sys_work 23 suspend 0x0000005c 0x00000800 29% 0x00000002 000
phy 30 suspend 0x00000078 0x00000400 11% 0x00000002 000
tcpip 10 suspend 0x000000c8 0x00000800 17% 0x00000013 000
etx 12 suspend 0x00000094 0x00000400 14% 0x00000010 000
erx 12 suspend 0x00000094 0x00000400 14% 0x00000010 000
tidle 31 ready 0x00000040 0x00000100 34% 0x0000001d 000
timer 4 suspend 0x00000058 0x00000200 21% 0x00000009 000
usage fault:
SCB_CFSR_UFSR:0x02 INVSTATE
前些日也遇到这样的问题:
别人总结的进入hardfault的过程:
我的某次输出:
psr: 0x000b0000
r00: 0x00000001
r01: 0x00000000
r02: 0x00000010
r03: 0x00000001
r04: 0x00000000
r05: 0x00000000
r06: 0x00000000
r07: 0x00000000
r08: 0xdeadbeef
r09: 0xdeadbeef
r10: 0xdeadbeef
r11: 0xdeadbeef
r12: 0xffffffff
lr: 0x08003185
pc: 0x00000000
hard fault on thread: main
thread pri status sp stack size max used left tick error
-------- --- ------- ---------- ---------- ------ ---------- ---
at_clnt 9 suspend 0x00000100 0x00000800 14% 0x00000005 000
tshell 20 suspend 0x000000cc 0x00001000 05% 0x00000009 000
tidle0 31 ready 0x00000074 0x00000400 11% 0x0000001b 000
main 10 running 0x000003a8 0x00000800 75% 0x00000003 000
FPU active!
usage fault:
SCB_CFSR_UFSR:0x02 INVSTATE
上述寄存器信息中,lr寄存器中的值为0x08003185 ,此值为进入fault异常中断之前的lr的值。
我们知道lr为连接寄存器里面保存的是调用子程序之前的PC的值。 因为 内部 使用了指令流水线,读 PC 时返回的值是当前指令的地址+4 ,所以进入异常之前自动加载到lr的值也为调用子程序前的指令地址+4。由于PC的最低位保存ARM/Thumb 运行状态,Cortex-M3只能运行在Thumb 状态,即LSB = 1。所以我们想要找到出错误程序的指令位置, 只需要对打印出来的lr的值减去5即可。
0x08003185 减去5后为0x08003180 说明我们程序出错位置在PC = 0x08003180 附近。
在Disassembly窗口下,我们找到0x08003180 指令位置:(当时我用的gcc,所以用的gcc工具链的反汇编工具生成下面内容,如果你用keil,更简单)
再看打印结果:
还有代码位置:
结合前面0x08003180的反汇编,问题应该处在这个附近。
如果你用keil,打开反汇编的窗口,一切会更简单,思路相同。