-
Notifications
You must be signed in to change notification settings - Fork 17
/
binmaker.py
92 lines (87 loc) · 3.82 KB
/
binmaker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# this script takes the compiled firmware (sw/Release/plinkyblack.bin) and
# bundles it with a bootloader (golden_bootloader.bin) into a single binary file
# with a version number and filename extracted from the firmware.
# it USED to read the bootloader from (bootloader/Release/plinkybl.bin) but
# to avoid unnecessary flashing, it now reads the bootloader from the copy.
# if you want to update the bootloader, you need to copy it over the golden_bootloader.bin
# and rerun this script with the magic argument 'bootloader'
def main():
# bin file maker
ver1 = '0'
ver2 = '0'
ver3 = '0'
bootloader_file = 'golden_bootloader.bin' # "bootloader/Release/plinkybl.bin"
try:
with open(bootloader_file, "rb") as f1:
bl_content = f1.read()
with open("sw/Release/plinkyblack.bin", "rb") as f2:
app_content = f2.read()
except IOError as e:
print(f"Failed to open file: {e}")
exit(2)
appsize = len(app_content)
bootloader_version = "0000"
if chr(bl_content[-3])=='.':
bootloader_version = chr(bl_content[-4]) + chr(bl_content[-3]) + chr(bl_content[-2]) + chr(bl_content[-1])
print(f'SIZES: {appsize} app, {len(bl_content)} bootloader, bootloader version [{bootloader_version}]')
# pad bl_content and app_content to reach their sizes
og_bl_size = len(bl_content)
bl_content += b'\xff' * (65536 - len(bl_content) - 4)
bl_content += bootloader_version.encode('ascii')
assert(len(bl_content) == 65536)
app_content += b'\xff' * (1024 * 1024 - 65536 - 2048 - len(app_content)) # leave the last sector empty for the calibration
app = bl_content + app_content
if chr(app[appsize + 65536 - 6])=='v' and chr(app[appsize + 65536 - 4]) == '.':
ver1 = chr(app[appsize + 65536 - 5])
ver2 = chr(app[appsize + 65536 - 3])
ver3 = chr(app[appsize + 65536 - 2])
else:
print("!!!!!!!!!!!!!!!! NO VERSION FOUND IN BIN FILE")
exit(2)
print(f"bootloader size {len(bl_content)}, app size {appsize}, version {ver1}{ver2}{ver3}")
fname = f"plink{ver1}{ver2}{ver3}.bin"
print(f'outputting {fname}...')
try:
with open(fname, "wb") as fo:
fo.write(app)
except IOError as e:
print(f"Failed to write file: {e}")
exit(2)
fname = f"plink{ver1}{ver2}{ver3}.uf2"
print(f'outputting {fname}...')
# python ../../uf2conv.py -o ${ProjName}.uf2 -c -f STM32L4 ${ProjName}.hex
class DotAccessibleObject:
def __getattr__(self, key): return False
uf2args = DotAccessibleObject()
uf2args.output=fname
uf2args.convert=True
uf2args.family='STM32L4'
uf2args.input='sw/Release/plinkyblack.hex'
uf2args.base='0x2000' # lol this is wrong, but luckily we were using .hex which has addresses. phew.
# the actual base address is 0x08010000 ie 64k into the flash.
import uf2conv
uf2conv.uf2conv(uf2args)
with open("tempbl.bin", "wb") as f1:
f1.write(bl_content)
uf2args.input='tempbl.bin'
uf2args.base='0x20008000'
uf2args.output=f"tempbl.uf2"
uf2conv.uf2conv(uf2args)
# concatenate the two uf2 files tempbl.uf2 and fname
with open(f"BOOTLOAD.UF2", "wb") as f1:
with open("tempbl.uf2", "rb") as f2:
f1.write(f2.read())
with open(fname, "rb") as f2:
f1.write(f2.read())
# delete temp files
import os
os.remove("tempbl.bin")
os.remove("tempbl.uf2")
print("wrote a combiled firmware and bootloader package to BOOTLOAD.UF2")
checksum=0
# interpret bl_content as a list of 32-bit words
for i in range(0, len(bl_content), 4):
checksum = (checksum * 23 + int.from_bytes(bl_content[i:i+4], 'little')) & 0xffffffff
print(f"bootloader checksum: 0x{checksum:08x} - this should be copied to GOLDEN_CHECKSUM in config.h")
if __name__ == "__main__":
main()