2. AW31 升级结构和双备份升级

2.1. 主动升级和被动升级

  • 主动升级:由设备端主动向远端获取升级数据,通信协议需要能支持文件内容获取能力,分为单备份和双备份两种

  • 被动升级:由远端主动推送升级数据,设备端被动写入的方式,远端可控制升级流程,仅支持双备份

2.2. 单备份升级

  • 单备份:需要使用到ota.bin(包含各种升级方式的loader,如串口,测试盒EDR、BLE、RCSP等),升级首先需要先将loader(ota.bin里对应当前升级方式的loader)加载到VM区域(需要需要保留VM数据需要在lib_update_config.c进行配置)。加载完成之后,会在flash里写入update_record,接下来跳转到loader进行升级流程。

Note

VM的大小决定了单备份是否能将loader写入,如果VM空间不足以写入loader,则升级会提示loader大小错误,具体需要的大小可以通过编译最后的提示信息来得知: 升级过程被中断,如遭遇断电,测试盒通信失败等,若当前升级流程处于loader加载的过程,则固件不会丢失。若已经加载完loader,那固件会在loader里等待继续升级(此时原有的固件已经被擦除),测试蓝牙升级可以重新搜索xxx_update或者xxx_LE_UPDATE进行升级。测试盒串口可以继续点击开始升级来升级。

2.3. 双备份主动升级

  • 双备份升级存储结构有两个app code区域,当芯片正在运行app code1,升级时将新固件写入app code 2区域,反之亦然。升级时对app code N区域数据校验成功后,复位即可运行app code N代码。当升级中断或者新写入固件校验不成功,不会影响原来app code 的运行

  • 双备份主动升级区别于单备份升级,不需要ota.bin,也就是没有加载loader的流程,即使升级中途失败,原有的代码也不会丢失。流程图如下:

主动升级流程图

其中app rcsp的双备份升级就是双备份主动升级,配置如下

#define CONFIG_BOARD_AW31N_DEMO板级为例

  • apps/demo/hid/board/bd47/board_aw31n_demo_global build_cfg.h打开CONFIG_APP_OTA_EN

  • apps/demo/hid/board/bd47/board_aw31n_demo_global build_cfg.h打开CONFIG_DOUBLE_BANK_ENABLE

  • 后续流程和单备份一致,参考AW31手机OTA升级slave章节

Warning

双备份和单备份之间不能互相升级,配置双备份升级成功后使用强制升级工具去升级,会提示正常擦除CODE2…,说明当前flash结构已经为双备份

2.4. 双备份被动升级

双备份被动升级用于用户自定义的协议或者第三方协议接入,可使用dual_bank_updata_api.h,此种升级方式,使用的升级文件为db_update_data.bin,(需要在ini里配置flash结构为双备份,且生成db_update.bin的配置)。使用该升级方式,用户只需要提供升级的文件信息已经实现升级的数据通路(完成协议),调用提供的接口即可。ini配置:

#define CONFIG_BOARD_AW31N_DEMO板级为例

  • apps/demo/hid/board/bd47/board_aw31n_demo_global build_cfg.h打开CONFIG_APP_OTA_EN

  • apps/demo/hid/board/bd47/board_aw31n_demo_global build_cfg.h打开CONFIG_DB_UPDATE_DATA_GENERATE_EN

双备份被动升级流程图:

双备份被动升级流程图

2.4.1. 相关接口介绍:

  • u32 dual_bank_passive_update_init(u32 fw_crc, u32 fw_size, u16 max_pkt_len, void *priv);

    • Note:初始化升级模块,创建升级任务

    • param1: db_data_update.bin的crc

    • param2: db_data_update.bin的大小

    • param3: 每次调用模块写入接口写入数据的最大长度

    • param4: reverse

    • return: 0:succ -2:no_memroy -3:获取不到当前flash的文件接口(检查当前ini是否正确配置)

  • u32 dual_bank_update_allow_check(u32 fw_size);

    • Note:检查当前的flash空间是否满足升级需求

    • param1: db_data_update.bin的大小

    • return: 0:succ -1: 升级模块未初始化 -2:当前flash空间小于升级文件需要的大小

  • u32 dual_bank_update_write(void *data, u16 len, int (*write_complete_cb)(void *priv))

    • Note: 升级文件数据写入接口,数据并非调用完该接口就已经写入flash,需要等write_complete_cb回调被调用才是成功写入了

    • param1: 写入数据的指针

    • param2: 写入数据的长度

    • param3: 数据写入成功的回调函数,只有该接口被调用,数据才算写入成功,这样设计是为了调用写入之后不用等到flash操作完成,可以在下次写的时候再去查上一次是否写入成功。

    • return: 0:succ -1: 升级模块未初始化 -3: 写入的数据长度 大于初始化的时候传递的参数max_pkt_len

  • u32 dual_bank_update_verify(void (*crc_init_hdl)(void),u32(*crc_calc_hdl)(u32 init_crc, u8 *data, u32 len), int (*verify_result_hdl)(int calc_crc))

    • Note: 数据校验接口,所有数据写入完成调用。

    • param1: crc计算初始化接口,初始化CRC变量(用户端提供),传递NULL,使用默认的CRC16-CCITT Standard

    • param2: crc计算接口(用户提供),传递NULL,使用默认的CRC16-CCITT Standard

    • param2: crc计算成功回调函数,和写入数据的接口一样,需要等待回调函数通知校验结果,回调函数参数传参calc_crc为1时,校验成功,为0则表示校验失败。

  • u32 dual_bank_update_burn_boot_info(int(*burn_boot_info_result_hdl)(int err));

    • Note: boot_info写入接口,在校验成功之后调用,cpu复位之后则会运行新的代码。

    • param1: boot_info成功写入回调。 -1表示写入失败,0表示写入成功。

    • return: -1: 升级模块未初始化

  • u32 dual_bank_passive_update_exit(void *priv);

    • Note: 释放升级模块资源,在失败或者升级结束之后调用。

    • param1: reverse

  • u8 dual_bank_update_verify_without_crc(void)

    • Note: 对于手机没有传CRC过来的方案,提供该接口来进行crc校验

    • return: 0: 校验成功 1:校验失败。