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

2023-11-20

现象

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
...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 腾讯云函数的Python依赖库打包注意事项

    云函数Python3 6依赖库 官网文档链接 前两天写了一个Python程序要用pycryptodome库 但是腾讯云函数并没有自带这个库 感觉还是记录一下比较好 要使用CentOS 7下的Python Python版本要是3 6的 我一开
  • VIM选择文本块/复制/粘贴

    在正常模式下 按ESC进入 按键v进入可视化模式 然后按键盘左右键或h l键即可实现文本的选择 其它相关命令 v 按字符选择 经常使用的模式 所以亲自尝试一下它 V 按行选择 这在你想拷贝或者移动很多行的文本的时候特别有用 CTRL v 按
  • QT中修改QCalendarWidget样式时,令周几(表头)与日期文字颜色不同的方法,设置文字样式冲突的问题

    太长不看版 Qt日历中使用setWeekdayTextFormat修改周末文字颜色和setHeaderTextFormat修改表头文字颜色发生冲突 通过找到每个周末日期来修改文字颜色 效果图和代码见文末 在Qt中用到了QCalendarWi
  • Prometheus Blackbox Exporter 的 HTTP 探测指标中各个阶段的时间统计信息

    在 Prometheus Blackbox Exporter 的 HTTP 探测指标中 probe http duration seconds 指标包含各个阶段的时间统计信息 这些阶段代表了 HTTP 探测的不同阶段和指标 以下是各个阶段的
  • 同步时间

    系统时间与硬件时间 一台计算机有两个时钟 一是硬件时间时钟 RTC Real Time Clock 又实时时钟 二是系统时钟 System Clock 1 概念 硬件时钟是嵌在主板上的特殊电路 平时关机后还可计算时间 系统时钟是操作系统的k
  • 安装tensorflow version `CXXABI_1.3.7' not found

    现象 ImportError usr lib64 libstdc so 6 version CXXABI 1 3 7 not found required by root anaconda3 lib python3 6 site ntern
  • mybatis+oracle+map入参,并获取主键ID的返回值

    insert id insert parameterType map useGeneratedKeys true keyProperty id gt insert into person name pswd values name pswd
  • 第五章 Gateway--服务网关

    接上一篇文章开始网关之旅 首先告诉大家网关是什么 Gateway简介 怎么配置 怎么入门 执行流程等等相关介绍 第一章 微服务的架构介绍发展第二章 微服务环境搭建第三章 Nacos Discovery 服务治理第四章 Sentinel 服务
  • 基于深度学习的关系抽取综述

    论文 https arxiv org pdf 1705 03645 pdf 一 介绍 信息抽取是NLP的一个基本任务 从非结构化文本中抽取机器或程序能够理解的结构化知识 信息抽取包括以下子任务 NER 关系抽取 事件抽取等等 本文中 我们着
  • Java list判空

    if null list list size 0 list isEmpty 和list size 0 没有区别 isEmpty 判断有没有元素 而size 返回有几个元素 如果判断一个集合有无元素 建议用isEmpty 方法 这清晰 简明
  • 0基础,自学3个月转行软件测试,从月薪3k到12k我整理的超全学习指南

    大家好我是小娜 现在是一名软件测试测试工程师 工资在1w2阶段还需努力 我大学期间学的是电气工程及其自动化专业 可以说是一事无成哈哈 大学三天打鱼 两天筛网导致专业水平学的不怎么样 毕业后从事了一份销售 买房子 的工作 但是 销售工作压力大
  • GIT代码仓库迁移

    GIT代码仓库迁移 保留原有的提交记录 查看原有提交路径 git remote v 变更为新的提交路径 git remote set url origin 新路径 拉取新路径下的内容 允许不相关历史提交 并强制合并 git pull ori
  • 亲密关系沟通-【正向情绪】创造一场愉快的沟通体验

    为什么有的时候聊天越聊越开心 有时候却让你意兴阑珊 正向情绪体验 积极议题 充分发挥 谁都喜欢被看见 让他不断得到关注 得到你持续的关注 你知道吗 我这个月业绩第一 哇 你超棒的 哪里哪里 话题聊不下去 你给他夸奖 他只能谦虚 天哪你怎么做
  • [转]使用Midjourney命令输出稳定的漫画角色

    转载自 用对Midjourney命令你也可以输出稳定的漫画角色 qq com 昨天的文章已经教会了大家如何成为15分钟快速制作一幅小漫画 有兴趣的可以翻阅上一篇文章 但是不少同学会发现 Midjourney的随机性比较强 即使输入相同的命令
  • 转载:《七周成为数据分析师》

    百日计划第一周总结 1 计划 1 彻底结束之前预定暑假完成的天善学院课程 七周数据分析师 2 总结 七周数据分析师 2 完成情况 1 完成 七周成为数据分析师 任务 2 周总结与 七周数据分析师 一起完成 七周数据分析师 总结 第一周 数据
  • 【Python零基础入门篇 · 17】:模块、模块的使用、过滤执行代码写法、包的使用

    文章目录 模块 内置模块 第三方模块 自定义模块 模块的使用 import 模块名 导入自定义模块 from import 模块起别名 as 导入多模块 模块 模块 就是 py文件 里面定义了一些函数和变量 需要的时候就可以导入这些模块 执
  • 零基础Java详细的jdk的下载以及安装配置

    文章目录 一 下载jdk 二 配置jdk 三 查看配置是否成功 一 下载jdk 1 登录oracle官网 2 3 4 点进去往下拉 会有jdk新版本 接受许可协议 直接下载 zip压缩文档就行 也可以直接下载 exe安装版本 5 找到压缩包
  • FPGA实现VGA显示图片

    利用FPGA在带有VGA接口的液晶显示器上显示图片 电路原理图 端口说明 VGA R2 VGAB0的8个端口位VGA的RGB数据位 VGA HS为行同步信号 VGA VS为场同步信号 以分辨率为640x480为例 刷新速率为60Hz 每幅图
  • [Python学习] 专题六.局部变量、全局变量global、导入模块变量

    定义在函数内的变量有局部作用域 在一个模块中最高级别的变量有全局作用域 本文主要讲述全局变量 局部变量和导入模块变量的方法 参考 Python核心编程 第二版 一 局部变量 声明适用的程序的范围被称为了声明的作用域 在一个过程中 如果名字在
  • 基于芯科Ember SDK开发的ZigBee ota client验证固件时崩溃(Reset info: 0x0A (FLT)), SDK Bug导致!

    现象 ZigBee子设备新固件下载完成后 准备校验其合法性 代码运行至检验部分 MCU崩溃重启 日志如下 RECV ASCII gt Processing message len 33 profile 0104 cluster 0019 T