mirror of https://github.com/commaai/panda.git
python: non-zero default timeout (#1279)
* non-zero default timeout * respect timeout in spi
This commit is contained in:
parent
df7952ec13
commit
deaad254d9
|
@ -3,30 +3,32 @@ from typing import List
|
|||
|
||||
from .constants import McuType
|
||||
|
||||
TIMEOUT = int(15 * 1e3) # default timeout, in milliseconds
|
||||
|
||||
class BaseHandle(ABC):
|
||||
"""
|
||||
A handle to talk to a panda.
|
||||
Borrows heavily from the libusb1 handle API.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def close(self) -> None:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = 0) -> int:
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT) -> int:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = 0) -> bytes:
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT) -> bytes:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = 0) -> int:
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = TIMEOUT) -> int:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = 0) -> bytes:
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes:
|
||||
...
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ from contextlib import contextmanager
|
|||
from functools import reduce
|
||||
from typing import List, Optional
|
||||
|
||||
from .base import BaseHandle, BaseSTBootloaderHandle
|
||||
from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT
|
||||
from .constants import McuType, MCU_TYPE_BY_IDCODE
|
||||
|
||||
try:
|
||||
|
@ -25,7 +25,7 @@ DACK = 0x85
|
|||
NACK = 0x1F
|
||||
CHECKSUM_START = 0xAB
|
||||
|
||||
ACK_TIMEOUT_SECONDS = 0.1
|
||||
MIN_ACK_TIMEOUT_MS = 100
|
||||
MAX_XFER_RETRY_COUNT = 5
|
||||
|
||||
USB_MAX_SIZE = 0x40
|
||||
|
@ -96,9 +96,11 @@ class PandaSpiHandle(BaseHandle):
|
|||
cksum ^= b
|
||||
return cksum
|
||||
|
||||
def _wait_for_ack(self, spi, ack_val: int) -> None:
|
||||
def _wait_for_ack(self, spi, ack_val: int, timeout: int) -> None:
|
||||
timeout_s = max(MIN_ACK_TIMEOUT_MS, timeout) * 1e-3
|
||||
|
||||
start = time.monotonic()
|
||||
while (time.monotonic() - start) < ACK_TIMEOUT_SECONDS:
|
||||
while (timeout == 0) or ((time.monotonic() - start) < timeout_s):
|
||||
dat = spi.xfer2(b"\x12")[0]
|
||||
if dat == NACK:
|
||||
raise PandaSpiNackResponse
|
||||
|
@ -107,7 +109,7 @@ class PandaSpiHandle(BaseHandle):
|
|||
|
||||
raise PandaSpiMissingAck
|
||||
|
||||
def _transfer(self, spi, endpoint: int, data, max_rx_len: int = 1000) -> bytes:
|
||||
def _transfer(self, spi, endpoint: int, data, timeout: int, max_rx_len: int = 1000) -> bytes:
|
||||
logging.debug("starting transfer: endpoint=%d, max_rx_len=%d", endpoint, max_rx_len)
|
||||
logging.debug("==============================================")
|
||||
|
||||
|
@ -121,7 +123,7 @@ class PandaSpiHandle(BaseHandle):
|
|||
spi.xfer2(packet)
|
||||
|
||||
logging.debug("- waiting for header ACK")
|
||||
self._wait_for_ack(spi, HACK)
|
||||
self._wait_for_ack(spi, HACK, timeout)
|
||||
|
||||
# send data
|
||||
logging.debug("- sending data")
|
||||
|
@ -129,7 +131,7 @@ class PandaSpiHandle(BaseHandle):
|
|||
spi.xfer2(packet)
|
||||
|
||||
logging.debug("- waiting for data ACK")
|
||||
self._wait_for_ack(spi, DACK)
|
||||
self._wait_for_ack(spi, DACK, timeout)
|
||||
|
||||
# get response length, then response
|
||||
response_len_bytes = bytes(spi.xfer2(b"\x00" * 2))
|
||||
|
@ -150,26 +152,26 @@ class PandaSpiHandle(BaseHandle):
|
|||
def close(self):
|
||||
self.dev.close()
|
||||
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = 0):
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT):
|
||||
with self.dev.acquire() as spi:
|
||||
return self._transfer(spi, 0, struct.pack("<BHHH", request, value, index, 0))
|
||||
return self._transfer(spi, 0, struct.pack("<BHHH", request, value, index, 0), timeout)
|
||||
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = 0):
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT):
|
||||
with self.dev.acquire() as spi:
|
||||
return self._transfer(spi, 0, struct.pack("<BHHH", request, value, index, length))
|
||||
return self._transfer(spi, 0, struct.pack("<BHHH", request, value, index, length), timeout)
|
||||
|
||||
# TODO: implement these properly
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = 0) -> int:
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = TIMEOUT) -> int:
|
||||
with self.dev.acquire() as spi:
|
||||
for x in range(math.ceil(len(data) / USB_MAX_SIZE)):
|
||||
self._transfer(spi, endpoint, data[USB_MAX_SIZE*x:USB_MAX_SIZE*(x+1)])
|
||||
self._transfer(spi, endpoint, data[USB_MAX_SIZE*x:USB_MAX_SIZE*(x+1)], timeout)
|
||||
return len(data)
|
||||
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = 0) -> bytes:
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes:
|
||||
ret: List[int] = []
|
||||
with self.dev.acquire() as spi:
|
||||
for _ in range(math.ceil(length / USB_MAX_SIZE)):
|
||||
d = self._transfer(spi, endpoint, [], max_rx_len=USB_MAX_SIZE)
|
||||
d = self._transfer(spi, endpoint, [], timeout, max_rx_len=USB_MAX_SIZE)
|
||||
ret += d
|
||||
if len(d) < USB_MAX_SIZE:
|
||||
break
|
||||
|
@ -216,7 +218,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(self, cmd: int, data: Optional[List[bytes]] = None, read_bytes: int = TIMEOUT, predata=None) -> bytes:
|
||||
ret = b""
|
||||
with self.dev.acquire() as spi:
|
||||
# sync + command
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import struct
|
||||
from typing import List
|
||||
|
||||
from .base import BaseHandle, BaseSTBootloaderHandle
|
||||
from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT
|
||||
from .constants import McuType
|
||||
|
||||
class PandaUsbHandle(BaseHandle):
|
||||
|
@ -11,16 +11,16 @@ class PandaUsbHandle(BaseHandle):
|
|||
def close(self):
|
||||
self._libusb_handle.close()
|
||||
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = 0):
|
||||
def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT):
|
||||
return self._libusb_handle.controlWrite(request_type, request, value, index, data, timeout)
|
||||
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = 0):
|
||||
def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT):
|
||||
return self._libusb_handle.controlRead(request_type, request, value, index, length, timeout)
|
||||
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = 0) -> int:
|
||||
def bulkWrite(self, endpoint: int, data: List[int], timeout: int = TIMEOUT) -> int:
|
||||
return self._libusb_handle.bulkWrite(endpoint, data, timeout) # type: ignore
|
||||
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = 0) -> bytes:
|
||||
def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes:
|
||||
return self._libusb_handle.bulkRead(endpoint, length, timeout) # type: ignore
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue