帮你快速理解、总结文档立即下载

设备 OTA 升级

最近更新时间:2026-09-10 14:51:32
我的收藏
本文将介绍 OTA 接入流程,包括配置当前固件版本处理升级通知发起固件下载固件刷写以及上报升级进度和结果等。

前提条件

接入前需完成以下准备工作:
1. 按照 登录与注册 文档跑通 tc_iot_login 登录功能。
2. 按照 OTA 升级包 文档在后台为需要升级的模块创建并发布固件版本,确保模块名称与 OTA 初始化配置中的 module_name 完全一致。
3. 确认下载目录可写且有足够空间;设备没有文件系统时,可联系技术支持。

接入步骤

步骤 1:配置当前固件信息并初始化 OTA

SDK 登录成功后,填写各模块当前运行的固件版本,注册回调,并调用 tc_iot_ota_init。SDK 上报各模块当前版本,并在有可用升级时通过回调通知升级任务。
字段
说明
module_name
固件模块名称,以 \\0 结尾;须与后台固件模块名称一致。
module_version
当前运行的固件版本,以 \\0 结尾。
firmware_info
各模块当前固件信息数组。
firmware_info_count
firmware_info 数组中的模块数量。
#include <stdio.h>
#include <string.h>

#include "tc_iot.h"
#include "tc_iot_ota.h"

static void on_receive_firmware_upgrade_notify(
const tc_iot_ota_firmware_info_t *firmware_info, void *user_data);
static void on_download_firmware_progress(
const tc_iot_ota_firmware_info_t *firmware_info, uint32_t current_size,
uint32_t total_size, void *user_data);
static void on_download_firmware_result(
const tc_iot_ota_firmware_info_t *firmware_info, tc_iot_error_e error_code,
const char *error_message, const char *file_path, void *user_data);

tc_iot_ota_firmware_info_t firmware_info[] = {
{
.module_name = "mcu",
.module_version = "1.0.0",
},
{
.module_name = "wifi",
.module_version = "1.1.0",
}
}; // 示例版本;实际接入时填写当前运行的固件版本。

tc_iot_ota_config_t ota_config = {
.firmware_info = firmware_info,
.firmware_info_count = sizeof(firmware_info) / sizeof(firmware_info[0]),
};

tc_iot_ota_observer_t ota_observer;
memset(&ota_observer, 0, sizeof(ota_observer));
ota_observer.on_receive_firmware_upgrade_notify =
on_receive_firmware_upgrade_notify;
ota_observer.on_download_firmware_progress = on_download_firmware_progress;
ota_observer.on_download_firmware_result = on_download_firmware_result;

tc_iot_error_e error = tc_iot_ota_init(&ota_config, &ota_observer, NULL);
if (error != TC_IOT_ERR_SUCCESS) {
printf("tc_iot_ota_init failed: %d\\n", error);
}
on_receive_firmware_upgrade_notifyon_download_firmware_result 必须注册;不需要处理下载进度时,on_download_firmware_progress 可设为 NULL
注意:
同一个 module_name 只能注册一次。
user_data 为自定义回调上下文,其指向的对象须在 OTA 反初始化及相关回调完成前保持有效。

步骤 2:处理升级通知,检查更新条件并发起下载

有可用升级时,SDK 调用 on_receive_firmware_upgrade_notify,通知目标模块和目标版本。设备检查本地状态,确认满足更新条件后,调用 tc_iot_ota_download_firmware 发起下载。
以下示例假设本地更新条件已满足,在回调中发起下载:
#define OTA_DOWNLOAD_DIRECTORY "./ota_firmware"

static void on_receive_firmware_upgrade_notify(
const tc_iot_ota_firmware_info_t *firmware_info, void *user_data) {
(void)user_data;
printf("[ota] receive upgrade: module=%s, target_version=%s\\n",
firmware_info->module_name, firmware_info->module_version);

tc_iot_error_e error =
tc_iot_ota_download_firmware(firmware_info, OTA_DOWNLOAD_DIRECTORY);
if (error != TC_IOT_ERR_SUCCESS) {
printf("[ota] submit download failed: %d\\n", error);
}
}
download_directory 指定固件保存目录。下载成功后,使用结果回调提供的 file_path 读取固件。
注意:
firmware_info 的模块名称和目标版本须与本次升级通知一致;延后下载时须先复制该信息。
SDK 同一时间只能处理一个 OTA 任务,下载进行中不得重复调用下载接口。
OTA 回调中不得执行耗时或阻塞操作。

步骤 3:处理固件下载进度(可选)

下载期间,SDK 通过 on_download_firmware_progress 通知已下载字节数和固件总字节数。示例按字节数计算下载百分比:
static void on_download_firmware_progress(
const tc_iot_ota_firmware_info_t *firmware_info, uint32_t current_size,
uint32_t total_size, void *user_data) {
(void)user_data;
uint32_t progress =
total_size == 0 ? 0 : (uint32_t)(((uint64_t)current_size * 100u) / total_size);
printf("[ota] downloading: module=%s, version=%s, progress=%u%% (%u/%u)\\n",
firmware_info->module_name, firmware_info->module_version, progress,
current_size, total_size);
}
tc_iot_ota_report_upgrade_progress 用于上报固件刷写进度。

步骤 4:处理下载结果并执行固件刷写

SDK 通过 on_download_firmware_result 通知下载结果。仅在 error_codeTC_IOT_ERR_SUCCESS 时执行固件刷写:
场景
error_code
error_message
file_path
下载并校验成功
TC_IOT_ERR_SUCCESS
NULL
固件文件路径
下载或校验失败
TC_IOT_ERR_SUCCESS
失败原因
NULL
static void on_download_firmware_result(
const tc_iot_ota_firmware_info_t *firmware_info, tc_iot_error_e error_code,
const char *error_message, const char *file_path, void *user_data) {
ota_demo_context_t *context = (ota_demo_context_t *)user_data;

if (error_code != TC_IOT_ERR_SUCCESS) {
printf("[ota] download failed: module=%s, version=%s, error=%d, message=%s\\n",
firmware_info->module_name, firmware_info->module_version, error_code,
error_message ? error_message : "");
return;
}

printf("[ota] firmware ready: module=%s, version=%s, path=%s\\n",
firmware_info->module_name, firmware_info->module_version, file_path);

/* 复制回调参数并通知升级线程执行固件刷写,不能长期持有回调中的指针。 */
schedule_firmware_install(context, firmware_info, file_path);
}
示例中的 schedule_firmware_install 由接入方实现,用于复制固件信息和文件路径,并通知独立升级线程执行固件刷写。
注意:
firmware_infoerror_messagefile_path 仅在回调期间有效,延后使用时必须复制内容。

步骤 5:上报固件刷写进度和结果

设备在固件刷写过程中,按实际进度调用 tc_iot_ota_report_upgrade_progress。固件刷写失败,或成功后无需重启时,调用 tc_iot_ota_report_upgrade_result 上报结果。
如果固件刷写成功后需要重启,设备在新固件启动并登录后,将实际运行的新版本填入 tc_iot_ota_init 配置。SDK 会上报新版本,后台据此确认升级完成。
以下示例演示固件刷写函数返回后主动上报结果的用法:
static void install_firmware(const tc_iot_ota_firmware_info_t *firmware_info,
const char *file_path) {
tc_iot_error_e error =
tc_iot_ota_report_upgrade_progress(firmware_info, 0);
if (error != TC_IOT_ERR_SUCCESS) {
printf("[ota] report upgrade progress failed: %d\\n", error);
}

/* 平台固件刷写过程中,应继续按实际固件刷写进度调用进度上报接口。 */
bool install_success = platform_install_firmware(file_path);
if (install_success) {
error = tc_iot_ota_report_upgrade_progress(firmware_info, 100);
if (error != TC_IOT_ERR_SUCCESS) {
printf("[ota] report upgrade progress failed: %d\\n", error);
}
}

int32_t result_code = install_success ? 0 : -1;
const char *description = install_success ? "upgrade_success" : "upgrade_failed";
error = tc_iot_ota_report_upgrade_result(
firmware_info, result_code, description);
if (error != TC_IOT_ERR_SUCCESS) {
printf("[ota] report upgrade result failed: %d\\n", error);
}
}
接口
说明
tc_iot_ota_report_upgrade_progress(firmware_info, progress)
上报固件刷写进度,progress 取值范围为 0~100。
tc_iot_ota_report_upgrade_result(firmware_info, 0, description)
上报升级成功。
tc_iot_ota_report_upgrade_result(firmware_info, -1, description)
上报升级失败。
注意:
下载成功后才能上报固件刷写进度或结果。
上报时使用下载成功回调中的目标模块和目标版本。

步骤 6:反初始化 OTA

设备退出登录或释放 SDK 前,调用 tc_iot_ota_deinit 停止下载并释放 OTA 资源:
tc_iot_error_e error = tc_iot_ota_deinit();
if (error != TC_IOT_ERR_SUCCESS) {
printf("tc_iot_ota_deinit failed: %d\\n", error);
}

tc_iot_logout();
tc_iot_deinit();

常见问题

现象
排查建议
tc_iot_ota_init 返回 TC_IOT_ERR_NOT_INITIALIZED
先调用 tc_iot_init 初始化 SDK,并调用 tc_iot_login 登录。
tc_iot_ota_init 返回 TC_IOT_ERR_NOT_CONNECTED
等待 tc_iot_login 回调通知登录成功后,再初始化 OTA。
tc_iot_ota_init 返回 TC_IOT_ERR_OTA_INIT_PARAM_INVALID
检查 firmware_infofirmware_info_count 是否正确;模块名称不可重复,名称和版本字符串以 \\0 结尾。
tc_iot_ota_init 返回 TC_IOT_ERR_OTA_INIT_OBSERVER_NULL
需要传入合法的 observer,至少包含必填的 on_receive_firmware_upgrade_notifyon_download_firmware_result
on_download_firmware_result 回调中的 error_codeTC_IOT_ERR_OTA_START_FAILED
检查模块名称和目标版本是否与本次升级通知一致,以及是否重复调用下载接口。
烧录完成重启后仍收到相同升级通知
确认新固件已生效,并在 tc_iot_ota_init 中使用实际运行的新版本初始化

联系我们

接入或使用过程中遇到问题,或有相关建议,可通过 联系我们 提交反馈。