ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ESP IoT Solution BLE OTA 升级方案:基于 esp_ble_conn_mgr 的分扇区固件传输协议与完整实践

ESP IoT Solution BLE OTA 升级方案:基于 esp_ble_conn_mgr 的分扇区固件传输协议与完整实践 ESP IoT Solution BLE OTA 升级方案基于 esp_ble_conn_mgr 的分扇区固件传输协议与完整实践【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solutionBLE OTAOver-The-Air 固件升级是物联网设备量产后的核心维护能力。本篇文章围绕 ESP IoT Solution 仓库中的 BLE OTA Profile 文档系统讲解基于esp_ble_conn_mgr实现的分扇区 BLE 固件传输协议包括 OTA 服务UUID0x8018与四个特征值的定义、START/STOP 命令与固件数据包的逐字节格式、CRC16 三级校验机制并结合 ble_ota 示例 的源码与配置文件说明从编译烧录到 NimBLE/Bluedroid、Protocomm 安全通道、预加密 OTA 与 Delta OTA 的完整落地路径。读完本文你将能够理解 BLE OTA 的协议细节并能在自己的 ESP32 系列项目上复刻这套升级链路。一、BLE OTA Profile 是什么BLE OTA Profile 是建立在esp_ble_conn_mgr连接管理组件之上的一层分扇区固件传输协议。它解决的核心问题是BLE 链路 MTU 有限、单包载荷小而固件镜像通常有数百 KB 甚至更大因此必须把固件切分为多个扇区Sector每个扇区再拆成多个**数据包Packet**顺序下发由设备端边收边校验、边写入 flash。根据 docs/en/bluetooth/ble_ota.rst 的定义该 Profile 的核心特征为使用 OTA 服务 UUID0x8018解析来自主机Central的 START / STOP 命令以及固件数据包数据交付给应用层回调之前执行严格的三重校验。三重校验是协议可靠性的关键也是本文后续重点展开的内容命令包 CRC16命令帧必须通过 CRC 校验才会被解析执行扇区序号与分包序号连续性扇区不能跳跃、包序号必须严格递增否则立即回错误 ACK 请求重传扇区 CRC16一个扇区4KB收满后先校验整扇区 CRC通过后才把该扇区数据回调给应用层写入 OTA 分区。配套的服务定义见 docs/en/bluetooth/ble_ota_svc.rst0x8018服务是传输层的可以被不同的 OTA Profile 逻辑复用当与ble_ota_raw配合使用时命令和固件载荷的解析由该 Profile 完成。二、OTA 服务与四个特征值BLE OTA Service 在 GATT 层定义了 4 个特征值完整说明如下特征值UUID权限说明RECV_FW_CHAR0x8020Write, notify固件数据接收通道设备端收到后回复 ACKPROGRESS_BAR_CHAR0x8021Read, notify读取 / 上报升级进度COMMAND_CHAR0x8022Write, notifyOTA 命令下发与命令 ACK 回复CUSTOMER_CHAR0x8023Write, notify厂商自定义数据收发通道从源码实现看esp_ble_ota_raw.c 中通过esp_ble_ota_svc_init()初始化该服务通过esp_ble_ota_notify_command_raw()向0x8022发送命令 ACK、通过esp_ble_ota_notify_recv_fw_raw()向0x8020发送固件 ACK与应用层完全解耦。此外 Profile 初始化时还会同时初始化esp_ble_dis_init()DIS 服务对外广播软件/硬件版本信息方便主机端识别设备固件版本。三、协议格式详解以下格式定义与数值均来自 examples/bluetooth/ble_ota/README.md并被源码 esp_ble_ota_raw.c 一一印证。3.1 命令包格式Command Package命令包固定 20 字节布局如下单位Command_IDPayLoadCRC16字节Byte: 0 ~ 1Byte: 2 ~ 17Byte: 18 ~ 19Command_ID 取值源码中以BLE_OTA_CMD_START/STOP/ACK宏定义0x0001START开始 OTA。Payload bytes(2 ~ 5) 填入固件总长度小端 32 位源码中通过get_u32_le(data[2])读取其余 Payload 置 0。CRC16 计算 bytes(0 ~ 17)。0x0002STOP结束 OTA。剩余 Payload 全部置 0CRC16 计算 bytes(0 ~ 17)。0x0003ACK命令回复。Payload bytes(2 ~ 3) 填入被回复的命令 IDPayload bytes(4 ~ 5) 为该命令的响应结果——0x0000表示接受ACCEPT0x0001表示拒绝REJECT其余 Payload 置 0。CRC16 计算 bytes(0 ~ 17)。一个值得注意的实现细节START 命令的 ACK 在ack_status之后还允许携带扩展字段仍被 bytes(0 ~ 17) 的 CRC 覆盖——byte 6 为推荐的扇区发送窗口Central 最多可流水线预发的扇区数byte 7 保留。该窗口由esp_ble_ota_raw_set_sector_send_window_for_ringbuf()根据应用层环形缓冲容量动态计算窗口 ringbuf 容量 / 4096下限 1、上限 64。这解释了示例中OTA_RINGBUF_SIZE 8192时窗口为 2 的来源可在吞吐量与内存占用之间取得平衡。3.2 固件包格式Firmware Package主机发送的固件包格式如下单位Sector_IndexPacket_SeqPayLoad字节Byte: 0 ~ 1Byte: 2Byte: 3 ~ (MTU_size - 4)Sector_Index当前写入的扇区号。扇区号从 0 开始递增、不能跳跃必须发送完 4KBLE_OTA_SECTOR_SIZE 4096数据后才能进入下一个扇区否则设备立即回复错误 ACK 请求重传。Packet_Seq扇区内包序号从 0 递增。特殊值0xFF表示该扇区的最后一包此时 Payload 末尾 2 字节为整个扇区 4K 数据的 CRC16其余字节填充0x0。设备端收到末包后校验数据总长度与 CRC通过则回复正确 ACK主机再开始发送下一个扇区。3.3 固件应答包格式ACK Package设备回复主机的应答包格式如下单位Sector_IndexACK_StatusCRC16字节Byte: 0 ~ 1Byte: 2 ~ 3Byte: 18 ~ 19ACK_Status 取值源码中的ble_ota_fw_ack_status_t0x0000成功SUCCESS0x0001CRC 错误CRC_ERR0x0002Sector_Index 错误INDEX_ERRbytes(4 ~ 5) 携带设备期望的 Sector_Index便于主机跳转到正确扇区续传0x0003Payload 长度错误LEN_ERR。3.4 CRC16 算法与校验流程源码中的校验算法为CRC16-CCITT多项式0x1021初值0x0000与 BLE OTA 主机工具保持兼容。设备端完整的接收校验流水线对应文档所述三重校验如下命令包到达后先检查长度是否为固定 20 字节再以 bytes(0 ~ 17) 计算 CRC 并与 bytes(18 ~ 19) 比对不通过直接回 REJECT固件包到达后先比对Sector_Index是否等于当前期望扇区不匹配回0x0002非末包Packet_Seq ! 0xFF还要比对包序号是否连续乱序回0x0003末包拆出尾部 2 字节 CRC与设备端对整扇区累计数据的 CRC 计算结果比对不一致回0x0001并清空该扇区接收状态等待重传全部通过后通过esp_ble_ota_raw_recv_fw_data_callback()注册的recv_fw回调把整扇区数据交给应用层同时累计recv_total_len与 START 命令声明的固件总长度比对防止超长数据。四、示例工程实战从编译到 OTA 完成官方示例位于 examples/bluetooth/ble_ota其工作流程为通过 BLE 接收固件以扇区为单位依次写入 flash直至升级完成。4.1 分区表升级依赖 OTA 分区示例的 partitions.csv 需保证有足够的 app0 / app1 双 OTA 分区设备当前固件运行在某个 OTA 分区新固件写入另一个esp_ota_set_boot_partition()切换启动分区后重启生效。4.2 应用层数据流与源码佐证从 app_main.c 可以看到一条完整的BLE 数据 → 环形缓冲 → OTA 写入流水线ble_ota_ringbuf_init(OTA_RINGBUF_SIZE)创建 8KB 字节型 RingBufferProfile 的固件接收回调ota_recv_fw_cb()把每个通过校验的 4K 扇区写入 RingBuffer独立任务ota_task()通过xRingbufferReceive()阻塞取出数据调用esp_ota_write()普通 OTA或esp_delta_ota_feed_patch()Delta OTA写入目标分区当累计写入长度达到esp_ble_ota_get_fw_length()即 START 命令声明的固件长度后执行esp_ota_end()、esp_ota_set_boot_partition()并esp_restart()重启到新固件。该任务栈大小OTA_TASK_SIZE 8192优先级 5notify_sem计数信号量用于控制读写速率避免环形缓冲溢出。4.3 编译与配置通用示例提供两套主机栈配置Bluedroid双模sdkconfig.ci.bluedroidNimBLEBLE onlysdkconfig.ci.nimble。默认配置见 sdkconfig.defaults。标准构建命令为idf.py set-target esp32h2 idf.py menuconfig idf.py build flash monitor4.4 主机侧 APP协议设计为通用 BLE OTA 主机服务示例配套的主机端 APP 由 Espressif 官方提供esp-ble-ota-android。使用 Bluedroid 且需与该 APP 兼容时若选择Bluedroid - Dual-mode需按以下步骤关闭 BLE 5.0 特性Component configBluetoothBluedroid Options取消勾选Enable BLE 5.0 featuresComponent configBluetoothController Options取消勾选Enable BLE 5 feature。4.5 ESP32-H2 使用注意构建 ESP32-H2 的 BLE OTA 示例需使用ESP-IDF 5.0 或更高版本。另外需保证通过 BLE 传输的固件镜像与示例设置的FLASHSIZE4MB一致即确认ESPTOOLPY_FLASHSIZE_4MB已被设置否则会出现镜像尺寸与 flash 布局不匹配的问题。五、进阶升级模式示例在基础裸传输之上还支持三种进阶模式均可通过idf.py menuconfig在Example Configuration → Type of OTA中选择5.1 NimBLE 高吞吐配置若主机栈选择 NimBLE为获得最大吞吐Component config → Bluetooth → Bluetooth → Host → NimBLE - BLE onlyComponent config → Bluetooth → NimBLE Options → Preferred MTU size in octets设为517更大 MTU 意味着单个固件包可携带更多载荷扇区切包次数更少。5.2 Protocomm 安全通道 OTA利用 protocomm 层做安全握手与加密传输Example Configuration → Type of OTA → Use protocomm layer for securityComponent config → OTA Manager → Type of OTA → Enable protocomm level security。该模式下 app_main.c 走esp_ble_ota_init()/esp_ble_ota_start()流程支持 Security 1PoP 口令与 Security 2salt/verifier 认证两种安全等级示例中通过CONFIG_EXAMPLE_OTA_SECURITY_VERSION_1/2切换。5.3 预加密 OTAPre-Encrypted OTA固件在产线/发布侧先用 rsa_key/private.pem 私钥加密设备端用内置公钥解密后写入若使用 ESP32-S3需将Component config → Bluetooth → Bluetooth → NimBLE Options → NimBLE Host task stack size设为8192Example Configuration → Type of OTA → Use Pre-Encrypted OTAComponent config → OTA Manager → Type of OTA → Enable pre encrypted OTA。源码中通过esp_encrypted_img_decrypt_start()创建解密句柄再以esp_ble_ota_recv_fw_data_callback(cb, decrypt_handle)将解密流程挂入固件接收回调链。5.4 Delta OTA差分升级Delta OTA 只传输新旧固件之间的差异补丁可显著减小 BLE 传输量NimBLE选择Use Delta OTA若目标芯片为 ESP32-H2 / ESP32-C6还需在 NimBLE Options 中取消Enable BLE 5 feature并在Example Configuration取消Enable Extended Adv。Bluedroid选择Use Delta OTA并取消Enable BLE 5.0 feature与Enable BLE 4.2 feature。补丁生成工具位于 tools/esp_delta_ota_patch_gen.py先安装依赖pip install -r tools/requirements.txt生成补丁必须使用设备上当前运行的固件作为base_binary请务必保留设备内固件的备份python esp_delta_ota_patch_gen.py create_patch --chip target --base_binary base_binary --new_binary new_binary --patch_file_name patch_file_name校验补丁正确性python esp_delta_ota_patch_gen.py verify_patch --chip target --base_binary base_binary --new_binary new_binary --patch_file_name patch_file_name生成的补丁文件部署到 OTA 更新服务器后设备端在 app_main.c 中通过verify_patch_header()校验补丁魔数0xfccdde10与当前固件 SHA-256 摘要和verify_chip_id()校验 chip_id 与CONFIG_IDF_FIRMWARE_CHIP_ID一致双重把关再经esp_delta_ota_feed_patch()边接收边还原新固件最终由esp_delta_ota_finalize()完成落盘。六、与其他 BLE Profile 的协作与复用本文所述的 OTA Service0x8018是传输层服务与 Profile 逻辑解耦同样的四个特征值可以承载不同的 OTA Profile 实现而ble_ota_raw这类 Profile 只负责命令/固件载荷的解析与校验最终数据通过应用回调交付。这种分层设计让开发者既可以按本文协议直接复用也可以基于esp_ble_ota_svc自行实现更贴近业务的安全校验、续传或分包策略。仓库中 ble_profiles 文档 对该组件族的整体结构有更全面的说明可作为扩展阅读。七、关键文件索引Profile 文档docs/en/bluetooth/ble_ota.rst中文版服务文档docs/en/bluetooth/ble_ota_svc.rstProfile 实现components/bluetooth/ble_profiles/esp/ble_ota_raw/src/esp_ble_ota_raw.c 与 esp_ble_ota_raw.h示例工程examples/bluetooth/ble_ota主程序 app_main.c、分区表 partitions.csv、示例说明 README.md结语BLE OTA 的关键在于小管道传大文件通过 4KB 扇区切分、20 字节命令帧、CRC16-CCITT 三级校验把不可靠的无线链路变成可控的可靠传输。本文从 Profile 协议定义、GATT 特征值、逐字节帧格式到源码级校验流程再到 Bluedroid/NimBLE、Protocomm、预加密与 Delta OTA 的完整配置路径均可在当前仓库中逐文件验证。开发者可直接基于 examples/bluetooth/ble_ota 起步按需裁剪出适合自己产品形态的 BLE 升级方案。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表