ginlong_upgrade.h
源文件路径:
midware/inverter/ginlong/ginlong_upgrade.h所属模块:midware / inverter / ginlong(锦浪逆变器固件升级) 代码行数:98
1. 文件职责
本文件是锦浪逆变器固件升级模块(ARM 主控单元 / DSP 单元)的对外声明头。它定义了升级对象枚举 GINLONG_UPGRADE_OBJECT_E、两套升级状态机枚举(ARM 与 DSP)、升级过程表结构 GINLONG_UPGRADE_TABLE_T 以及若干缓冲区尺寸与调试宏。升级数据流为:服务器下发固件 → 存入 SDRAM → 本模块经 USART2 分帧写入逆变器 → 上报百分比供 HMI 显示。头文件本身无逻辑,仅提供接口与类型契约,实现全部在 ginlong_upgrade.c。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
GINLONG_UPGRADE_DEBUG | 宏 | 调试打印开关,值 (0)。置 1 后 ginlong_upgrade.c 中所有 printf 生效(ginlong_upgrade.h:15) |
DAT_PCK_UPGRADE_INV | 宏 | (300),向逆变器发送连续升级数据包之间的最小间隔(毫秒),用于流控(ginlong_upgrade.h:16) |
INV_RECV_UPGRADE_BUFFER_SIZE | 宏 | (200),接收升级应答缓冲区大小(ginlong_upgrade.h:17) |
SEND_UPGRADE_DATA_SIZE | 宏 | (1024),每包固件负载字节数(1 KB)(ginlong_upgrade.h:18) |
GINLONG_UPGRADE_OBJECT_E | 枚举 | 升级对象:GINLONG_NONE(0)、GINLONG_MASTER(1)、GINLONG_SLAVE(2)、GINLONG_ARM(3)(ginlong_upgrade.h:20-26) |
GINLONG_UPGRADE_ARM_STATE_E | 枚举 | ARM 升级状态机:UPGRADE_ARM_IDLE、SEND_ARM_OFF_GRID_COMMAND、ENTER_ARM_UPGRADE_BOOT、WAIT_ARM_ERASE_RESPONSE、WRITE_ARM_FIRMWARE_CONTENT、UPGRADE_ARM_FINISH(ginlong_upgrade.h:46-55) |
GINLONG_UPGRADE_DSP_STATE_E | 枚举 | DSP 升级状态机:UPGRADE_DSP_IDLE、SEND_OFF_GRID_COMMAND、ENTER_DSP_UPGRADE_BOOT、WRITE_DSP_API_DATA、WAIT_DSP_ERASE_RESPONSE、WRITE_DSP_FIRMWARE_DATA、EXIT_DSP_UPGRADE、UPGRADE_DSP_FINISH(ginlong_upgrade.h:57-68) |
GINLONG_UPGRADE_TABLE_T | 结构体 | 升级过程表,见下 |
(已注释)GINLONG_UPGRADE_SATE_E | 枚举(注释掉的) | 早期 ARM+DSP 合并单状态机版本,共 12 个状态,已被拆分成两套状态机取代(ginlong_upgrade.h:28-44) |
GINLONG_TABLE_T / GINLONG_COMM_INFO_T | 结构体 | 由 ginlong_comm_usart.h 提供,升级百分比标志经 g_t_ginlong_info 汇总 |
GINLONG_UPGRADE_TABLE_T(ginlong_upgrade.h:71-81)字段:
| 字段 | 类型 | 说明 |
|---|---|---|
u8_upgrade_addr | u8* | 固件在 SDRAM 中的起始地址(g_u8_fw_sdram1 或 g_u8_fw_sdram2) |
u8_upgrade_object | u8 | 当前升级对象,取值来自 GINLONG_UPGRADE_OBJECT_E |
u16_send_line_num | u16 | 下一包应发送的包序号(从 1 起,用于协议中的行号字段) |
u8_upgrade_buf[1035] | u8[] | 组帧缓冲区。最大负载 1024 字节,加上 ARM 帧头 9 字节 + 校验 1 字节 = 1034,DSP 帧头 7 字节 + 校验 1 字节 = 1032,取 1035 留有余量 |
u16_upgrade_line_num | u16 | 逆变器已确认接收的包序号(用于与 u16_send_line_num 比较判断丢包) |
u32_upgrade_file_len | u32 | 固件文件总长度(字节) |
u32_upgrade_file_offset | u32 | 已成功写入的字节偏移,也是百分比计算分子 |
3. 函数清单
本文件不含函数定义,仅声明以下 10 个函数(均在 ginlong_upgrade.c 中实现):
| 函数名 | 作用域 | 说明 |
|---|---|---|
ginlong_upgrade_arm_handle | 全局(仅声明) | ARM 单元升级状态机主函数 |
ginlong_upgrade_dsp_handle | 全局(仅声明) | DSP 单元升级状态机主函数 |
ginlong_upgrade_handle | 全局(仅声明) | 仅有声明,全工程无定义(见第 7 节) |
ginlong_send_upgrade_data | 全局(仅声明) | 带流控的升级数据发送封装 |
ginlong_read_upgrade_flag_master | 全局(仅声明) | 查询当前是否在升级逆变器主机 |
ginlong_read_upgrade_percent_master | 全局(仅声明) | 查询主机升级百分比 |
ginlong_read_upgrade_flag_slave | 全局(仅声明) | 查询当前是否在升级逆变器从机 |
ginlong_read_upgrade_percent_slave | 全局(仅声明) | 查询从机升级百分比 |
ginlong_read_upgrade_flag_arm | 全局(仅声明) | 查询当前是否在升级 ARM 单元 |
ginlong_read_upgrade_percent_arm | 全局(仅声明) | 查询 ARM 升级百分比 |
4. 核心逻辑解析
(头文件层面说明协议契约,实现细节见 ginlong_upgrade.c 文档。)
4.1 状态机拆分设计
头文件保留了一段被注释掉的 GINLONG_UPGRADE_SATE_E(ginlong_upgrade.h:28-44),其状态序列为:UPGRADE_IDLE → ENTER_ARM_UPGRADE_BOOT → WAIT_ARM_ERASE_RESPONSE → WRITE_ARM_FIRMWARE_CONTENT → SEND_OFF_GRID_COMMAND → ENTER_DSP_UPGRADE_BOOT → WRITE_DSP_API_DATA → WAIT_DSP_ERASE_RESPONSE → WRITE_DSP_FIRMWARE_DATA → EXIT_DSP_UPGRADE → UPGRADE_FINISH。
这段注释清晰记录了设计演进:早期版本用单一状态机串联 ARM 与 DSP 两阶段升级,现版本拆成两套独立状态机(GINLONG_UPGRADE_ARM_STATE_E 与 GINLONG_UPGRADE_DSP_STATE_E),由 ginlong_comm_usart.c 根据升级类型分别调用 ginlong_upgrade_arm_handle() 或 ginlong_upgrade_dsp_handle()。拆分后两阶段的超时计数、错误计数互不干扰,但也意味着 ARM 与 DSP 不能并行升级。
4.2 升级对象与状态语义
GINLONG_MASTER:逆变器主机(DSP 固件写完后,WAIT_DSP_ERASE_RESPONSE阶段切到该对象,对应g_u8_fw_sdram1/UPDT_INV1)。GINLONG_SLAVE:逆变器从机(WRITE_DSP_API_DATA阶段写入,对应g_u8_fw_sdram2/UPDT_INV2)。GINLONG_ARM:ARM 控制单元(对应g_u8_fw_sdram1/UPDT_INV3)。
u8_upgrade_object 是判断"当前在升级谁"的唯一依据,4 个读取接口全部基于它做相等比较(ginlong_upgrade.c:275、307、337 等),并用来驱动 g_t_inv_info.t_run_info.u8_run_mode 显示为 cUpdateMaster / cUpdateSlave / cUpdateArm。
4.3 缓冲区尺寸的推导
SEND_UPGRADE_DATA_SIZE = 1024 与 u8_upgrade_buf[1035] 的关系:
- ARM 帧(命令字
0xC4):7E 01 C4 LEN_L LEN_H LINE_L LINE_H + payload + CHECK,帧头 9 字节 + 负载 + 1 字节校验,最大占用7 + 1024 + 1 = 1032字节,下标最高到 1031。 - DSP 帧(命令字
0xC6):7E 01 C6 LEN_L LEN_H LINE_L LINE_H + payload + CHECK,帧头 7 字节 + 负载 + 1 字节校验,最大占用5 + 1024 + 1 = 1030,下标最高到 1029。
因此 1035 有约 3 字节余量,安全但无显式 static_assert 保护——若将来把 SEND_UPGRADE_DATA_SIZE 调大(例如 2048),缓冲区会静默溢出。
4.4 与 uCOS-II 的配合
头文件本身不涉及任务/信号量。从枚举命名与实现看,*_handle() 函数是状态机单步推进器:每次调用只执行当前状态的一小段(通常发一帧、收一帧、判一次重试),配合内部 OSTimeDlyHMSM 实现阻塞式等待。因此它们必须运行在独立的、可长时间阻塞的任务上下文中(实际由 ginlong_comm_usart.c:4875/4885 在固件下载期间调用,此时常规通信已被挂起)。
5. 对外接口
本文件导出:
- 类型:
GINLONG_UPGRADE_OBJECT_E、GINLONG_UPGRADE_ARM_STATE_E、GINLONG_UPGRADE_DSP_STATE_E、GINLONG_UPGRADE_TABLE_T。 - 宏:
GINLONG_UPGRADE_DEBUG、DAT_PCK_UPGRADE_INV、INV_RECV_UPGRADE_BUFFER_SIZE、SEND_UPGRADE_DATA_SIZE。 - 函数声明:第 3 节列出的 10 个。
本文件(头)依赖:
includes.h:统一类型定义与公共宏。
6. 依赖关系
- 依赖:
includes.h(ginlong_upgrade.h:13)。 - 被依赖:
midware/inverter/ginlong/ginlong_upgrade.c(#include "ginlong_upgrade.h",ginlong_upgrade.c:13)。midware/inverter/ginlong/ginlong_comm_usart.c:固件下载期间调用ginlong_upgrade_dsp_handle()(ginlong_comm_usart.c:4875)与ginlong_upgrade_arm_handle()(ginlong_comm_usart.c:4885),并通过ginlong_read_upgrade_flag_master()等接口决定u8_run_mode。- HMI 升级进度界面:通过
ginlong_read_upgrade_percent_*()取百分比。
7. 备注与风险点
ginlong_upgrade_handle是死声明:ginlong_upgrade.h:90声明了该函数,但全工程搜索(grep -rn "ginlong_upgrade_handle")只找到这一处声明,没有任何定义或调用。若外部模块误调用会链接失败;建议删除或在实现中补齐。- 被注释掉的旧状态机:
ginlong_upgrade.h:28-44的GINLONG_UPGRADE_SATE_E保留了大量历史状态名,是理解升级流程演进的重要线索,但属于版本遗留代码,长期保留易与其他状态机混淆。 u8_upgrade_buf[1035]无编译期边界保护:尺寸与SEND_UPGRADE_DATA_SIZE的耦合靠人工推导,没有#if断言。u8类型不够安全:状态机与对象虽用枚举定义,但结构体成员u8_upgrade_object声明为u8而非枚举类型(ginlong_upgrade.h:74),失去编译器类型检查。GINLONG_NONE从未被赋值:枚举成员GINLONG_NONE(值 0)作为"无升级对象"的初始态,但实现中一旦进入UPGRADE_ARM_IDLE就会立即赋值为具体对象;由于s_t_upgrade_tab是static且被memset清零,重置后回到GINLONG_NONE表示空闲,语义上是自洽的,但 4 个read_upgrade_flag_*接口在空闲态全部返回 0,调用方需自行区分"空闲"与"对象不匹配"。DAT_PCK_UPGRADE_INV单位为毫秒:ginlong_upgrade.c:62-64中与OSTimeGet()差值直接比较,说明 uCOS-II 的OS_TICKS_PER_SEC为 1000(1 拍 = 1 ms)。若将来修改系统节拍频率,该宏含义会随之改变,属于隐式耦合。