二、修改了负载启动的顺序,先开启辅助继电器使地相通,再开启D+D-继电器 feat: 发布V1.1.23版本,优化负载初始化继电器时序 - 更新所有头文件版本号至V1.1.21~V1.1.23,协议板固件版本更新为0x0127 - 新增纹波滤波相关宏定义与函数,实现继电器闭合后纹波过滤 - 调整负载初始化流程:先下发辅助继电器,等待回码后延迟30ms再打开北向继电器 - 优化D+/D-寄存器上位机显示单位,适配0.001V解析格式 - 补充YMODEM升级文档说明,完善传输校验与重发规则 - 清理冗余调试打印与Allegro工程日志文件
4.8 KiB
4.8 KiB
协议板 Boot:UPK 打包规则
1. 适用范围
本文用于实现协议板 App 固件的 .upk 打包和解析工具,适配 apps/boot 当前 Boot。传输层 YMODEM 规则见协议板Boot_YMODEM上位机实现规则.md。
2. 1K 文件布局
当前 Boot 收到第一个文件数据帧时,只取其中前 96 字节作为 UPK 头,会忽略该帧其余数据。因此打包文件必须使用固定 1024 字节首数据块:
输出 .upk 文件
偏移 0x000 ~ 0x05F : 96 字节 UPK 逻辑头
偏移 0x060 ~ 0x3FF : 928 字节 0x00 填充
偏移 0x400 起 : package body(未加密 BIN 或 AES 加密后的 body)
.upk实际文件大小:1024 + pkg_size。- YMODEM 元数据包的文件大小必须为上述实际文件大小。
- 上位机必须从偏移 0 开始以
STX/1024发送;第一个 STX 是头区,真正 body 从第二个 STX 开始。 - YMODEM 最后一帧的
0x1A补齐仅属于传输层,不能计入文件大小、raw_size或pkg_size。
YMODEM 1K 帧字节数
STX/1024 中的 1024 指数据区长度,不是串口线上完整帧长度。每个完整 STX 数据帧固定为 1029 字节:
STX 1 字节
PacketNo 1 字节
~PacketNo 1 字节
Data 1024 字节
CRC16 2 字节
总计 1029 字节
因此,UPK 首数据块和后续固件数据块的有效数据均为 1024 字节,实际串口发送时均应连续发送 1029 字节。YMODEM 元数据使用 SOH 帧,完整帧为 133 字节(128 字节数据区 + 5 字节控制/校验字段)。
界面中的“表头尺寸 1024 (ymodem1k)”应改名为“YMODEM 首数据块/头区尺寸”,并固定为 1024;UPK 逻辑头固定为 96,不能让用户修改。
3. 输入、分区与版本
| 项目 | 规则 |
|---|---|
| 输入文件 | 仅协议板 App 裸 bin,例如 apps/chrg/build/chrg.bin;拒绝 .hex、.elf、已有 .upk。 |
name[4] |
固定 ASCII upk\0。 |
part_name[16] |
仅允许 app、download、factory,ASCII NUL 结尾;协议板常规升级默认 app,Boot 会修正为 download 后安装到 app。 |
fw_old_ver[16] |
目标设备当前版本,前 4 字节为数值 major, minor, fix, build,其余 0x00。 |
fw_new_ver[16] |
新固件版本,编码同上。 |
| 版本输入 | 界面应分别提供“当前/旧版本”与“新版本”;不能只保留一个版本号,且不得写 ASCII 版本字符串。 |
user_string[16] |
ASCII 水印最多 15 字节,NUL 结尾,其余 0x00。 |
timestamp |
当前 Unix 时间戳,uint32 小端。 |
| 大小限制 | raw_size <= 262144 且 pkg_size <= 262144,即 App/download 分区各 256KB。 |
4. 加密、大小与 CRC
raw_body为原始.bin:raw_size = len(raw_body),raw_crc = crc32_boot(raw_body)。- 未加密:
package_body = raw_body,pkg_size = raw_size,pkg_crc = raw_crc,config[1]=0x00。 - AES:
config[1]=0x01,使用 AES-256-CBC;Key=0123456789ABCDEF0123456789ABCDEF,IV=0123456789ABCDEF。加密前 body 必须补齐到 16 字节整数倍;pkg_size、pkg_crc对应加密后的 body。Key、IV 必须与 Boot 编译配置一致。 config[0]、config[2]、config[3]固定0x00。head_crc = crc32_boot(逻辑头前 92 字节);最后 4 字节按小端写入head_crc。- 所有
uint32字段按 STM32 小端序写入。
crc32_boot() 必须与 apps/boot/application/func/utils.c 的 crc32_step(0xFFFFFFFF, data, size) 完全一致;不能直接使用未校验的库默认 CRC32。
5. 96 字节逻辑头字段
0x00 name[4]
0x04 config[4]
0x08 fw_old_ver[16]
0x18 fw_new_ver[16]
0x28 user_string[16]
0x38 part_name[16]
0x48 raw_size uint32 little-endian
0x4C pkg_size uint32 little-endian
0x50 timestamp uint32 little-endian
0x54 raw_crc uint32 little-endian
0x58 pkg_crc uint32 little-endian
0x5C head_crc uint32 little-endian
6. 打包完成前的强制自检
- 重新解析刚生成的
.upk。 - 校验总长度是否为
1024 + pkg_size,并检查0x60~0x3FF全部为0x00。 - 校验
name、分区名、版本字段、大小限制和head_crc。 - 校验
pkg_crc;未加密时还必须校验raw_crc。加密时使用相同 Key/IV 解密后校验raw_crc。 - 解析页显示
raw_size、pkg_size、全部 CRC、加密状态、分区、旧/新版本和时间戳;任一项异常时禁止输出成功文件。
7. 当前样本
工程中的 apps/chrg/chrg.upk 已验证:实际长度 155816,pkg_size=154792,两者相差 1024,符合本规则。
8. 代码依据
apps/boot/application/include/firmware.happs/boot/application/func/firmware.capps/boot/application/func/app.capps/boot/application/func/utils.c