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].bIsUpdateForce | net/server.c:2408 set_flag_force_update(updType, TRUE)(云端特殊命令带强制位时) | “云端要求下载 BMS 固件” —— 下载尚未结束 | 决定 HMI 显示“下载中”,并配合百分比限制逆变器行为 |
IsUpgradeBMS() | stUpt[UPDT_BMS].bIsUpdatedFromServer | net/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
- 分母
u32LenFile:由net/server.c:3318set_file_updating_info_for_dev()从云端 JSON 的Length解析,且必须落在(1024*10, SDRAM_3M)(10 KB ~ 3 MB)区间内才被接受,见net/server.c:3465-3468。未通过时保持 0。 - 分子
u32OffsetFile:由net/server.c:3568increase_current_offset_file_updt()按每包长度递增(调用点net/server.c:3831)。 - 收尾时
net/upd_download.c:429无条件把u32OffsetFile清零,所以百分比会自然回落到 0。
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 通信协议帧格式与重试机制
本文件不构造/解析任何报文,也不含帧格式、校验、超时或重试逻辑。相关的外部契约:
- 包级校验在
net/server.c:3692起:FileMask(8 字符) →FileOffset(必须等于本地已下载偏移,server.c:3699)→FileType(必须与bms_read_battery_model()匹配,server.c:3706)→FileLength(不得超过单包上限LEN_REQ_FILE,server.c:3717)→FileData(十六进制串)。任一步失败即return,丢弃该包,等云端超时重发。 - 整卷校验是 MD5(
net/upd_download.c:391),失败置md5_error位而不修改完成标志,由上层重新走一次下载。
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. 对外接口
本文件导出(供谁调用):
| 导出名 | 调用方 |
|---|---|
IsDownloadBMS | hmi/ui/ui_main.c:844;net/ems_download.c:254(IsSystemDownload()) |
GetPercentDownloadBMS | hmi/ui/ui_main.c:850;midware/bms/bms.c:3280、:3307;midware/inverter/parallel.c:261;midware/inverter/pvcharger.c:49 |
IsUpgradeBMS | hmi/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_stEMSInfo | net/ems.h |
get_flag_force_update / Get_Status_Is_Updated_From_Server / get_curr_offset_file_request / get_length_file_updating | net/upd_download.c(声明于 upd_download.h:26/28/37/40) |
6. 依赖关系
依赖(第 13-20 行 include):
upd_download.h、bms_download.h、ems.h、server.h、MD5.h、bms.h、sdram.h、iwdg.h- 其中
MD5.h、sdram.h、iwdg.h、bms.h在本文件内均无直接引用(MD5 计算在upd_download.c,BMS 相关读取在调用方各自完成),是从早期「下载+校验+刷写」一体化文件拆分后遗留的冗余 include。
被依赖(include bms_download.h 的文件):
net/bms_download.c:14net/ems.c:19、net/ems_download.c:18、net/server.c:21hmi/ui/ui_main.c:23midware/bms/bms.c:21、midware/bms/alpha/battery_upgrade.c:16midware/interface/modbus/modbus.c:33midware/inverter/parallel.c:21、midware/inverter/pvcharger.c:17midware/inverter/alphaess/alphaess_comm_usart.c:27midware/inverter/ginlong/ginlong_comm_usart.c:24midware/inverter/inovance/inovance_comm_can.c:11midware/inverter/kelong/kelong_comm.c:23
7. 备注与风险点
- 百分比函数存在除零可能:
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% 而非崩溃,但严格说是依赖平台行为的隐式假设。 - 文件头与函数头注释问题:
@file写的是BMSUpdate.c(第 2 行),与真实文件名bms_download.c不符;@date为2017/05/18,是本文件群(bms/evc/inv/meter四个 download 文件)共用的历史日期。文件名与@file不一致会干扰按文件名检索。 u8截断:返回类型是u8,而中间计算是u32。正常流程比值 ≤ 100 不触发截断;但若u32OffsetFile因重复包或包长异常而超过u32LenFile,结果会被截断成任意 8 位数后显示到 LCD(Lcd_Draw_Number(3, 11, (u16)GetPercentDownloadBMS(), 3)只画 3 位)。- 命名歧义:
IsDownloadBMS()与IsUpgradeBMS()仅一词之差,含义分别是“要下载”和“已下载完成”。hmi/ui/ui_main.c:844、:853靠这两个条件区分“Download BMS FW”和“upgrade BMS”两种界面文案,改错一个就会显示相反的提示。建议在调用点或命名上加强区分。 - 冗余 include:
MD5.h/sdram.h/iwdg.h/bms.h在本文件未被使用,可移除以减少编译依赖(见 6. 依赖)。