diff --git a/python/__init__.py b/python/__init__.py index 6537893a..dd135c4e 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -421,7 +421,7 @@ class Panda: except Exception: logging.debug("reconnecting is taking %d seconds...", i + 1) try: - dfu = PandaDFU(PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type)) + dfu = PandaDFU(self.get_dfu_serial()) dfu.recover() except Exception: pass @@ -493,7 +493,7 @@ class Panda: self.reconnect() def recover(self, timeout: Optional[int] = None, reset: bool = True) -> bool: - dfu_serial = PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type) + dfu_serial = self.get_dfu_serial() if reset: self.reset(enter_bootstub=True) @@ -677,6 +677,9 @@ class Panda: """ return self._serial + def get_dfu_serial(self): + return PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type) + def get_uid(self): """ Returns the UID from the MCU diff --git a/python/spi.py b/python/spi.py index b742f28f..63be5e44 100644 --- a/python/spi.py +++ b/python/spi.py @@ -149,7 +149,7 @@ class PandaSpiHandle(BaseHandle): return dat[:-1] except PandaSpiException as e: exc = e - logging.debug("SPI transfer failed, %d retries left", n, exc_info=True) + logging.debug("SPI transfer failed, %d retries left", MAX_XFER_RETRY_COUNT - n - 1, exc_info=True) raise exc # libusb1 functions @@ -201,7 +201,7 @@ class STBootloaderSPIHandle(BaseSTBootloaderHandle): spi.xfer([self.SYNC, ]) try: self._get_ack(spi) - except PandaSpiNackResponse: + except (PandaSpiNackResponse, PandaSpiMissingAck): # NACK ok here, will only ACK the first time pass @@ -222,7 +222,7 @@ class STBootloaderSPIHandle(BaseSTBootloaderHandle): elif data != self.ACK: raise PandaSpiMissingAck - def _cmd(self, cmd: int, data: Optional[List[bytes]] = None, read_bytes: int = 0, predata=None) -> bytes: + def _cmd_no_retry(self, cmd: int, data: Optional[List[bytes]] = None, read_bytes: int = 0, predata=None) -> bytes: ret = b"" with self.dev.acquire() as spi: # sync + command @@ -252,6 +252,16 @@ class STBootloaderSPIHandle(BaseSTBootloaderHandle): return bytes(ret) + def _cmd(self, cmd: int, data: Optional[List[bytes]] = None, read_bytes: int = 0, predata=None) -> bytes: + exc = PandaSpiException() + for n in range(MAX_XFER_RETRY_COUNT): + try: + return self._cmd_no_retry(cmd, data, read_bytes, predata) + except PandaSpiException as e: + exc = e + logging.debug("SPI transfer failed, %d retries left", MAX_XFER_RETRY_COUNT - n - 1, exc_info=True) + raise exc + def _checksum(self, data: bytes) -> bytes: if len(data) == 1: ret = data[0] ^ 0xFF diff --git a/tests/hitl/0_dfu.py b/tests/hitl/0_dfu.py index cff4c02c..a8afa24a 100644 --- a/tests/hitl/0_dfu.py +++ b/tests/hitl/0_dfu.py @@ -1,8 +1,12 @@ +import pytest +import random + from panda import Panda, PandaDFU +from panda.python.spi import SpiDevice def test_dfu(p): app_mcu_type = p.get_mcu_type() - dfu_serial = PandaDFU.st_serial_to_dfu_serial(p.get_usb_serial(), p.get_mcu_type()) + dfu_serial = p.get_dfu_serial() p.reset(enter_bootstub=True) p.reset(enter_bootloader=True) @@ -16,3 +20,24 @@ def test_dfu(p): dfu._handle.clear_status() dfu.reset() p.reconnect() + + +@pytest.mark.test_panda_types((Panda.HW_TYPE_TRES, )) +def test_dfu_with_spam(p): + dfu_serial = p.get_dfu_serial() + + # enter DFU + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + assert Panda.wait_for_dfu(dfu_serial, timeout=20), "failed to enter DFU" + + # send junk + for _ in range(10): + speed = 1000000 * random.randint(1, 5) + d = SpiDevice(speed=speed) + with d.acquire() as spi: + dat = [random.randint(0, 255) for _ in range(random.randint(1, 100))] + spi.xfer(dat) + + # should still show up + assert dfu_serial in PandaDFU.list() diff --git a/tests/hitl/1_program.py b/tests/hitl/1_program.py index 6db33550..eb0c6a5a 100644 --- a/tests/hitl/1_program.py +++ b/tests/hitl/1_program.py @@ -33,7 +33,7 @@ def test_a_known_bootstub(p): p.reset(enter_bootstub=True) p.reset(enter_bootloader=True) - dfu_serial = PandaDFU.st_serial_to_dfu_serial(p._serial, p._mcu_type) + dfu_serial = p.get_dfu_serial() assert Panda.wait_for_dfu(dfu_serial, timeout=30) dfu = PandaDFU(dfu_serial) diff --git a/tests/hitl/conftest.py b/tests/hitl/conftest.py index 669ae99c..c01538ae 100644 --- a/tests/hitl/conftest.py +++ b/tests/hitl/conftest.py @@ -3,7 +3,7 @@ import os import time import pytest -from panda import Panda +from panda import Panda, PandaDFU from panda_jungle import PandaJungle # pylint: disable=import-error from panda.tests.hitl.helpers import clear_can_buffers @@ -61,6 +61,8 @@ _all_panda_serials = list(_all_pandas.keys()) def init_jungle(): + if _panda_jungle is None: + return clear_can_buffers(_panda_jungle) _panda_jungle.set_panda_power(True) _panda_jungle.set_can_loopback(False) @@ -121,6 +123,11 @@ def func_fixture_panda(request, module_panda): yield p # Teardown + + # reconnect + if p.get_dfu_serial() in PandaDFU.list(): + PandaDFU(p.get_dfu_serial()).reset() + p.reconnect() if not p.connected: p.reconnect() if p.bootstub: