kelong_upgrade.h
KELONG_UPGRADE_TABLE_T 的缓冲区布局3. 函数清单4. 核心逻辑解析4.1 命令字分段与常规通信的隔离4.2 上下文结构的静态性4.3 两套枚举的对应关系5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
midware/inverter/kelong/kelong_upgrade.h所属模块:midware/inverter/kelong(科隆逆变器 CAN 固件升级协议) 代码行数:60
1. 文件职责
本头文件是科隆逆变器在线固件升级(IAP over CAN)的协议定义与状态容器声明。它把升级专用的 4 个下行命令字(0x301 握手 / 0x302 传文件 / 0x303 校验 / 0x304 查状态)与 1 个上行应答字(0x401 ACK)固化成宏,并定义升级"对象"(主机/从机)与升级"阶段"两套枚举、以及升级运行期上下文结构体 KELONG_UPGRADE_TABLE_T。文件本身无逻辑,被 kelong_comm.h:14 直接 include,从而让常规通信模块与升级模块处在同一个协议命名空间内;同时把 5 个供上层(inverter.c 的转发层)查询升级进度/进度的接口暴露出去。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
EMS_INV_SHAKE_HANDS | 宏 0x301 | EMS→INV 升级握手,携带升级对象与总行数,要求逆变器应答 0x401 |
EMS_INV_SEND_UPGRADE_FILE | 宏 0x302 | EMS→INV 发送固件数据,每帧 8 字节 = 行号(2) + 段序号(1) + 5 字节 HEX 文本 |
EMS_INV_CHECK_UPGRADE_FILE | 宏 0x303 | EMS→INV 逐块校验(每 3 行一次),要求 ACK |
EMS_INV_CHECK_UPGRADE_SATTE | 宏 0x304 | EMS→INV 查询升级最终状态,要求 ACK(注意原文件名/宏名把 STATE 拼写为 SATTE,属原始拼写,全工程一致沿用) |
INV_EMS_ACK | 宏 0x401 | INV→EMS 统一应答帧,不同命令用不同数据域字段做匹配 |
KELONG_UPGRADE_OBJECT_E | 枚举 | 升级对象:KELONG_NONE(0) / KELONG_MASTER(1) / KELONG_SLAVE(2) |
KELONG_UPGRADE_SATE_E | 枚举 | 升级阶段:UPGRADE_INIT → QUERY_NUMBER_ROWS → SEND_UPGRADE_FILE → CHECK_UPGRADE_FILE → UPGRADE_END(枚举名同样把 STATE 拼为 SATE) |
KELONG_UPGRADE_TABLE_T | 结构体 | 升级运行期上下文:u8_upgrade_addr(SDRAM 中固件首地址)、u8_upgrade_object(当前升级对象)、u8_upgrade_buf[3][40](每次打包 3 行的行缓冲,每行 40 字节)、u16_send_line_num(已发送行计数)、u16_upgrade_line_num(文件总行数)、u32_upgrade_file_len(文件字节长度)、u32_upgrade_file_offset(已解析字节偏移) |
2.1 KELONG_UPGRADE_TABLE_T 的缓冲区布局
u8_upgrade_buf[3][40] 的结构并非 HEX 文本原样存放,而是"解析后的紧凑二进制 + 分字段头":
| 偏移 | 长度 | 含义 |
|---|---|---|
[i][0] | 1 | 数据长度 u8_data_len |
[i][1..2] | 2 | 目标地址 u16_addr(大端) |
[i][3] | 1 | 记录类型 u8_code_type |
[i][4..] | 最长 32 | u16_data_buf[32] 展开成大端字节流,每字节 1 位 |
[i][4+u8_data_len] | 1 | HEX 累加和 u8_sum_check |
即单行最大占用 4 + 32 + 1 = 37 字节,40 预留了 3 字节余量(见 kelong_upgrade.c 中 memset(...,0,120) 的用法,120 = 3×40)。
3. 函数清单
本文件为纯头文件,不含函数定义。声明的 5 个外部接口函数如下:
| 函数名 | 作用域 | 说明 |
|---|---|---|
kelong_upgrade_handle | 全局(声明) | 升级主状态机,被 kelong_inverter_comm 在固件下载完成后每轮调用 |
kelong_read_upgrade_flag_master | 全局(声明) | 返回"当前是否正在升级逆变器主机"(内部判断 u8_upgrade_object == KELONG_MASTER) |
kelong_read_upgrade_percent_master | 全局(声明) | 返回逆变器主机升级百分比,非主机升级时返回 0 |
kelong_read_upgrade_flag_slave | 全局(声明) | 返回"当前是否正在升级逆变器从机" |
kelong_read_upgrade_percent_slave | 全局(声明) | 返回逆变器从机升级百分比,非从机升级时返回 0 |
4. 核心逻辑解析
本文件无执行逻辑,此节说明其声明的内容在升级流程中的作用。
4.1 命令字分段与常规通信的隔离
升级命令字使用 0x3xx(下行)与 0x4xx(上行),与常规通信的 0x181~0x1DE / 0x201~0x28C 完全不重叠。但二者共用同一条 CAN1 总线和同一个接收队列,因此 kelong_inverter_comm 用 is_inverter_firm_download_finished() 做整轮互斥:升级期间常规帧一个不发,避免常规 0x184 开关机帧打断 IAP。
4.2 上下文结构的静态性
KELONG_UPGRADE_TABLE_T 的唯一实例 s_t_upgrade_tab 是 kelong_upgrade.c:28 的 static 变量,本头文件不提供 extern 声明。外部只能通过 4 个 getter 读取"是否在升级/进度百分比",无法直接读到升级对象、总行数或文件长度。这是刻意的封装,但也意味着"当前升级的是主机还是从机"只能由两个 flag 间接判断。
4.3 两套枚举的对应关系
KELONG_UPGRADE_OBJECT_E 与 KELONG_UPGRADE_SATE_E 分别充当 s_t_upgrade_tab.u8_upgrade_object 与 kelong_upgrade_handle 内静态 s_u8_upgrade_sate 的取值域。由于它们被声明为 u8 字段/变量而非枚举类型变量,编译器不会做类型检查,赋任何 u8 值都合法 —— 这为 default: 分支的存在提供了必要性(kelong_upgrade.c:591-595)。
5. 对外接口
本文件导出(供外部调用/引用)
- 宏:
EMS_INV_SHAKE_HANDS、EMS_INV_SEND_UPGRADE_FILE、EMS_INV_CHECK_UPGRADE_FILE、EMS_INV_CHECK_UPGRADE_SATTE、INV_EMS_ACK - 类型:
KELONG_UPGRADE_OBJECT_E、KELONG_UPGRADE_SATE_E、KELONG_UPGRADE_TABLE_T - 函数声明:
kelong_upgrade_handle、kelong_read_upgrade_flag_master、kelong_read_upgrade_percent_master、kelong_read_upgrade_flag_slave、kelong_read_upgrade_percent_slave
本文件依赖(include)
includes.h:工程统一聚合头,提供u8/u16/u32/TRUE/FALSE等基础类型与宏
6. 依赖关系
- 依赖:
includes.h - 被依赖:
midware/inverter/kelong/kelong_upgrade.c(本文件的实现者)midware/inverter/kelong/kelong_comm.h:14直接 include 本文件,因此任何包含kelong_comm.h的编译单元都会间接获得升级协议声明midware/inverter/kelong/kelong_comm.c直接 include(kelong_comm.c:18),调用kelong_upgrade_handle与两个 flag 读取函数midware/inverter/inverter.c:3807/3843/3878/3913的inverter_read_upgrade_flag_master/percent_master/flag_slave/percent_slave在KELONG_TYPE时转调本文件的同系列函数,供 HMI/云端显示升级进度
7. 备注与风险点
- 枚举/宏拼写遗留:
KELONG_UPGRADE_SATE_E、UPGRADE_INIT~UPGRADE_END的容器名把STATE拼为SATE;协议宏EMS_INV_CHECK_UPGRADE_SATTE也同样拼错。全工程一致,改动会波及多处,建议保留但补注释。 u8_upgrade_buf[3][40]无边界校验:容纳单行解析结果的最大长度为4 + 32 + 1 = 37字节,余 3 字节。若 HEX 记录的数据长度字段损坏为大于 32 的值,kelong_upgrade.c的写循环j < u8_data_len/2可能写到 40 字节之外(见对应实现文档的风险点)。- 无
extern声明的上下文结构:外部无法获知升级的总体进度分母(u32_upgrade_file_len),百分比只能通过 getter 获得;kelong_read_upgrade_percent_*内部做除法,若u32_upgrade_file_len == 0存在除零风险(具体条件见实现文档)。 - 命令字宏未包含校验/长度字段:升级帧同样依赖 CAN 硬件 CRC,协议层没有额外校验字,数据完整性完全靠 HEX 自带的
u8_sum_check与最终0x304状态查询。 EMS_INV_CHECK_UPGRADE_SATTE与EMS_INV_CHECK_UPGRADE_FILE语义接近:前者查"最终升级结果状态",后者查"当前块写入是否正确",命名极易混淆,两者在实现中均为"发帧 + 等 ACK + 100 ms 超时"的同构形式。