上一篇相关文章后遇到的问题:
OTA升级中设备内部Flash不够分区,外部Flash的SPI接口和芯片串口引脚复用导致不能调用硬件SPI,只能程序模拟SPI电平,尚未和协议栈融合成功;调试中还存在Flash芯片和协议栈指定芯片不一致问题;原协议栈还用了DMA,增加移植难度
移植前一些注意事项:
FLASH最后一个可用页面的最后16个字节被保留给flash锁定位
#define HAL_FLASH_PAGE_SIZE 2048
#define HAL_FLASH_WORD_SIZE 4
默认外部flash 一页 2k
#define HAL_OTA_DL_MAX 0x40000 // 映像最大256字节
#define HAL_OTA_DL_SIZE (0x40000 - ((HAL_NV_PAGE_CNT+HAL_OTA_BOOT_PG_CNT)*HAL_FLASH_PAGE_SIZE)) //减去计数页 和bootloader占的前2k
#define HAL_OTA_DL_OSET 0x0 // Configurable offset into an external NV.保存的信息默认在外部flash的第一个字节开始,可以做偏移
// Flash is partitioned into 8 banks of 32 KB or 16 pages.
#define HAL_FLASH_PAGE_PER_BANK 16 //共256k 8块 每块16页,每页2k
uint8 *pData = (uint8 *)(offset + HAL_FLASH_PAGE_MAP) + //开辟一片空间将flash映射地址存入,将指针指向pData
((pg % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE); //获取当前页位于当前块的哪一页
自带串口相关SPI可以注释,但是相关中断不能注释,因为OTA中不能有中断打断,待定··
CC2530是8K的内存,这部分就是XDATA的大小,官方例程编译完成已经用了7K左右的内存,优化代码
XDATA是用于静态变量,包括全局变量和本地变量,如全局变量中的路由表,绑定表,以及协议栈使用的内存堆等,以及本地变量如ZDP_BUF
// CODE banks get mapped into the XDATA range 8000-FFFF.
#define HAL_FLASH_PAGE_MAP 0x8000 //flash地址映射到内存中是从0x8000开始
dl2rc:Copy the DL image to the RC image location. 通过判断app的CRC是否发生改变为依据,进行镜像转移
HalOTAInvRC(void) :此函数用来恢复crc为0xFFFF,保证升级外flash完成后可以进行镜像转移
可能存在的问题是:某个flash地址是应该改动的,会不会也任务程序CRC变了,要升级------>不会,参见上一句,crc不是每次都会重新计算,是通过函数人为主动改变的
转移过程是:每从外部flash读取4个字节就写入一次CC2530内存,同时判断累计有没有写或读达2k,到2k就擦除2k内存
真正映像文件,即可以运行的bin文件起始地址是 :// Calculate the update image start address
programStart = header.headerLength + OTA_SUB_ELEMENT_HDR_LEN;
修改#if HAL_OTA_XNV_IS_INT//片内flash
oset += HAL_OTA_RC_START + HAL_OTA_DL_OSET;中的HAL_OTA_DL_OSET决定用片内flash升级时的偏移地址,但是限制是文件不能大于120K
if ((oset % HAL_FLASH_PAGE_SIZE) == 0)//必须2k为单位进行写入 不管片内还是片外
{
HalFlashErase(oset / HAL_FLASH_PAGE_SIZE);
}
注意flash的几根信号线不要和别的功能比如灯复用,或者分时复用
实操经验:
先打断电在zclOTA_ProcessImageData 的HalOTAWrite(zclOTA_FileOffset, pData, len, HAL_OTA_DL);看能不能收到镜像,不能就一步步上推调用函数,打断点,仿真。担心灯和flash引脚复用,因为原栈有灯提示,可以#define HAL_LED FALSE #define HAL_KEY FALSE
上图圈中的可以去掉,因为用的是自己的SPI读写函数,和串口函数无关,不用也无法调用硬件SPI的寄存器
注意上图的版本要一致,这个0x600也不知道怎么来的 始终不能用 就重新解压了一下,恢复0x1了
两个坑:1,flash片选信号引脚和下载器引脚复用,导致插着下载器仿真时,片选电平不正常;2、flash时钟信号和一个自定义指示灯引脚复用,导致指示灯在调用时,时钟信号异常
注意写之前,要把外部flash全擦除一下,擦除需要时间
OTA空中下载更新虽然显示100%但是之后就跳转显示“download failed(150)这个问题把外部flash移植好就不会出现了,不用外部flash也能到这一步,如果到不了这一步,看看协调器和终端有没有组网成功,可以把协调器(服务器)的按键失能试试
进不了 if ((++zclOTA_FileOffset) >= zclOTA_DownloadedImageSize)可能是造成download failed(150)的原因,flash移植成功也没有了
目前问题是下载成功了100% complete,但是没反应,也没有重启 类似
解决思路,先看一下.zigbee文件和外部flash文件的内容是否一致,.zigbee文件可以用notepad++查看,notepad++要装一个HexEditor插件,参考
如下图看.zigbee比较明晰
再仿真ZCL_OTA_DL_COMPLETE_CALLBACK会掉有没有进去,判断外部flash校验是否成功,crc信息有没有置位;如果都过了,再仿真bootloader,判断镜像是否转移成功;中间需要看关键参数时就比对上图二进制文件进行判断
下图是升级过程:
从100% Complete 到 Complete Sucessfully 大概 需要40s,触发下载成功条件是下图标红的
从下载成功到下图回调函数24s
从回调函数到成功更新程序 40s ,以上时间为参考 如果是用路由器更新程序,再加上没有硬件SPI和DMA更慢,参考值是整个流程半小时
osal_start_timerEx(zclOTA_TaskID, ZCL_OTA_UPGRADE_WAIT_EVT, 10000);//重启时间,原60s
移植bootloader程序注意:要把spi引脚的初始化加上,因为默认是串口引脚,bootloader并没有初始化自定义的重指定的spi引脚;interrupt_stubs.s51文件路径要正确,多个同名文件,IAR可能会路径混淆;放大相关函数或宏定义去掉;
移植协调器程序注意:开硬件流控,串口工具接线正确,RTS-CTS反向接;波特率必须38400,PANID一致,是否加密,回调是否正确uartConfig.callBackFunc = MT_UartProcessZToolData; 把预编译的LCD_SUPPORTED=DEBUG去掉;把按键使能去掉;LCD等不相关的预编译去掉
移植客户端程序注意:流程是否规范,参考zstack ota文章;SPI引脚重映射;DMA判断去掉;外部FLASH是否先擦后写;SPI模拟电平是否可以正常写入读出flash;复用引脚分时复用;屏蔽中断要保留,否则会显示successfully 但是没成功;注意如果复用P2.1 或者P2.2 必须下载完成重新上一次电并且拔掉仿真器,使这俩引脚退出仿真模式,才能进行升级;转移校验升级文件时要把看门狗关闭了,关不了就在ota文件校验那喂狗,缺点是升级变慢些;如果有外部中断函数,放到读取OTA文件后面,如下图
客户端头文件路径:$PROJ_DIR$
$PROJ_DIR$\..\Source
$PROJ_DIR$\..\..\Source
$PROJ_DIR$\..\..\..\OTA\Source
$PROJ_DIR$\..\..\..\..\..\Components\stack\zcl
$PROJ_DIR$\..\..\..\ZMain\TI2530DB
$PROJ_DIR$\..\..\..\..\..\Components\hal\include
$PROJ_DIR$\..\..\..\..\..\Components\hal\target\CC2530EB
$PROJ_DIR$\..\..\..\..\..\Components\mac\include
$PROJ_DIR$\..\..\..\..\..\Components\mac\high_level
$PROJ_DIR$\..\..\..\..\..\Components\mac\low_level\srf04
$PROJ_DIR$\..\..\..\..\..\Components\mac\low_level\srf04\single_chip
$PROJ_DIR$\..\..\..\..\..\Components\mt
$PROJ_DIR$\..\..\..\..\..\Components\osal\include
$PROJ_DIR$\..\..\..\..\..\Components\services\saddr
$PROJ_DIR$\..\..\..\..\..\Components\services\sdata
$PROJ_DIR$\..\..\..\..\..\Components\stack\af
$PROJ_DIR$\..\..\..\..\..\Components\stack\nwk
$PROJ_DIR$\..\..\..\..\..\Components\stack\sapi
$PROJ_DIR$\..\..\..\..\..\Components\stack\sec
$PROJ_DIR$\..\..\..\..\..\Components\stack\sys
$PROJ_DIR$\..\..\..\..\..\Components\stack\zdo
$PROJ_DIR$\..\..\..\..\..\Components\zmac
$PROJ_DIR$\..\..\..\..\..\Components\zmac\f8w
预编译项:
ZIGBEEPRO
ZTOOL_P1
NV_RESTORE
WDT_IN_PM1
OTA_CLIENT=TRUE
ZCL_READ
ZCL_WRITE
ZCL_REPORT
ZCL_DISCOVER
OTA_IMAGE_PAGE
xMT_TASK
xMT_SYS_FUNC
xMT_ZDO_FUNC
xLCD_SUPPORTED=DEBUG
生成文件:"$PROJ_DIR$\..\..\..\Tools\CC2530DB\OtaConverter.exe" "$PROJ_DIR$\Door Indicator\Exe\Door Indicator.sim" -o"$PROJ_DIR$\Door Indicator\Exe" -t0x1234 -m0x5678 -pCC2530DB
目前的问题是开启AES加密后,路由器状态特别不稳定,频繁掉线导致无法进行OTA
提示错误:Error[e46]: Undefined external "MAC_RfFrontendSetup" referred in hal_flash ( F:\YF\software\ZStack-2.5.1a-200604\ZStack-2.5.1a\Projects\zstack\OTA\Boot\CC2530DB\OTA-Boot\Obj\hal_flash.r51 ) 需要把#define HAL_PA_LNA改为#define xHAL_PA_LNA 或者改hal_board_cfg.h 的#define xHAL_PA_LNA 改为
#ifndef HAL_OTA_BOOT_CODE //
#define HAL_PA_LNA //自己的用这个放大
#endif
zigbee的bootloader不带放大,精简版
ota合并文件问题:目前采用的方式将bootloader和app都下载进去,然后读出来一个合并文件,因为使能掉电保存了,IEEE存到缓存区,一起读出来了,造成把这个合成hex下载到其它电路板时,ieee也变了,参考,解决方法:static void zmain_ext_addr(void)的第一个if全注释掉
2020.8.27:解决失败率过高的问题。
目前失败现象是100% Complete但是无法Complete Sucessfully,前提是文件全部传过去,校验通过,并不是其它问题导致的这个现象,而是上位机偶尔收不到终端发出COMMAND_UPGRADE_END_REQ的回馈(仿真发现终端已经发出),无法显示Complete Sucessfully,同时上位机给终端无法返回COMMAND_UPGRADE_END_RSP,导致终端一直在等待而无法进入ZCL_OTA_DL_COMPLETE_CALLBACK判断中,解决方法如下,修改static ZStatus_t zclOTA_ProcessImageBlockRsp( zclIncoming_t *pInMsg )函数
传输收到少一个字节,可以判断zclOTA_FileOffset == (zclOTA_DownloadedImageSize-1)一段时间后进行强制复位
参考视频www.bilibili.com/video/av711…