杰理 SDK 文档中心
首页
首页
  • 概述

    • SDK 概览与产品定位
    • 支持芯片平台与蓝牙认证
    • SDK 架构与目录分层
  • 快速开始

    • 环境搭建与编译工具链
    • 编译构建系统
    • 板级工程与配置
    • 烧录与固件升级工具
  • 应用工程

    • 应用选择与工程总览
    • SPP + BLE 数传应用框架
    • 透传与 AT 指令示例
    • BLE 广播/中心与定位示例
    • 2.4G 私有协议与 Dongle 示例
    • 云平台接入示例
    • HID 人机交互应用框架
    • HID 示例工程(键盘/鼠标/遥控器/手柄)
    • Bluetooth Mesh 应用框架
    • Mesh 模型与 Mesh DFU 固件升级
    • Mesh 音频编解码演示
  • 芯片平台与硬件抽象

    • 芯片平台总览与差异
    • 音频编解码与时钟管理
    • 外设驱动接口(ADC/IIC/SPI/PWM/LED/充电)
    • 芯片配置工具与下载支持
  • 蓝牙协议栈

    • 蓝牙控制器层(btctrler)
    • 蓝牙协议栈与 Profile(btstack)
    • 蓝牙模块选择与配置
  • 媒体与音频框架

    • 音频流框架
    • 音频编解码与 A2DP 媒体
    • 音频效果处理(EQ/频谱/变调/环绕/超低音)
    • 本地 TWS 与音频同步
  • 系统服务与运行时

    • 实时操作系统与任务调度
    • 消息事件机制
    • 电源管理与低功耗
    • 存储与配置系统
    • 设备驱动框架(USB/RTC)
  • 应用公共组件

    • 音频应用组件
    • 设备外设抽象(按键/触摸/传感器/存储)
    • 蓝牙公共模块与消息联动
    • 调试与配置组件
    • 杰理关键词唤醒(jl_kws)
  • 第三方协议与云平台接入

    • 杰理 RCSP 私有协议
    • 低功耗蓝牙 Mesh 方案(llsync_mesh)
    • Sig Mesh 方案
    • 涂鸦协议接入
    • 腾讯连连接入
    • 华为 HiLink 接入
  • 固件升级与维护

    • OTA 升级机制
    • 升级补丁与版本维护
    • 升级工具链(BLE OTA / USB Dongle OTA)
  • 文档与开发资源

    • 数据手册与架构文档
    • 协议与云平台开发文档
    • 常见问题与技术支持

Mesh 模型与 Mesh DFU 固件升级

本文档介绍 AC63 系列 SDK 中 SIG Mesh 应用(apps/mesh)的模型框架与 Mesh DFU(Distributed Firmware Update,分布式固件升级)实现,涵盖 Distributor(分发器)与 Target(目标节点)两种角色、APP 命令协议、固件文件读取/校验/擦写流程及状态机。

Purpose and Scope

本页覆盖以下内容:

  • apps/mesh 应用工程的启动流程与 Mesh 模型配置入口(CONFIG_MESH_MODEL)。
  • Mesh DFU 的两种角色实现:Distributor(mesh_distributor_loader.c、mesh_dfu_app_cmd_protocol.c)与 Target(mesh_target_node_ota.c/h)。
  • Distributor 与 APP 之间的私有命令协议(帧头、SN 防重放、应答机制)。
  • 固件文件从 flash 配置区读取、CRC-16-XMODEM 校验、经 Mesh 网络下发、目标节点写 flash 的完整链路。
  • Target 节点的 OTA 状态机、命令类型与错误码。

不在本页范围内的相关内容:SIG Mesh 协议栈底层实现(apps/common/third_party_profile/sig_mesh 下的 API 与适配层)、Tencent LLsync Mesh(llsync_mesh)私有实现,以及各芯片板级 BLE 配置,请参见对应的协议栈与板级文档页。

Overview

Mesh DFU 是 SIG Mesh 标准中用于对网络中多个节点进行固件升级的机制。在本 SDK 中,其被实现为一种"分发器-目标节点"(Distributor–Target)架构:

  • APP(手机端) 通过私有串口/BLE 通道把固件升级请求发给 Distributor;
  • Distributor 从 flash 配置区读取预先烧录的固件 bin 文件,按命令协议组包,并通过 Mesh 模型消息广播/单播给网络中的 Target 节点;
  • Target 节点接收数据包,按序写入自身 flash,完成校验后重启生效。

该设计把"固件文件管理"与"无线传输"分离:Distributor 只负责把固件文件切分成 Mesh 消息并跟踪下发进度;Target 只负责接收、落盘与校验。这样可以在不改变 Mesh 协议栈的前提下,通过 CONFIG_MESH_MODEL 编译开关选择设备角色,实现同一套代码仓库支持"升级发起方"和"升级执行方"两种形态。

应用入口位于 app_mesh.c:app_start() 中调用 btstack_init() 启动蓝牙协议栈并注册按键事件,随后由 state_machine() 处理 APP_STA_CREATE/APP_STA_START 生命周期。

Architecture

下图展示了 Mesh DFU 的整体架构与数据流向:

flowchart TD
    subgraph sg_App["APP / 手机端"]
        AppClient["APP Client"]
    end

    subgraph sg_Dist["Distributor 设备 (SIG_MESH_DFU_DISTRIBUTOR_DEMO)"]
        CmdProto["mesh_dfu_app_cmd_protocol.c<br/>命令协议 / SN 校验 / 应答"]
        Loader["mesh_distributor_loader.c<br/>读取固件文件 + CRC-16-XMODEM"]
        FlashCfg["Flash 配置区<br/>mnt/sdfile/app/mesh"]
        MeshTx["Mesh 模型发送<br/>(sig_mesh_api)"]
        CmdProto --> Loader
        Loader --> FlashCfg
        Loader --> MeshTx
        CmdProto --> MeshTx
    end

    subgraph sg_Mesh["BLE Mesh 网络"]
        MeshNet["Mesh 消息 (广播/单播)"]
    end

    subgraph sg_Target["Target 设备 (SIG_MESH_DFU_TARGET_DEMO)"]
        MeshRx["mesh_target_node_ota.c<br/>状态机 / 分包接收"]
        FlashWrite["Flash 写入 (sfc)"]
        MeshRx --> FlashWrite
    end

    AppClient -->|"升级命令/固件信息"| CmdProto
    MeshTx --> MeshNet
    MeshNet --> MeshRx
    MeshRx -->|"应答/状态上报"| MeshNet
    MeshNet -->|"应答"| CmdProto

各组件职责:

  • mesh_dfu_app_cmd_protocol.c:定义 Distributor 与 APP 间的命令帧格式(帧头 0x5A、6 字节协议头、命令/响应标志位),维护 opcode_state_t dfu_app_cmd 做 SN 连续性校验,防止重放与乱序攻击;同时提供广播过滤数据供发现设备使用。
  • mesh_distributor_loader.c:负责从 flash 配置区(路径 mnt/sdfile/app/mesh)读取目标固件文件,计算 CRC-16-XMODEM(多项式 0x1021),按 4096+16 字节的读块大小切分,并驱动擦写与下发进度。
  • mesh_target_node_ota.c/h:Target 侧实现,按 dfu_node_cmd_type_t 命令类型(REQ/FILE_INFO/DATA/END/FAIL)驱动 MESH_TARGET_OTA_st_e 状态机,把收到的数据写入 flash。
  • app_mesh.c:应用主入口,初始化蓝牙协议栈,根据 CONFIG_MESH_MODEL 加载对应的 Mesh Demo 配置。

角色选择通过编译宏 CONFIG_MESH_MODEL == SIG_MESH_DFU_DISTRIBUTOR_DEMO 或 SIG_MESH_DFU_TARGET_DEMO 决定,相关代码均以该宏包裹(见 mesh_dfu_app_cmd_protocol.c、mesh_distributor_loader.c、mesh_target_node_ota.c)。

命令协议:Distributor 与 APP 的交互

帧格式与常量

mesh_dfu_app_cmd_protocol.c 定义了 Distributor 与 APP 之间的私有命令协议,关键常量如下:

#define CMD_HEADER_FLAG     0x5A

/* total length of Head flag, Length, Flag, OP, SN, CRC */
#define CMD_PROTOCOL_LENGTH 6

#define COMMAND_PACKET      0x81

#define NO_RESPONSE_PACKET  0x01

#define RESPONSE_PACKET     0x00

#define BUFFER_SIZE_TARGET  4096

Source: mesh_dfu_app_cmd_protocol.c

协议头固定 6 字节,依次为:帧头标志(0x5A)、长度、标志字节、操作码(OP)、序号(SN)、CRC。标志字节区分三类帧:

标志值含义
COMMAND_PACKET(0x81)APP 下发的命令帧
RESPONSE_PACKET(0x00)Distributor 的应答帧
NO_RESPONSE_PACKET(0x01)无需应答的帧

命令处理过程中,固件数据被累积到全局缓冲区 global_buffer(global_buffer_size / global_buffer_used 跟踪使用量),global_file_size 记录固件总大小;dfu_cfg_block_data[200] 用于承载固件配置块信息。

SN 防重放校验

SN(序号)校验由 opcode_state_t dfu_app_cmd 维护,逻辑如下:

static bool check_sn(opcode_state_t *op, uint8_t sn)
{
    if (!op->valid) {
        /* If the op was not previously recorded, it is considered valid (initialized) */
        op->prev_sn = sn;
        op->valid = true;
        return true;
    }

    /* Check the serial number for legitimacy */
    if (sn == (op->prev_sn + 1) % 256) {
        /* Sequence number is legal, update prev_sn  */
        op->prev_sn = sn;
        return true;
    }

    /* Sequence number is not legal, could be a retransmission or an attack */
    return false;
}

Source: mesh_dfu_app_cmd_protocol.c

设计意图:SN 按 (prev_sn + 1) % 256 严格递增。首次收到任意 SN 即认为合法(初始化);此后非连续序号一律拒绝,从而同时防御重放攻击(重复的旧序号)和乱序/丢包(跳过序号)。clear_sn() 用于会话结束或复位时把 valid 置为 false,重新开始计数。由于 SN 只有 8 位,循环 256 个包后复用,适合每包数据量较小、单次升级包数可控的固件传输场景。

广播过滤与设备发现

Distributor 通过 get_mesh_dfu_adv_filter() 向广播数据中附加厂商过滤字段,用于让 APP 识别可升级设备:

void get_mesh_dfu_adv_filter(u8 *len, u8 **data)
{
    u8 adv_filter[] = {0x04, 0x16, 0x00, 0xBD, 0x01};
    u8 adv_len = 0x5;

    memcpy((*data) + (*len), adv_filter, adv_len);
    *len += adv_len;
}

Source: mesh_dfu_app_cmd_protocol.c

该字段格式为 BLE AD Type 0x16(Service Data)+ 16 位 Company ID 0x01BD(杰理/JieLi 的 SIG 公司标识),配合 0x04 长度字节。APP 侧扫描到该 Service Data 即可判定这是支持 Mesh DFU 的 Distributor 设备。

固件文件读取与校验:mesh_distributor_loader.c

Distributor 侧固件管理由 mesh_distributor_loader.c 承担。它把目标固件 bin 文件预先存放在 flash 配置区(路径 mnt/sdfile/app/mesh,由 isd_config_rule.c 配置),运行时按块读取并下发。

CRC-16-XMODEM 校验

每个下发块都带 CRC 校验,采用 CRC-16-XMODEM(多项式 0x1021):

static uint16_t crc16_xmodem(const uint8_t *data, size_t length, uint16_t crc)
{
    for (size_t i = 0; i < length; i++) {
        crc ^= (uint16_t)data[i] << 8; // 将当前字节移入CRC高位
        for (int j = 0; j < 8; j++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ POLY; // 如果最高位为1,左移并异或多项式
            } else {
                crc <<= 1; // 否则直接左移
            }
        }
    }
    return crc;
}

Source: mesh_distributor_loader.c

逐字节、逐位(8 轮)的软件实现,每次先左移 8 位再按最高位决定是否异或多项式。它同时被 Distributor(计算发送块 CRC)和 Target(校验接收块 CRC)使用,保证两端算法一致。

Flash 配置区擦除与读取

下发前需要确保目标 flash 区域可写,mesh_dis_loader_info_zone_earse() 负责擦除:

static bool mesh_dis_loader_info_zone_earse(u32 fsize, u32 sclust)
{
    if (!fsize || !sclust) {
        log_error("please enter the correct file size and address!");
        return false;
    }

    if (sfc_erase_zone(sclust, fsize)) {
        log_info("erase ok!");
        return true;
    } else {
        log_error("erase fail!");
        return false;
    }
}

Source: mesh_distributor_loader.c

要点:

  • 参数为文件大小 fsize 与起始簇地址 sclust,两者任一为 0 直接失败——这是防止误擦除全盘的保护性检查;
  • 通过 sfc_erase_zone()(串行 flash 控制器擦除接口)按扇区擦除;
  • 文件句柄 mesh_distributor_loader_fp、读取偏移 mesh_dist_loader_cur_offset(volatile,供回调/中断上下文读取)以及完成回调 mesh_dist_complete_cb 构成文件读取的三要素。

分块读取

读块大小常量:

#define OTA_READ_FLASH_SIZE       (4096 + 16)

Source: mesh_distributor_loader.c

每次从 flash 读取 4096 字节固件数据外加 16 字节头/校验信息,装入 test_buffer[OTA_READ_FLASH_SIZE] 后交由上层组包发送。4096 字节与 BUFFER_SIZE_TARGET 保持一致,保证单次读出的数据块恰好是 Target 单次可处理的最大负载。

Core Flow:一次完整的 Mesh DFU 升级

以下时序图展示了从 APP 发起升级到 Target 写入完成的完整链路:

sequenceDiagram
    participant APP as APP / 手机端
    participant D as Distributor<br/>(cmd_protocol + loader)
    participant M as Mesh 网络
    participant T as Target 节点<br/>(mesh_target_node_ota)

    APP->>D: 命令帧 (0x5A + OP + SN + CRC)
    D->>D: check_sn 校验序号连续性
    D->>D: 解析 OP / 累积数据到 global_buffer
    D->>D: 读取固件文件 (mnt/sdfile/app/mesh)
    D->>D: crc16_xmodem 计算发送块 CRC
    D->>M: Mesh 模型消息 (DFU_NODE_OTA_DATA)
    M->>T: 广播/单播转发
    T->>T: 状态机推进 (IDLE→REQ→CHECK_FILESIZE→WRITE_DATA)
    T->>T: 校验 CRC / 写入 flash (sfc)
    T-->>M: 应答帧 (RESPONSE_PACKET 0x00 / 错误码)
    M-->>D: 应答消息
    D-->>APP: 应答帧 (含状态/错误码)

流程要点:

  1. 命令接收:APP 发送以 0x5A 开头的命令帧,Distributor 的 check_sn() 先做序号校验,非法序号(重放/乱序)直接丢弃。
  2. 文件装载:确认升级意图后,mesh_distributor_loader.c 打开 mnt/sdfile/app/mesh 下的固件文件,必要时先 sfc_erase_zone 擦除目标区域。
  3. 分块发送:每次读取 4096+16 字节,计算 CRC-16-XMODEM 后组包,经 Mesh 模型发送接口(sig_mesh_api)下发。
  4. Target 接收:mesh_target_node_ota.c 按 dfu_node_cmd_type_t 解析命令,驱动状态机完成写 flash;每步可回送应答(RESPONSE_PACKET 0x00)或错误码。
  5. 会话结束:收到 DFU_NODE_OTA_END 后 Target 进入 MESH_TARGET_OTA_STATE_COMPLETE;任一步骤失败则进入 MESH_TARGET_OTA_STATE_WRITE_ERROR 并上报 DFU_NODE_OTA_FAIL。

Target 节点状态机

mesh_target_node_ota.h 定义了 Target 侧 flash 写入状态:

stateDiagram-v2
    [*] --> IDLE
    IDLE --> REQ: DFU_NODE_OTA_REQ (1)
    REQ --> CHECK_FILESIZE: DFU_NODE_OTA_FILE_INFO (2)
    CHECK_FILESIZE --> WRITE_DATA: DFU_NODE_OTA_DATA (3)
    WRITE_DATA --> WRITE_DATA: 连续数据包 / CRC 通过
    WRITE_DATA --> WRITE_ERROR: CRC 失败 / 写失败 / 序号错误
    WRITE_DATA --> COMPLETE: DFU_NODE_OTA_END (4)
    WRITE_ERROR --> IDLE: DFU_NODE_OTA_FAIL (5) / 复位
    COMPLETE --> [*]

对应枚举(mesh_target_node_ota.h):

typedef enum {
    MESH_TARGET_OTA_STATE_IDLE = 0,
    MESH_TARGET_OTA_STATE_REQ,
    MESH_TARGET_OTA_STATE_CHECK_FILESIZE,
    MESH_TARGET_OTA_STATE_WRITE_DATA,
    MESH_TARGET_OTA_STATE_COMPLETE,
    MESH_TARGET_OTA_STATE_WRITE_ERROR,
} MESH_TARGET_OTA_st_e;

命令类型(mesh_target_node_ota.h):

typedef enum {
    DFU_NODE_OTA_REQ = 1,
    DFU_NODE_OTA_FILE_INFO,
    DFU_NODE_OTA_DATA,
    DFU_NODE_OTA_END,
    DFU_NODE_OTA_FAIL,
} dfu_node_cmd_type_t;

设计意图:把"请求-文件信息-数据-结束-失败"五类命令显式建模,使 Target 的状态迁移完全由命令驱动、无歧义;WRITE_DATA 状态可自循环接收连续数据包,直到 END 命令收敛到 COMPLETE,任何异常统一汇入 WRITE_ERROR,避免悬挂状态。

错误码定义

Target 操作结果通过以下枚举返回给 Distributor/APP(mesh_target_node_ota.h):

错误码值含义
MESH_TARGET_OTA_OP_SUCC0成功
MESH_TARGET_OTA_OP_NO_SPACE1flash 空间不足
MESH_TARGET_OTA_OP_INIT_FAIL2初始化失败
MESH_TARGET_OTA_OP_WRITE_FAIL3flash 写入失败
MESH_TARGET_OTA_OP_CRC_FAIL4CRC 校验失败
MESH_TARGET_OTA_OP_MALLOC_FAIL5内存申请失败
MESH_TARGET_OTA_OP_PKT_NUM_ERR6包序号错误
MESH_TARGET_OTA_OP_LEN_ERR7长度错误
MESH_TARGET_OTA_OP_OTHER_ERR8其他错误

Configuration Options

Mesh 模型与 DFU 的配置集中在编译宏与 flash 配置规则中:

配置项类型默认/可选值说明
CONFIG_MESH_MODEL编译宏SIG_MESH_DFU_DISTRIBUTOR_DEMO / SIG_MESH_DFU_TARGET_DEMO选择设备角色:Distributor(升级分发)或 Target(升级执行);决定 mesh_dfu 目录下哪份代码被编译
mesh_dist_loader_test_en宏0是否开启 loader 自测试(见 mesh_distributor_loader.c)
mesh_dist_loader_path字符串mnt/sdfile/app/mesh固件 bin 在 flash 配置区中的存放路径(见 mesh_distributor_loader.c)
OTA_READ_FLASH_SIZE宏4096 + 16每次从 flash 读取的固件块大小
BUFFER_SIZE_TARGET宏4096Target 单包可处理的最大负载
CMD_HEADER_FLAG宏0x5A命令帧帧头标志
CMD_PROTOCOL_LENGTH宏6协议头长度(Head flag/Length/Flag/OP/SN/CRC)
POLY宏0x1021CRC-16-XMODEM 多项式

注意:mesh_dfu_app_cmd_protocol.c 与 mesh_distributor_loader.c 整体被 #if (CONFIG_MESH_MODEL == SIG_MESH_DFU_DISTRIBUTOR_DEMO) 包裹,Target 侧文件同理,因此配置宏直接决定链接进固件的 DFU 代码路径。

API Reference

以下为 Mesh DFU 模块对外暴露的关键接口(均为 C 函数,实现在 apps/mesh/mesh_dfu 目录)。

get_mesh_dfu_adv_filter(u8 *len, u8 **data)

向广播数据末尾追加 Mesh DFU 厂商 Service Data 过滤字段(0x16 + Company ID 0x01BD)。

参数:

  • len(u8 *):输入为当前广播数据长度,输出为追加后的总长度;
  • data(u8 **):指向广播数据缓冲区的指针,函数在 (*data) + (*len) 处写入过滤字段。

返回: 无(通过 len 输出新长度)。实现在 mesh_dfu_app_cmd_protocol.c。

clear_sn(void)

复位 SN 校验状态:将 dfu_app_cmd.valid 置为 false,使下一个到达的 SN 重新作为基准。用于升级会话开始/结束时重置防重放计数。实现在 mesh_dfu_app_cmd_protocol.c。

check_sn(opcode_state_t *op, uint8_t sn)

校验序号连续性(详见"SN 防重放校验"一节)。

参数:

  • op(opcode_state_t *):序号状态结构体,含 prev_sn 与 valid;
  • sn(uint8_t):本次接收的序号。

返回: true 表示序号合法(首次或 (prev_sn + 1) % 256 连续);false 表示重放/乱序/攻击,调用方应丢弃该帧。实现在 mesh_dfu_app_cmd_protocol.c。

crc16_xmodem(const uint8_t *data, size_t length, uint16_t crc)

计算 CRC-16-XMODEM 校验值(多项式 0x1021),Distributor 发送块与 Target 接收块共用同一实现。

参数:

  • data(const uint8_t *):输入数据指针;
  • length(size_t):数据长度;
  • crc(uint16_t):初始 CRC 值(通常为 0x0000)。

返回: 计算后的 16 位 CRC。实现在 mesh_distributor_loader.c。

mesh_dis_loader_info_zone_earse(u32 fsize, u32 sclust)

擦除 flash 配置区中用于存放目标固件的区域。

参数:

  • fsize(u32):固件文件大小;
  • sclust(u32):起始簇地址。

返回: true 擦除成功;false 参数非法或 sfc_erase_zone 失败。实现在 mesh_distributor_loader.c。

mesh_dist_loader_complete_cb(回调)

mesh_distributor_loader.c 中保存的 static void (*mesh_dist_loader_complete_cb)(void),在固件文件装载完成后由 loader 调用,用于通知命令协议层可以开始发送(见 mesh_distributor_loader.c)。

失败模式、边界情况与并发

重放/乱序攻击:check_sn 的严格递增策略可拒绝重放旧包;但代价是丢包会导致会话中断,需要 APP 侧重发整个会话或重新建立 SN 基准(调用 clear_sn)。

CRC 失败:Target 侧对每个数据块做 CRC-16-XMODEM 校验,失败返回 MESH_TARGET_OTA_OP_CRC_FAIL(4)并进入 WRITE_ERROR 状态,上报 DFU_NODE_OTA_FAIL——此时 Distributor 需要重新发起升级,不提供块级重传。

flash 擦写失败:mesh_dis_loader_info_zone_earse 对 fsize == 0 || sclust == 0 直接拒绝,防止空参数误擦除;sfc_erase_zone 失败返回 false,上层应终止流程。Target 写 flash 失败返回 MESH_TARGET_OTA_OP_WRITE_FAIL(3)。

内存压力:Target 侧接收使用 global_buffer(动态分配,global_buffer_size/global_buffer_used 跟踪),内存申请失败对应 MESH_TARGET_OTA_OP_MALLOC_FAIL(5);dfu_cfg_block_data[200] 为栈上固定缓冲,承载配置块。

并发/中断:mesh_dist_loader_cur_offset 声明为 volatile,因为读取进度可能被中断回调或事件循环并发访问;mesh_dist_loader_fp 为模块级文件句柄,同一时刻只允许一个升级会话,避免并发打开导致文件指针错乱。SN 状态 dfu_app_cmd 为模块级静态变量,天然串行化命令处理。

包序/长度:MESH_TARGET_OTA_OP_PKT_NUM_ERR(6)与 MESH_TARGET_OTA_OP_LEN_ERR(7)覆盖 Mesh 层分包乱序或长度不符的场景,Target 依据 DFU_NODE_OTA_DATA 内的包号/长度字段做校验。

性能与运维注意点

  • 分块粒度:单次读取/发送 4096 字节(+16 字节开销),在 Mesh 低功耗广播带宽下是较保守的块大小,兼顾吞吐与丢包影响面;增大块大小可提升吞吐但会放大单包失败损失。
  • CRC 计算开销:逐位软件实现,CPU 占用随块大小线性增长;如性能敏感可换用查表法,但需保证 Distributor 与 Target 两端算法一致。
  • 广播过滤字段:0x16 Service Data + Company ID 0x01BD 用于 APP 侧设备发现,修改需与 APP 端同步,否则设备无法被识别。
  • 升级中断恢复:状态机没有持久化断电续传机制,断电/复位后回到 IDLE,需重新发起完整升级。
  • 日志开关:各文件通过 mesh_log.h 的 LOG_INFO_ENABLE/LOG_DEBUG_ENABLE/LOG_ERROR_ENABLE/LOG_CLI_ENABLE 控制日志级别,排查问题时可按需打开 LOG_DEBUG_ENABLE 观察分包与状态迁移。

扩展点

  • 新命令类型:在 dfu_node_cmd_type_t 中追加枚举值,并在 Target 状态机中增加对应迁移分支,即可扩展协议(如块级重传、断点续传)。
  • 新校验算法:crc16_xmodem 是唯一校验入口,替换为其他 CRC 或哈希只需改动该函数,协议帧格式不受影响。
  • 新固件存放介质:mesh_dist_loader_path 与 mesh_dist_loader_fp 抽象了文件来源,可替换为其他介质(如外部存储)而不改命令协议层。
  • 角色扩展:CONFIG_MESH_MODEL 的 #if 隔离使新增角色(如同时具备 Distributor 与 Target 能力的中继节点)只需新增一个宏值并复用现有源文件。

Related Links

  • apps/mesh 应用工程入口(app_mesh.c)
  • Mesh 公共配置(apps/mesh/api/mesh_config_common.c)
  • SIG Mesh API(sig_mesh_api.h)
  • SIG Mesh 配置(mesh_config.h)
  • Distributor 命令协议实现
  • Distributor 固件装载实现
  • Target OTA 实现
  • Target OTA 头文件(状态/命令/错误码定义)
  • Tencent LLsync Mesh 示例(apps/mesh/examples/tencent_mesh.c)
Prev
Bluetooth Mesh 应用框架
Next
Mesh 音频编解码演示