ZigBee子设备新固件下载完成后,准备校验其合法性,代码运行至检验部分,MCU崩溃重启。
日志如下:
# RECV ASCII>
Processing message: len=33 profile=0104 cluster=0019
T00000000:RX len 33, ep 01, clus 0x0019 (Over the Air Bootloading) FC 19 seq 78 cmd 05 payload[00 02 10 00 FF 08 00 00 00 BE 5E 04 00 10 FF 01 FF 00 FC 04 04 FC 04 00 00 00 78 D9 9D FD ]
Download: 100% complete
ota current ota image (version 0x00000009)(image type 0xFF00).
Bootload state: Verifying Image
Last offset downloaded: 0x0004603E
No signature verification support, assuming image is okay.
St?
# RECV ASCII>
Reset info: 0x0A (FLT)
Extended Reset info: 0x0A04 (USG)
Thread mode using main stack (200010E0 to 20001A40), SP = 20001920
1824 bytes used (76%) in main stack (out of 2400 bytes total)
No interrupts active
Reset cause: Usage Fault
Instruction address: 00002B1A
CFSR.UNALIGNED: attempted an unaligned memory access
R0 = 20003BFB, R1 = 000000FF, R2 = 00000018, R3 = 00000000
R4 = 20003BFB, R5 = 20003D7F, R6 = 00000000, R7 = 20003D17
R8 = FFFFFFFF, R9 = FFFFFFFF, R10 = 1FFF1A40, R11 = 00000000
R12 = 200018A4, R13(LR) = FFFFFFF9, MSP = 20001920, PSP = 20001A40
PC = 00002B1A, xPSR = 29100000, MSP used = 00000720, PSP used = 00000000
CSTACK bottom = 200010E0, ICSR = 00400806, SHCSR = 00070008, INT_ACTIVE0 = 00000000
INT_ACTIVE1 = 00000000, CFSR = 01000000, HFSR = 00000000, DFSR = 00000000
MMAR/BFAR = E000ED34, AFSR = 00000000, Ret0 = 0002239F, Ret1 = 00014977
Ret2 = 00007B5B, Ret3 = 00015013, Ret4 = 0000FFF7, Ret5 = 0000EECF
Dat0 = A45646B1, Dat1 = B6229825
上述日志关键信息:
将代码 异常地址 转换到程序 源码 位置,使用工具 arm-none-eabi-addr2line
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 0x0002239F
0x0002239f
FRC_IRQHandler
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 0x00014977
0x00014977
COM_PrintfVarArg
D:/SiliconLabs/SimplicityStudio/v5/developer/sdks/gecko_sdk_suite/v3.2/platform/base/hal/plugin/serial/cortexm/efm32/com.c:1702
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 00007B5B
0x00007b5b
emberSerialPrintf
D:/SiliconLabs/SimplicityStudio/v5/developer/sdks/gecko_sdk_suite/v3.2/platform/base/hal/plugin/serial/ember-printf.c:417
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 00015013
0x00015013
emberAfPluginSlotManagerImageIsValidReset
D:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.2\app\build\RexZigBeeRadarSoc\GNU ARM v7.2.1 - Default/../slot-manager/slot-manager.c:319
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 0000FFF7
0x0000fff7
emberAfOtaClientCustomVerifyCallback
D:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.2\app\build\RexZigBeeRadarSoc\GNU ARM v7.2.1 - Default/../ota-client-policy/ota-client-policy.c:143
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 0000EECF
0x0000eecf
continueImageVerification
D:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.2\app\build\RexZigBeeRadarSoc\GNU ARM v7.2.1 - Default/../ota-client/ota-client.c:1787
通过上述返回地址 Ret0/Ret1/Ret2/Ret3/Ret4/Ret5 的嵌套联系,大致可以推断程序嵌套调用的关系:
continueImageVerification
emberAfOtaClientCustomVerifyCallback
emberAfPluginSlotManagerImageIsValidReset
emberSerialPrintf
COM_PrintfVarArg
FRC_IRQHandler
再继续定位PC指针出错位置:
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 00002B1A
0x00002b1a
??
??:0
上述结果并未给我有效信息,查看ZigBeeSoc
对应的map
文件,部分信息如下:
...
.bat.noinit 0x00000000 0x54
*(.bat.noinit)
.bat.noinit 0x00000000 0x54 ./efr32/cstartup-common.o
0x00000000 halBootloaderAddressTable
0x00000054 . = ALIGN (0x2)
[!provide] PROVIDE (__BAT_NOINIT__end, .)
.bat.init 0x00000000 0x0
*(.bat .bat.*)
0x00000000 . = ALIGN (0x2)
[!provide] PROVIDE (__BAT_INIT__end, .)
[!provide] PROVIDE (__BAT__begin, MFB_BOTTOM)
[!provide] PROVIDE (__BAT__size, MAX (SIZEOF (.bat.noinit), SIZEOF (.bat.init)))
[!provide] PROVIDE (__BAT__end, (MFB_BOTTOM + MAX (SIZEOF (.bat.noinit), SIZEOF (.bat.init))))
0x00004000 . = MAX ((MFB_BOTTOM + BTL_SIZE), .)
.aat 0x00004000 0xac
[!provide] PROVIDE (__AAT__begin, .)
*(.aat .aat.*)
.aat 0x00004000 0xac ./efr32/cstartup-common.o
0x00004000 halAppAddressTable
0x000040ac . = ALIGN (0x2)
[!provide] PROVIDE (__AAT__end, .)
[!provide] PROVIDE (__AAT__size, SIZEOF (.aat))
0x00004200 . = ALIGN (HEADER_SIZE)
.intvec 0x00004200 0x0
[!provide] PROVIDE (__INTVEC__begin, .)
*(.intvec .intvec.*)
0x00004200 . = ALIGN (0x2)
[!provide] PROVIDE (__INTVEC__end, .)
[!provide] PROVIDE (__INTVEC__size, SIZEOF (.intvec))
.vectors 0x00004200 0x134
[!provide] PROVIDE (__VECTORS__begin, .)
*(.vectors .vectors.*)
.vectors 0x00004200 0x134 D:/SiliconLabs/SimplicityStudio/v5/developer/sdks/gecko_sdk_suite/v3.2//protocol/zigbee/build/hal-library-cortexm3-gcc-efr32mg21-rail/hal-library.a(startup_efr32mg21.o)
0x00004200 __Vectors
0x00004334 . = ALIGN (0x2)
[!provide] PROVIDE (__VECTORS__end, .)
[!provide] PROVIDE (__VECTORS__size, SIZEOF (.vectors))
.text 0x00004334 0x3b264
*(.init)
.init 0x00004334 0x4 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/thumb/v8-m.main/fpv5-sp/hard/crti.o
0x00004334 _init
.init 0x00004338 0x8 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/thumb/v8-m.main/fpv5-sp/hard/crtn.o
*(.fini)
.fini 0x00004340 0x4 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/thumb/v8-m.main/fpv5-sp/hard/crti.o
0x00004340 _fini
.fini 0x00004344 0x8 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/thumb/v8-m.main/fpv5-sp/hard/crtn.o
0x0000434c PROVIDE (__TEXT__begin, .)
*(.text .text.*)
.text 0x0000434c 0x40 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/thumb/v8-m.main/fpv5-sp/hard/crtbegin.o
.text 0x0000438c 0x74 d:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/7.2_2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v8-m.main/fpv5-sp/hard/crt0.o
0x0000438c _mainCRTStartup
0x0000438c _start
.text.sleep_s 0x00004400 0x20 ./RexZigBeeRadarSoc_callbacks.o
0x00004400 sleep_s
.text.commissioningLedEventHandler
0x00004420 0x88 ./RexZigBeeRadarSoc_callbacks.o
0x00004420 commissioningLedEventHandler
.text.findingAndBindingEventHandler
....
ZigBeeSoc
代码段起始位置是0x00004334
,而PC指针出问题点位于0x00002B1A
处,因此我们需要去Bootloader
中定位PC指针出错点。
arm-none-eabi-addr2line.exe -e ZigBeeBootloader.axf -af 00002B1A
0x00002b1a
parser_init
:?
由上述结果可知,代码出错位置在parser_init
中。
备注:
打开ZigBeeBootloader.map
文件,同样可以手动定位到0x00002b1a
位于代码段parser_init
中,函数parser_init
被封装在libparser-noenc_efr32xg21_gcc.a
,因此无法查看到源码。
...
.text.parser_init
0x00002afe 0x82 D:/SiliconLabs/SimplicityStudio/v5/developer/sdks/gecko_sdk_suite/v3.2//platform/bootloader/build/lib/libparser-noenc_efr32xg21_gcc.a(btl_ebl_parser.o)
0x00002afe parser_init
.text.parser_parse
0x00002b80 0x7fc D:/SiliconLabs/SimplicityStudio/v5/developer/sdks/gecko_sdk_suite/v3.2//platform/bootloader/build/lib/libparser-noenc_efr32xg21_gcc.a(btl_ebl_parser.o)
0x00002b80 parser_parse
...
通过arm-none-eabi-objdump
工具可以查看axf文件的反汇编代码,操作如下:
arm-none-eabi-objdump.exe -d -j .text ZigBeeBootloader.axf
RexZigBeeRadarBootloader.axf: file format elf32-littlearm
Disassembly of section .text:
...
00002afe <parser_init>:
2afe: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr}
2b02: 2600 movs r6, #0
2b04: f04f 38ff mov.w r8, #4294967295
2b08: 4604 mov r4, r0
2b0a: 460f mov r7, r1
2b0c: 4615 mov r5, r2
2b0e: f003 0320 and.w r3, r3, #32
2b12: f880 3042 strb.w r3, [r0, #66] ; 0x42
2b16: 2218 movs r2, #24
2b18: 21ff movs r1, #255 ; 0xff
2b1a: e9c0 6618 strd r6, r6, [r0, #96] ; 0x60
2b1e: f8a0 6040 strh.w r6, [r0, #64] ; 0x40
2b22: f880 6043 strb.w r6, [r0, #67] ; 0x43
2b26: f8a0 6044 strh.w r6, [r0, #68] ; 0x44
2b2a: f880 6046 strb.w r6, [r0, #70] ; 0x46
2b2e: f8c0 8088 str.w r8, [r0, #136] ; 0x88
2b32: 3068 adds r0, #104 ; 0x68
2b34: f000 fc55 bl 33e2 <memset>
2b38: 2288 movs r2, #136 ; 0x88
2b3a: 4631 mov r1, r6
2b3c: e9c4 7512 strd r7, r5, [r4, #72] ; 0x48
2b40: f8c4 8080 str.w r8, [r4, #128] ; 0x80
2b44: f8c4 8084 str.w r8, [r4, #132] ; 0x84
2b48: f104 0090 add.w r0, r4, #144 ; 0x90
2b4c: f000 fc49 bl 33e2 <memset>
2b50: f884 6118 strb.w r6, [r4, #280] ; 0x118
2b54: f7ff f96a bl 1e2c <parser_requireConfidentiality>
2b58: b120 cbz r0, 2b64 <parser_init+0x66>
2b5a: b91f cbnz r7, 2b64 <parser_init+0x66>
2b5c: f241 000b movw r0, #4107 ; 0x100b
2b60: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc}
2b64: f7ff f960 bl 1e28 <parser_requireAuthenticity>
2b68: b130 cbz r0, 2b78 <parser_init+0x7a>
2b6a: 2d00 cmp r5, #0
2b6c: d0f6 beq.n 2b5c <parser_init+0x5e>
2b6e: 6ce0 ldr r0, [r4, #76] ; 0x4c
2b70: f7fd fc32 bl 3d8 <btl_initSha256>
2b74: 2000 movs r0, #0
2b76: e7f3 b.n 2b60 <parser_init+0x62>
2b78: 2d00 cmp r5, #0
2b7a: d1f8 bne.n 2b6e <parser_init+0x70>
2b7c: 4628 mov r0, r5
2b7e: e7ef b.n 2b60 <parser_init+0x62>
...
定位到0x00002b1a
刚好位于函数parser_init
内部。
uint8_t emberAfPluginSlotManagerImageIsValidReset(uint32_t slotId)
{
int32_t rv;
if (!initializeBootloader()) {
return SLOT_MANAGER_INVALID_CALL;
}
if (slotId >= gBootloaderNumSlots) {
slotManagerPrintln("Slot Manager: cannot verify to out-of-range slot %d "
"(max slot %d)", slotId, gBootloaderNumSlots - 1);
return SLOT_MANAGER_BAD_ARG;
}
pokeStackOrWatchDog();
rv = bootloader_initVerifyImage(slotId,
(void*)gVerificationContext,
SLOT_MANAGER_VERIFICATION_CONTEXT_SIZE);
return (BOOTLOADER_OK == rv) ? SLOT_MANAGER_SUCCESS : SLOT_MANAGER_ERROR;
}
由Ret3记录的返回位置可知,函数下一条执行的代码位于slot-manager.c:319
处,因此程序是在执行bootloader_initVerifyImage
时导致的异常。继续结合崩溃时的异常提示:
CFSR.UNALIGNED: attempted an unaligned memory access
大意是我们访问了未对齐的内存地址,函数bootloader_initVerifyImage
入参中,唯一用到的内存区域是gVerificationContext
指向的地址,再继续查看全局变量gVerificationContext
在内存中的位置信息,如ZigBeeSoc.map
文件中:
.bss.gVerificationContext
0x20003bcf 0x22c ./slot-manager/slot-manager.o
再查看gVerificationContext
定义的位置:
static uint32_t gBootloaderNumSlots;
static uint8_t gVerificationContext[SLOT_MANAGER_VERIFICATION_CONTEXT_SIZE];
static int32_t gSlotsToBoot[SLOT_MANAGER_NUM_SLOTS];
因此是由gVerificationContext
在内存中未处于对齐的地址(0x20003bcf)造成了代码奔溃。
__attribute__((packed,aligned(4))) static uint8_t gVerificationContext[SLOT_MANAGER_VERIFICATION_CONTEXT_SIZE];
类似问题已有人在SiliconLab官方论坛反馈,可参考此处链接。
正常OTA时,gVerificationContext
在map文件中的位置
...
.bss.gVerificationContext
0x20003bb8 0x22c ./slot-manager/slot-manager.o
...