diff options
author | Joachim Strömbergson <joachim@secworks.se> | 2014-03-13 16:00:43 +0100 |
---|---|---|
committer | Joachim Strömbergson <joachim@secworks.se> | 2014-03-13 16:00:43 +0100 |
commit | 0e51a3e262b691e1d2dc28fa4f1b21fae58a634c (patch) | |
tree | e0f1675148f906d7be0b541562a1d2dba6954963 | |
parent | 96ef23fce4b7f789cabcac637dc434ddee35defb (diff) |
Adding sw to run tests on a FPGA device connected to the FPGA board via a serial port.
-rwxr-xr-x | src/sw/core_tester.py | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/sw/core_tester.py b/src/sw/core_tester.py new file mode 100755 index 0000000..0dec165 --- /dev/null +++ b/src/sw/core_tester.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +#======================================================================= +# +# core_tester.py +# -------------- +# This program sends several commands to the coretest subsystem +# in order to check the functionality of the uart and test_core +# cores connected to coretest. +# +# Note: This proram requires the PySerial module. +# http://pyserial.sourceforge.net/ +# +# +# Author: Joachim Strömbergson +# Copyright (c) 2014 SUNET +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#======================================================================= + +#------------------------------------------------------------------- +# Python module imports. +#------------------------------------------------------------------- +import sys +import serial +import os +import time +import threading + + +#------------------------------------------------------------------- +# Defines. +#------------------------------------------------------------------- +VERBOSE = False + +# Memory map. +SOC = '\x55' +EOC = '\xaa' +READ_CMD = '\x10' +WRITE_CMD = '\x11' +TEST_CORE_ADDR_PREFIX = '\x01' +UART_ADDR_PREFIX = '\x02' +NAME0_ADDR = '\x00' +NAME1_ADDR = '\x01' +TYPE_ADDR = '\x02' +VERSION_ADDR = '\x03' +TEST_CORE_RW_REG = '\x10' +TEST_CORE_DEBUG_REG = '\x20' + + +#------------------------------------------------------------------- +# print_response() +# +# Parses a received buffer and prints the response. +#------------------------------------------------------------------- +def print_response(buffer): + if VERBOSE: + print "Length of response: %d" % len(buffer) + if buffer[0] == '\xaa': + print "Response contains correct Start of Response (SOR)" + if buffer[-1] == '\x55': + print "Response contains correct End of Response (EOR)" + + response_code = ord(buffer[1]) + + if response_code == 0xfe: + print "UNKNOWN response code received." + + elif response_code == 0xfd: + print "ERROR response code received." + + elif response_code == 0x7f: + read_addr = ord(buffer[2]) * 256 + ord(buffer[3]) + read_data = (ord(buffer[4]) * 16777216) + (ord(buffer[5]) * 65536) +\ + (ord(buffer[6]) * 256) + ord(buffer[7]) + print "READ_OK. address 0x%02x = 0x%04x." % (read_addr, read_data) + + elif response_code == 0x7e: + read_addr = ord(buffer[2]) * 256 + ord(buffer[3]) + print "WRITE_OK. address 0x%02x." % (read_addr) + + elif response_code == 0x7d: + print "RESET_OK." + + else: + print "Response 0x%02x is unknown." % response_code + print buffer + + +#------------------------------------------------------------------- +# read_serial_thread() +# +# Function used in a thread to read from the serial port and +# collect response from coretest. +#------------------------------------------------------------------- +def read_serial_thread(serialport): + if VERBOSE: + print "Serial port response thread started. Waiting for response..." + + buffer = [] + while True: + response = serialport.read() + buffer.append(response) + if response == '\x55': + print_response(buffer) + buffer = [] + + +#------------------------------------------------------------------- +# write_serial_bytes() +# +# Send the bytes in the buffer to coretest over the serial port. +#------------------------------------------------------------------- +def write_serial_bytes(tx_cmd, serialport): + if VERBOSE: + print "Command to be sent:", tx_cmd + + for tx_byte in tx_cmd: + serialport.write(tx_byte) + + # Allow the device to complete the transaction. + time.sleep(0.1) + + +#------------------------------------------------------------------- +# main() +# +# Parse arguments. +#------------------------------------------------------------------- +def main(): + # Open device + ser = serial.Serial() + ser.port='/dev/cu.usbserial-A801SA6T' + ser.baudrate=9600 + ser.bytesize=8 + ser.parity='N' + ser.stopbits=1 + ser.timeout=1 + ser.writeTimeout=0 + + if VERBOSE: + print "Setting up a serial port and starting a receive thread." + + try: + ser.open() + except: + print "Error: Can't open serial device." + sys.exit(1) + + try: + my_thread = threading.Thread(target=read_serial_thread, args=(ser,)) + except: + print "Error: Can't start thread." + sys.exit() + + my_thread.daemon = True + my_thread.start() + + # TC1: Read name, type and version from test_core: + print "TC1: Reading name, type and version words from test_core." + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, NAME0_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, NAME1_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, TYPE_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, VERSION_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + + + # TC2: Read id0, id1 and version from test_core: + print "TC2: Reading id and version words from uart." + my_cmd = [SOC, READ_CMD, UART_ADDR_PREFIX, NAME0_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, UART_ADDR_PREFIX, NAME1_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, UART_ADDR_PREFIX, TYPE_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, UART_ADDR_PREFIX, VERSION_ADDR, EOC] + write_serial_bytes(my_cmd, ser) + + + # TC3: Read, write, read and write again from the RW register in the test core. + print "TC3: Read, write, read and write again from the RW register in the test core." + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_RW_REG, EOC] + write_serial_bytes(my_cmd, ser) + test_pattern = ['\xde', '\xad', '\xbe', '\xef'] + my_cmd = [SOC, WRITE_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_RW_REG] + test_pattern + [EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_RW_REG, EOC] + write_serial_bytes(my_cmd, ser) + test_pattern = ['\x13', '\x37', '\xfe', '\xed'] + my_cmd = [SOC, WRITE_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_RW_REG] + test_pattern + [EOC] + write_serial_bytes(my_cmd, ser) + my_cmd = [SOC, READ_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_RW_REG, EOC] + write_serial_bytes(my_cmd, ser) + + + # TC4: Write a sequence of words to the debug registers. This should be visible on the leds." + for i in range (0, 256, 7): + print "Sending write command: address 0x0120 = 0x%08x." % i + my_cmd = [SOC, WRITE_CMD, TEST_CORE_ADDR_PREFIX, TEST_CORE_DEBUG_REG] +\ + ['\x00', '\x00', '\x00'] + [chr(i)] + [EOC] + for tx_byte in my_cmd: + ser.write(tx_byte) + time.sleep(0.01) + + # Exit nicely. + if VERBOSE: + print "Done. Closing device." + ser.close() + + +#------------------------------------------------------------------- +# __name__ +# Python thingy which allows the file to be run standalone as +# well as parsed from within a Python interpreter. +#------------------------------------------------------------------- +if __name__=="__main__": + # Run the main function. + sys.exit(main()) + +#======================================================================= +# EOF serial_write_sequence.py +#======================================================================= |