杰理 SDK 文档中心
首页
首页
  • 项目概览

    • AD23N SDK 概述与芯片平台
    • 工程结构与模块划分
  • 快速开始

    • 开发环境搭建与工具链
    • 编译构建指南
    • 烧录与固件升级工具
  • 应用框架与产品工作流

    • 应用入口与模式调度
    • 音乐播放应用
    • MIDI 解码与键盘演奏
    • 录音应用
    • LINEIN 与扩音应用
    • USB 从设备应用
    • 待机、软关机与空闲检测
    • 公共 UI 与 LED 显示
  • 音频子系统

    • 音频解码器框架
    • 音频编码器框架
    • 音效算法库
    • 音频管理与输出通路
  • 存储与文件系统

    • 文件系统层
    • NOR Flash 与虚拟机存储
    • 设备与设备管理
  • 系统服务与运行时

    • 消息机制与事件分发
    • 按键扫描与输入处理
    • 电源管理与低功耗控制
    • 定时器与系统任务
  • 外设驱动与平台

    • CPU 平台与启动流程
    • USB 协议栈与主机/设备驱动
    • SPI 与通用外设接口
  • 固件升级与构建工具

    • 固件升级机制
    • 编译后处理与镜像打包
    • 构建系统与命令行工具

烧录与固件升级工具

AD23N 语音 MCU SDK 的固件烧录与升级能力总览:覆盖开发期首次烧录(USB 升级工具)、量产裸片烧写(一拖二/一拖八烧写器)、运行期 OTA 双备份升级与 UART 升级,并详解设备端升级 API 与配置要点。

Purpose and Scope

本页面向 AD23N SDK 使用者(嵌入式开发工程师、量产/测试工程师)说明如何把编译产物写入芯片以及芯片如何自我升级,是"从编译完成到设备运行新固件"这一环节的端到端参考。

本页覆盖:

  • 开发期首次烧录(USB 升级工具 + 编程模式)的完整步骤与前置条件;
  • 量产生产烧写(一拖二/一拖八烧写器)的使用场景与工具来源;
  • 运行期 OTA 双备份升级(dual_bank 被动升级 API 的职责、调用时序、CRC 校验与 boot info 烧录);
  • UART 升级路径(uart_update 模块);
  • 与烧录相关的配置(ISD_CONFIG.INI)与常见问题排查。

以下主题留给同目录其他页面(此处仅做交叉指引):

  • 编译产物如何生成、.cbp 工程与 Makefile target 的选择,参见 编译指南 页面;
  • 应用层功能开关(app_config.h)与 ISD_CONFIG.INI 之外的 SDK 配置,参见 配置说明 页面;
  • 芯片硬件特性(Flash 分区、电源、复位时序),参见 芯片用户手册(doc/AD23N用户手册V1.1(杰理).pdf)。

Overview

AD23N 是杰理科技 32 位语音 MCU 系列,固件存放在内置 NOR Flash(支持外置 NOR Flash)。与其他 MCU 一样,芯片出厂或开发调试时需要通过烧录工具将固件写入 Flash;而产品交付后则依赖设备端升级能力(OTA/UART)让固件可以现场更新。

整个烧录与升级体系分为三条并行的路径,按使用阶段划分:

阶段工具/路径适用场景关键入口
开发调试USB 升级工具(上位机)将编译产物烧入开发板按住烧录键复位进入编程模式
量产生产烧写工具(一拖二/一拖八)裸片/整板批量烧写代理商提供的量产烧录上位机
运行期OTA 双备份升级产品交付后的固件更新dual_bank_passive_update_* API 族
运行期UART 升级串口通道固件更新uart_update 模块(uart_update.c/.h)

SDK 中的固件升级实现集中在两处:

  • sdk/include_lib/update/code_v2/ —— 以预编译头文件形式对外暴露的升级 API 契约(dual_bank_updata_api.h、update.h、dev_update.h、uart_update.h、update_loader_download.h);
  • sdk/app/bsp/common/update/ 与 sdk/app/bsp/common/uart_update/ —— 设备端升级逻辑的源码实现(update.c、dev_update.c、uart_update.c/.h)。

这种"头文件即契约 + BSP 公共实现"的布局说明:升级能力被设计为与应用解耦的公共基础设施,任何基于该 SDK 的应用(如 mbox_flash)都可以直接调用升级 API 而无需关心 Flash 驱动细节。

Architecture

flowchart TD
    subgraph sg_Host["PC 侧工具"]
        USB_Tool["USB 升级工具<br/>(开发/调试烧录)"]
        MassProd["生产烧写工具<br/>(一拖二 / 一拖八)"]
        ISD_CFG["ISD_CONFIG.INI<br/>烧录配置"]
    end

    subgraph sg_Device["AD23N 目标板"]
        subgraph sg_Boot["启动与编程模式"]
            BOOT["Boot ROM / 编程模式入口"]
            APP["应用固件 (mbox_flash)"]
        end

        subgraph sg_Update["设备端升级模块 (sdk/app/bsp/common)"]
            UPDATE_C["update.c / dev_update.c<br/>升级核心逻辑"]
            UART_U["uart_update.c/.h<br/>UART 升级通道"]
            DUAL_BANK["dual_bank 双备份升级<br/>(include_lib/update/code_v2)"]
        end

        subgraph sg_Flash["NOR Flash 存储"]
            BANK_A["Bank A (运行区)"]
            BANK_B["Bank B (升级区)"]
            BOOT_INFO["Boot Info"]
        end
    end

    USB_Tool -->|"USB / UART 传输"| BOOT
    MassProd -->|"批量烧写"| BOOT
    ISD_CFG -.-> USB_Tool
    APP -->|"触发升级"| UPDATE_C
    UPDATE_C --> DUAL_BANK
    UART_U --> UPDATE_C
    DUAL_BANK -->|"写入/擦除/校验"| BANK_A
    DUAL_BANK -->|"写入/擦除/校验"| BANK_B
    DUAL_BANK -->|"烧录切换信息"| BOOT_INFO

架构说明

  • PC 侧工具:USB 升级工具与生产烧写工具都是杰理官方上位机,通过 USB 或 UART 与目标板通信。ISD_CONFIG.INI 是烧录上位机读取的配置文件,控制烧录选项(详见 ISD 配置说明),仓库的 doc/stuff/ISD_CONFIG.INI配置文件说明.pdf 也提供了离线说明。
  • 编程模式:目标板只有在特定条件下(按住烧录键复位/重新上电,或由升级工具拉入)才接受烧录,避免运行中的应用固件与烧录器争用 Flash。
  • 设备端升级模块:update.c/dev_update.c 承载升级任务调度,uart_update 提供串口数据通路,dual_bank API 负责把下载数据写入非易失存储(Flash)并完成校验与启动信息切换。运行期升级不依赖 PC 工具,由应用固件(或外部主机)把新固件数据流式喂给升级模块。
  • 双备份(A/B)Flash 布局:同一片 NOR Flash 上划分运行区(Bank A)与升级区(Bank B),配合 Boot Info 记录当前应启动哪个区,实现"升级失败不砖机"的可靠性设计(详见下文 OTA 章节)。

开发期首次烧录(USB 升级工具)

工具获取与安装

按 README.md 的说明,开发期烧录需要向杰理官方渠道申请 USB 升级工具(硬件 + 上位机软件),它负责把编译生成的固件烧入目标板:

工具用途获取方式
USB 升级工具将固件烧录到目标板申请链接 · 使用文档
生产烧写工具量产/裸片烧写代理商处 · 一拖二使用文档

安装上位机后,将开发板通过 USB 或 USB 升级工具 连接到 PC,即可进入烧录流程。

首次烧录流程

README 的烧录与升级章节定义了首次烧录的标准步骤:

  1. 连接硬件:将开发板通过 USB 或者 USB 升级工具 连接到 PC;
  2. 进入编程模式:
    • 方式一(USB):按住开发板上的烧录按键,然后复位或重新上电;
    • 方式二(USB/UART):通过 USB 升级工具进入编程模式;
  3. 打开 USB 升级工具:启动烧录上位机;
  4. 选择固件:选择编译生成的固件文件;
  5. 开始烧录:点击下载按钮,等待烧录完成。

注意:烧录前请确保 USB 升级工具正确连接且目标板已进入编程模式。关于 ISD_CONFIG.INI 配置详见 ISD 配置说明。

设计意图解读

  • 为何需要"编程模式":芯片上电时 Boot ROM 先于应用运行;只有处于编程模式,Boot ROM 才会监听烧录协议(而不是跳转到应用)。这保证了烧录器与运行中的应用不会同时操作 Flash,避免写坏固件。
  • 为何提供两种进入方式:开发板上有物理烧录按键时用方式一最直观;而通过升级工具拉入(方式二)无需人工按键,适合后续自动化与产线场景。
  • 为何强调"先进入编程模式再烧录":USB 升级工具下载过程不可中断(掉线/断电会导致 Flash 写入不完整),README 在编译并烧录章节也特别提示:"编译前请确保 USB 升级工具正确连接且目标板已进入编程模式"。

与编译流程的衔接

编译与烧录的衔接点在工程文件与固件产物上:双击 AD23N_mbox_flash.cbp 打开工程 → Build → Build(Ctrl+F9)→ 编译成功后,使用 USB 升级工具烧录生成的固件(见 README.md#L142-L148)。即:CodeBlocks 负责产出固件,USB 升级工具负责把它写进 Flash,两者通过"固件文件"解耦。

量产生产烧写

量产场景与开发调试的关键差异是产能与裸片支持:

  • 使用杰理生产烧写工具(一拖二 / 一拖八),一个上位机同时驱动多个烧录座/烧录头,成倍提升烧录吞吐;
  • 支持裸片烧写(芯片未贴板时直接烧录),这是封装前工序的必需能力;
  • 工具与使用文档均需通过代理商获取(README.md#L288-L290),量产线配置(如烧录座型号、校验选项)也由代理 FAE 配合完成。

量产烧写通常还会配合 ISD_CONFIG.INI 统一各产线的烧录参数(加密、校验、Flash 分区等),确保同一固件在所有产线烧出一致结果。

运行期 OTA 双备份升级

双备份(A/B)机制概述

README 在OTA 升级章节中明确:支持双备份固件升级。所谓双备份,即 Flash 上同时存在两个可启动的固件区(Bank A / Bank B),配合 Boot Info 记录"当前应启动哪个区":

  • 升级时,新固件写入非运行区(更新 Bank),不影响当前运行的固件;
  • 新固件写完后先校验(CRC),校验通过才烧录新的 Boot Info;
  • 下次复位后从新固件启动;若校验失败,则保留旧固件继续运行。

这种设计的核心价值是升级不砖机:即使升级过程中断电、传输中断或固件损坏,系统仍可回退到上一个完好的固件。代价是 Flash 容量占用翻倍,因此该机制通过预编译库的方式按需启用。

升级 API 契约(dual_bank)

设备端被动升级(passive update,即由外部主机/上位机主动推送数据)的 API 全部定义在 dual_bank_updata_api.h,调用方(应用或升级服务器代码)按固定时序使用:

API职责关键参数
get_dual_bank_passive_update_max_buf()查询临时缓冲最大大小无
dual_bank_passive_update_init(fw_crc, fw_size, max_pkt_len, priv)初始化升级任务,登记新固件 CRC 与文件大小fw_crc:新固件 CRC;fw_size:固件总大小;max_pkt_len:单次编程最大长度
dual_bank_update_allow_check(fw_size)判断 Flash 剩余空间是否足够fw_size:新固件大小
dual_bank_update_write(data, len, write_complete_cb)将数据拷入临时缓冲并通知任务写非易失存储data/len:下载数据;write_complete_cb:编程完成回调(返回 0 表示无错)
dual_bank_update_verify(crc_init_hdl, crc_calc_hdl, verify_result_hdl)计算已写入数据的 CRC 并与 init 时登记的 CRC 比对三个回调均可传 NULL 走内部 CRC16-CCITT 实现
dual_bank_update_burn_boot_info(burn_boot_info_result_hdl)校验通过后烧录新固件的启动信息回调 err == 0 表示烧录成功
dual_bank_passive_update_exit(priv)退出升级任务无
dual_bank_update_read_data(offset, read_buf, read_len)读取升级区数据(用于外部 CRC 计算)offset:相对升级区的偏移
dual_bank_passive_update_get_target_update_addr()获取待升级目标地址(init 之后有效)无
flash_update_clr_boot_info(type)擦除指定区的启动信息(慎用)CLEAR_APP_RUNNING_BANK / CLEAR_APP_UPDATE_BANK
dual_bank_update_verify_without_crc_new(verify_result_hdl)不带 CRC 参数的校验入口结果回调

其中 dual_bank_updata_api.h 中对校验与启动信息切换的设计意图注释非常明确(第 35-48 行):先全量校验、再烧 boot info——即"数据完整"与"启动切换"是两个严格分离的阶段,只有数据完整才允许切换启动目标,这正是 A/B 升级可靠性的保证。

Core Flow:OTA 双备份升级时序

以下时序图基于 dual_bank_updata_api.h 的 API 调用契约绘制,展示了外部主机推送新固件到设备并完成切换的完整流程:

sequenceDiagram
    participant H as 外部主机/上位机
    participant A as 应用固件(升级任务)
    participant DB as dual_bank 升级模块
    participant F as NOR Flash (Bank B / Boot Info)

    H->>A: 协商升级参数(固件大小、CRC)
    A->>DB: get_dual_bank_passive_update_max_buf()
    DB-->>A: 临时缓冲大小
    A->>DB: dual_bank_passive_update_init(fw_crc, fw_size, max_pkt_len)
    DB->>DB: 校验固件大小/分区空间
    A->>DB: dual_bank_update_allow_check(fw_size)
    DB-->>A: 允许/拒绝

    loop 分片下载
        H->>A: 固件数据包(data, len)
        A->>DB: dual_bank_update_write(data, len, write_complete_cb)
        DB->>F: 写入/擦除升级区
        F-->>DB: 编程完成
        DB-->>A: write_complete_cb(0=成功)
    end

    A->>DB: dual_bank_update_verify(NULL, NULL, verify_result_hdl)
    DB->>F: 读取已写数据计算 CRC
    F-->>DB: 数据
    DB-->>A: verify_result_hdl(crc_res: 1=通过 0=失败)
    alt CRC 校验通过
        A->>DB: dual_bank_update_burn_boot_info(burn_boot_info_result_hdl)
        DB->>F: 烧录新 Boot Info
        F-->>DB: err=0
        DB-->>A: 升级成功,待复位
    else CRC 校验失败
        A->>DB: 保留旧固件,上报失败
    end

时序要点解读

  1. 初始化先行:init 阶段登记新固件的 fw_crc 与 fw_size,升级模块据此规划写入范围并预留临时缓冲(max_pkt_len 决定单次编程包大小上限,间接约束上位机分包粒度)。
  2. 空间预检:dual_bank_update_allow_check 必须在 init 之后调用,用于在开始写入前确认目标分区容量,避免写到一半才发现空间不足。
  3. 流式写入:dual_bank_update_write 每次接收一段数据,先拷入临时缓冲,再由内部任务异步写入非易失存储,通过 write_complete_cb 通知完成——这是"被动升级"(数据由外部推入)与"主动升级"(设备自己去拉取)的本质区别。
  4. 校验与切换分离:dual_bank_update_verify 支持传入自定义 CRC 回调,传 NULL 则使用内部 CRC16-CCITT 实现;只有 verify_result_hdl 返回通过后,才允许 dual_bank_update_burn_boot_info 烧录新启动信息。
  5. 收尾:全部完成后调用 dual_bank_passive_update_exit 退出升级任务;dual_bank_update_get_target_update_addr 可用于在写入前确认目标地址(如打印日志或做分区校验)。

UART 升级路径

除 OTA(数据经网络/主机下发)外,SDK 还提供 UART 升级通道,实现位于 sdk/app/bsp/common/uart_update/uart_update.c 与 uart_update.h,对外契约在 sdk/include_lib/update/code_v2/uart_update.h。

UART 升级与 USB 升级工具烧录的定位不同:

  • USB 升级工具面向开发/量产,走 Boot ROM 编程模式,设备端无需运行应用;
  • UART 升级面向运行期维护,走应用内升级任务,通过串口接收固件数据,再复用 update 模块(update.c/dev_update.c)写入 Flash——适用于没有 USB 通路、只有串口的产品形态(如通过蓝牙/Wi-Fi 模块转发或产线串口治具)。

由于本仓库以预编译库形式提供升级实现,uart_update.c 与 update.c 的详细内部逻辑未在仓库中展开,具体调用方式以 code_v2 头文件契约为准;如需深入阅读,可直接查看 uart_update.h 与 update.h。

Usage Examples

以下代码片段全部提取自仓库真实源码,展示 OTA 双备份升级 API 的声明与用法契约。

示例 1:初始化升级任务并登记新固件 CRC 与大小

/* @brief:Initializes the update task,and setting the crc value and file size of new fw;
 * @param fw_crc:crc value of new fw file
 * @param fw_size:total size of new fw file
 * @param priv:reserved
 * @param max_ptk_len: Supported maxium length of every programming,it decides the max size of programming every time
 */
u32 dual_bank_passive_update_init(u32 fw_crc, u32 fw_size, u16 max_pkt_len, void *priv);

Source: dual_bank_updata_api.h

这是整个被动升级流程的第一个调用:在收到外部主机下发的固件元信息(CRC、大小)后立即调用,升级模块据此初始化任务并规划写入。

示例 2:流式写入下载数据并注册编程完成回调

/* @brief:copy the data to temporary buffer and notify task to write non-volatile storage
 * @param data:the pointer to download data
 * @param len:the length to download data
 * @param write_complete_cb:callback for programming done,return 0 if no err occurred
*/
u32 dual_bank_update_write(void *data, u16 len, int (*write_complete_cb)(void *priv));

Source: dual_bank_updata_api.h

每次收到数据包就调用一次;内部先拷入临时缓冲,再由升级任务异步写 Flash。write_complete_cb 返回 0 表示本次编程成功,非 0 表示出错,调用方应据此决定是否中断升级。

示例 3:全量校验后烧录新固件启动信息

/* @brief: caculate all the data had flashed,and compare with the cre value intializeed when update init;
 * @crc_init_hdl:if it equals NULL,use internal implementation(CRC16-CCITT Standard);otherwise,use user's customization;
 * @crc_calc_hdl:if it equals NULL,use internal implementation(CRC16-CCITT Standard);otherwise,use user's customization;
 * @verify_result_hdl:when the verification completed,this callback for result notification;
 *                    if crc_res equals 1,crc verification passed,if 0,the verification failed.
*/
u32 dual_bank_update_verify(void (*crc_init_hdl)(void), u32(*crc_calc_hdl)(u32 init_crc, const void *data, u32 len), int (*verify_result_hdl)(int calc_crc));

Source: dual_bank_updata_api.h

三个回调全部传 NULL 时使用内部 CRC16-CCITT 实现,这是最常见的用法;若产品有自定义校验协议,可注入自己的 crc_init/crc_calc。校验结果通过 verify_result_hdl 通知(1=通过,0=失败),通过后调用:

/* @brief:After the new fw verification succeed,call this api to program the new boot info for new fw
 * @param burn_boot_info_result_hdl:this callback for error notification
 *                                  if err equals 0,the operate to burn boot info succeed,other value means to fail.
 */
u32 dual_bank_update_burn_boot_info(int (*burn_boot_info_result_hdl)(int err));

Source: dual_bank_updata_api.h

burn_boot_info_result_hdl 收到 err == 0 表示切换信息烧录成功,此后系统复位将从新固件启动。

示例 4:谨慎操作——擦除指定区的启动信息

enum {
    CLEAR_APP_RUNNING_BANK = 0,
    CLEAR_APP_UPDATE_BANK,
};

/* @brief:this api for erasing the boot info of specific bank,it should be called much carefully
 * @param type:it decides which bank's boot info would be erased;
 *             clean the boot info of running bank and call system_reset,system will run the other bank if available;
 */
int flash_update_clr_boot_info(u8 type);

Source: dual_bank_updata_api.h

该 API 的头文件注释明确标注 "it should be called much carefully"(须非常谨慎):擦除运行区的 boot info 并复位后,系统会尝试从另一区启动——这是"回滚到上一个版本"的实现手段,通常只在固件损坏恢复或双区对调场景使用。

Configuration Options

烧录与升级相关的配置集中在两个层面:

烧录上位机配置(PC 侧)

配置项类型默认值说明
ISD_CONFIG.INI配置文件由工具模板提供USB 升级工具/量产工具读取的烧录配置,含烧录选项、校验、加密等;仓库内离线说明见 doc/stuff/ISD_CONFIG.INI配置文件说明.pdf,在线文档见 ISD 配置说明
固件文件选择文件路径无编译生成的固件文件(.cbp 工程 Build 产物),由用户在上位机中选择

设备端升级配置(固件侧)

配置项类型默认值说明
max_pkt_len(dual_bank_passive_update_init 参数)u16由调用方指定单次编程最大长度,决定每次 dual_bank_update_write 可接受的最大数据量,需与上位机分包策略匹配
fw_crc / fw_size(dual_bank_passive_update_init 参数)u32无新固件的 CRC 值与总大小,用于写入前的空间规划与写入后的完整性校验
CRC 实现选择回调参数内部 CRC16-CCITTdual_bank_update_verify 传入 NULL 时使用内部实现,也可注入自定义 crc_init/crc_calc

注:应用功能开关(如是否启用升级功能)在 sdk/app/src/mbox_flash/app_config.h 中配置,属配置说明页面主题,此处不展开。

API Reference

以下为设备端双备份升级 API 的完整签名(均定义于 dual_bank_updata_api.h)。

u32 get_dual_bank_passive_update_max_buf(void)

获取升级过程中临时存储所需的缓冲大小,用于调用方分配缓冲或约束分包。

返回: 临时缓冲最大大小(字节)。

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

初始化被动升级任务,登记新固件的 CRC 与文件大小。

参数:

  • fw_crc (u32):新固件文件的 CRC 值;
  • fw_size (u32):新固件文件总大小;
  • max_pkt_len (u16):单次编程支持的最大长度,决定每次编程的数据量上限;
  • priv (void *):保留参数。

返回: u32,0 表示成功。

u32 dual_bank_passive_update_exit(void *priv)

退出升级任务。

参数: priv (void *):保留参数。

u32 dual_bank_update_allow_check(u32 fw_size)

判断是否有足够空间存放新固件。必须在 dual_bank_passive_update_init 之后调用。

参数: fw_size (u32):新固件大小。

返回: 空间是否充足(0 表示允许)。

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

将下载数据拷入临时缓冲,并通知任务写入非易失存储。

参数:

  • data (void *):下载数据指针;
  • len (u16):下载数据长度;
  • write_complete_cb (int (*)(void *)):编程完成回调,返回 0 表示无错误。

返回: u32,0 表示成功接收。

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

计算所有已写入数据的 CRC 并与 init 时登记的 CRC 比对。

参数:

  • crc_init_hdl (void (*)(void)):CRC 初始化回调,传 NULL 使用内部实现(CRC16-CCITT 标准);
  • crc_calc_hdl (u32 (*)(u32, const void *, u32)):CRC 计算回调,传 NULL 使用内部实现;
  • verify_result_hdl (int (*)(int)):校验结果通知回调,crc_res == 1 表示通过,0 表示失败。

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

新固件校验成功后,烧录新固件的启动信息(Boot Info)。

参数: burn_boot_info_result_hdl (int (*)(int)):烧录结果回调,err == 0 表示成功,其他值表示失败。

int flash_update_clr_boot_info(u8 type)

擦除指定区的启动信息(谨慎使用)。

参数: type (u8):CLEAR_APP_RUNNING_BANK(0) 擦除运行区,CLEAR_APP_UPDATE_BANK(1) 擦除升级区。擦除运行区 boot info 后调用 system_reset,系统将尝试从另一区启动。

u32 dual_bank_update_read_data(u32 offset, u8 *read_buf, u32 read_len)

读取升级区数据(相对升级区的偏移),供调用方自行计算 CRC。

参数:

  • offset (u32):相对升级区的偏移;
  • read_buf (u8 *):用户数据缓冲;
  • read_len (u32):读取长度。

返回: 实际读取长度。

u8 dual_bank_update_verify_without_crc_new(int (*verify_result_hdl)(int calc_crc))

不携带 CRC 参数的校验入口,行为与 dual_bank_update_verify 的校验阶段一致,结果通过回调通知。

u32 dual_bank_passive_update_get_target_update_addr(void)

获取待升级目标地址,在 dual_bank_passive_update_init 之后使用有效。

Failure Modes, Edge Cases & Concurrency

以下分析基于头文件注释与 README 操作指引中的明确证据:

失败场景表现防护/处理
未进入编程模式就烧录烧录失败或工具无法识别设备README 明确要求"先进入编程模式",并提供两种进入方式;工具连接/目标板状态是烧录前置条件
烧录过程中断电/断开Flash 写入不完整,固件损坏双备份机制下旧固件区不受影响;开发期需保证连接稳定
升级数据写入出错write_complete_cb 返回非 0调用方应中断升级流程,等待重试
CRC 校验失败verify_result_hdl 收到 0不烧录 Boot Info,保留旧固件继续运行——这是 A/B 升级的核心回退保证
新固件过大dual_bank_update_allow_check 拒绝在写入前拦截,避免写一半失败;应检查固件大小与分区容量
误擦除运行区 Boot Info系统复位后切换启动区API 注释明示"must be called much carefully",仅用于回滚/恢复场景
分包与 max_pkt_len 不匹配单次写入超限上位机分包策略必须遵守 dual_bank_passive_update_init 登记的 max_pkt_len,可先用 get_dual_bank_passive_update_max_buf 查询缓冲上限

并发与异步注意:dual_bank_update_write 采用"拷贝到临时缓冲 + 后台任务写 Flash"的异步模型,write_complete_cb 是编程完成的同步信号——调用方应基于回调做流程推进,而不是在 write 返回后立即发送下一包(除非协议明确允许流水线)。Flash 擦写是慢操作,升级期间应避免应用其他任务同时访问目标分区。

Performance & Operational Notes

  • 分包粒度:max_pkt_len 同时约束单次编程数据量与上位机分包大小,选择较大值可减少回调次数、提升吞吐,但会增大临时缓冲(get_dual_bank_passive_update_max_buf 可查询)——需在 RAM 占用与传输效率间权衡。
  • 擦写成本:NOR Flash 以扇区为单位擦除、以页为单位编程,升级写入速度受 Flash 擦写时序主导;dual_bank_update_write 内部异步化可让传输与擦写重叠,降低主机等待时间。
  • 产线一致性:量产建议通过统一的 ISD_CONFIG.INI 固化烧录参数,避免人工选择差异;一拖二/一拖八工具可摊薄单颗烧录时间。
  • 升级窗口:OTA 升级建议在设备空闲/供电稳定时进行,避免升级中途进入低功耗模式或断电;双备份机制虽可回退,但频繁回退说明升级包质量或传输链路存在问题。

Extension Points

  • 自定义 CRC:dual_bank_update_verify 允许注入 crc_init_hdl/crc_calc_hdl,支持产品自定义校验协议(默认 CRC16-CCITT);
  • 结果回调:write_complete_cb、verify_result_hdl、burn_boot_info_result_hdl 均为调用方注册的回调,可在此接入日志、指示灯、上报服务器等业务逻辑;
  • UART 通道:uart_update 模块(sdk/app/bsp/common/uart_update/)可作为自定义传输层(蓝牙透传、串口透传等)接入升级任务的参考实现;
  • 启动区管理:flash_update_clr_boot_info 与 CLEAR_APP_RUNNING_BANK/CLEAR_APP_UPDATE_BANK 枚举为 OTA 对调、版本回滚提供设备端原语。

Tests

本仓库以预编译库(sdk/include_lib/、include_lib/liba/)形式发布升级组件,仓库内未包含升级模块的独立测试用例。测试与验证烧录/升级效果的可行手段包括:

  • 首次烧录后检查设备是否正常运行(验证 USB 升级工具链路);
  • 构造一个"升级到新固件 → 复位 → 确认启动新固件"的闭环,验证 OTA 流程与 Boot Info 切换;
  • 在写入阶段人为断电,验证复位后仍能从旧固件启动(双备份回退验证);
  • 修改 dual_bank_passive_update_init 传入错误的 fw_crc,验证 verify_result_hdl 收到失败且不烧录 Boot Info。

Related Links

  • README.md — 烧录与升级章节:官方首次烧录/生产烧写/OTA 说明
  • dual_bank_updata_api.h:双备份升级 API 契约
  • dev_update.h:设备升级接口
  • uart_update.h:UART 升级接口
  • update.h:升级核心接口
  • update_loader_download.h:升级引导下载接口
  • 在线文档:USB 升级工具使用文档、一拖二烧写器、一拖八烧写器、ISD 配置说明
  • 仓库离线资料:doc/AD23N_SDK手册_v1.0.pdf、doc/stuff/ISD_CONFIG.INI配置文件说明.pdf、AD23N_SDK_发布版本信息.pdf
  • 交叉指引:编译产物的生成与工程选择见 编译指南;应用功能开关配置见 配置说明;芯片硬件与 Flash 分区细节见 AD23N 用户手册
Prev
编译构建指南