杰理 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)
  • 文档与开发资源

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

华为 HiLink 接入

本文档介绍 AC63 系列蓝牙 SoC SDK 中接入华为 HiLink(华为智能家居/智慧生活)生态的实现,涵盖 HiLink 协议栈、任务调度、GATT Profile、OTA 升级与应用集成的完整机制。

Purpose and Scope

本页面向希望在 AC63 SDK 上开发 HiLink 设备的开发者,完整说明 HiLink 接入能力的端到端实现:

  • HiLink 协议栈(hilink_protocol.c/h):消息编解码、命令类型、AES-GCM 加解密相关定义;
  • 任务调度层(hilink_task.c/h):基于环形缓冲区 + 信号量的独立任务,负责 BLE 数据包的接收与分发;
  • HiLink OTA(hilink_ota.c/h):基于双 Bank 升级的固件空中升级通道;
  • BLE GATT Profile(hilink_profile.h):华为 HiLink 私有服务与特征值的二进制 Profile 定义;
  • 应用集成(app_hilink.c、app_main.c):应用入口、蓝牙初始化、软关机与线程创建。

与 HiLink 相关的密钥协商细节、华为云账号绑定流程属于华为私有协议,SDK 中仅保留数据结构与消息入口,具体字节级语义以仓库内 doc/HiLink协议开发说明/HiLink协议开发说明.pdf 及华为官方文档为准。其他第三方接入(如涂鸦、米家等)不在本页范围内,参见目录中对应的第三方集成页面。

Overview

华为 HiLink 是华为面向智能家居设备推出的互联协议。在 AC63 蓝牙 SDK 中,设备以 BLE GATT 从机 身份暴露华为定义的私有服务(UUID 前缀 15F1E6xx-A277-43FC-A484-DD39EF8A9100),通过特征值读写承载 HiLink 消息。手机端华为智慧生活 App 作为 GATT 主机发起连接、配对与数据交互。

整个接入采用"协议栈 + 独立任务 + 应用壳"的三层结构:

  1. 协议层负责 HiLink 消息的编解码、设备信息描述(dev_info_t)与认证信息管理(hi_auth_info_t),并对消息按 REQ/RSP/RPT(请求/响应/上报)分类;
  2. 任务层(hilink_task)把 BLE 控制器回调上来的裸数据写入环形缓冲区(cbuf),由独立任务按包头中的通道号分发到设备信息消息处理(hilink_msg_handle)或 OTA 控制/数据通道;
  3. 应用层(app_hilink.c)负责系统启动流程:切换时钟、初始化 EDR/BLE、注册 Profile、处理电源事件与软关机。

该设计把协议处理与 BLE 协议栈解耦:即便蓝牙链路抖动或数据突发,环形缓冲 + 信号量也能平滑吸收,协议解析不阻塞蓝牙任务;OTA 通道与设备信息通道分离,保证升级大流量数据与业务消息互不干扰。

Architecture

flowchart TD
    subgraph sg_App["应用层 apps/spp_and_le/examples/hilink"]
        AppHilink["app_hilink.c<br/>应用状态机/启动/软关机"]
        Profile["hilink_profile.h<br/>HiLink GATT Profile"]
        AppMain["app_main.c<br/>创建 hilink_task 线程"]
    end

    subgraph sg_Protocol["HiLink 协议栈 apps/common/third_party_profile/hilink_protocol"]
        Task["hilink_task.c<br/>环形缓冲+信号量分发"]
        Proto["hilink_protocol.c<br/>消息解析/设备与认证信息"]
        Ota["hilink_ota.c<br/>OTA 控制/数据通道"]
    end

    subgraph sg_Bt["蓝牙协议栈"]
        BtStack["btstack<br/>BLE GATT/ATT"]
    end

    subgraph sg_Hw["硬件/系统服务"]
        Flash["dual_bank_updata_api<br/>双 Bank Flash 升级"]
        Power["电源管理<br/>软关机"]
    end

    AppMain -->|"task_create hilink_task"| Task
    BtStack -->|"hilink_packet_recieve"| Task
    Task -->|"HILINK_DEVICE_INFO_MSG_CH"| Proto
    Task -->|"HILINK_OTA_CTL/DATA_MSG_CH"| Ota
    AppHilink -->|"注册/使用"| Profile
    Profile --> BtStack
    Ota --> Flash
    AppHilink --> Power

架构说明:app_main.c 在系统启动时按 CONFIG_APP_HILINK 创建 hilink_task 线程(见 app_main.c),BLE 协议栈通过 hilink_packet_recieve() 把收到的数据写入任务层环形缓冲区;任务按包头的 packet_channel 分发给协议层或 OTA 层。hilink_profile.h 中定义的 GATT 表由应用层注册进 btstack,手机 App 通过读写/指示特征值完成与协议层的双向数据交换。OTA 通道最终调用 dual_bank_updata_api 落盘到 Flash,实现断点续传式的固件升级。

classDiagram
    class dev_info_t {
        +const char *prodId
        +const char *sn
        +const char *dev_id
        +const char *model
        +const char *dev_t
        +const char *manu
        +const char mac[18]
        +const char *hiv
        +const char *fwv
        +const char *hwv
        +const char *swv
        +const char *prot_t
    }
    class hi_auth_info_t {
        +uint8_t hilink_authcode[16]
        +uint8_t hilink_sessionkey[16]
        +uint8_t sessid[32]
        +uint8_t hilink_authcodeid_tmp[33]
        +uint8_t hilink_hmackey[32]
        +char time[13]
        +uint8_t hilink_pair_flag
        +hi_attribute_t hilink_attr
    }
    class hi_msg_store_t {
        +uint8_t msg_id
        +uint16_t data_len
        +uint16_t data_index
        +uint8_t *data
    }
    hi_auth_info_t --> hi_attribute_t : "包含属性"
    dev_info_t ..> hi_auth_info_t : "配套使用"

以上类型定义取自 hilink_protocol.h:dev_info_t 描述设备身份(产品 ID、SN、型号、MAC、各版本号),hi_auth_info_t 承载配网/认证后的会话材料(认证码、会话密钥、会话 ID、HMAC 密钥),hi_msg_store_t 用于暂存分片消息。

核心模块与实现分析

1. 协议层:hilink_protocol

协议头文件 hilink_protocol.h 定义了 HiLink 消息的基本契约:

宏值含义
HILINK_MCU0标识设备端为 MCU(非 SoC 主控)
AES128_KEY_LENGTH128AES-128 密钥长度(bit)
GCM_TAG_LEN16GCM 认证标签长度(字节)
CMD_TYPE_REQ0命令类型:请求
CMD_TYPE_RSP1命令类型:响应
CMD_TYPE_RPT2命令类型:上报(主动上报状态/事件)
MSG_WITHOUT_ENCRY0消息明文传输
MSG_ENCRY1消息加密传输

设计意图:命令类型三态(REQ/RSP/RPT)是 HiLink 消息体系的基础——App 下发指令为 REQ,设备处理完毕回 RSP,设备状态变化主动推送用 RPT。加解密开关 MSG_ENCRY 配合 AES128_KEY_LENGTH/GCM_TAG_LEN 表明协议采用 AES-128-GCM 认证加密:GCM 同时提供机密性与完整性保护,防止中间人篡改固件或控制指令,这是 HiLink 安全模型的核心。

协议对外只暴露一个处理入口:

void hilink_msg_handle(uint8_t *buf, uint16_t len);

它接收完整的一条 HiLink 消息(已由任务层组包完成),在 hilink_protocol.c 内部完成解密、解析与业务分发。hi_msg_store_t 的存在说明协议支持分片消息重组(data_len + data_index 记录片段的长度与偏移),用于承载超过单包 MTU 的长消息。

2. 任务调度层:hilink_task

任务层 hilink_task.c 是 HiLink 数据通路的"心脏",由三部分组成:

a) 全局控制块:HILINK_PACKET_CONTROL HILINK_packet_c,内含信号量 hilink_sem、环形缓冲区 cbuf 及其内存 hilink_buf。

b) 任务主循环:hilink_task() 永久阻塞在 os_sem_pend 上,被唤醒后检查 cbuf 中是否凑齐一帧(数据长度 > HILINK_PACKET_HEAD_LEN 包头长度),随后:

  1. 读取包头(含包长 len 与通道号 packet_channel);
  2. malloc(len) 分配一帧缓冲区;
  3. 读取整帧数据;
  4. 按通道号分发:
    • HILINK_DEVICE_INFO_MSG_CH → hilink_msg_handle()(业务/设备信息消息);
    • HILINK_OTA_CTL_MSG_CH → hilink_ota_ctl_deal()(OTA 控制:开始/校验/结束);
    • HILINK_OTA_DATA_MSG_CH → hilink_ota_data_deal()(OTA 数据块写入);
  5. free(buffer) 释放。

设计意图:把"接收"(BLE 中断/回调上下文)与"处理"(任务上下文)分离——接收侧只做 cbuf_write 快速入队,处理侧在独立线程中慢速消费,天然实现生产者-消费者解耦,避免在蓝牙回调里做加解密等耗时操作导致丢包。

c) 初始化与接收接口:

int hilink_task_init(void)
{
    os_sem_create(&(__this->hilink_sem), 0);
    u32 malloc_size = HILINK_MSG_POOL_SIZE;
    __this->hilink_buf = malloc(malloc_size);
    memset(__this->hilink_buf, 0x0, malloc_size);
    cbuf_init(&(__this->cbuf), __this->hilink_buf, malloc_size);
    int ret = task_create(hilink_task, 0, "hilink_task");
    if (ret) {
        log_info("hilink task create error:%d", ret);
    }
    return 0;
}

void hilink_packet_recieve(void *buf, u16 len)
{
    if (cbuf_is_write_able(&(__this->cbuf), len) >= len) {
        cbuf_write(&(__this->cbuf), buf, len);
    } else {
        log_info("[L]\n");
    }
    os_sem_post(&(__this->hilink_sem));
}

来源:hilink_task.c

设计意图:hilink_packet_recieve 是 BLE 协议栈到 HiLink 任务层的唯一入口,任何 GATT Write 收到的裸数据都经此入队。cbuf_is_write_able 的容量检查保证环形缓冲区永不溢出;写满时打印 [L](overflow 简记)并丢弃,属于有界背压策略——宁可丢帧也不破坏缓冲区一致性。task_create 创建的线程在 app_main.c 中定义为 {"hilink_task", 2, 0, 1024, 0}(优先级 2、栈 1024 字)。

3. OTA 升级:hilink_ota

hilink_ota.c 实现 HiLink 固件空中升级:

  • 依赖 dual_bank_updata_api.h(双 Bank 升级接口)与 hilink_ota.h;
  • 维护三个静态状态对象:
    • hilink_ota_t hilink_ota —— 当前升级会话(进度、分块参数);
    • hilink_hash_list_t hilink_hash —— 分块哈希链表,用于逐块校验数据完整性;
    • hilink_signature_t hilink_signature —— 整包签名校验;
  • 通过 extern dev_info_t *hilink_info 与 extern uint16_t hilink_mtu 读取设备信息与协商后的 MTU;
  • 关键函数:ota_reply(uint8_t clean_map) 回复 OTA 结果(并按需清理升级区映射)、hilink_ota_rsp_send(uint16_t op, ...) 发送 OTA 命令响应。

设计意图:双 Bank(A/B)升级机制保证升级失败时可回滚到上一版本;逐块哈希 + 整包签名构成"边收边验"链路——App 分块下发,设备每块校验哈希,最后校验整体签名,任何篡改都会导致升级中止并回滚,符合 HiLink 对固件安全的要求。MTU 协商结果(hilink_mtu)用于决定单帧 OTA 数据块大小,最大化吞吐同时避免超出链路 MTU。

4. 应用集成:app_hilink.c 与 app_main.c

apps/spp_and_le/examples/hilink/app_hilink.c 是 HiLink Demo 应用(以 CONFIG_APP_HILINK 编译开关启用),职责包括:

  • 启动序列 hilink_app_start():打印 banner → 首次进入时 clk_set("sys", BT_NORMAL_HZ) 切到蓝牙工作频率 → bt_pll_para() 配置 PLL → 按 TCFG_USER_EDR_ENABLE/TCFG_USER_BLE_ENABLE 分别 btstack_edr_start_before_init / btstack_ble_start_before_init → btstack_init() 完成协议栈初始化 → sys_key_event_enable() 使能按键;
  • BLE 初始化配置:hilink_data_ble_config 设置 appearance = BD_CLASS_HEADPHONES,并依据 DOUBLE_BT_SAME_MAC 决定 EDR/BLE 是否同 MAC;
  • 电源事件 hilink_power_event_to_user():把电源事件包装成 SYS_DEVICE_EVENT 通过 sys_event_notify 广播;
  • 软关机 hilink_set_soft_poweroff():先主动断开蓝牙链路(btstack_ble_exit/btstack_edr_exit),延时 WAIT_DISCONN_TIME_MS(300ms) 确保链路断开后调用 power_set_soft_poweroff()——注释明确说明"必须先主动断开蓝牙链路,否则要等链路超时断开",避免关机时序问题;
  • 状态机 hilink_state_machine():标准杰理应用状态机(APP_STA_CREATE → ...),处理应用创建、消息分发等生命周期。
static void hilink_set_soft_poweroff(void)
{
    log_info("set_soft_poweroff\n");
    is_app_hilink_active = 1;
    //必须先主动断开蓝牙链路,否则要等链路超时断开

#if TCFG_USER_BLE_ENABLE
    btstack_ble_exit(0);
#endif

#if TCFG_USER_EDR_ENABLE
    btstack_edr_exit(0);
#endif

#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
    //延时300ms,确保BT退出链路断开
    sys_timeout_add(NULL, power_set_soft_poweroff, WAIT_DISCONN_TIME_MS);
#else
    power_set_soft_poweroff();
#endif
}

来源:app_hilink.c

在 app_main.c 中,CONFIG_APP_HILINK 同时决定线程表项({"hilink_task", 2, 0, 1024, 0})与应用启动动作 ACTION_HILINK_MAIN(it.name = "hilink"),即编译该宏后系统会自动拉起 HiLink 任务并进入 HiLink 应用。

BLE GATT Profile:hilink_profile.h

华为 HiLink 依赖一组固定的 BLE 服务。hilink_profile.h 中的 hilink_profile_data[] 是二进制 GATT 表(由杰理 gatt_inc_generator.exe 工具生成),定义如下结构:

Handle类型UUID属性
0x0001PRIMARY_SERVICE0x1800 (GAP)-
0x0003VALUE0x2A00 (Device Name)READ | DYNAMIC
0x0004PRIMARY_SERVICE0x1801 (GATT)-
0x0006VALUE0x2A05 (Service Changed)INDICATE
0x0007CCCD0x2902-
0x0008PRIMARY_SERVICE15F1E600-A277-43FC-A484-DD39EF8A9100HiLink 控制服务
0x000AVALUE15F1E601-...-DD39EF8A9100INDICATE | READ | DYNAMIC
0x000BCCCD0x2902-
0x000DVALUE15F1E602-...-DD39EF8A9100WRITE | DYNAMIC
0x000EPRIMARY_SERVICE15F1E610-A277-43FC-A484-DD39EF8A9100HiLink OTA 服务
0x0010VALUE15F1E611-...-DD39EF8A9100INDICATE | WRITE | DYNAMIC
0x0011CCCD0x2902-
0x0013VALUE15F1E612-...-DD39EF8A9100WRITE_WITHOUT_RESPONSE | DYNAMIC

来源:hilink_profile.h

通道语义(结合任务层分发逻辑):

  • 15F1E601(下行→设备):手机 Write,走 HILINK_DEVICE_INFO_MSG_CH,即普通 HiLink 业务消息(配网、属性控制、查询等);
  • 15F1E602(设备→上行):设备 Indicate,用于回复/上报,App 订阅后通过 CCCD 0x000B 接收;
  • 15F1E611(OTA 双向):OTA 控制通道(开始/停止/校验/响应),走 HILINK_OTA_CTL_MSG_CH;
  • 15F1E612(OTA 下行大流量):Write Without Response,承载 OTA 数据分块,走 HILINK_OTA_DATA_MSG_CH——无响应对写避免逐包握手,是升级吞吐的关键。

设计意图:业务通道与 OTA 通道分开(两个服务、四个特征值),使升级大流量数据不阻塞业务消息处理;OTA 数据用 WriteWithoutResponse 提升吞吐、控制命令用有响应 Write 保证可靠性、上行用 Indicate 由 App 主动订阅控制流量,是一套针对"控制面可靠、数据面高效"的典型 BLE 服务设计。

文件末尾导出了句柄宏(如 ATT_CHARACTERISTIC_15F1E601_A277_43FC_A484_DD39EF8A9100_01_VALUE_HANDLE 0x000a),应用层与协议栈通过这些宏直接引用特征值句柄,避免硬编码魔法数。

核心数据流

sequenceDiagram
    participant Phone as 华为智慧生活 App
    participant Bt as btstack BLE GATT
    participant Task as hilink_task 线程
    participant Proto as hilink_protocol.c
    participant Ota as hilink_ota.c
    participant Flash as 双 Bank Flash

    Note over Phone,Flash: 业务消息通路(设备信息通道)
    Phone->>Bt: Write 15F1E601 (HiLink 消息, 可加密)
    Bt->>Task: hilink_packet_recieve(buf, len)
    Task->>Task: cbuf_write + os_sem_post
    Task->>Task: 读包头, channel=DEVICE_INFO
    Task->>Proto: hilink_msg_handle(buf, len)
    Proto->>Proto: AES-128-GCM 解密/解析, REQ/RSP/RPT 分发
    Proto-->>Bt: 回写 Indicate (15F1E602)
    Bt-->>Phone: Indicate 通知

    Note over Phone,Flash: OTA 升级通路(控制 + 数据通道)
    Phone->>Bt: Write 15F1E611 OTA 控制(开始)
    Task->>Ota: hilink_ota_ctl_deal
    loop 逐块下发
        Phone->>Bt: WriteWithoutResponse 15F1E612 (数据块)
        Task->>Ota: hilink_ota_data_deal
        Ota->>Ota: 块哈希校验 (hilink_hash_list)
        Ota->>Flash: dual_bank 写入
    end
    Phone->>Bt: Write 15F1E611 OTA 结束/校验
    Task->>Ota: hilink_ota_ctl_deal
    Ota->>Ota: 整包签名校验 (hilink_signature)
    Ota->>Flash: 切换 Bank + 重启
    Ota-->>Phone: 通过 15F1E611 Indicate 回复结果

逐步说明:

  1. 入队:GATT Write 回调调用 hilink_packet_recieve,数据进入环形缓冲并 os_sem_post 唤醒任务——接收路径 O(1),不涉及任何协议解析;
  2. 组帧:hilink_task 依据包头长度字段判断帧完整性,malloc 后整帧读出,避免 cbuf 中残留半包;
  3. 分发:按 packet_channel 路由到协议层或 OTA 层,两个通道互不阻塞;
  4. 处理:协议层解密(AES-128-GCM)并解析为 REQ/RSP/RPT;OTA 层逐块校验哈希后写入双 Bank Flash;
  5. 回程:设备通过 Indicate 特征值向 App 上报结果/状态,App 侧收到通知后更新 UI 或发起下一动作。

异常路径:若 cbuf 容量不足(cbuf_is_write_able 失败),接收侧打印 [L] 并丢帧——由于协议层支持分片重组(hi_msg_store_t),对端会因缺少响应而重发,属于可恢复的丢包策略;malloc 失败时任务打印 buf malloc err 并退出循环,属致命错误,由系统 watchdog 兜底。

认证与设备信息

设备上电后需向 App 提供身份信息完成配网/绑定。dev_info_t 字段即为此设计:

字段长度约束说明
prodId(0,5]设备 HiLink 认证号
sn(0,40]设备唯一标识(SN)
dev_id-设备 ID
model(0,32]设备型号
dev_t(0,4]设备类型
manu(0,4]设备制造商
mac[18]固定 18 字节MAC 地址(字符串)
hiv(0,32]HiLink 协议版本
fwv[0,64]固件版本
hwv[0,64]硬件版本
swv[0,64]软件版本
prot_t[1,3]设备协议类型

来源:hilink_protocol.h

配网/认证成功后,hi_auth_info_t 保存会话密钥材料:hilink_authcode(16B 认证码)、hilink_sessionkey(16B 会话密钥,AES-GCM 加密数据用)、sessid(32B 会话 ID)、hilink_hmackey(32B HMAC 密钥)、time[13](时间戳,防重放)、hilink_pair_flag(配对标志)、hilink_attr(设备属性,如 onoff 开关状态)。hilink_authcodeid_tmp[33] 特意比 32 多 1 字节用于存放字符串结尾的 \0,注释直接标注了这一意图。

使用示例

示例 1:创建 HiLink 任务并接入数据接收

以下代码展示了 HiLink 任务层的初始化与接收接口——这是把 BLE 数据接入 HiLink 协议栈的标准写法(由 SDK 内部在启动时调用):

int hilink_task_init(void)
{
    os_sem_create(&(__this->hilink_sem), 0);
    u32 malloc_size = HILINK_MSG_POOL_SIZE;
    __this->hilink_buf = malloc(malloc_size);
    memset(__this->hilink_buf, 0x0, malloc_size);
    cbuf_init(&(__this->cbuf), __this->hilink_buf, malloc_size);
    int ret = task_create(hilink_task, 0, "hilink_task");
    if (ret) {
        log_info("hilink task create error:%d", ret);
    }
    return 0;
}

void hilink_packet_recieve(void *buf, u16 len)
{
    if (cbuf_is_write_able(&(__this->cbuf), len) >= len) {
        cbuf_write(&(__this->cbuf), buf, len);
    } else {
        log_info("[L]\n");
    }
    os_sem_post(&(__this->hilink_sem));
}

来源:hilink_task.c

示例 2:任务主循环的通道分发

BLE 数据入队后,任务线程按包头通道号分发——新增业务通道时在此扩展 switch:

switch (hilink_packet_head.packet_channel) {
case HILINK_DEVICE_INFO_MSG_CH:
    hilink_msg_handle(buffer, hilink_packet_head.len);
    break;
case HILINK_OTA_CTL_MSG_CH:
    hilink_ota_ctl_deal(buffer, hilink_packet_head.len);
    break;
case HILINK_OTA_DATA_MSG_CH:
    hilink_ota_data_deal(buffer, hilink_packet_head.len);
    break;
}

来源:hilink_task.c

示例 3:应用启动与 BLE 初始化

在 app_hilink.c 中,HiLink 应用首次启动时完成时钟切换、EDR/BLE 协议栈初始化与 GATT Profile 注册前置准备:

if (enter_btstack_num == 0) {
    enter_btstack_num = 1;
    clk_set("sys", BT_NORMAL_HZ);

#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
    u32 sys_clk =  clk_get("sys");
    bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);

#if TCFG_USER_EDR_ENABLE
    btstack_edr_start_before_init(NULL, 0);
#endif

#if TCFG_USER_BLE_ENABLE
    btstack_ble_start_before_init(&hilink_data_ble_config, 0);
#endif

    btstack_init();
#else
    printf("no bt!!!");
#endif
}
/* 按键消息使能 */
sys_key_event_enable();

来源:app_hilink.c

示例 4:GATT 特征值句柄宏

hilink_profile.h 末尾导出特征值句柄宏,业务代码通过宏引用而非硬编码句柄值:

#define ATT_CHARACTERISTIC_2A00_01_VALUE_HANDLE 0x0003
#define ATT_CHARACTERISTIC_2a05_01_VALUE_HANDLE 0x0006
#define ATT_CHARACTERISTIC_2a05_01_CLIENT_CONFIGURATION_HANDLE 0x0007
#define ATT_CHARACTERISTIC_15F1E601_A277_43FC_A484_DD39EF8A9100_01_VALUE_HANDLE 0x000a

来源:hilink_profile.h

配置选项

HiLink 功能通过编译宏与线程表项启用,无运行时配置文件:

配置项类型默认值说明
CONFIG_APP_HILINK编译宏未定义定义后编译 HiLink Demo 应用,创建 hilink_task 线程并设置 ACTION_HILINK_MAIN 启动动作
hilink_task 线程项线程表项优先级 2 / 栈 1024在 app_main.c 中定义({"hilink_task", 2, 0, 1024, 0})
HILINK_MSG_POOL_SIZE宏由 hilink_task.h 定义环形缓冲池大小,决定可缓冲的帧数上限
HILINK_PACKET_HEAD_LEN宏由 hilink_task.h 定义帧头长度(含包长与通道号)
HILINK_DEVICE_INFO_MSG_CH / HILINK_OTA_CTL_MSG_CH / HILINK_OTA_DATA_MSG_CH宏由 hilink_task.h 定义通道号枚举,用于帧分发
TCFG_USER_BLE_ENABLE / TCFG_USER_EDR_ENABLE编译宏按工程是否启用 BLE/EDR 协议栈,直接决定 HiLink 启动路径
DOUBLE_BT_SAME_MAC编译宏按工程EDR 与 BLE 是否共用同一 MAC,影响 hilink_data_ble_config.same_address
HILINK 日志开关日志配置v/i/d/w/e 均使能见 log_config.c,LOG_TAG_CONST HILINK

API 参考

void hilink_msg_handle(uint8_t *buf, uint16_t len)

  • 描述:HiLink 业务消息唯一处理入口,接收完整一帧(已组包、含头部),内部完成解密、解析与 REQ/RSP/RPT 分发。定义于 hilink_protocol.h。
  • 参数:buf 消息帧指针;len 帧长度。
  • 返回:无。回复通过 GATT Indicate 特征值(15F1E602)异步发出。

int hilink_task_init(void)

  • 描述:初始化 HiLink 任务:创建信号量、分配 HILINK_MSG_POOL_SIZE 环形缓冲、创建 hilink_task 线程。见 hilink_task.c。
  • 返回:0 表示成功;task_create 返回非 0 时打印 hilink task create error:%d。

void hilink_packet_recieve(void *buf, u16 len)

  • 描述:BLE 协议栈数据接收接口(生产者侧):数据写入环形缓冲并唤醒任务线程。见 hilink_task.c。
  • 参数:buf 原始数据;len 数据长度。
  • 行为:缓冲不足时打印 [L] 并丢弃该帧(有界背压),随后仍 os_sem_post。

void hilink_ota_ctl_deal(void *buf, u16 len) / void hilink_ota_data_deal(void *buf, u16 len)

  • 描述:OTA 控制/数据通道处理函数(消费者侧),由 hilink_task 按通道号调用;内部完成块哈希校验(hilink_hash_list_t)、双 Bank 写入与整包签名校验(hilink_signature_t)。
  • 参数:buf OTA 帧数据;len 帧长度。
  • 返回:无,结果经 hilink_ota_rsp_send(op, buf, len) 回传。

void hilink_set_soft_poweroff(void)

  • 描述:HiLink 软关机流程:先断开 BLE/EDR 链路,延时 WAIT_DISCONN_TIME_MS(300ms) 后调用 power_set_soft_poweroff()。见 app_hilink.c。
  • 设计要点:必须先主动断开蓝牙,避免关机时等待链路超时。

void hilink_power_event_to_user(u8 event)

  • 描述:把电源事件包装为 SYS_DEVICE_EVENT(DEVICE_EVENT_FROM_POWER)广播给系统事件队列,供上层 UI/业务响应。
  • 参数:event 电源事件码。

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

缓冲溢出与丢帧

hilink_packet_recieve 中 cbuf_is_write_able 失败时打印 [L] 并丢弃整帧。这是有界背压设计:环形缓冲容量(HILINK_MSG_POOL_SIZE)决定吸收突发的能力。若手机端连续大流量写入(如 OTA 数据通道),而任务线程因加解密/Flash 写入繁忙,可能出现丢帧。由于协议层支持分片重组(hi_msg_store_t)且 OTA 通道有块哈希校验,对端(App 或 OTA 主控)检测到缺少响应后会重传,丢帧可恢复——但需保证重传机制存在,否则升级会停滞。

内存分配失败

任务主循环对每帧 malloc(len),失败时打印 buf malloc err 并 break 退出循环(线程结束)。这是致命路径:此后 hilink_packet_recieve 仍可写缓冲并 post 信号量,但无人消费,缓冲区最终写满后持续丢帧。生产环境依赖系统级 watchdog 或任务重启机制兜底;len 受帧头长度字段约束,理论上不应超过缓冲池大小,建议协议层对超长帧做拒收校验。

并发模型

  • 生产者:BLE 协议栈回调(中断/协议栈任务上下文)调用 hilink_packet_recieve,只操作 cbuf 写指针 + 信号量 post,全程无锁但依赖 cbuf 的单生产者单消费者(SPSC)语义;
  • 消费者:hilink_task 线程独占 cbuf 读端,负责 malloc/解析/分发/释放;
  • 因此 cbuf 无需加锁,前提是接收入口只能有一个调用者——若未来有多个 GATT 特征值同时写入,需在接收侧串行化,否则 SPSC 假设被破坏;
  • hilink_ota/hilink_hash/hilink_signature 为静态全局变量,只在任务线程内访问,天然线程安全;dev_info_t *hilink_info 为跨模块 extern,若被其他线程修改需自行保证一致性。

时序边界

  • 软关机要求先断开蓝牙链路再关机,WAIT_DISCONN_TIME_MS(300ms) 延时不足或链路异常时可能导致关机被阻塞;
  • OTA 升级期间若出现断电,双 Bank 机制保证回滚到旧固件;若出现链路断开,任务层继续等待后续块,App 侧需提供断点续传或重新开始策略。

安全与加密边界

  • MSG_ENCRY 指示消息加密,配套 AES-128-GCM;hilink_sessionkey 只在配对成功后有效,未配对(hilink_pair_flag 未置位)时设备应拒绝加密消息或仅接受白名单明文命令;
  • time[13] 时间戳用于防重放,设备 RTC 不准确时可能误拒合法消息——需评估时间同步策略。

性能与运维注意事项

  • 吞吐瓶颈:OTA 数据走 WRITE_WITHOUT_RESPONSE(15F1E612),无逐包应答,吞吐上限取决于 BLE 连接间隔、MTU(hilink_mtu)与任务侧处理耗时。如需提升,可优先增大 MTU 与减小连接间隔;
  • CPU 占用:AES-128-GCM 解密与 SHA 哈希在任务线程内完成,属于 CPU 密集操作;hilink_task 优先级 2、栈 1024,若 Flash 写入慢可考虑调整任务优先级或拆分校验线程;
  • 日志:LOG_TAG_CONST HILINK 各级日志默认全开(见 log_config.c),量产固件建议关闭 d/v 级以降低开销;hilink_ota.c 使用独立的 [HILINK_OTA] printf 前缀,便于从串口日志中过滤升级过程;
  • 调试抓手:printf_buf(log_info_hexdump)可打印收发原始帧,是排查加解密/组包问题的第一手段。

扩展点

  1. 新增业务通道:在 hilink_task.c 的 switch 中增加新 packet_channel 枚举与对应处理函数,即可在任务线程内扩展独立协议通道,无需改动接收侧;
  2. 新增设备属性:扩展 hi_attribute_t(当前仅有 onoff),并同步华为开发者平台属性定义与 App 侧联动;
  3. 替换认证算法:hilink_protocol.c 内封装 AES-GCM 与 HMAC 调用点,可替换为软件实现或硬件加密引擎,接口不变;
  4. 自定义 OTA 策略:hilink_ota.c 依赖 dual_bank_updata_api,可替换为单 Bank + 外部 Flash 方案,只要保留 hilink_ota_ctl_deal/hilink_ota_data_deal 的帧接口;
  5. GATT Profile 调整:hilink_profile.h 由杰理 gatt 工具生成,修改服务/特征值后用工具重新生成二进制表并同步句柄宏;
  6. 多设备形态:dev_info_t 字段完整覆盖华为平台对设备描述的要求,量产时从配置分区/产品信息模块填充即可,无需改协议层。

相关链接

  • hilink_protocol.h(协议定义与数据结构)
  • hilink_task.c(任务调度与通道分发)
  • hilink_ota.c(HiLink OTA 升级)
  • hilink_profile.h(HiLink GATT Profile)
  • app_hilink.c(HiLink 应用入口)
  • hilink_demo.c / hilink_demo.h(Demo 业务示例)
  • app_main.c(线程与应用启动配置)
  • HiLink 协议开发说明(PDF,仓库内文档)
  • 华为 HiLink 官方开发者文档:详见华为智能家居开放平台(外部链接)
Prev
腾讯连连接入