EMS 知识库
首页 / knowledge/代码解析/net

bms_download.c

源文件路径:net/bms_download.c 所属模块:net(网络应用层 / 设备固件升级下载) 代码行数:61

1. 文件职责

本文件是 BMS(电池管理系统)云端固件下载流程的标志查询适配层,一共只有 3 个函数,全部是对 g_stEMSInfo.stUpt[UPDT_BMS] 的只读包装:IsDownloadBMS() 查询“云端是否要求强制下载”、IsUpgradeBMS() 查询“是否已完成从服务器的固件更新”、GetPercentDownloadBMS() 计算下载百分比。

它在数据流中不参与任何字节搬运,位置是「升级状态的两个状态位 + 一个进度值的只读出口」。上游由 net/server.c:2346 handle_special_cmd_for_dev() 置位强制标志、net/server.c:3675 handle_fw_file_from_server() 逐包写入 SDRAM、net/upd_download.c:412 calculate_dev_FW_Flash_MD5() 在 MD5 匹配后置位“已完成”。

驱动方有两类:HMI(hmi/ui/ui_main.c:844、:850、:853 轮询后显示“BMS 下载中 / 升级中”)与逆变器通信层(midware/inverter/kelong/kelong_comm.c:2203、midware/inverter/ginlong/ginlong_comm_usart.c 等用 IsUpgradeBMS() 决定是否让逆变器进入“配合电池升级”模式)。

2. 关键数据结构与宏

名称类型说明
STUpdateTab结构体定义于 net/server.h:216;本文件读取其中的 bIsUpdateForce(强制更新)、bIsUpdatedFromServer(已更新完成)、u32LenFile(文件总长)、u32OffsetFile(已下载偏移)
ENUpdateType枚举定义于 net/server.h:186;本文件使用 UPDT_BMS(值 1,紧跟 UPDT_EMS)作为 stUpt[] 下标
ST_EMS_INFO(g_stEMSInfo)全局结构体实例定义于 net/ems.h;stUpt[UPDT_MAX] 是升级表(net/ems.h:346),本文件唯一的状态来源
FILE_MASK_BMS宏net/server.h:84,值 "00000002";BMS 的升级文件掩码,本文件未直接引用,由 server.c / ems.c 匹配时使用
BOOLEAN类型uCOS/uC-LIB 定义;bIsUpdateForce / bIsUpdatedFromServer 的声明类型,本文件把它们提升为 u8 返回

本文件不定义任何结构体、枚举、联合体、位域或宏常量。

3. 函数清单

函数名作用域说明
IsDownloadBMS全局bms_download.c:36。返回 get_flag_force_update(UPDT_BMS),即云端下发的 BMS 强制下载标志
IsUpgradeBMS全局bms_download.c:47。返回 Get_Status_Is_Updated_From_Server(UPDT_BMS),即 BMS 固件是否已从服务器更新到位
GetPercentDownloadBMS全局bms_download.c:58。返回 已下载偏移 * 100 / 文件总长

共 3 个函数,全部为全局作用域,无 static 函数、无函数指针、无回调、无循环。

4. 核心逻辑解析

4.1 两个标志的语义区别(本文件最重要的信息点)

IsDownloadBMS() 与 IsUpgradeBMS() 名字相近但语义完全不同,是理解 BMS 升级流程的关键:

接口底层字段置位者含义典型消费场景
IsDownloadBMS()stUpt[UPDT_BMS].bIsUpdateForcenet/server.c:2408 set_flag_force_update(updType, TRUE)(云端特殊命令带强制位时)“云端要求下载 BMS 固件” —— 下载尚未结束决定 HMI 显示“下载中”,并配合百分比限制逆变器行为
IsUpgradeBMS()stUpt[UPDT_BMS].bIsUpdatedFromServernet/upd_download.c:412 Set_Status_Is_Updated_From_Server(updType, TRUE)(整包收妥且 MD5 匹配后)“固件已经下载并校验完成” —— 接下来由 BMS 侧执行刷写让逆变器/并机进入“配合 BMS 升级”的降额/停机模式

值得注意的是,net/server.c:2410-2412 在非强制升级时会显式把 UPDT_BMS(以及 UPDT_EVC、UPDT_INV3)的标志清零,也就是说:对这两个设备类型,普通升级不会让 IsDownloadBMS() 变真,它们走的是“先下载、后由 IsUpgradeBMS() 驱动刷写”的路径。

4.2 下载百分比公式与取值来源

u8 GetPercentDownloadBMS(void)
{
    return get_curr_offset_file_request(UPDT_BMS) * 100 / get_length_file_updating(UPDT_BMS);
}   // bms_download.c:58-61

4.3 状态迁移与外部状态机

本文件没有状态机,只提供两个读点,对应的外部迁移链为:

[云端特殊命令] server.c:2346 handle_special_cmd_for_dev
      ├─ 强制升级: server.c:2408 set_flag_force_update(UPDT_BMS, TRUE)
      │            → IsDownloadBMS()==1
      └─ 普通升级: server.c:2411 set_flag_force_update(UPDT_BMS, FALSE)
                   → IsDownloadBMS()==0,只靠 IsUpgradeBMS() 驱动后续
      ↓  server.c:3465 set_file_updating_info_for_dev(UPDT_BMS, 10K, SDRAM_3M)
      ↓  server.c:3762 save_fw_to_spi_flash(..., UPDT_BMS) → save_fw_to_sdram(..., g_u8_fw_sdram1)
      ↓  server.c:3801 calculate_dev_FW_Flash_MD5(UPDT_BMS, g_u8_fw_sdram1, BMS_FIRM_DOWNLOAD)
      ├─ MD5 一致 → upd_download.c:412 Set_Status_Is_Updated_From_Server(UPDT_BMS, TRUE)
      │             → IsUpgradeBMS()==1 → 逆变器/BMS 进入刷写阶段
      └─ MD5 不一致 → upd_download.c:422 u16_upgrade_error.BIT.md5_error = 1

4.4 通信协议帧格式与重试机制

本文件不构造/解析任何报文,也不含帧格式、校验、超时或重试逻辑。相关的外部契约:

4.5 与 uCOS-II 的配合

本文件不涉及任何 uCOS-II API:无任务、无信号量、无消息邮箱、无延时。三个函数都是对全局变量的同步单次读取。

g_stEMSInfo.stUpt[UPDT_BMS] 由 EMS 网络任务写(net/server.c、net/upd_download.c),由 HMI 任务与逆变器通信任务读,全程无临界区保护,依赖单字节布尔写入与 u32 自然对齐访问的原子性。* 100 / len 的读-算序列跨两次全局读,理论上可能与网络任务的写入交错,产生一次瞬时错误百分比(下一轮即恢复)。

5. 对外接口

本文件导出(供谁调用):

导出名调用方
IsDownloadBMShmi/ui/ui_main.c:844;net/ems_download.c:254(IsSystemDownload())
GetPercentDownloadBMShmi/ui/ui_main.c:850;midware/bms/bms.c:3280、:3307;midware/inverter/parallel.c:261;midware/inverter/pvcharger.c:49
IsUpgradeBMShmi/ui/ui_main.c:853;midware/interface/modbus/modbus.c:9379;midware/inverter/ginlong/ginlong_comm_usart.c:4363、:4370、:4378、:4397、:4748、:4759、:4830、:5156;midware/inverter/kelong/kelong_comm.c:2203

典型组合用法是 (GetPercentDownloadBMS() > 50) && IsDownloadBMS()(midware/bms/bms.c:3280、:3307、parallel.c:261、pvcharger.c:49):下载过半才认为“BMS 正在被更换/升级”,置位从机与 PV 充电机的 bit_bms_upgrade_flag。

本文件不导出全局变量。

本文件调用的外部符号:

名称来源
g_stEMSInfonet/ems.h
get_flag_force_update / Get_Status_Is_Updated_From_Server / get_curr_offset_file_request / get_length_file_updatingnet/upd_download.c(声明于 upd_download.h:26/28/37/40)

6. 依赖关系

依赖(第 13-20 行 include):

被依赖(include bms_download.h 的文件):

7. 备注与风险点

  1. 百分比函数存在除零可能:bms_download.c:60 的除数是 u32LenFile。bIsUpdateForce 在 net/server.c:2408 置位时文件长度尚未解析(值为 0),而 HMI 的显示路径是「先判 IsDownloadBMS() 再算百分比」(ui_main.c:844、:850),存在分母为 0 的窗口。ARM 平台上 32 位无符号除法除零不触发硬件异常(UDIV 或库函数 __aeabi_uidiv 均返回 0),故表现为显示 0% 而非崩溃,但严格说是依赖平台行为的隐式假设。
  2. 文件头与函数头注释问题:@file 写的是 BMSUpdate.c(第 2 行),与真实文件名 bms_download.c 不符;@date 为 2017/05/18,是本文件群(bms/evc/inv/meter 四个 download 文件)共用的历史日期。文件名与 @file 不一致会干扰按文件名检索。
  3. u8 截断:返回类型是 u8,而中间计算是 u32。正常流程比值 ≤ 100 不触发截断;但若 u32OffsetFile 因重复包或包长异常而超过 u32LenFile,结果会被截断成任意 8 位数后显示到 LCD(Lcd_Draw_Number(3, 11, (u16)GetPercentDownloadBMS(), 3) 只画 3 位)。
  4. 命名歧义:IsDownloadBMS() 与 IsUpgradeBMS() 仅一词之差,含义分别是“要下载”和“已下载完成”。hmi/ui/ui_main.c:844、:853 靠这两个条件区分“Download BMS FW”和“upgrade BMS”两种界面文案,改错一个就会显示相反的提示。建议在调用点或命名上加强区分。
  5. 冗余 include:MD5.h / sdram.h / iwdg.h / bms.h 在本文件未被使用,可移除以减少编译依赖(见 6. 依赖)。