Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 91 additions & 44 deletions host/min.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ def _rx_bytes(self, data: bytes):

if self._rx_frame_checksum != computed_checksum:
min_logger.warning(
"CRC mismatch (0x%08X vs 0x%08X), frame dropped",
"CRC mismatch (0x%08X received vs 0x%08X computed), frame dropped",
self._rx_frame_checksum,
computed_checksum,
)
Expand Down Expand Up @@ -793,11 +793,32 @@ def _serial_read_all(self):
def _serial_close(self):
self._serial.close()

def __init__(self, port, baudrate=9600, loglevel=ERROR):
def __init__(
self,
port,
baudrate=9600,
window_size=8,
rx_window_size=16,
transport_fifo_size=100,
idle_timeout_ms=3000,
ack_retransmit_timeout_ms=25,
frame_retransmit_timeout_ms=50,
loglevel=ERROR,
):
"""
Open MIN connection on a given port.
:param port: serial port
:param debug:
:param baudrate: baud rate
:param window_size: Number of outstanding unacknowledged frames
permitted to send
:param rx_window_size: Number of outstanding unacknowledged frames
that can be received
:param transport_fifo_size: Maximum number of outstanding frames to send
:param idle_timeout_ms: Time before connection assumed to have been lost and
retransmissions stopped
:param ack_retransmit_timeout_ms: Time before ACK frames are resent
:param frame_retransmit_timeout_ms: Time before frames are resent
:param loglevel: set the logging desired
"""
self.fake_errors = False
try:
Expand All @@ -806,7 +827,13 @@ def __init__(self, port, baudrate=9600, loglevel=ERROR):
self._serial.reset_output_buffer()
except SerialException:
raise MINConnectionError(f"Transport MIN cannot open port '{port}'")
super().__init__(loglevel=loglevel)
super().__init__(window_size=window_size,
rx_window_size=rx_window_size,
transport_fifo_size=transport_fifo_size,
idle_timeout_ms=idle_timeout_ms,
ack_retransmit_timeout_ms=ack_retransmit_timeout_ms,
frame_retransmit_timeout_ms=frame_retransmit_timeout_ms,
loglevel=loglevel)


class ThreadsafeTransportMINSerialHandler(MINTransportSerial):
Expand All @@ -819,55 +846,75 @@ class ThreadsafeTransportMINSerialHandler(MINTransportSerial):
The application can send directly and pick up incoming frames from the queue.
"""

def __init__(self, port, loglevel=ERROR):
super().__init__(port=port, loglevel=loglevel)
def __init__(
self,
port,
baudrate=9600,
window_size=8,
rx_window_size=16,
transport_fifo_size=100,
idle_timeout_ms=3000,
ack_retransmit_timeout_ms=25,
frame_retransmit_timeout_ms=50,
loglevel=ERROR,
):
"""
Open MIN connection on a given port.
:param port: serial port
:param baudrate: baud rate
:param window_size: Number of outstanding unacknowledged frames
permitted to send
:param rx_window_size: Number of outstanding unacknowledged frames
that can be received
:param transport_fifo_size: Maximum number of outstanding frames to send
:param idle_timeout_ms: Time before connection assumed to have been lost and
retransmissions stopped
:param ack_retransmit_timeout_ms: Time before ACK frames are resent
:param frame_retransmit_timeout_ms: Time before frames are resent
:param loglevel: set the logging desired
"""
super().__init__(port=port,
baudrate=baudrate,
window_size=window_size,
rx_window_size=rx_window_size,
transport_fifo_size=transport_fifo_size,
idle_timeout_ms=idle_timeout_ms,
ack_retransmit_timeout_ms=ack_retransmit_timeout_ms,
frame_retransmit_timeout_ms=frame_retransmit_timeout_ms,
loglevel=loglevel)
self._thread_lock = Lock()

def close(self):

def _with_lock(self, func):
"""Execute a function with the thread lock acquired.

Args:
func: Function to execute with the lock

Returns:
The result of the function
"""
self._thread_lock.acquire()
try:
super().close()
except Exception as e:
return func()
finally:
self._thread_lock.release()
raise e
self._thread_lock.release()

def transport_stats(self):
self._thread_lock.acquire()
try:
result = super().transport_stats()
except Exception as e:
self._thread_lock.release()
raise e
self._thread_lock.release()
def close(self):
self._with_lock(super().close)

return result
def transport_stats(self):
return self._with_lock(super().transport_stats)

def transport_reset(self):
self._with_lock(super().transport_reset)

def send_frame(self, min_id: int, payload: bytes):
self._thread_lock.acquire()
try:
super().send_frame(min_id=min_id, payload=payload)
except Exception as e:
self._thread_lock.release()
raise e
self._thread_lock.release()
parent_send_frame = super().send_frame
self._with_lock(lambda: parent_send_frame(min_id=min_id, payload=payload))

def queue_frame(self, min_id: int, payload: bytes):
self._thread_lock.acquire()
try:
super().queue_frame(min_id=min_id, payload=payload)
except Exception as e:
self._thread_lock.release()
raise e
self._thread_lock.release()
parent_queue_frame = super().queue_frame
self._with_lock(lambda: parent_queue_frame(min_id=min_id, payload=payload))

def poll(self):
self._thread_lock.acquire()
try:
result = super().poll()
except Exception as e:
self._thread_lock.release()
raise e
self._thread_lock.release()

return result
return self._with_lock(super().poll)
Loading