From f6d3ad02e055413e7789d3b490366254da1ccc84 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Mon, 25 Mar 2024 11:45:02 -0500 Subject: [PATCH] support writing new configs as .uf2 files via the TUI `edit-config --filename foo.uf2` can now create standalone config UF2 files. still working on reading UF2s, or maybe what edit-config needs is a "Save As..." in order to read from a board/config and output it to a new file, but this is a start Signed-off-by: Brian S. Stephan --- gp2040ce_bintools/builder.py | 11 ++++++++--- gp2040ce_bintools/gui.py | 5 +++-- tests/test_builder.py | 19 ++++++++++++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/gp2040ce_bintools/builder.py b/gp2040ce_bintools/builder.py index b1693cd..11985e2 100644 --- a/gp2040ce_bintools/builder.py +++ b/gp2040ce_bintools/builder.py @@ -214,11 +214,16 @@ def write_new_config_to_filename(config: Message, filename: str, inject: bool = with open(filename, 'rb') as file: existing_binary = file.read() binary = replace_config_in_binary(bytearray(existing_binary), config_binary) + with open(filename, 'wb') as file: + file.write(binary) else: binary = serialize_config_with_footer(config) - - with open(filename, 'wb') as file: - file.write(binary) + with open(filename, 'wb') as file: + if filename[-4:] == '.uf2': + file.write(convert_binary_to_uf2(pad_config_to_storage_size(binary), + start=USER_CONFIG_BINARY_LOCATION)) + else: + file.write(binary) def write_new_config_to_usb(config: Message, endpoint_out: object, endpoint_in: object): diff --git a/gp2040ce_bintools/gui.py b/gp2040ce_bintools/gui.py index 86e9490..1b87bec 100644 --- a/gp2040ce_bintools/gui.py +++ b/gp2040ce_bintools/gui.py @@ -409,8 +409,9 @@ def edit_config(): group = parser.add_mutually_exclusive_group(required=True) group.add_argument('--usb', action='store_true', help="retrieve the config from a RP2040 board connected over USB " "and in BOOTSEL mode") - group.add_argument('--filename', help=".bin file of a GP2040-CE board's config + footer or entire storage section, " - "or of a GP2040-CE's whole board dump if --whole-board is specified") + group.add_argument('--filename', help=".bin of a GP2040-CE's whole board dump if --whole-board is specified, or a" + ".bin file of a GP2040-CE board's config + footer or entire storage section; " + "if creating a new config, it can also be written in .uf2 format") args, _ = parser.parse_known_args() if args.usb: diff --git a/tests/test_builder.py b/tests/test_builder.py index d847d28..e73ff1e 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -15,7 +15,7 @@ from gp2040ce_bintools.builder import (FirmwareLengthError, combine_firmware_and concatenate_firmware_and_storage_files, get_gp2040ce_from_usb, pad_binary_up_to_board_config, pad_binary_up_to_user_config, replace_config_in_binary, write_new_config_to_filename, write_new_config_to_usb) -from gp2040ce_bintools.storage import (get_board_storage_section, get_config, get_config_footer, +from gp2040ce_bintools.storage import (STORAGE_SIZE, get_board_storage_section, get_config, get_config_footer, get_user_storage_section, serialize_config_with_footer) HERE = os.path.dirname(os.path.abspath(__file__)) @@ -272,6 +272,23 @@ def test_write_new_config_to_config_bin(firmware_binary, tmp_path): assert len(config_dump) == config_size + 12 +@with_pb2s +def test_write_new_config_to_config_uf2(firmware_binary, tmp_path): + """Test that the config can be written to a file.""" + tmp_file = os.path.join(tmp_path, 'config.uf2') + config_pb2 = get_config_pb2() + config = config_pb2.Config() + config.boardVersion = 'v0.7.5-COOL' + write_new_config_to_filename(config, tmp_file) + + # read new file + with open(tmp_file, 'rb') as file: + config_dump = file.read() + # the current implementation of UF2 writing does it in 256 blocks, so each 256 byte block of + # binary is 512 bytes in the UF2 + assert len(config_dump) == STORAGE_SIZE * 2 + + @with_pb2s def test_write_new_config_to_usb(config_binary): """Test that the config can be written to USB at the proper alignment."""