iotc 移植适配指南

本文说明把 iotc(iot_connect)SDK 适配到新芯片/新平台时需要完成的工作、接口清单与注意事项。


一、总体思路

iotc 是分层结构:

应用层(业务回调、设备/服务信息)
        │  IotcOhSetOption / IotcOhDevInit / IotcOhBleEnable / IotcOhMain
SDK 层  iotc/sdk/oh_connect/*
        │
核心层  iotc/core/*(BLE 会话、SPEKE 安全、GATT 服务、上报、调度)
        │  只依赖适配层抽象接口
适配层  iotc/adapter/*  ← 移植工作主要在这里
        │
芯片平台(协议栈 / OS / 存储 / 加密 / TRNG / WiFi / SLE)

核心层不直接调用芯片 API,平台差异全部由适配层头文件(iotc_os.h、iotc_ble.h 等)隔离。
移植 = 选择裁剪范围 + 实现这些接口 + 把组件接入构建与启动流程。


二、第一步:确定裁剪范围

编译面由两部分共同决定:

  1. 构建系统的源码列表:决定哪些文件参与编译。未加入构建的目录,宏取任何值都不参与编译。
  2. 配置宏:决定已编文件内部的条件编译分支。

配置宏按来源分两类,不要混淆:

类别来源特点
SDK 默认宏iotc_conf.h 中的 #ifndef 默认值仅覆盖部分配置,可被编译选项覆盖
构建开关宏只由构建选项提供,iotc_conf.h 中无默认值不显式定义就完全不生效

常见宏:

宏作用默认值来源
IOTC_CONF_BLE_ONLY只保留 BLE 通路,不编 WiFi/SLE/CoAP/TCP构建选项
IOTC_CONF_BLE_SUPPORT启用 BLE构建选项
IOTC_CONF_LITEOS_M_SUPPORTLiteOS-M / 裸跑形态适配构建选项
IOTC_CONF_OH_NEARLINK_SUPPORT广播是否携带靠近发现扩展字段构建选项
IOTC_CONF_DEVICE_LEVEL设备等级,决定任务栈与缓冲区大小iotc_conf.h
IOTC_CONF_LOG_BUILD_LEVEL编译期日志级别iotc_conf.h
IOTC_CONF_TCP_SUPPORT是否启用 TCPiotc_conf.h
IOTC_CONF_AES_SUPPORT是否启用 AESiotc_conf.h
IOTC_CONF_ADAPTER_MBEDTLS_MAJOR_VERSIONmbedtls 主版本(2/3)iotc_conf.h
IOTC_CONF_ADAPTER_SOCKET_LWIP_SUPPORTsocket 是否基于 lwIPiotc_conf.h

2.1 按宏的消费方式决定如何定义

  • #if IOTC_CONF_XXX:按数值判断,-DIOTC_CONF_XXX=0 可关闭。
  • #ifdef IOTC_CONF_XXX 或 #if defined(IOTC_CONF_XXX):只判断是否定义,
    -DXXX=0 仍算已定义、仍生效;对无默认值的构建开关宏,只能不定义或用 -U。
  • 例:IOTC_CONF_BLE_ONLY 以 #ifndef 判断,定义成任何值都表示“BLE-only 生效”。
  • 例:IOTC_CONF_BLE_SUPPORT 若与 IOTC_CONF_WIFI_SUPPORT 用 defined() 组合判断,
    写成 =0 会误开本应关闭的分支。

2.2 定义位置与默认值

  • 只影响库内部实现的宏放 PRIVATE_DEFINES。
  • 会影响公开头文件(被使用方 include)的宏必须放 PUBLIC_DEFINES,
    否则库和使用方编译单元看到的值不一致。
  • 所有功能开关应显式定义,不要依赖默认值;默认值可能为 1 或与平台不符。
  • 不建议修改 SDK 头文件默认值:SDK 升级时会丢失,且不利于追踪差异。

裁剪原则:

  • 先定源码列表,再定宏;未使用的适配目录保留但不加入构建即可。
  • BLE-only 最小集合通常为:OS、BLE、Crypto、JSON、Log、Memory,以及核心 BLE/SPEKE/netcfg。
  • WiFi/SLE/Socket/TLS 仅在确有联网或相应通路需求时编入。
  • 注意第三方库版本差异带来的 API 变化,按实际版本增删适配代码。

三、适配层接口清单

以适配层头文件为准,接口数量可能随 SDK 版本变化。

模块头文件必需性说明
OSiotc_os.h必须任务、互斥、信号量、延时、时间、errno
BLEiotc_ble.h必须(BLE 方案)广播、GATT Server、indicate/response、MAC
BLE HALohos_bt_gatt*.h二选一协议栈已有 OHOS HAL 时实现垫层
内存iotc_mem.h必须malloc/calloc/free
日志iotc_log.h必须日志输出与级别控制
JSONiotc_json.h必须JSON 解析/构造/打印
加密iotc_aes.h、iotc_md.h、iotc_kdf.h、iotc_drbg.h、iotc_mpi.h、iotc_rsa.h、iotc_base64.h必须通常基于 mbedtls 适配
KViotc_kv.h视需求持久化密钥/会话/注册信息
WiFiiotc_wifi.h、iotc_network.h可选WiFi 配网/网络状态
SLEiotc_sle*.h可选SLE 通路
Socketiotc_socket.h可选TCP/UDP 通信
TLSiotc_tls.h可选云连接加密

3.1 OS 适配(iotc_os.h)

主要接口:

任务:IotcTaskCreate / Suspend / Resume / Delete / GetCurrentTaskId
互斥:IotcMutexCreate / Lock / Unlock / Destroy
信号量:IotcSemCreate / Wait / Post / GetCount / Destroy
其它:IotcSleepMs / IotcSchedYield / IotcGetSysTimeMs / IotcGetErrno

注意点:

  • 任务栈大小:默认值在低设备等级下偏小,BLE 会话 + mbedtls 场景需实测,
    必要时调大默认栈或提高设备等级。
  • 优先级映射:低/中/高优先级需映射到目标 OS 的合法区间。
  • 时间单位:接口超时参数为毫秒,注意与 OS tick 换算。
  • IotcTaskGetCurrentTaskId:需能反查到当前任务上下文。
  • 互斥锁语义:确认目标 OS 是否支持递归锁、超时锁,iotc 内部存在嵌套加锁场景。
  • IotcGetErrno:无 errno 的裸机环境可返回 0 或最近一次错误码。

3.2 BLE 适配(iotc_ble.h)

主要接口:

IotcBleInitStack / DeInitStack
IotcBleSetConnectParam / SetBleName
IotcBleStartAdv / StopAdv
IotcBleRegisterGattCb
IotcBleStartGattsService / StopGattsService
IotcBleSendGattsIndicate / SendGattsResponse
IotcBleGetBleMac / DisconnectGatt

两种实现路线:

路线 A:协议栈已提供 OHOS 风格 HAL(推荐)

只需实现一层 HAL 垫层,BLE 适配层可直接复用,改动量最小。

  • 头文件:ohos_bt_gatt.h、ohos_bt_gatt_server.h、ohos_bt_def.h
  • 实现内容:协议栈初始化/使能、广播参数与数据、MAC 读取、安全参数、
    GATT server 注册/加服务/加特征/加描述符/启停服务/发送 indication 与 response
  • 关键接口示例:InitBtStack、EnableBtStack、SetDeviceName、BleSetAdvData、
    BleStartAdv、BleStopAdv、BleUpdateAdv、ReadBtMacAddr、
    BleGattRegisterCallbacks、BleGattsRegister、BleGattsAddService、
    BleGattsAddCharacteristic、BleGattsStartService、BleGattsSendIndication

路线 B:协议栈没有 OHOS HAL

直接按 iotc_ble.h 实现全套接口,封装芯片原生 BLE 协议栈。

BLE 适配常见问题:

  1. UUID 字节序:适配层通常包含十六进制字符串与字节序转换,移植时不要改动其约定。
  2. 广播参数单位:interval 一般以 0.625ms 为单位,不是毫秒。
  3. 断开后不要重复开广播:iotc 内部已负责重连/重启广播,在断开回调中再次调用
    启动广播接口会与内部逻辑重复,并可能因同步等待死锁。
  4. 回调上下文:协议栈回调多运行在协议栈线程或中断上下文,禁止阻塞、长打印、
    直接调用同步 API,应投递到 iotc 调度器处理。
  5. GATT 句柄生命周期:删除/清理服务时要同步清理本地上下文,避免重连后句柄错乱。
  6. 连接参数/MTU/indicate 分片/CCCD:需与 iotc 的 profile 实现对齐。
  7. 全局符号冲突:HAL 中的全局变量可能与已有 BLE 库同名,注意编译选项或命名隔离。

3.3 熵源 / TRNG(必须)

  • iotc 的 DRBG 初始化时会注册 TRNG 回调,用于 mbedtls 熵源。
  • 应用侧通过设备选项注册 TRNG 回调。
  • 无 /dev/urandom 的裸机环境必须接硬件 TRNG,否则熵源不可用或安全强度不足。

3.4 KV(视需求)

主要接口:

IotcKvInit / DeInit / SetValue / GetValue / GetLen / DelValue
  • 用于持久化设备密钥、会话密钥、注册信息。
  • 若要求重启后免重新配网/免重新注册,必须实现且保证掉电可靠:
    建议写后校验、双备份、版本号管理。
  • 需评估 NV/Flash 容量,预留密钥与会话数据空间。

3.5 其它适配

  • 内存:保证 IotcMalloc/IotcCalloc/IotcFree 与 iotc 内部、JSON 释放策略一致;
    IOTC_CONF_JSON_FREE_EQUAL_MALLOC_FREE 与实际释放方式匹配。
  • 日志:中断上下文不要使用阻塞式打印。
  • JSON:一般直接复用 cJSON,只需适配接口映射。
  • Crypto:通常直接复用 mbedtls,重点处理版本宏与模块裁剪。
  • Socket/TLS:仅在联网场景需要;TLS 还需要时间源与随机源回调。
  • 网络状态:需映射到目标平台真实网络状态。

四、组件与构建集成

通用步骤:

  1. 顶层构建:把 iotc 组件(以及 BLE HAL 垫层,如有)加入顶层构建系统。
  2. 组件列表:把 iotc 组件加入目标的 RAM/镜像组件清单。
  3. iotc 组件构建:配置源码列表、include 路径、平台宏、依赖库与链接方式。
    • 宏按可见性分 PRIVATE_DEFINES / PUBLIC_DEFINES:影响公开头文件的必须放 PUBLIC。
    • 显式定义所有功能开关;#ifdef/defined() 类宏不能靠 =0 关闭。
  4. BLE HAL 组件构建:独立成组件,定义适配层识别宏,统一头文件与编译选项。
  5. 应用/示例:增加 sample 配置开关(Kconfig 等),并在目标配置文件中默认打开。
  6. 启动入口:使用平台支持的启动机制注册入口,确保在 OSAL/协议栈初始化之后执行。

链接注意:

  • 入口函数常放在特殊初始化段中,需用 whole-archive/whole-link 方式链接,
    否则会被当作死代码裁剪。
  • 编译标准、告警选项、C 运行时配置按平台约定设置。
  • 依赖库:OSAL、BLE 协议栈、安全库/安全 C 库(securec 等)头文件路径。

五、与既有 BLE 业务共存

同一芯片上不能同时运行两套 GATT Server / 广播:

  • 关闭基线 BLE 的初始化入口,避免两套代码都注册 GATT 回调或启动广播。
  • 广播句柄、GATT serverId、回调注册保持全局唯一。
  • 若平台还使用 SLE 等其它无线通路,确认其初始化顺序与共享资源不冲突。
  • BLE 使能回调必须注册并返回成功,否则 BLE 使能流程会报错(部分错误非致命,但应消除)。

六、分区与资源规划

  • iotc + mbedtls 会显著增大应用镜像,需要重新规划 Flash 分区:
    • 应用分区大小
    • FOTA 区偏移/大小
    • NV/KV 区大小与对齐
  • 修改分区配置后必须重新生成分区表镜像,并同步所有 target 的配置。
  • 资源评估:
    • Flash:应用镜像、KV/NV、FOTA 预留
    • RAM:iotc 任务栈、mbedtls 上下文、JSON 缓冲、协议栈缓冲
    • 内核对象:任务数、信号量数、互斥锁数上限是否足够

七、同平台换芯片型号的额外检查

  1. 预编译库符号差异:用 nm/readelf 比对基线库,确认 iotc 依赖的符号存在;
    缺失时通过条件编译隔离或改用替代接口。
  2. 分区布局:不同型号 Flash 大小不同,APP/FOTA/NV 偏移必须分别核算。
  3. 配置项:每个 target 的配置文件都要更新,不能只改一个默认配置。
  4. 协议栈能力:确认广播扩展、indication、MTU、连接数等能力一致。
  5. 时钟/低功耗:确认休眠唤醒后的 BLE 保连、时钟漂移校准等接口是否存在。

八、安全参数一致性

  • pincode:iotc 按固定长度参与 HKDF,必须填满定义长度且与 App 侧逐字节一致,
    否则 SPEKE 共享密钥不同、HMAC 校验失败。
  • acKey:长度与内容需与云端/App 登记值一致。
  • 设备信息:产品 ID、设备类型 ID、型号、厂商 ID 等必须与云端产品定义一致。
  • 时间源:TLS/证书校验依赖时间,启用时需提供获取时间回调。
  • 密钥存储:KV 实现需防掉电损坏,建议双备份 + 校验。

九、移植步骤(建议顺序)

  1. 选定裁剪范围,配置 IOTC_CONF_* 宏。
  2. 实现 OS 适配,单独验证任务/互斥/信号量/延时。
  3. 实现内存、日志、JSON,跑通 iotc 核心初始化。
  4. 接入 TRNG 回调,确认 DRBG 初始化成功。
  5. 实现 BLE(优先走 HAL 垫层 + 现有适配层)。
  6. 实现 KV(若需要持久化)。
  7. 接入构建:顶层构建、组件列表、sample 开关、目标配置。
  8. 处理与基线 BLE/外设的共存,注册启动入口。
  9. 调整分区并重新生成分区表。
  10. 按验证清单逐项验收。

十、验证清单

阶段验证项期望
OS任务创建/删除、互斥/信号量超时无死锁、无栈溢出
核心设备初始化、主循环启动接口返回成功,任务正常运行
熵源DRBG 初始化无初始化失败日志
BLE手机扫描设备广播名与厂商字段正确
会话SPEKE 协商与鉴权配对成功,无 HMAC 失败
业务属性读写、全量上报读写与上报均成功
存储掉电重启密钥/注册信息保持
稳定性断连重连、长时间运行广播恢复、无句柄泄漏、无死锁
低功耗休眠唤醒保连正常、广播可恢复

十一、常见问题检查表

现象可能原因排查方向
初始化失败熵源未接入/TRNG 返回失败检查 TRNG 回调与 DRBG 日志
扫描不到设备广播参数单位错误、广播未启动核对 interval 单位与启动返回值
配对失败/HMAC 失败pincode 长度或内容不一致核对固定长度与 App 配置
断连后死锁断开回调中重复启动广播/调用同步 API移除重复启动,改为异步投递
重连后读写异常GATT 句柄/上下文未清理检查服务删除与上下文生命周期
链接失败预编译库缺符号、初始化段被裁剪nm 比对符号,检查 whole-link
栈溢出/重启任务栈不足、中断中阻塞增大栈、检查回调执行上下文
掉电后需重新配网KV 未实现或写入不完整检查 KV 掉电可靠性与容量
镜像放不下分区未重新规划调整 APP/FOTA/NV 分区并重生成分区表
宏设了不生效/关不掉宏用 #ifdef/defined() 消费,=0 仍算定义改为不定义或 -U,并确认 PRIVATE/PUBLIC 可见性
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐