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

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_addru8*固件在 SDRAM 中的起始地址(g_u8_fw_sdram1 或 g_u8_fw_sdram2)
u8_upgrade_objectu8当前升级对象,取值来自 GINLONG_UPGRADE_OBJECT_E
u16_send_line_numu16下一包应发送的包序号(从 1 起,用于协议中的行号字段)
u8_upgrade_buf[1035]u8[]组帧缓冲区。最大负载 1024 字节,加上 ARM 帧头 9 字节 + 校验 1 字节 = 1034,DSP 帧头 7 字节 + 校验 1 字节 = 1032,取 1035 留有余量
u16_upgrade_line_numu16逆变器已确认接收的包序号(用于与 u16_send_line_num 比较判断丢包)
u32_upgrade_file_lenu32固件文件总长度(字节)
u32_upgrade_file_offsetu32已成功写入的字节偏移,也是百分比计算分子

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 升级对象与状态语义

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] 的关系:

因此 1035 有约 3 字节余量,安全但无显式 static_assert 保护——若将来把 SEND_UPGRADE_DATA_SIZE 调大(例如 2048),缓冲区会静默溢出。

4.4 与 uCOS-II 的配合

头文件本身不涉及任务/信号量。从枚举命名与实现看,*_handle() 函数是状态机单步推进器:每次调用只执行当前状态的一小段(通常发一帧、收一帧、判一次重试),配合内部 OSTimeDlyHMSM 实现阻塞式等待。因此它们必须运行在独立的、可长时间阻塞的任务上下文中(实际由 ginlong_comm_usart.c:4875/4885 在固件下载期间调用,此时常规通信已被挂起)。

5. 对外接口

本文件导出:

本文件(头)依赖:

6. 依赖关系

7. 备注与风险点

  1. ginlong_upgrade_handle 是死声明:ginlong_upgrade.h:90 声明了该函数,但全工程搜索(grep -rn "ginlong_upgrade_handle")只找到这一处声明,没有任何定义或调用。若外部模块误调用会链接失败;建议删除或在实现中补齐。
  2. 被注释掉的旧状态机:ginlong_upgrade.h:28-44 的 GINLONG_UPGRADE_SATE_E 保留了大量历史状态名,是理解升级流程演进的重要线索,但属于版本遗留代码,长期保留易与其他状态机混淆。
  3. u8_upgrade_buf[1035] 无编译期边界保护:尺寸与 SEND_UPGRADE_DATA_SIZE 的耦合靠人工推导,没有 #if 断言。
  4. u8 类型不够安全:状态机与对象虽用枚举定义,但结构体成员 u8_upgrade_object 声明为 u8 而非枚举类型(ginlong_upgrade.h:74),失去编译器类型检查。
  5. GINLONG_NONE 从未被赋值:枚举成员 GINLONG_NONE(值 0)作为"无升级对象"的初始态,但实现中一旦进入 UPGRADE_ARM_IDLE 就会立即赋值为具体对象;由于 s_t_upgrade_tab 是 static 且被 memset 清零,重置后回到 GINLONG_NONE 表示空闲,语义上是自洽的,但 4 个 read_upgrade_flag_* 接口在空闲态全部返回 0,调用方需自行区分"空闲"与"对象不匹配"。
  6. DAT_PCK_UPGRADE_INV 单位为毫秒:ginlong_upgrade.c:62-64 中与 OSTimeGet() 差值直接比较,说明 uCOS-II 的 OS_TICKS_PER_SEC 为 1000(1 拍 = 1 ms)。若将来修改系统节拍频率,该宏含义会随之改变,属于隐式耦合。