evc_upgrade.h
#pragma pack(1)4.4 关键常量语义5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
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_UPGRADE_STATE_E是流程状态机:INIT → 取私钥 → 进 Boot → 握手 → 擦除 → 写 Flash(循环直到文件解析完)→ 发送跳转密钥 → 结束。进度不可回退,只能靠EVC_UPGRADE_END回到 INIT 重来。EVC_UPGRADE_CODE_E是下发给桩内 Bootloader 的命令码:它作为数据域中的"命令字节"出现在evc_upgrade_send_code()组帧里(evc_upgrade.c:190与evc_upgrade.c:203的code字段),桩侧回显同一命令码表示接受。
两者的映射关系: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 关键常量语义
EVC_MAX_PRG_LENGTH = 224:拼包时s_u8_data_len <= EVC_MAX_PRG_LENGTH才允许下发(evc_upgrade.c:391),否则把长度归零丢弃并重新开始拼。224 字节对应 14 个 16 位寄存器,正好落在 Modbus 单帧 256 字节缓存(EVC_BUF_LEN)之内:帧头 8 字节 + 224 字节数据 + CRC 2 字节 = 234 < 256。EVC_UPGRADE_TEMP_DATA_LEN = 80:每次取 80 字节 Hex 文本(约 2~3 行 Intel Hex)交给hex_parse(),解析失败时按行边界推进u32_parse_length(evc_upgrade.c:324-340)。
5. 对外接口
导出的函数(供谁调用)
| 导出函数 | 调用方 |
|---|---|
evc_upgrad_handle | midware/interface/interface.c:343 |
is_upgrade_evc | midware/interface/interface.c:341、hmi/ui/ui_main.c:889 |
set_evc_upgrad_flag | net/server.c:2458 |
get_percent_upgrade_evc | hmi/ui/ui_main.c:895 |
get_upgrade_file_offset_evc | net/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. 依赖关系
- 依赖:
includes.h、evc.h、evc_ii.h(evc_upgrade.h:9-11)。 - 被依赖:
midware/evc/evc_upgrade.c(evc_upgrade.c:13,唯一实现者);接口声明被midware/interface/interface.c、net/server.c、net/ems.c、hmi/ui/ui_main.c通过包含链间接使用。
7. 备注与风险点
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,当前状态会造成符号污染,并失去编译器的参数类型检查(就近调用时无原型)。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中无任何引用,属版本迭代遗留。u8_upgrad_file_buf是指针而非数组(evc_upgrade.h:50):由evc_upgrade.c:381指向发送缓存的固定偏移 18,一旦evc_upgrade_send_cmd的帧头长度(当前 8 字节 data 头 + 2 字节长度域)发生变化,该偏移必须同步修改,否则会写坏帧头。此偏移量是隐性耦合,无宏保护。EVC_UPGRADE_T被pack(1)包裹(evc_upgrade.h:40):如 4.3 节所述,对纯 RAM 结构体做 1 字节对齐没有收益,只会引入非对齐 32 位访问。建议后续移除。- 缩进/命名不一致:
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在升级模块里却用二代前缀,一代桩也复用同一字段。 - 无版本/长度字段保护:
EVC_UPGRADE_T未记录本次升级的文件总长度或校验和,百分比计算完全依赖外部get_length_file_updating(UPDT_EVC)(evc_upgrade.c:769)。若云端长度与实际文件不符,进度会超过 100%。