Files
hulk 9492a8dcce release(v2.6.1): GUI 2.6.1 安装包发布,板卡 BL bin 改随本仓库 Release 分发
- app_gui.py APP_VERSION 2.6.0→2.6.1;重建 onedir + 组 zip(23.1 MB,MD5 ae9aa6590bf46b8e46472dc2d1f1ebc7)并上传 DAPLinkFlash-v2.6.1 Release
- 本版 GUI 首次随包分发 fw_pack 2.2(含 CeramixNano_EDDY_Dual_FW profile,CLI 与「打包 v2」弹窗均可用)
- Release 同时附 MB/EDDY 两板 BL bin + bootloader_bins.md5.txt(BL bin 分发渠道自此为本仓库 Release)
- 入库发布脚本 publish_bl_release.py(建 Release + 传 BL 附件);bootloader_disasm*.txt 分析副产物加入 .gitignore(维持不入库)
- AGENTS.md 补 v2.6.1 发布进度(含 zip MD5,供复现核对)
2026-10-25 00:49:48 +08:00

100 lines
4.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""发布 DAPLinkFlash-v2.6.1:fw_pack 2.2(EDDY profile)+ 随 Release 附板卡 BL bin"""
import hashlib
import json
import os
import ssl
import time
import urllib.request
from pathlib import Path
BASE = "https://gitea.hulk.wang/api/v1"
REPO = "hulk/gd32e230f8_firmware_merge_tool"
TOKEN = os.environ["GITEA_TOKEN"]
CTX = ssl._create_unverified_context()
BL_DIR = Path(r"E:\Hulk-Coding\gd32e230_bootloader\Build\Release")
BLS = [
BL_DIR / "gd32e23x_V0.1.0_bootloader_CeramixNano_MB_2026-10-22.bin",
BL_DIR / "gd32e23x_V0.1.0_bootloader_CeramixNano_EDDY_2026-10-24.bin",
]
MANIFEST = BL_DIR / "bootloader_bins.md5.txt"
BODY = """## 本版变更
- **fw_pack 2.1 → 2.2**:新增内置布局 profile `CeramixNano_EDDY_Dual_FW`(CeramixNano EDDY 板 / LDC1612 电涡流传感器单板;Flash 分配与 MB 逐字节相同,BL 用各自的板卡分支 bin)。
- **DAPLinkFlash GUI 无改动**——需要 GUI 请继续用 [v2.6.0](https://gitea.hulk.wang/hulk/gd32e230f8_firmware_merge_tool/releases/tag/DAPLinkFlash-v2.6.0) 的安装包。
- **新增:随 Release 分发各板卡双固件 BL bin**(拼 FULL/FACTORY 时 `-b` 传入):
| 附件 | 板卡 | 大小 | MD5 | 来源 |
|---|---|---|---|---|
| `gd32e23x_V0.1.0_bootloader_CeramixNano_MB_2026-10-22.bin` | CeramixNano-MB(LED=PA14) | 4,044B | f7b447cf800e062cdf15abd8d7edc723 | BL 仓库 `bootloader_CeramixNano_MB` 分支,tag `v0.1.0` |
| `gd32e23x_V0.1.0_bootloader_CeramixNano_EDDY_2026-10-24.bin` | CeramixNano-EDDY(LED=PB1,升级会话期间 SWD 可用) | 4,040B | 1dcc17bf530930a9686afa4dd04d30db | BL 仓库 `bootloader_CeramixNano_EDDY` 分支,V0.1.0 |
| `bootloader_bins.md5.txt` | 清单 | — | — | 上述两文件的 MD5 |
## 用法
```bash
# MB 双固件打包(在 APP bin 所在目录)
python gd32e230_firmware_tool.py app_a.bin app_b.bin -b gd32e23x_V0.1.0_bootloader_CeramixNano_MB_2026-10-22.bin
# EDDY 双固件打包
python gd32e230_firmware_tool.py app_a.bin app_b.bin \
-b gd32e23x_V0.1.0_bootloader_CeramixNano_EDDY_2026-10-24.bin \
--profile CeramixNano_EDDY_Dual_FW
```
两块板 Flash 布局完全一致(BL 8K + FW_A 36K + FW_B 19K + 末页标志),仅 LED 引脚不同;
**BL 版本号按板卡分支独立编号,勿跨板混烧**(MB 版 LED=PA14 会占 SWCLK)。
"""
def api(method, path, data=None, ctype="application/json", tries=6):
for i in range(tries):
try:
r = urllib.request.Request(BASE + path, method=method)
r.add_header("Authorization", "token " + TOKEN)
body = None
if data is not None:
body = json.dumps(data).encode() if ctype == "application/json" else data
r.add_header("Content-Type", ctype)
with urllib.request.urlopen(r, body, context=CTX) as resp:
txt = resp.read()
return resp.status, (json.loads(txt) if txt else {})
except Exception as e:
print(f" retry {i + 1} {method} {path.split('?')[0]}: {e!r}")
time.sleep(8)
raise SystemExit(f"API 多次重试失败: {method} {path}")
# 0) 生成 BL 清单
lines = ["# 双固件板卡 BL bin 清单(来源:gd32e230_bootloader 仓库对应板卡分支)"]
for p in BLS:
md5 = hashlib.md5(p.read_bytes()).hexdigest()
lines.append(f"{md5} {p.stat().st_size:>6}B {p.name}")
MANIFEST.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(MANIFEST.read_text(encoding="utf-8"))
# 1) 创建 Release(tag 打在 main 顶端)
st, rel = api("POST", f"/repos/{REPO}/releases", {
"tag_name": "DAPLinkFlash-v2.6.1",
"target_commitish": "main",
"name": "DAPLinkFlash v2.6.1 — fw_pack 2.2(EDDY profile)+ 板卡 BL 分发",
"body": BODY,
})
print("release:", st, rel.get("id"), rel.get("html_url"))
rid = rel["id"]
# 2) 附件
boundary = "----zcodebl"
for p in BLS + [MANIFEST]:
blob = p.read_bytes()
parts = (
f"--{boundary}\r\n"
f'Content-Disposition: form-data; name="attachment"; filename="{p.name}"\r\n'
f"Content-Type: application/octet-stream\r\n\r\n"
).encode() + blob + f"\r\n--{boundary}--\r\n".encode()
st, res = api("POST", f"/repos/{REPO}/releases/{rid}/assets?name={p.name}", parts,
ctype=f"multipart/form-data; boundary={boundary}")
print("asset:", st, p.name)