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:
parent
1a44e8c1e3
commit
314fc909ff
|
@ -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))
|
||||
|
|
Binary file not shown.
|
@ -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."""
|
||||
|
|
Loading…
Reference in New Issue