Skip to content

Commit 2bb049c

Browse files
committed
take multiple binary arguments to convert_binary_to_uf2
this is in preparation for making smaller .uf2 files buy not needing padding, instead passing multiple location+binary combos to the converter Signed-off-by: Brian S. Stephan <[email protected]>
1 parent ea4d4be commit 2bb049c

File tree

3 files changed

+37
-33
lines changed

3 files changed

+37
-33
lines changed

gp2040ce_bintools/builder.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ def concatenate_firmware_and_storage_files(firmware_filename: str,
117117
# the correct way to do the above would be to pass a list of {offset,binary_data} to convert...,
118118
# and have it calculate the total block size before starting to write, and then iterating over
119119
# the three lists. doable, just not on the top of my mind right now
120-
new_binary = storage.convert_binary_to_uf2(combine_firmware_and_config(firmware_binary, board_config_binary,
121-
user_config_binary,
122-
replace_extra=replace_extra))
120+
new_binary = storage.convert_binary_to_uf2([
121+
(0, combine_firmware_and_config(firmware_binary, board_config_binary, user_config_binary,
122+
replace_extra=replace_extra)),
123+
])
123124

124125
if combined_filename:
125126
with open(combined_filename, 'wb') as combined:
@@ -256,8 +257,9 @@ def write_new_config_to_filename(config: Message, filename: str, inject: bool =
256257
binary = storage.serialize_config_with_footer(config)
257258
with open(filename, 'wb') as file:
258259
if filename[-4:] == '.uf2':
259-
file.write(storage.convert_binary_to_uf2(storage.pad_config_to_storage_size(binary),
260-
start=storage.USER_CONFIG_BINARY_LOCATION))
260+
file.write(storage.convert_binary_to_uf2([
261+
(storage.USER_CONFIG_BINARY_LOCATION, storage.pad_config_to_storage_size(binary)),
262+
]))
261263
else:
262264
file.write(binary)
263265

gp2040ce_bintools/storage.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,36 +53,37 @@ class ConfigMagicError(ConfigReadError):
5353
"""Exception raised when the config section does not have the magic value in its footer."""
5454

5555

56-
def convert_binary_to_uf2(binary: bytearray, start: int = 0) -> bytearray:
56+
def convert_binary_to_uf2(binaries: list[tuple[int, bytearray]]) -> bytearray:
5757
"""Convert a GP2040-CE binary payload to Microsoft's UF2 format.
5858
5959
https://github.com/microsoft/uf2/tree/master#overview
6060
6161
Args:
62-
binary: bytearray content to convert to a UF2 payload
63-
start: position offset to start at rather than flash start (for creating e.g. user config UF2s)
62+
binaries: list of start,binary pairs of binary data to write at the specified memory offset in flash
6463
Returns:
6564
the content in UF2 format
6665
"""
67-
size = len(binary)
68-
blocks = (len(binary) // 256) + 1 if len(binary) % 256 else len(binary) // 256
69-
uf2 = bytearray()
66+
total_blocks = sum([(len(binary) // 256) + 1 if len(binary) % 256 else len(binary) // 256
67+
for offset, binary in binaries])
7068

71-
index = 0
72-
while index < size:
73-
pad_count = 476 - len(binary[index:index+256])
74-
uf2 += struct.pack('<LLLLLLLL',
75-
UF2_MAGIC_FIRST, # first magic number
76-
UF2_MAGIC_SECOND, # second magic number
77-
0x00002000, # familyID present
78-
0x10000000 + start + index, # address to write to
79-
256, # bytes to write in this block
80-
index // 256, # sequential block number
81-
blocks, # total number of blocks
82-
UF2_FAMILY_ID) # family ID
83-
uf2 += binary[index:index+256] + bytearray(b'\x00' * pad_count) # content
84-
uf2 += struct.pack('<L', UF2_MAGIC_FINAL) # final magic number
85-
index += 256
69+
uf2 = bytearray()
70+
for start, binary in binaries:
71+
size = len(binary)
72+
index = 0
73+
while index < size:
74+
pad_count = 476 - len(binary[index:index+256])
75+
uf2 += struct.pack('<LLLLLLLL',
76+
UF2_MAGIC_FIRST, # first magic number
77+
UF2_MAGIC_SECOND, # second magic number
78+
0x00002000, # familyID present
79+
0x10000000 + start + index, # address to write to
80+
256, # bytes to write in this block
81+
index // 256, # sequential block number
82+
total_blocks, # total number of blocks
83+
UF2_FAMILY_ID) # family ID
84+
uf2 += binary[index:index+256] + bytearray(b'\x00' * pad_count) # content
85+
uf2 += struct.pack('<L', UF2_MAGIC_FINAL) # final magic number
86+
index += 256
8687
return uf2
8788

8889

@@ -393,8 +394,9 @@ def dump_config():
393394
with open(args.filename, 'wb') as out_file:
394395
if args.filename[-4:] == '.uf2':
395396
# we must pad to storage start in order for the UF2 write addresses to make sense
396-
out_file.write(convert_binary_to_uf2(pad_config_to_storage_size(binary_config),
397-
start=USER_CONFIG_BINARY_LOCATION))
397+
out_file.write(convert_binary_to_uf2([
398+
(USER_CONFIG_BINARY_LOCATION, pad_config_to_storage_size(binary_config)),
399+
]))
398400
else:
399401
out_file.write(binary_config)
400402

tests/test_storage.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def test_config_from_whole_board_parses(whole_board_dump):
133133

134134
def test_convert_binary_to_uf2(whole_board_with_board_config_dump):
135135
"""Do some sanity checks in the attempt to convert a binary to a UF2."""
136-
uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump)
136+
uf2 = storage.convert_binary_to_uf2([{0, whole_board_with_board_config_dump}])
137137
assert len(uf2) == 4194304 # binary is 8192 256 byte chunks, UF2 is 512 b per chunk
138138
assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic
139139
assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set
@@ -142,7 +142,7 @@ def test_convert_binary_to_uf2(whole_board_with_board_config_dump):
142142

143143
def test_convert_unaligned_binary_to_uf2(firmware_binary):
144144
"""Do some sanity checks in the attempt to convert a binary to a UF2."""
145-
uf2 = storage.convert_binary_to_uf2(firmware_binary)
145+
uf2 = storage.convert_binary_to_uf2([{0, firmware_binary}])
146146
assert len(uf2) == math.ceil(len(firmware_binary)/256) * 512 # 256 byte complete/partial chunks -> 512 b chunks
147147
assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic
148148
assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set
@@ -151,7 +151,7 @@ def test_convert_unaligned_binary_to_uf2(firmware_binary):
151151

152152
def test_convert_binary_to_uf2_with_offsets(whole_board_with_board_config_dump):
153153
"""Do some sanity checks in the attempt to convert a binary to a UF2."""
154-
uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump, start=storage.USER_CONFIG_BINARY_LOCATION)
154+
uf2 = storage.convert_binary_to_uf2([{storage.USER_CONFIG_BINARY_LOCATION, whole_board_with_board_config_dump}])
155155
assert len(uf2) == 4194304 # binary is 8192 256 byte chunks, UF2 is 512 b per chunk
156156
assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic
157157
assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set
@@ -160,15 +160,15 @@ def test_convert_binary_to_uf2_with_offsets(whole_board_with_board_config_dump):
160160

161161
def test_convert_binary_to_uf2_to_binary(whole_board_with_board_config_dump):
162162
"""Do some sanity checks in the attempt to convert a binary to a UF2."""
163-
uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump)
163+
uf2 = storage.convert_binary_to_uf2([{0, whole_board_with_board_config_dump}])
164164
binary = storage.convert_uf2_to_binary(uf2)
165165
assert len(binary) == 2097152
166166
assert whole_board_with_board_config_dump == binary
167167

168168

169169
def test_malformed_uf2(whole_board_with_board_config_dump):
170170
"""Check that we expect a properly-formed UF2."""
171-
uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump)
171+
uf2 = storage.convert_binary_to_uf2([{0, whole_board_with_board_config_dump}])
172172

173173
# truncated UF2 --- byte mismatch
174174
with pytest.raises(ValueError):

0 commit comments

Comments
 (0)