嵌入式 OTA(远程固件升级)(二)

1. 引言

本文档详细描述了本项目(储能备份管理系统)中 OTA(Over-The-Air)远程固件升级功能的完整技术实现方案。OTA 升级是嵌入式系统的重要功能,确保设备能够在不人工干预的情况下远程更新固件,提高系统的维护效率和安全性。

本方案基于 MQTT 通信协议,通过云端下发升级命令,设备自动执行下载、校验、安装和重启流程。整个升级过程采用状态机设计,确保可靠性。

2. 升级包格式

2.1 包结构设计

升级包采用分层压缩格式,确保传输效率和安全性:

复制代码
远程升级包 (app_nccu.tar.gz)
├── app_nccu.tar.gz          # 实际应用固件包
├── pkg.sum                  # MD5校验文件
└── [可选] upgrade_script.sh # 升级脚本(本项目未使用)

2.2 内部固件包内容

app_nccu.tar.gz 包含完整的应用程序和配置文件:

复制代码
/app/                        # 目标安装目录
├── nccu                     # 主应用程序
├── config/                  # 配置文件目录
├── lib/                     # 依赖库
└── [其他应用文件]

2.3 包命名规范

  • 下载文件名LOCAL_UPGRADE_FIRMWARE_NAME (定义为固定的本地文件名)

  • 解压后文件名app_nccu.tar.gz

  • 校验文件名pkg.sum

2.4 包大小限制

  • 最大包大小:受限于 /var/volatile 目录空间(通常为 RAM 盘)

  • 建议包大小:< 100MB(考虑解压时间和内存限制)

3. 校验命令

3.1 MD5 校验机制

3.1.1 校验文件格式 (pkg.sum)
复制代码
MD5(app_nccu.tar.gz)= [32位十六进制MD5值]

例如:

复制代码
MD5(app_nccu.tar.gz)= a1b2c3d4e5f678901234567890abcdef
3.1.2 校验函数实现
复制代码
// 函数位置:sampler_system.c
BOOL DoMD5Chk_ForRemotePkg(BOOL bIsForCCU)
{
    // 读取 pkg.sum 文件
    // 计算 app_nccu.tar.gz 的实际 MD5
    // 比较校验值
    // 返回校验结果
}
3.1.3 校验流程
  1. 读取 /var/volatile/pkg.sum 文件内容

  2. 计算 /var/volatile/app_nccu.tar.gz 的 MD5 值

  3. 比较两个 MD5 值是否一致

  4. 校验失败时记录错误日志并上报失败状态

3.2 文件存在性校验

在解压后进行基础校验:

复制代码
# 检查必需文件是否存在
if [ ! -f "/var/volatile/app_nccu.tar.gz" ] || [ ! -f "/var/volatile/pkg.sum" ]; then
    # 校验失败处理
fi

3.3 校验失败处理

  • 状态上报FIRMUPDATE_InstallFailed

  • 日志记录:详细记录校验失败原因

  • 清理操作:删除下载的无效文件

  • 重置状态 :回到 UPDOWN_IDLE 状态

4. 升级日志机制

4.1 日志分类

4.1.1 系统日志 (通过 LogOut 函数)
复制代码
LogOut(MAIN_MODULE_SAMPLER, "Sys", LOG_TYPE_INFO,
    "Begin download firmware from URL[%s]!", url);

LogOut(MAIN_MODULE_SAMPLER, "Sys", LOG_TYPE_ERROR,
    "MD5 chk FAILED after downloaded from URL[%s]!", url);
4.1.2 事件日志 (通过 EVENT_TYPE_FIRMWARE_UPDATE)
复制代码
EVENT_FIRMWAREUPDATE_STATUS evFirmUpdt;
evFirmUpdt.emUpdateStatus = FIRMUPDATE_Downloading;
SendMsg(pSys_Rough->hSampler, EVENT_TYPE_FIRMWARE_UPDATE, 
    EVENT_MSG_BEGIN, &evFirmUpdt, sizeof(EVENT_FIRMWAREUPDATE_STATUS));

4.2 日志级别定义

  • LOG_TYPE_INFO:正常操作信息

  • LOG_TYPE_ERROR:错误信息

  • LOG_TYPE_WARING:警告信息

4.3 关键日志点

  1. 开始下载:记录下载 URL

  2. 下载进度:通过 TRACE 记录下载状态

  3. 下载完成/失败:记录结果和重试次数

  4. 校验开始/结果:记录 MD5 校验过程

  5. 安装过程:记录解压、文件替换操作

  6. 重启触发:记录系统重启原因

4.4 日志存储位置

  • 运行时日志 :存储在内存或 /var/log/

  • 持久化日志:可能通过专门的日志模块保存到 Flash

5. 重启策略

5.1 重启时机控制

5.1.1 充电状态检查

在准备重启前,检查所有充电枪状态:

复制代码
DATA_PROCESSOR* pDPR = (DATA_PROCESSOR*)((SAMPLER*)pSys_Rough->hSampler)->hDPR;
for(n = 0; n < 3; n++) {
    pDPR->Get(pSys_Rough->hSampler, GETTYPE_SP_VAR,
        201 + n, 101, &varV, 4);
    if((varV.emValue >= GUN_STATE_RESERVE_PENDING) &&
        (varV.emValue <= GUN_STATE_WAITING_END)) {
        // 正在充电,延迟重启
        return;
    }
}
5.1.2 CCU 升级同步

如果升级包包含 CCU(充电控制器)固件:

复制代码
if(IsInclued_CCUFimrwarePkg(pSys_Rough)) {
    pSys_Rough->emDownloadStatus = UPDOWN_WAIT_REBOOT_AND_CCU;
    // 等待 CCU 升级完成后再重启主系统
}

5.2 重启执行流程

5.2.1 发送重启事件
复制代码
EVENT_SYSTEM_EXIT evExit;
evExit.nExitType = SYS_EXIT_FIRMWAREUPDT;
SendMsg(pSys_Rough->hSampler, EVENT_TYPE_SYSTEM_EXIT, 
    EVENT_MSG_BEGIN, &evExit, sizeof(EVENT_SYSTEM_EXIT));
5.2.2 系统级重启

重启由系统事件处理器处理,通常执行:

复制代码
# 系统重启命令(在事件处理器中)
reboot
# 或
shutdown -r now

5.3 重启安全保障

5.3.1 原子性保证
  • 文件替换使用 sync 命令确保写入 Flash

  • 重启前确保所有文件操作完成

5.3.2 失败回滚机制
  • 保留旧版本应用文件

  • 启动脚本检测升级标志,失败时回滚

5.3.3 重启超时保护
  • 设置 watchdog 确保重启过程不卡死

  • 重启失败时自动恢复到安全模式

6. 完整升级流程图

复制代码
云端下发升级命令 (MQTT S_404)
        ↓
设备解析命令 → 生成 A_BLOB_UPDATEFIRMWARE_CMD
        ↓
写入 DAI 控制参数
        ↓
采样器检测到新命令
        ↓
等待 dtRetrieveDate 时间到达
        ↓
开始下载固件包 (HTTP/FTP)
        ↓
下载中... (状态: UPDOWN_PENDING)
        ↓
下载完成/失败?
    ↓ (失败)
重试 (最多 nDownloadRetries 次)
    ↓ (成功)
解压到 /var/volatile/
        ↓
检查文件存在性 (app_nccu.tar.gz + pkg.sum)
        ↓
MD5 校验
        ↓
校验通过?
    ↓ (失败)
上报失败状态,清理文件
    ↓ (成功)
解压到 /app 目录 (tar -zxf ... -C /app)
        ↓
sync 确保写入完成
        ↓
检查充电状态 (是否可以安全重启)
        ↓
检查 CCU 升级状态
        ↓
发送重启事件 (EVENT_SYSTEM_EXIT)
        ↓
系统重启,完成升级

7. 配置参数说明

7.1 升级相关配置项

参数 类型 默认值 说明
nDownloadRetries int 3 下载重试次数
nRetryInterv int 60 重试间隔(秒)
dtRetrieveDate time_t 0 升级开始时间

7.2 超时设置

  • 下载超时:1800 秒 (30 分钟)

  • 重启等待:检查充电状态间隔

  • CCU 同步等待:最多 3 次状态检查

8. 异常处理策略

8.1 下载异常

  • 网络断开:重试机制

  • 服务器错误:记录错误并重试

  • 磁盘空间不足:立即失败并上报

8.2 校验异常

  • MD5 不匹配:删除下载文件,标记失败

  • 文件损坏:同上

8.3 安装异常

  • 解压失败:回滚到原版本

  • 文件替换失败:保持原版本运行

8.4 重启异常

  • 重启失败:系统 watchdog 触发安全重启

  • 启动失败:启动脚本检测并回滚

9. 测试建议

9.1 单元测试

  • MD5 校验函数测试

  • 状态机转换测试

  • 事件上报测试

9.2 集成测试

  • 完整升级流程测试

  • 网络异常测试

  • 断电重启测试

9.3 压力测试

  • 大文件下载测试

  • 并发升级测试

  • 长时间运行稳定性测试

10. 维护建议

  1. 定期检查升级日志:监控升级成功率

  2. 升级包版本管理:确保云端只下发兼容版本

  3. 回滚机制完善:准备手动回滚方案

  4. 监控升级状态:实时监控设备升级进度

  5. 安全加固:验证升级包来源和完整性


本文档基于项目源码分析编写,涵盖了 OTA 升级功能的核心技术实现。

相关推荐
V1ncent Chen1 小时前
SQL大师之路 14 子查询
数据库·sql·mysql·数据分析
奇点爆破XC2 小时前
统计数据库当前数据容量
数据库
Leon-Ning Liu2 小时前
OGG同步Oracle到Kafka
数据库·oracle·kafka
远方16092 小时前
117-Oracle 26ai FILTER(过滤)子句新特性
大数据·数据库·sql·oracle·database
Maverick062 小时前
Oracle 归档日志(Archive Log)操作手册
数据库·oracle
isNotNullX2 小时前
一文讲清8大数据清洗方法
大数据·数据库·数据挖掘·数据迁移
Francek Chen2 小时前
【大数据存储与管理】分布式数据库HBase:05 HBase运行机制
大数据·数据库·hadoop·分布式·hdfs·hbase
十五年专注C++开发2 小时前
Linux 下用 VS Code 高效调试
linux·运维·服务器·c++·vscode
小小怪7502 小时前
将Python Web应用部署到服务器(Docker + Nginx)
jvm·数据库·python