113 lines
3.6 KiB
Python
113 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
合并多个 bin 文件到一个完整的固件文件
|
||
空白区域填充 0xFF(Flash 擦除后的默认值)
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 固件配置:(地址偏移, bin文件路径)
|
||
FIRMWARE_MAP = [
|
||
(0x000000, "./res/ap.bin"),
|
||
(0x100000, "./res/algo/face_detect_thinker.bin"),
|
||
(0x170000, "./res/algo/face_align_thinker.bin"),
|
||
(0x300000, "./res/algo/face_nir_thinker_lineart_split.bin"),
|
||
(0x410000, "./res/algo/face_verify_thinker.bin"),
|
||
(0x800000, "./build/arcs.bin"),
|
||
]
|
||
|
||
# 输出文件配置
|
||
OUTPUT_FILE = "./merged_firmware.bin"
|
||
FILL_BYTE = 0xFF # 空白区域填充字节(0xFF 或 0x00)
|
||
|
||
def merge_bins():
|
||
"""合并所有 bin 文件"""
|
||
|
||
# 检查所有输入文件是否存在
|
||
print("检查输入文件...")
|
||
for offset, filepath in FIRMWARE_MAP:
|
||
if not os.path.exists(filepath):
|
||
print(f"❌ 错误: 文件不存在: {filepath}")
|
||
return False
|
||
file_size = os.path.getsize(filepath)
|
||
print(f" ✓ 0x{offset:08X}: {filepath} ({file_size} bytes)")
|
||
|
||
# 计算总固件大小(最后一个文件的结束位置)
|
||
last_offset, last_file = FIRMWARE_MAP[-1]
|
||
last_size = os.path.getsize(last_file)
|
||
total_size = last_offset + last_size
|
||
|
||
print(f"\n固件总大小: {total_size} bytes ({total_size / 1024 / 1024:.2f} MB)")
|
||
|
||
# 创建填充的固件缓冲区
|
||
print(f"创建固件缓冲区,填充字节: 0x{FILL_BYTE:02X}...")
|
||
firmware = bytearray([FILL_BYTE] * total_size)
|
||
|
||
# 将每个 bin 文件写入对应位置
|
||
print("\n合并 bin 文件...")
|
||
for offset, filepath in FIRMWARE_MAP:
|
||
print(f" 写入 {filepath} 到偏移 0x{offset:08X}...")
|
||
with open(filepath, 'rb') as f:
|
||
data = f.read()
|
||
firmware[offset:offset + len(data)] = data
|
||
print(f" ✓ 已写入 {len(data)} bytes")
|
||
|
||
# 写入输出文件
|
||
print(f"\n保存合并后的固件到 {OUTPUT_FILE}...")
|
||
with open(OUTPUT_FILE, 'wb') as f:
|
||
f.write(firmware)
|
||
|
||
output_size = os.path.getsize(OUTPUT_FILE)
|
||
print(f"✓ 完成! 输出文件大小: {output_size} bytes ({output_size / 1024 / 1024:.2f} MB)")
|
||
|
||
# 显示固件布局
|
||
print("\n固件布局:")
|
||
print("=" * 70)
|
||
print(f"{'起始地址':<12} {'结束地址':<12} {'大小':<12} {'文件'}")
|
||
print("-" * 70)
|
||
|
||
for i, (offset, filepath) in enumerate(FIRMWARE_MAP):
|
||
file_size = os.path.getsize(filepath)
|
||
end_offset = offset + file_size
|
||
|
||
# 显示当前文件
|
||
print(f"0x{offset:08X} 0x{end_offset:08X} {file_size:>10} B {filepath}")
|
||
|
||
# 显示空白区域
|
||
if i < len(FIRMWARE_MAP) - 1:
|
||
next_offset = FIRMWARE_MAP[i + 1][0]
|
||
gap_size = next_offset - end_offset
|
||
if gap_size > 0:
|
||
print(f"0x{end_offset:08X} 0x{next_offset:08X} {gap_size:>10} B (填充 0x{FILL_BYTE:02X})")
|
||
|
||
print("=" * 70)
|
||
|
||
return True
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("=" * 70)
|
||
print("固件合并工具")
|
||
print("=" * 70)
|
||
print()
|
||
|
||
# 切换到脚本所在目录
|
||
script_dir = Path(__file__).parent
|
||
os.chdir(script_dir)
|
||
print(f"工作目录: {os.getcwd()}\n")
|
||
|
||
# 执行合并
|
||
if merge_bins():
|
||
print("\n✓ 固件合并成功!")
|
||
print(f"\n烧录命令:")
|
||
print(f" cskburn -s /dev/ttyACM0 -b 3000000 -C arcs 0x00 {OUTPUT_FILE}")
|
||
return 0
|
||
else:
|
||
print("\n❌ 固件合并失败!")
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|