forked from PAWPAW-Mirror/lib_xua
Add initial test tx + checkers from fwk_io
This commit is contained in:
177
tests/uart_rx_checker.py
Normal file
177
tests/uart_rx_checker.py
Normal file
@@ -0,0 +1,177 @@
|
||||
# Copyright 2022 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import Pyxsim as px
|
||||
from typing import Sequence
|
||||
from functools import partial
|
||||
|
||||
# We need to disable output buffering for this test to work on MacOS; this has
|
||||
# no effect on Linux systems. Let's redefine print once to avoid putting the
|
||||
# same argument everywhere.
|
||||
print = partial(print, flush=True)
|
||||
|
||||
Parity = dict(
|
||||
UART_PARITY_EVEN=0,
|
||||
UART_PARITY_ODD=1,
|
||||
UART_PARITY_NONE=2,
|
||||
UART_PARITY_BAD=3
|
||||
)
|
||||
|
||||
|
||||
class DriveHigh(px.SimThread):
|
||||
def __init__(self, p):
|
||||
self._p = p
|
||||
|
||||
def run(self):
|
||||
xsi = self.xsi
|
||||
|
||||
xsi.drive_port_pins(self._p, 1);
|
||||
|
||||
|
||||
class UARTRxChecker(px.SimThread):
|
||||
def __init__(self, rx_port, tx_port, parity, baud, stop_bits, bpb, data=[0x7f, 0x00, 0x2f, 0xff],
|
||||
intermittent=False):
|
||||
"""
|
||||
Create a UARTRxChecker instance.
|
||||
|
||||
:param rx_port: Receive port of the UART device under test.
|
||||
:param tx_port: Transmit port of the UART device under test.
|
||||
:param parity: Parity of the UART connection.
|
||||
:param baud: BAUD rate of the UART connection.
|
||||
:param stop_bits: Number of stop_bits for each UART byte.
|
||||
:param bpb: Number of data bits per "byte" of UART data.
|
||||
:param data: A list of bytes to send (default: [0x7f, 0x00, 0x2f, 0xff])
|
||||
:param intermittent: Add a random delay between sent bytes.
|
||||
"""
|
||||
self._rx_port = rx_port
|
||||
self._tx_port = tx_port
|
||||
self._parity = parity
|
||||
self._baud = baud
|
||||
self._stop_bits = stop_bits
|
||||
self._bits_per_byte = bpb
|
||||
self._data = data
|
||||
self._intermittent = intermittent
|
||||
# Hex value of stop bits, as MSB 1st char, e.g. 0b11 : 0xC0
|
||||
|
||||
def send_byte(self, xsi, byte):
|
||||
"""
|
||||
Send a byte to the rx_port
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
:param byte: Byte to send
|
||||
"""
|
||||
# Send start bit
|
||||
self.send_start(xsi)
|
||||
|
||||
# Send data
|
||||
self.send_data(xsi, byte)
|
||||
|
||||
# Send parity
|
||||
self.send_parity(xsi, byte)
|
||||
|
||||
# Send stop bit(s)
|
||||
self.send_stop(xsi)
|
||||
|
||||
|
||||
def send_start(self, xsi):
|
||||
"""
|
||||
Send a start bit.
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
"""
|
||||
xsi.drive_port_pins(self._rx_port, 0)
|
||||
self.wait_baud_time(xsi)
|
||||
|
||||
def send_data(self, xsi, byte):
|
||||
"""
|
||||
Write the data bits to the rx_port
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
:param byte: Data to send.
|
||||
"""
|
||||
# print "0x%02x:" % byte
|
||||
for x in range(self._bits_per_byte):
|
||||
# print " Sending bit %d of 0x%02x (%d)" % (x, byte, (byte >> x) & 0x01)
|
||||
xsi.drive_port_pins(self._rx_port, (byte & (0x01 << x)) >= 1)
|
||||
# print " (x): %d" % ((byte & (0x01 << x))>=1)
|
||||
self.wait_baud_time(xsi)
|
||||
|
||||
def send_parity(self, xsi, byte):
|
||||
"""
|
||||
Send the parity bit to the rx_port
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
:param byte: Data to send parity of.
|
||||
"""
|
||||
parity = (self._parity - 1) % 3 #parity enum in lib_uart (old XC) different from SDK
|
||||
if parity < 2:
|
||||
crc_sum = 0
|
||||
for x in range(self._bits_per_byte):
|
||||
crc_sum += ((byte & (0x01 << x)) >= 1)
|
||||
crc_sum += parity
|
||||
# print "Parity for 0x%02x: %d" % (byte, crc_sum%2)
|
||||
xsi.drive_port_pins(self._rx_port, crc_sum % 2)
|
||||
self.wait_baud_time(xsi)
|
||||
elif parity == Parity['UART_PARITY_BAD']:
|
||||
# print "Sending bad parity bit"
|
||||
self.send_bad_parity(xsi)
|
||||
|
||||
def send_stop(self, xsi):
|
||||
"""
|
||||
Send the stop bit(s) to the rx_port
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
"""
|
||||
for x in range(self._stop_bits):
|
||||
xsi.drive_port_pins(self._rx_port, 1)
|
||||
self.wait_baud_time(xsi)
|
||||
|
||||
def send_bad_parity(self, xsi):
|
||||
"""
|
||||
Send a parity bit of 1 to simulate an incorrect parity state.
|
||||
|
||||
:param xsi: XMOS Simulator Instance.
|
||||
"""
|
||||
# Always send a parity bit of 1
|
||||
xsi.drive_port_pins(self._rx_port, 0)
|
||||
self.wait_baud_time(xsi)
|
||||
|
||||
def get_bit_time(self):
|
||||
"""
|
||||
Returns the expected time between bits for the currently set BAUD rate.
|
||||
|
||||
Returns float value in nanoseconds.
|
||||
"""
|
||||
# Return float value in ps
|
||||
return (1.0 / self._baud) * 1e12
|
||||
|
||||
def wait_baud_time(self, xsi):
|
||||
"""
|
||||
Wait for 1 bit time, as determined by the baud rate.
|
||||
"""
|
||||
self.wait_until(xsi.get_time() + self.get_bit_time())
|
||||
|
||||
def wait_half_baud_time(self, xsi):
|
||||
"""
|
||||
Wait for half a bit time, as determined by the baud rate.
|
||||
"""
|
||||
self.wait_until(xsi.get_time() + (self.get_bit_time() / 2))
|
||||
|
||||
def run(self):
|
||||
xsi = self.xsi
|
||||
# Drive the uart line high.
|
||||
xsi.drive_port_pins(self._rx_port, 1)
|
||||
|
||||
# Wait for the device to bring up it's tx port, indicating it is ready
|
||||
self.wait((lambda _x: self.xsi.is_port_driving(self._tx_port)))
|
||||
|
||||
# If we're doing an intermittent send, add a delay between each byte
|
||||
# sent. Delay is in ns. 20,000ns = 20ms, 100,000ns = 100ms. Delays could
|
||||
# be more variable, but it hurts test time substantially.
|
||||
if self._intermittent:
|
||||
for x in self._data:
|
||||
k = randint(20000, 100000)
|
||||
self.wait_until(xsi.get_time() + k)
|
||||
self.send_byte(xsi, x)
|
||||
else:
|
||||
for x in self._data:
|
||||
self.send_byte(xsi, x)
|
||||
Reference in New Issue
Block a user