flag and method to visualize the board config

via file dump or via USB. used to test the writing of the board config
to binary

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
Brian S. Stephan 2024-01-06 16:55:23 -06:00
parent 1a44e8c1e3
commit 314fc909ff
Signed by: bss
GPG Key ID: 3DE06D3180895FCB
3 changed files with 51 additions and 4 deletions

View File

@ -17,6 +17,7 @@ from gp2040ce_bintools.rp2040 import get_bootsel_endpoints, read
logger = logging.getLogger(__name__)
BOARD_CONFIG_BINARY_LOCATION = 0x1F8000
BOARD_CONFIG_BOOTSEL_ADDRESS = 0x10000000 + BOARD_CONFIG_BINARY_LOCATION
STORAGE_SIZE = 16384
USER_CONFIG_BINARY_LOCATION = 0x1FC000
USER_CONFIG_BOOTSEL_ADDRESS = 0x10000000 + USER_CONFIG_BINARY_LOCATION
@ -124,13 +125,15 @@ def get_config_footer(content: bytes) -> tuple[int, int, str]:
return config_size, config_crc, config_magic
def get_config_from_file(filename: str, whole_board: bool = False, allow_no_file: bool = False) -> Message:
def get_config_from_file(filename: str, whole_board: bool = False, allow_no_file: bool = False,
board_config: bool = False) -> Message:
"""Read the specified file (memory dump or whole board dump) and get back its config section.
Args:
filename: the filename of the file to open and read
whole_board: optional, if true, attempt to find the storage section from its normal location on a board
allow_no_file: if true, attempting to open a nonexistent file returns an empty config, else it errors
board_config: if true, the board config is provided instead of the user config
Returns:
the parsed configuration
"""
@ -144,7 +147,10 @@ def get_config_from_file(filename: str, whole_board: bool = False, allow_no_file
return config_pb2.Config()
if whole_board:
return get_config(get_user_storage_section(content))
if board_config:
return get_config(get_board_storage_section(content))
else:
return get_config(get_user_storage_section(content))
else:
return get_config(content)
@ -165,6 +171,15 @@ def get_config_from_usb(address: int) -> tuple[Message, object, object]:
return get_config(bytes(storage)), endpoint_out, endpoint_in
def get_board_config_from_usb() -> tuple[Message, object, object]:
"""Read the board configuration from the detected USB device.
Returns:
the parsed configuration, along with the USB out and in endpoints for reference
"""
return get_config_from_usb(BOARD_CONFIG_BOOTSEL_ADDRESS)
def get_user_config_from_usb() -> tuple[Message, object, object]:
"""Read the user configuration from the detected USB device.
@ -286,6 +301,8 @@ def visualize():
)
parser.add_argument('--whole-board', action='store_true', help="indicate the binary file is a whole board dump")
parser.add_argument('--json', action='store_true', help="print the config out as a JSON document")
parser.add_argument('--board-config', action='store_true', default=False,
help="display the board config rather than the user 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")
@ -295,9 +312,12 @@ def visualize():
args, _ = parser.parse_known_args()
if args.usb:
config, _, _ = get_user_config_from_usb()
if args.board_config:
config, _, _ = get_board_config_from_usb()
else:
config, _, _ = get_user_config_from_usb()
else:
config = get_config_from_file(args.filename, whole_board=args.whole_board)
config = get_config_from_file(args.filename, whole_board=args.whole_board, board_config=args.board_config)
if args.json:
print(MessageToJson(config))

View File

@ -94,6 +94,15 @@ def test_get_config_from_file_whole_board_dump():
assert config.addonOptions.bootselButtonOptions.enabled is False
@with_pb2s
def test_get_board_config_from_file_whole_board_dump():
"""Test that we can open a storage dump file and find its config."""
filename = os.path.join(HERE, 'test-files', 'test-whole-board-with-board-config.bin')
config = storage.get_config_from_file(filename, whole_board=True, board_config=True)
assert config.boardVersion == 'v0.7.6-15-g71f4512'
assert config.addonOptions.bootselButtonOptions.enabled is False
@with_pb2s
def test_get_config_from_file_file_not_fonud_ok():
"""If we allow opening a file that doesn't exist (e.g. for the editor), check we get an empty config."""
@ -164,6 +173,24 @@ def test_pad_config_to_storage_raises(config_binary):
_ = storage.pad_config_to_storage_size(config_binary * 5)
@with_pb2s
def test_get_board_config_from_usb(config_binary):
"""Test we attempt to read from the proper location over USB."""
mock_out = mock.MagicMock()
mock_out.device.idVendor = 0xbeef
mock_out.device.idProduct = 0xcafe
mock_out.device.bus = 1
mock_out.device.address = 2
mock_in = mock.MagicMock()
with mock.patch('gp2040ce_bintools.storage.get_bootsel_endpoints', return_value=(mock_out, mock_in)) as mock_get:
with mock.patch('gp2040ce_bintools.storage.read', return_value=config_binary) as mock_read:
config, _, _ = storage.get_board_config_from_usb()
mock_get.assert_called_once()
mock_read.assert_called_with(mock_out, mock_in, 0x101F8000, 16384)
assert config == storage.get_config(config_binary)
@with_pb2s
def test_get_user_config_from_usb(config_binary):
"""Test we attempt to read from the proper location over USB."""