From 2d024c5b344de9bee55ae9aec0bff202e7ff129e Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sun, 9 Jul 2023 09:16:55 -0500 Subject: [PATCH] pico.write must happen at 256 byte boundaries there's no good way to tell if the payload should be padded or if it should just be realigned, so raise an exception and make the caller figure it out --- gp2040ce_bintools/pico.py | 12 ++++++++++++ tests/test_pico.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/gp2040ce_bintools/pico.py b/gp2040ce_bintools/pico.py index 6d86892..f9a2caa 100644 --- a/gp2040ce_bintools/pico.py +++ b/gp2040ce_bintools/pico.py @@ -32,6 +32,15 @@ PICO_COMMANDS = { } +################# +# LIBRARY ITEMS # +################# + + +class PicoAlignmentError(ValueError): + """Exception raised when the address provided for an operation is invalid.""" + + def get_bootsel_endpoints() -> tuple[usb.core.Endpoint, usb.core.Endpoint]: """Retrieve the USB endpoint for purposes of interacting with a Pico in BOOTSEL mode. @@ -189,6 +198,9 @@ def write(out_end: usb.core.Endpoint, in_end: usb.core.Endpoint, location: int, location: memory address of where to start reading from content: the data to write """ + if (location % 256) != 0: + raise PicoAlignmentError("writes must start at 256 byte boundaries, please pad or align as appropriate!") + # set up the data command_size = 8 diff --git a/tests/test_pico.py b/tests/test_pico.py index caf3b54..e55dccf 100644 --- a/tests/test_pico.py +++ b/tests/test_pico.py @@ -5,6 +5,7 @@ import sys import unittest.mock as mock from array import array +import pytest from decorator import decorator import gp2040ce_bintools.pico as pico @@ -144,3 +145,36 @@ def test_write(): ] end_out.write.assert_has_calls(expected_writes) assert end_in.read.call_count == 6 + + +def test_misaligned_write(): + """Test that we can't write to a board at invalid memory addresses.""" + end_out, end_in = mock.MagicMock(), mock.MagicMock() + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE001, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE008, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE010, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE020, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE040, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE080, b'\x00\x01\x02\x03') + with pytest.raises(pico.PicoAlignmentError): + _ = pico.write(end_out, end_in, 0x101FE0FF, b'\x00\x01\x02\x03') + + _ = pico.write(end_out, end_in, 0x101FE100, b'\x00\x01\x02\x03') + + expected_writes = [ + mock.call(struct.pack('