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

evc_upgrade.h

源文件路径:midware/evc/evc_upgrade.h 所属模块:midware/evc(充电桩固件升级) 代码行数:63

1. 文件职责

本文件是充电桩固件升级模块的对外声明头文件,定义升级流程的状态枚举、升级命令码枚举、升级上下文结构体 EVC_UPGRADE_T 以及 5 个对外接口原型。

它同时服务一代桩(单桩)与二代桩(最多 4 桩)的固件升级:通过 MAX_EVC_II_NUM 长度的数组把一/二代统一成"最多 4 个升级目标",一代固定使用下标 0(见 evc_upgrade.c:707)。

驱动链路:midware/interface/interface.c:341 在 is_upgrade_evc() 为真时优先调用 evc_upgrad_handle();升级标志由云端下发时经 net/server.c:2458 的 set_evc_upgrad_flag() 置位;进度由 net/ems.c:6719(断电续传偏移)与 hmi/ui/ui_main.c:895(界面百分比)消费。

2. 关键数据结构与宏

名称类型说明
DEBUG_EVC_UPGRADE宏调试打印开关,值为 0(evc_upgrade.h:14)
EVC_UPGRADE_TEMP_DATA_LEN宏每次从 SDRAM 中取 80 字节 Hex 文本交给解析器(evc_upgrade.h:16)
EVC_MAX_PRG_LENGTH宏单帧最大烧写数据长度 112*2 = 224(字节),对应 112 个 16 位字(evc_upgrade.h:17)
EVC_UPGRADE_STATE_E枚举升级主状态机 8 态:EVC_UPGRADE_INIT(0)/EVC_PRAVITE_KEY/EVC_BOOT_ENTER/EVC_HANDSHAKE/EVC_ERASE_FLASH/EVC_WRITE_FLASH/EVC_SEND_KEY_WORD/EVC_UPGRADE_END(evc_upgrade.h:18)
EVC_UPGRADE_CODE_E枚举下发给桩内 Bootloader 的命令码:EVC_APP_JUMP(0)/EVC_HAND_SHAKE/EVC_ERASE_APP/EVC_WRITE_APP/EVC_CHECK_FILE/EVC_BOOT_JUMP(evc_upgrade.h:30)
EVC_UPGRADE_T结构体升级上下文(evc_upgrade.h:41),全部字段见下
u8_upgrad_flag[MAX_EVC_II_NUM]结构体成员每个目标桩的升级使能标志,为 TRUE 才参与本轮升级
u8_upgrad_err_cnt[MAX_EVC_II_NUM]结构体成员每桩重试次数计数,非 0 表示本轮失败并放弃该桩
u32_addr_flash_base结构体成员Hex 文件中"扩展线性地址记录"(记录类型 0x04)给出的基址
u32_old_addr_offset结构体成员上一段数据的地址偏移,用于判断相邻两段是否连续
u32_addr_flash_offset结构体成员当前段数据的地址偏移
u32_addr_flash结构体成员实际烧写地址 = `addr_flash_base << 16 \addr_flash_offset`
u32_parse_length结构体成员已解析的文件字节偏移,同时作为升级进度与断电续传偏移
u8_upgrad_file_buf结构体成员指向发送缓存内实际放数据的游标(固定指向 s_evc_upgrade_send_buf[18])
u16_length结构体成员当前拼包后的数据长度(≤ EVC_MAX_PRG_LENGTH)
u8_evc_ii_encryption_flag[MAX_EVC_II_NUM]结构体成员每桩加密标志副本,决定升级帧是否走 AES 分支

3. 函数清单

本文件为纯声明头文件,不含函数定义,仅导出 5 个原型。

函数名作用域说明
evc_upgrad_handle全局(声明,evc_upgrade.h:56)升级主状态机,每个升级周期调用一次;定义于 evc_upgrade.c:433
set_evc_upgrad_flag全局(声明,evc_upgrade.h:57)由云端命令设置参与升级的桩(0 = 所有使能桩,N = 第 N 桩,>4 = 全部清除);定义于 evc_upgrade.c:694
is_upgrade_evc全局(声明,evc_upgrade.h:58)查询云端是否下发过 EVC 升级任务;定义于 evc_upgrade.c:755
get_percent_upgrade_evc全局(声明,evc_upgrade.h:59)返回升级百分比(已解析长度 / 文件总长 ×100);定义于 evc_upgrade.c:767
get_upgrade_file_offset_evc全局(声明,evc_upgrade.h:60)返回已解析文件偏移,供云端续传对账;定义于 evc_upgrade.c:780

4. 核心逻辑解析

本文件不含可执行逻辑,核心作用是为"多桩统一升级"与"Hex 解析状态传递"提供类型契约。

4.1 一套代码服务一/二代桩

EVC_UPGRADE_T 的 4 元素数组(u8_upgrad_flag[4]、u8_upgrad_err_cnt[4]、u8_evc_ii_encryption_flag[4])使升级器不必区分一/二代:一代桩固定占用下标 0,二代桩按下标对应;evc_upgrade.c:705-708 在 get_evc_enable_flag() == TRUE 时只置 u8_upgrad_flag[0]。数组长度复用二代宏 MAX_EVC_II_NUM,因此一代桩的升级目标数也被顺带扩到 4(当前无用)。

4.2 两个状态机

两者的映射关系:EVC_BOOT_ENTER 态发 EVC_BOOT_JUMP,EVC_HANDSHAKE 态发 EVC_HAND_SHAKE,EVC_ERASE_FLASH 态发 EVC_ERASE_APP,EVC_WRITE_FLASH 态发 EVC_WRITE_APP(在 evc_upgrade_send_data() 内硬编码填写),EVC_SEND_KEY_WORD 态发 EVC_APP_JUMP。EVC_CHECK_FILE 与 EVC_BOOT_JUMP 中的 EVC_CHECK_FILE 在本文件中定义但在 evc_upgrade.c 中从未使用,属预留命令。

4.3 结构体的 #pragma pack(1)

EVC_UPGRADE_T 被 #pragma pack(1)/#pragma pack() 包裹(evc_upgrade.h:40、evc_upgrade.h:54)。该结构体只存在于 RAM、不用于收发也不落 Flash,pack(1) 唯一的实际效果是把 5 个 u32 成员从自然 4 字节对齐改为紧凑排列——在 Cortex-M4 上会产生 ldr 非对齐访问(ARMCC 会用 ldrb 组合代替,性能略降)。evc_upgrade.c:671 的 memset(&s_evc_upgrade_tab, 0, sizeof(EVC_UPGRADE_T)) 是按 sizeof 操作的,因此不受影响。

4.4 关键常量语义

5. 对外接口

导出的函数(供谁调用)

导出函数调用方
evc_upgrad_handlemidware/interface/interface.c:343
is_upgrade_evcmidware/interface/interface.c:341、hmi/ui/ui_main.c:889
set_evc_upgrad_flagnet/server.c:2458
get_percent_upgrade_evchmi/ui/ui_main.c:895
get_upgrade_file_offset_evcnet/ems.c:6719

导出的类型与宏

EVC_UPGRADE_T、EVC_UPGRADE_STATE_E、EVC_UPGRADE_CODE_E、EVC_MAX_PRG_LENGTH、EVC_UPGRADE_TEMP_DATA_LEN —— 目前仅 evc_upgrade.c 自身使用,未发现其它文件引用这些类型(EVC_UPGRADE_T 与 EVC_UPGRADE_CODE_E 只在 .c 内部展开)。

本文件依赖的外部声明

includes.h(evc_upgrade.h:9)提供 u8/u16/u32/TRUE/FALSE;evc.h(evc_upgrade.h:10)提供 EVC_BUF_LEN 等;evc_ii.h(evc_upgrade.h:11)提供 MAX_EVC_II_NUM。头文件本体不调用任何函数。

6. 依赖关系

7. 备注与风险点

  1. evc_upgrade.c 中 5 个全局函数未在本头文件声明:evc_upgrade_send_cmd、evc_upgrade_recv_data、evc_upgrade_send_code、evc_upgrade_send_data、evc_upgrade_send_key_word 在 evc_upgrade.c:45/88/178/220/262 定义为非 static 的全局符号,却没有原型且没有外部调用者(全工程搜索确认)。它们应当声明为 static,当前状态会造成符号污染,并失去编译器的参数类型检查(就近调用时无原型)。
  2. EVC_UPGRADE_CODE_E 有两项从未使用:EVC_CHECK_FILE(4) 与枚举顺序末尾的 EVC_BOOT_JUMP(5)——EVC_BOOT_JUMP 实际被使用(evc_upgrade.c:486),但 EVC_CHECK_FILE 在 evc_upgrade.c 中无任何引用,属版本迭代遗留。
  3. u8_upgrad_file_buf 是指针而非数组(evc_upgrade.h:50):由 evc_upgrade.c:381 指向发送缓存的固定偏移 18,一旦 evc_upgrade_send_cmd 的帧头长度(当前 8 字节 data 头 + 2 字节长度域)发生变化,该偏移必须同步修改,否则会写坏帧头。此偏移量是隐性耦合,无宏保护。
  4. EVC_UPGRADE_T 被 pack(1) 包裹(evc_upgrade.h:40):如 4.3 节所述,对纯 RAM 结构体做 1 字节对齐没有收益,只会引入非对齐 32 位访问。建议后续移除。
  5. 缩进/命名不一致:u8_upgrad_flag、u8_upgrad_err_cnt 用的是 "upgrad"(少一个 e),而函数名是 "upgrad"(evc_upgrad_handle、set_evc_upgrad_flag)、文件名却是 "upgrade"(evc_upgrade.c),三种拼写混用;evc_upgrade.h:52 的 u8_evc_ii_encryption_flag 在升级模块里却用二代前缀,一代桩也复用同一字段。
  6. 无版本/长度字段保护:EVC_UPGRADE_T 未记录本次升级的文件总长度或校验和,百分比计算完全依赖外部 get_length_file_updating(UPDT_EVC)(evc_upgrade.c:769)。若云端长度与实际文件不符,进度会超过 100%。