基于芯科Ember SDK开发的ZigBee ota client验证固件时崩溃(Reset info: 0x0A (FLT)), SDK Bug导致!

现象

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

上述日志关键信息:

  • 指令运行异常位置 00002B1A
  • 返回地址 Ret0/Ret1/Ret2/Ret3/Ret4/Ret5

处理思路

将代码 异常地址 转换到程序 源码 位置,使用工具 arm-none-eabi-addr2line

  • 定位 Ret0=0002239F 的位置
arm-none-eabi-addr2line.exe -e ZigBeeSoc.axf -af 0x0002239F
0x0002239f
FRC_IRQHandler
  • 定位 Ret1=00014977 的位置
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
  • 定位 Ret2=00007B5B 的位置
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
  • 定位 Ret3=00015013 的位置
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
  • 定位 Ret4=0000FFF7 的位置
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
  • 定位 Ret5=0000EECF 的位置
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内部。

Application中出错位置

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
...
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Zigbee联盟发布的最新版本的ZCL SPEC中,可以找到关于Zigbee的各个cluster、命令和属性的相关信息。此外,Zigbee联盟由一组推广成员公司领导,这些公司组成了董事会。其中之一就是Silicon Labs。Zigbee还有许多参与者和采用者成员,他们在技术和市场工作组内工作,共同创建和维护标准。联盟通过专注于技术特定领域的工作组来实现其活动,包括网络组、安全组、应用配置文件组等。所有的Zigbee文档都可以在Zigbee网站www.zigbee.org上找到。当前的规范文档需要Zigbee联盟会员才能访问。要在产品中使用Zigbee技术,公司需要成为联盟的会员。 关于Zigbee的ZCL_ZLL_COMMISSIONING,它指的是Zigbee LightLink(ZLL)的委托过程。ZLL是一种基于Zigbee的无线通信协议,用于智能照明设备之间的通信。ZCL_ZLL_COMMISSIONING定义了在ZLL网络中进行设备配对和配置的命令和属性,包括找到可用的照明设备、建立连接、配置设备参数等。通过使用ZCL SPEC,开发者可以查阅到更详细的ZCL_ZLL_COMMISSIONING的相关信息,以便在Zigbee开发中进行相应的实现和配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ZCL_SPEC_R7.pdf](https://download.csdn.net/download/jinlu1990/12566609)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【ember zigbee】第二章:ug103-02-fundamentals-zigbee 学习笔记(上)](https://blog.csdn.net/tainjau/article/details/91358040)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值