Commit f7cd3f73 authored by Theodor-Adrian Stana's avatar Theodor-Adrian Stana

Added Python scripts for RTM PTS

parent e9f2131e
# NOTE: advised to use lower-case for board name
BOARD = t485-rtm
ELMAIP =
ELMAPWD =
ELMASLOT =
all:
mkdir -p ubuntu/$(BOARD)/log
touch ubuntu/$(BOARD)/log/fan-speeds
cp -r shell/ ubuntu/$(BOARD)/
mkdir -p ubuntu/$(BOARD)/pyts/
cp python/* ubuntu/$(BOARD)/pyts/
chmod +x rename; ./rename $(BOARD) $(ELMAIP) $(ELMAPWD) $(ELMASLOT)
cp ubuntu/$(BOARD)/pyts/pts.py ubuntu/$(BOARD)/pts
cp ubuntu/$(BOARD)/pyts/jpts.py ubuntu/$(BOARD)/jpts
ln -s pyts/leds.py ubuntu/$(BOARD)/test01.py
ln -s pyts/rs485_pulse_rtm.py ubuntu/$(BOARD)/test02.py
mkdir -p ubuntu/$(BOARD)/boot
mv ubuntu/$(BOARD)/shell/program ubuntu/$(BOARD)/boot
mv ubuntu/$(BOARD)/shell/flash ubuntu/$(BOARD)/boot
wget -P ubuntu/$(BOARD)/boot http://www.ohwr.org/attachments/download/3690/pts.bit
chmod +x ubuntu/$(BOARD)/shell/*
chmod +x ubuntu/$(BOARD)/boot/*
chmod +x ubuntu/$(BOARD)/jpts
chmod +x ubuntu/$(BOARD)/pts
clean:
rm -rf ubuntu/
#! /usr/bin/python
# coding: utf8
##________________________________________________________________________________________________
##
## CONV-TTL-RS485 PTS
##
## CERN,BE/CO-HT
##________________________________________________________________________________________________
##
##------------------------------------------------------------------------------------------------
##
## CONV-TTL-RS485 test sequencer
##
##------------------------------------------------------------------------------------------------
##
## Description This module gets called by the main PTS module (pts.py) to run the tests defined
## via the make-links.bat script. The tests are listed within this script and symlinks
## are created to point to the actual Pyton programs running the tests.
##
## The task of this module is to run these Python programs in a sequence and print the
## test results to output files.
##
## Two types of output files exist for this purpose. The first is the log file (.log),
## which contains brief information, PASS/FAIL for each test. The second, the info
## file (.inf) contains more detailed information, listing the steps the test takes
## and the reasons for which the test failed (if it failed).
##
## Authors Julian Lewis (Julian.Lewis@cern.ch)
## Theodor Stana (t.stana@cern.ch)
## Website http://www.ohwr.org/projects/conv-ttl-rs485
## Date 30/10/2014
##-------------------------------------------------------------------------------------------------
##
##-------------------------------------------------------------------------------------------------
## GNU LESSER GENERAL PUBLIC LICENSE
## ------------------------------------
## This source file is free software; you can redistribute it and/or modify it under the terms of
## the GNU Lesser General Public License as published by the Free Software Foundation; either
## version 2.1 of the License, or (at your option) any later version.
## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU Lesser General Public License for more details.
## You should have received a copy of the GNU Lesser General Public License along with this
## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
##-------------------------------------------------------------------------------------------------
##------------------------------------------------------------------------------------------------
## Import
##------------------------------------------------------------------------------------------------
import sys
sys.path.append('.')
sys.path.append("pyts")
import ptsexcept
import ptsdefine
import time
import traceback
import socket
from optparse import OptionParser
from vv_pts import *
from os import path, access, R_OK, readlink
##-------------------------------------------------------------------------------------------------
## Method to get the test program a symlink points to
##-------------------------------------------------------------------------------------------------
def lnk_ptr(tname):
lname = "./%s.py" % (tname)
if path.islink(lname):
return readlink(lname)
else:
return tname
##-------------------------------------------------------------------------------------------------
## Method to run the test
##-------------------------------------------------------------------------------------------------
def run_test(tname,bus,inf,log):
# Each test should have a main function in it running the necessary steps
# to run. Here we import the name of the test and run the main function,
# printing the docstring at the beginning of this function.
#
# The number of errors returned by the test's main function is returned
# by this function to the JPTS program.
try:
mod = __import__(tname)
msg = mod.main.__doc__
print msg
log.write("%s\n" % (msg))
inf.write("%s\n" % (msg))
time.sleep(1)
return mod.main(bus,tname,inf,log)
except PtsError, e:
msg = "%s %s->%s\n" % (e, tname, lnk_ptr(tname))
print "ABORT: %s" % (msg)
inf.write(msg)
log.write(msg)
return 1
##-------------------------------------------------------------------------------------------------
## Main "method" of JPTS
##-------------------------------------------------------------------------------------------------
if __name__ == '__main__':
# Print usage information
use = "Usage: %prog [--lun=0 --snum=1234 5678 --debug] test_num,run_count test_num,run_count..."
parser = OptionParser(usage=use, version="pts version 2.0")
parser.add_option("-l", "--lun", help="Logical Unit Number", type="int", default=ELMASLOT, dest="lun")
parser.add_option("-s", "--snum", help="Serial number(s)", dest="snum", action="store", nargs=2, default=("0","0"))
parser.add_option("-n", "--name", help="Board name", dest="board_name", default=BOARD)
parser.add_option("-b", "--bus", help="Bus VME/PCI/SKT", dest="bus_type", default="SKT")
parser.add_option("-o", "--outdir", help="Path to log directory", dest="dir_name", default=".")
parser.add_option("-d", "--debug", help="Debug Option", dest="debug", default=False, action="store_true")
options, args = parser.parse_args()
# Print further information if in debug mode
if options.debug:
print "\n"
print "options (Logical Unit Number) lun :%d" % options.lun
print "options (Serial numbers pair) snum :%s %s" % options.snum
print "options (Board name ) name :%s" % options.board_name
print "options (Bus VME PCI or SKT ) bus :%s" % options.bus_type
print "options (Location of log dir) outdir:%s" % options.dir_name
print "options (Debug printing flag) debug :%d" % options.debug
print "arglist (List: Test,RunCount) :%s" % (args)
# Create test array from existing test links
tns = []
if len(args):
for a in args:
nstr = a.split(',')
tn = int(nstr[0])
if len(nstr) == 2:
tc = int(nstr[1])
else:
tc = 1
tns.append((tn,tc))
else:
for a in range(19):
tns.append((a,1))
# Get logical unit number, serial numbers, board name, log file dir from command line args
# and create path strings for log and info files
lun = options.lun
sno, xno = options.snum
bnm = options.board_name
dir = options.dir_name
now = time.asctime(time.localtime(time.time()))
now = now.replace(" ","-")
now = now.replace(":","-")
lgf = "%s/log/%s-%s-%s-%s-%1d.log" % (dir,bnm,sno,xno,now,lun)
inf = "%s/log/%s-%s-%s-%s-%1d.inf" % (dir,bnm,sno,xno,now,lun)
# Open the log and info files
try:
log = open(lgf, "w")
inf = open(inf, "w")
except Exception, e:
msg = "Exception: %s" % (e)
print "Fatal: %s" % (msg)
sys.exit(1)
# and print them to console if in debug mode
if options.debug:
print "\n"
print "Log file is: %s" % lgf
print "Inf file is: %s" % inf
print "\n"
# Open up a bus object, can be one of following (depending on tested device):
# * VME -- VME board (SVEC, etc.)
# * PCI -- PCI board (SPEC, etc.)
# * SKT -- board connecting through I2C lines on VME backplane (CONV-TTL-BLO, etc.)
try:
if options.bus_type == "VME":
bus = VME(lun)
elif options.bus_type == "PCI":
bus = PCI(lun)
else:
bus = SKT(lun)
bus.vv_init()
except BusException, e:
print "Fatal:BUS Exception: %s" % (e)
except BusWarning, e:
print "Warning:Bus Exception: %s" % (e)
# Start running the tests.
for t in tns:
tname = "test%02d" % t[0]
pyt = "%s/%s.py" % (dir, tname)
if path.exists(pyt) and path.isfile(pyt) and access(pyt, R_OK):
for n in range(t[1]):
if n == 10:
msg = "Printing suppresses after 10 runs"
print msg
log.write('\n' + msg + '\n')
inf.write('\n' + msg + '\n')
if n < 10:
msg = "Run:%d Begin:%s" % (n+1,tname)
print msg
log.write('\n' + msg + '\n')
inf.write('\n' + msg + '\n')
try:
# First load a firmware and read back a register to confirm correct load.
if bus.vv_load() == 0:
msg = "INFO: Found CONV-TTL-RS485 board in slot %d\n" % (lun)
inf.write(msg + '\n')
# Each test is passed the test name, the log and info files and the
# bus object. The test program is expected to return the number of
# errors that occured. If no errors occur, the test PASSes, otherwise
# it FAILs.
cc = run_test(tname,bus,inf,log)
if cc == 0:
msg = "PASS: %s" % (tname)
log.write(msg + '\n')
inf.write(msg + '\n')
print msg
else:
msg = "FAIL: %s->%s" % (tname, lnk_ptr(tname))
log.write(msg + '\n')
inf.write(msg + '\n')
print msg
except Exception, e:
if options.debug:
print e
traceback.print_exc()
msg = "FAIL: %s->%s (%s)" % (tname, lnk_ptr(tname), e)
log.write(msg + '\n')
inf.write(msg + '\n')
print msg
if n < 10:
msg = "Run:%d End:%s\n" % (n+1,tname)
print msg
log.write(msg + '\n')
inf.write(msg + '\n')
# Close the bus and the files
bus.vv_close()
log.close()
inf.close()
# Print info file to console if in debug mode
if options.debug:
print "Debug: printing:%s" % (inf)
inf = open(inf, "r")
try:
for line in inf:
l = line.split("\n")
print "%s" % l[0]
finally:
inf.close()
sys.exit(0)
##_______________________________________________________________________________________________
##
## CONV-TTL-RS485 PTS
##
## CERN,BE/CO-HT
##_______________________________________________________________________________________________
##
##-----------------------------------------------------------------------------------------------
##
## CONV-TTL-RS485 LEDs test
##
##-----------------------------------------------------------------------------------------------
##
## Description Testing of the Front Panel status LEDs (IC1 and bi-color LEDs) and pulse
## LEDs (IC5 and channel LEDs) of the CONV-TTL-BLO board.
##
## For this test, the operator's intervention is needed; when prompted, the operator
## needs to visually check the LEDS.
##
## The FPGA gateware sequences through each of the front panel LEDs (pulse LEDs
## status LEDs) based on the value of the current test field in the PTS control
## register. In order to start and stop LED sequencing, the test sets and clears
## control bits in the PTS CSR.
##
## Authors Julian Lewis (Julian.Lewis@cern.ch)
## Theodor-Adrian Stana (t.stana@cern.ch)
## Website http://www.ohwr.org/projects/pts
## Date 30/10/2014
##-----------------------------------------------------------------------------------------------
##
##------------------------------------------------------------------------------------------------
## GNU LESSER GENERAL PUBLIC LICENSE
## ------------------------------------
## This source file is free software; you can redistribute it and/or modify it under the terms of
## the GNU Lesser General Public License as published by the Free Software Foundation; either
## version 2.1 of the License, or (at your option) any later version.
## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU Lesser General Public License for more details.
## You should have received a copy of the GNU Lesser General Public License along with this
## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
##-------------------------------------------------------------------------------------------------
##-------------------------------------------------------------------------------------------------
## Import
##-------------------------------------------------------------------------------------------------
# Import system modules
import sys
sys.path.append("pyts")
import time
import os, errno, re, sys, struct
import os.path
import traceback
# Import common modules
from ctypes import *
from ptsexcept import *
from vv_pts import *
from ptsdefine import *
##-------------------------------------------------------------------------------------------------
## main --
##-------------------------------------------------------------------------------------------------
def main(bus,tname,inf,log):
"""
tests : Front Panel LEDs, bicolor LEDs with transceiver IC1
uses : pts.bit and leds.py
"""
pel = PTS_ERROR_LOGGER(inf,log)
try:
# First phase of LED test, enable pulse LED sequencing
val = bus.vv_read(CSR)
val |= (1 << CSR_CHLEDT_OFS)
bus.vv_write(CSR, val)
# The gateware should blink the LEDs, ask the operator for input
inp = raw_input("--> Are the channel LEDs blinking one by one? yes/no: ")
while True:
if inp.find("yes") != -1 or inp.find("YES") != -1:
break
if inp.find("no") != -1 or inp.find("NO") != -1:
msg = "ERROR: Front Panel LEDs"
pel.set(msg)
break
inp = raw_input('Please type "yes" or "no" to continue: ')
return pel.get()
except BusException, e:
raise PtsError("SKT Exception: %s" % (e))
except BusWarning, e:
raise PtsError("SKT Warning: %s" % (e))
finally:
# Clean-up -- clear status and front LED test bits
val = bus.vv_read(CSR)
val &= ~((1 << CSR_CHLEDT_OFS) | (1 << CSR_STLEDT_OFS))
bus.vv_write(CSR, val)
#! /usr/bin/python
# coding: utf8
##________________________________________________________________________________________________
##
## CONV-TTL-RTM-RS485 PTS
##
## CERN,BE/CO-HT
##________________________________________________________________________________________________
##
##------------------------------------------------------------------------------------------------
##
## CONV-TTL-RTM-RS485 PTS main program
##
##------------------------------------------------------------------------------------------------
##
## Description This is the main program of the PTS suite. It is the high-level program of the
## suite, running scripts to turn the test system on and off and downloading bitfiles
## to the DUT FPGA(s) before finally running the test programs. This latter part is
## handled by JPTS (jpts.py), a Python program that cycles through the various tests
## to be performed and writes results to log (.log) and info (.inf) files.
##
## Each board has a barcode associated to it, which can be either read via a barcode
## reader device, or manually input by the user from a keyboard. The barcode is used
## as part of the output file names to identify a DUT board.
##
## The program begins by asking for this barcode and downloading a bitstream to the
## FPGA once the board has been plugged in. Then, JPTS gets called in an external
## shell to run the tests defined for a board's PTS.
##
## After the tests have finished running, the log and info files get stored to a USB
## stick provided with the test system.
##
## Authors Julian Lewis (Julian.Lewis@cern.ch)
## Theodor Stana (t.stana@cern.ch)
## Website http://www.ohwr.org/projects/conv-ttl-rs485
## Date 30/10/2014
##-------------------------------------------------------------------------------------------------
##
##-------------------------------------------------------------------------------------------------
## GNU LESSER GENERAL PUBLIC LICENSE
## ------------------------------------
## This source file is free software; you can redistribute it and/or modify it under the terms of
## the GNU Lesser General Public License as published by the Free Software Foundation; either
## version 2.1 of the License, or (at your option) any later version.
## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU Lesser General Public License for more details.
## You should have received a copy of the GNU Lesser General Public License along with this
## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
##-------------------------------------------------------------------------------------------------
##-------------------------------------------------------------------------------------------------
## Import
##-------------------------------------------------------------------------------------------------
import sys
sys.path.append('.')
sys.path.append("pyts")
import time
import traceback
import os
import subprocess
import re
# Import ptsdefine module to avoid wrong `make's
from ptsdefine import *
##-------------------------------------------------------------------------------------------------
## Method to turn on the VME crate.
##-------------------------------------------------------------------------------------------------
## It calls the men-on script which sends the necessary SMTP commands to the ELMA crate to turn on
## power to the VME backplane.
##-------------------------------------------------------------------------------------------------
def men_on():
print("Switching on the ELMA crate")
subprocess.call("shell/men-on", shell=True, stdout=fnull, stderr=fnull)
##-------------------------------------------------------------------------------------------------
## Method to turn off the VME crate.
##-------------------------------------------------------------------------------------------------
## It calls the men-off script which sends the necessary SMTP commands to the ELMA crate to turn off
## power to the VME backplane.
##-------------------------------------------------------------------------------------------------
def men_off():
print("Switching off the ELMA crate")
subprocess.call("shell/men-off", shell=True, stdout=fnull, stderr=fnull)
##-------------------------------------------------------------------------------------------------
## Main "method" of PTS
##-------------------------------------------------------------------------------------------------
if __name__ == '__main__':
print "\nHello and Welcome to the CONV-TTL-RTM-RS485 PTS!\n"
# Open NULL File and turn the crate off
fnull = open(os.devnull, "w")
# Clear the log dir (if any) and (re-)create it to store log and info files
subprocess.call("rm -rf ./log; mkdir log; chmod 777 log", shell=True, stdout=fnull, stderr=fnull)
# Turn off the VME crate
men_off()
# Scan the first barcode
while True:
sn1 = raw_input("--> Scan the 1st barcode: ")
if (not len(sn1)):
sn1 = "0"
m = re.search(r"[^a-z\-A-Z0-9_]+",sn1)
if m:
print "Bad character in barcode"
else:
break
# Scan the second barcode
while True:
sn2 = raw_input("--> Scan the 2nd barcode: ")
if len(sn2) > 2:
m = re.search(r"[^a-z\-A-Z0-9_]+",sn2)
if m:
print "Bad character in barcode"
else:
break
else:
sn2 = "0"
break
# Ask the user to plug in the board, turn on the crate and call the script to download bitstream
# to FPGA
msg = "\n--> Plug the CONV-TTL-RTM-RS485 board '%s-%s' into the VME crate.\n Then type 'ok': " % (sn1, sn2)
ok = raw_input(msg)
while True:
if ok.find("ok") != -1 or ok.find("OK") != -1:
break
else:
ok = raw_input("--> Please type 'ok' to continue: ")
print "\n"
men_on()
print "Loading FPGA bitstream..."
ret = subprocess.call("cd boot; ./program", shell=True, stdout=fnull, stderr=fnull)
time.sleep(1)
if (ret != 0):
print "ERROR: Bitstream download fail. Check JTAG connectivity."
else:
# Run JPTS in another shell script; JPTS will handle running each of the test scripts
cmd = "xterm -e ./jpts -s %s %s" % (sn1, sn2)
print "Running tests :%s\n" % (cmd)
subprocess.call(cmd, shell=True, stdout=fnull, stderr=fnull)
# After all testing has finished, grep the log files for PASS and FAIL messages and print the outcomes to the console
subprocess.call("grep PASS log/*.log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
subprocess.call("grep FAIL log/*.log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
# Save results on USB key...
print "\nSaving test results on USB key"
try:
subprocess.call("mkdir -p /media/pts/log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
subprocess.call("cp log/*.log /media/pts/log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
subprocess.call("cp log/*.inf /media/pts/log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
except e:
print "ERROR: No access to USB key at /media/pts"
print e
# We're done, turn off the VME crate
print "\nTesting completed!"
men_off()
# Finally, print anything that went wrong throughout the test programs by grepping the log and info files and
# exit when the user desires.
msg = "\n--> To see all the PTS errors, type 'ok': "
ok = raw_input(msg)
if ok.find("ok") != -1:
subprocess.call("grep FAIL log/*.log", shell=True, stdout=sys.stdout, stderr=sys.stderr)
subprocess.call("grep ERROR log/*.inf", shell=True, stdout=sys.stdout, stderr=sys.stderr)
subprocess.call("grep WARNING log/*.inf", shell=True, stdout=sys.stdout, stderr=sys.stderr)
print ""
print "--> You may now unplug the CONV-TTL-RTM-RS485 board %s-%s\n" % (sn1, sn2)
msg = "--> To exit PTS, type 'ok': "
ok = raw_input(msg)
while True:
if ok.find("ok") != -1 or ok.find("OK") != -1:
print "Exited PTS"
time.sleep(1)
sys.exit(1)
else:
ok = raw_input("--> To exit PTS, type 'ok': ")
#===============================================================================
# CERN (BE-CO-HT)
# PTS definitions file
#===============================================================================
# author: Theodor Stana (t.stana@cern.ch)
#
# date of creation: 2013-10-31
#
# version: 1.0
#
# description:
# This module contains register address definitions that are used across the
# various tests. Importing this module inside a test script makes these
# definitions available for use within a bus.vv_write or bus.vv_read method
# (see vv_pts.py for these methods).
#
# dependencies:
# none.
#
# references:
# none.
#
#===============================================================================
# GNU LESSER GENERAL PUBLIC LICENSE
#===============================================================================
# This source file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation; either version 2.1 of the License, or (at your
# option) any later version. This source is distributed in the hope that it
# will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with this
# source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
#===============================================================================
# last changes:
# 2014-10-31 Theodor Stana t.stana@cern.ch File created
#===============================================================================
# TODO: -
#===============================================================================
BOARD = "$BOARD"
# ELMA crate definitions
ELMAIP = "$ELMAIP"
ELMAPWD = "$ELMAPWD"
ELMASLOT = $ELMASLOT
# Board ID register
BIDR = 0x000
BIDR_ARR = [ "TBLO", "T485" ]
# Control and Status Register
CSR = 0x004
CSR_CHLEDT_OFS = 0
CSR_STLEDT_OFS = 1
#CSR_RLEDT_OFS = 2
CSR_TTLPT_OFS = 3
CSR_REARPT_OFS = 4
CSR_TSTCVCC_OFS = 5
CSR_TSTCMUXEN_OFS = 6
CSR_TSTCS0_OFS = 7
CSR_TSTCS1_OFS = 8
CSR_RST_UNLOCK_OFS = 14
CSR_RST_OFS = 15
CSR_SWITCH_OFS = 16
CSR_RTM_OFS = 24
CSR_I2C_ERR_OFS = 30
CSR_I2C_WDTO_OFS = 31
# Line Status Register
LSR = 0x008
LSR_FRONT_OFS = 0
LSR_FRONTINV_OFS = 6
LSR_REAR_OFS = 10
LSR_REARFS_OFS = 26
# Termination Enable Register
TER = 0x00c
TER_ITERM_OFS = 0
TER_OTERM_OFS = 6
# 1-Wire base address, used in therm_id.py
TEMP_1WIRE_BASE = 0x010
# DAC and clock info registers and offsets, used in dac_vcxo_pll.py
PLL_DAC_BASE = 0X020
VCXO_DAC_BASE = 0x080
PLL_CLKINFO_BASE = 0x100
VCXO_CLKINFO_BASE = 0x120
CLKINFO_RST_OFS = 0x014
CLKINFO_ENABLE_OFS = 0x018
CLKINFO_VALUE_OFS = 0x010
# SFP I2C master base address, used in sfp_eeprom.py
SFP_EEPROM_BASE = 0x140
# SFP endpoint, miniNIC and buffer RAM base addresses and offsets,
# used in sfp_test.py
SFP_BASE = 0x200
SFP_ENDPOINT_OFS = 0x000
SFP_MINIC_OFS = 0x200
SFP_DPRAM_OFS = 0x600
# Pulse counter base address
PULSE_CNT_BASE = 0xc00
class PtsException(Exception):
pass
class PtsCritical(PtsException):
"""critical error, abort the whole test suite"""
pass
class PtsUser(PtsException):
"""error, user intervention required"""
pass
class PtsWarning(PtsException):
"""warning, a cautionary message should be displayed"""
pass
class PtsInvalid(PtsException):
"""reserved: invalid parameters"""
class PtsNoBatch(PtsInvalid):
"""reserved: a suite was created without batch of tests to run"""
pass
class PtsBadTestNo(PtsInvalid):
"""reserved: a bad test number was given"""
pass
class PtsInfo(PtsException):
"""Information from the test, not an error"""
class PtsError(PtsException):
"""error, continue remaining tests in test suite"""
pass
class PTS_ERROR_LOGGER:
"""Log errors and continue testing without raising an exception"""
def __init__(self, inf, log):
self.inf = inf
self.log = log
self.er_count = 0
def set(self, msg):
self.inf.write(msg + "\n")
self.log.write(msg + "\n")
self.er_count = self.er_count + 1
def get(self):
return self.er_count
if __name__ == '__main__':
pass
##_______________________________________________________________________________________________
##
## CONV-TTL-RS485 PTS
##
## CERN,BE/CO-HT
##_______________________________________________________________________________________________
##
##-----------------------------------------------------------------------------------------------
##
## CONV-TTL-RS485 LEDs test
##
##-----------------------------------------------------------------------------------------------
##
## Description Testing the rear-transition module interface of the CONV-TTL-RS485 front module
## board. This is done in conjunction with gateware implemented on the
## CONV-TTL-RS485 FPGA.
##
## The gateware implements pulse repeaters which are controlled by this script to
## send pulses back to inputs. Externally to the RTM, there should be two boards
## containing differential multiplexers, and these are controlled by the FPGA HDL
## through this script such that each channel sends pulses back to itself, in the
## sequence Out1->In, Out2->In, Out3->In.
##
## In short, what this script does is to turn on pulse repetition, sleep for a
## predefined amount of time, and then check that the same number of pulses that has
## been sent at the channel output are received at its input. The checking is done by
## reading the input and output channel pulse counters, implemented in the FPGA HDL.
## Checking is done with input and output terminations ON and OFF (one run of the same
## test sequence for both).
##
## Authors Julian Lewis (Julian.Lewis@cern.ch)
## Theodor-Adrian Stana (t.stana@cern.ch)
## Website http://www.ohwr.org/projects/pts
## Date 11/11/2014
##-----------------------------------------------------------------------------------------------
##
##------------------------------------------------------------------------------------------------
## GNU LESSER GENERAL PUBLIC LICENSE
## ------------------------------------
## This source file is free software; you can redistribute it and/or modify it under the terms of
## the GNU Lesser General Public License as published by the Free Software Foundation; either
## version 2.1 of the License, or (at your option) any later version.
## This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU Lesser General Public License for more details.
## You should have received a copy of the GNU Lesser General Public License along with this
## source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
##-------------------------------------------------------------------------------------------------
# Import system modules
import sys
sys.path.append("pyts")
import time
# Import common modules
from ptsexcept import *
from vv_pts import *
from ptsdefine import *
#--------------------------------------------------------------------------------------------------
# Pulse counter class
#--------------------------------------------------------------------------------------------------
class CPulseCounter:
def __init__(self, bus, base):
self.bus = bus
self.base = base
def wr_reg(self, addr, val):
self.bus.vv_write(self.base + addr,val)
def rd_reg(self, addr):
return self.bus.vv_read(self.base + addr)
def wr_out_cnt(self, chan, val):
return self.wr_reg((chan-1)*8, val)
def wr_in_cnt(self, chan, val):
return self.wr_reg((chan-1)*8 + 4, val)
def rd_out_cnt(self, chan):
return self.rd_reg((chan-1)*8)
def rd_in_cnt(self, chan):
return self.rd_reg((chan-1)*8 + 4)
#--------------------------------------------------------------------------------------------------
# Test sequences
#--------------------------------------------------------------------------------------------------
def mux_sel(bus, sel):
val = bus.vv_read(CSR)
val &= ~(1 << CSR_TSTCS0_OFS)
val &= ~(1 << CSR_TSTCS1_OFS)
if (sel & 0x1):
val |= (1 << CSR_TSTCS0_OFS)
if (sel & 0x2):
val |= (1 << CSR_TSTCS1_OFS)
bus.vv_write(CSR, val)
time.sleep(0.1)
def en_pulse_gen(bus):
val = bus.vv_read(CSR)
val |= (1 << CSR_REARPT_OFS)
bus.vv_write(CSR, val)
time.sleep(0.1)
def dis_pulse_gen(bus):
val = bus.vv_read(CSR)
val &= ~(1 << CSR_REARPT_OFS)
bus.vv_write(CSR, val)
time.sleep(0.1)
def clear_counters(bus):
pc = CPulseCounter(bus, PULSE_CNT_BASE)
# Clear pulse counters for the TTL channels
for i in range(11, 17):
pc.wr_out_cnt(i, 0)
pc.wr_in_cnt(i, 0)
def check_counters(bus, inf, pel):
pc = CPulseCounter(bus, PULSE_CNT_BASE)
ic_arr = []
oc_arr = []
for i in range(11, 17):
ic_arr.append(pc.rd_in_cnt(i))
oc_arr.append(pc.rd_out_cnt(i))
# First, check for all-zeroes in counters, indicating enable NAND gate failure
if all(ic == 0 for ic in ic_arr):
msg = "ERROR: No pulses received - check tester board connection, or enable NAND gate IC8"
pel.set(msg)
else:
for i in range(len(ic_arr)):
if (ic_arr[i] == oc_arr[i]):
msg = "Ch%d input counter (%d) matches the output counter (%d) - good\n" % (i+1,
ic_arr[i], oc_arr[i])
inf.write(msg)
else:
msg = "ERROR: Ch%d input counter (%d) does not match output counter (%d)"% (i+1,
ic_arr[i], oc_arr[i])
pel.set(msg)
def pulse_test(bus, inf, pel, output, term):
if (output == 1):
disp = 3
elif (output == 2):
disp = 2
elif (output == 3):
disp = 1
msg = "Testing channel connections: O%d -> IN" % (disp)
print(msg)
mux_sel(bus, output)
clear_counters(bus)
inf.write('\n')
inf.write(msg+'\n')
en_pulse_gen(bus)
time.sleep(2)
dis_pulse_gen(bus)
check_counters(bus, inf, pel)
time.sleep(1)
##-------------------------------------------------------------------------------------------------
## main --
##-------------------------------------------------------------------------------------------------
def main(bus, tname, inf, log):
"""
tests : RS-485 pulse repetition, RS-485 transceivers IC31-IC56,
solid-state switches IC56-IC75, solid-state switches
IC23-IC28, RS-485 transceivers IC16-IC21, Schmitt trigger
inputs IC30, IC45, NAND gate IC8, IC69 Schmitt trigger for
the RTM detection lines
uses : pts.bit and rs485_pulse_rtm.py
"""
pel = PTS_ERROR_LOGGER(inf, log)
try:
# Read RTM lines
rtm = (bus.vv_read(CSR) >> CSR_RTM_OFS) & 0x3f
if (rtm == 0x09):
msg = "RTM detection lines read correctly: 0x%02X" % rtm
inf.write(msg+'\n')
else:
msg = "ERROR: RTM detection lines readout (0x%02X) incorrect - expected 0x09. Check RTM presence or IC69" % rtm
pel.set(msg)
return pel.get()
# First, clear the pulse counters
clear_counters(bus)
# Ask the user to make the daisy-chain
print("Connect the LEMO cable as follows:")
print(" - BLU cable to INV-TTL CH A")
print(" - GRN cable to INV-TTL CH B")
print(" - RED cable to INV-TTL CH C")
print(" - YEL cable to INV-TTL CH D")
reply = raw_input("Have the connections been made? (yes/no) ")
while (1):
if "yes" in reply.lower():
break
if "no" in reply.lower():
msg = "ERROR: Control connections to RS485 tester not made"
pel.set(msg)
return pel.get()
else:
reply = raw_input('Please type "yes" or "no" to continue: ')
# Power on the tester card
val = bus.vv_read(CSR)
val |= (1 << CSR_TSTCVCC_OFS)
bus.vv_write(CSR, val)
time.sleep(1)
# Start running tests (front module terminations off)
term = "OFF"
inf.write('\n')
# Read out fail-safe lines -- should now be high, since the MUXes are
# powered but not enabled
msg = "Testing RS-485 fail-safe on open-connection case"
print(msg)
inf.write('\n')
inf.write(msg+'\n')
val = bus.vv_read(LSR)
val >>= LSR_REARFS_OFS
if (val == 0x3f):
msg = "RS-485 failsafe lines read as expected: 0x%02X\n" % val
inf.write(msg)
else:
msg = "ERROR: Failsafe lines readout (0x%02X) incorrect - expected 0x3F" % val
pel.set(msg)
# Enable multiplexer
print("Enabling multiplexers")
val = bus.vv_read(CSR)
val |= (1 << CSR_TSTCMUXEN_OFS)
bus.vv_write(CSR, val)
time.sleep(1)
# Fail-safe test
msg = "Testing RS-485 fail-safe on short-circuit case"
print(msg)
mux_sel(bus, 0x0)
inf.write('\n')
inf.write(msg+'\n')
val = bus.vv_read(LSR)
val >>= LSR_REARFS_OFS
if (val == 0x3f):
msg = "RS-485 failsafe lines read as expected: 0x%02X\n" % val
inf.write(msg)
else:
msg = "ERROR: Failsafe lines readout (0x%02X) incorrect - expected 0x3F" % val
pel.set(msg)
time.sleep(1)
# Generate pulses & test correct reception
pulse_test(bus, inf, pel, 1, term)
pulse_test(bus, inf, pel, 2, term)
pulse_test(bus, inf, pel, 3, term)
# Disable multiplexer
print("Disabling multiplexers")
val = bus.vv_read(CSR)
val &= ~(1 << CSR_TSTCMUXEN_OFS)
bus.vv_write(CSR, val)
time.sleep(1)
return pel.get()
except BusException, e:
raise PtsError("SKT Exception: %s" % e)
except BusWarning, e:
raise PtsError("SKT Warning: %s" % e)
finally:
val = bus.vv_read(CSR)
val &= ~(1 << CSR_TSTCVCC_OFS)
val &= ~(1 << CSR_TSTCMUXEN_OFS)
val &= ~(1 << CSR_TSTCS0_OFS)
val &= ~(1 << CSR_TSTCS1_OFS)
bus.vv_write(CSR, val)
#! /usr/bin/python
# coding: utf8
# Copyright CERN, 2014
# Author: Julian Lewis <julian.lewis@cern.ch>
# Theodor Stana <t.stana@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import time
from ctypes import *
import os, errno, re, sys, struct
import os.path
from ptsexcept import *
import socket
from socket import SHUT_RDWR
import binascii
from ptsdefine import *
class BusException(Exception):
pass
class BusWarning(Exception):
pass
class VME(object):
def __init__(self,lun):
""" The vmeio driver lun (logical unit).
At driver install time, insmod maps lun on to
VME (csr, application window, interrupts).
Lun is set when creating a VME object
"""
self.lib = CDLL('./libvv_pts.so')
int = 0
if type(lun) == type(int):
self.lun = lun
else:
self.lun = int
raise BusWarning("Warning: VME __init__: Bad lun, default to 0")
def vv_init(self):
""" Initialize the library
loads the libvv_pts.so dynamic library
opens vmeio driver for lun 0
prepares the svec bootloader
"""
self.handle = cast(self.lib.vv_init(self.lun), c_void_p)
if self.handle == 0:
raise BusException("Failed vv_init: Can't initialize VME library")
return self.handle
def vv_close(self):
""" Close the driver and free up resources
"""
cc = self.lib.vv_close(self.handle)
self.handle = 0
if cc != 0:
raise BusException("Failed vv_close: Can't close VME library")
return cc
def vv_load(self, bit_stream, id):
""" Load the FPGA
reads the FPGA bitstream image file
initializes the svec bootloader
loads the FPGA image
initializes the loaded VME core for lun 0
"""
cc = self.lib.vv_load(self.handle, bit_stream, id)
if cc == -1:
raise BusException("Failed vv_load: Can't load bit_stream: %s" % (bit_stream))
return cc
def vv_write(self, byte_offset, value):
""" Write to the application FPGA wishbone bus
The byte offset will be aligned to D32
The value is a 32 bit integer
"""
x = c_int(value)
cc = self.lib.vv_write(self.handle, byte_offset, byref(x), 4)
if cc != 0:
raise BusException("Failed vv_write: offset:0x%X value:%d" % (byte_offset, value))
return cc
def vv_write_array(self, byte_offset, buf, size):
""" Write an array of data from the string array buf
size is the number of bytes to write aligned D32
"""
cc = self.lib.vv_write(self.handle, byte_offset, id(buf), size)
if cc != 0:
raise BusException("Failed vv_write_array: offset:0x%X size:%d" % (byte_offset, size))
return cc
def vv_read(self, byte_offset):
""" Read from the application FPGA wishbone bus
The byte offset will be aligned to D32
The value will contain the 32 bit integer read
"""
x = c_int(0)
cc = self.lib.vv_read(self.handle, byte_offset, byref(x), 4)
value = x.value
if cc != 0:
raise BusException("Failed vv_read: offset:0x%X" % (byte_offset))
return value & 0xFFFFFFFF
def vv_read_array(self, byte_offset, buf, size):
""" Read size bytes into the string array buf
The byte_offset and size will be D32 aligned
"""
cc = self.lib.vv_read(self.handle, byte_offset, id(buf), size)
if cc != 0:
raise BusException("Failed vv_read_array: offset:0x%X size:%d" % (byte_offset, size))
return cc
def vv_irqwait(self):
""" Wait for an interrupt
An ISR is installed and reads the interrupt source register from the FPGA application
If no interrupt occurs after one second the return is -1 and errno is ETIME
"""
x = c_int(0)
cc = self.lib.vv_irqwait(self.handle, byref(x))
irq_src = x.value
if cc != 0:
raise BusException("Failed vv_irqwait: No interrupt")
return irq_src
class PCI(object):
def __init__(self,lun):
""" The pciio driver lun (logical unit).
"""
self.lib = CDLL('./libvv_pts.so')
int = 0
if type(lun) == type(int):
self.lun = lun
else:
self.lun = int
raise BusWarning("Warning: PCI __init__: Bad lun, default to 0")
class SKT(object):
def __init__(self,lun):
""" Telnet access over a socket to ELMA I2C bus
"""
int = ELMASLOT
if type(lun) == type(int):
self.lun = lun
else:
self.lun = int
raise BusWarning("Warning: SKT __init__: Bad lun=(slot), default to %s" % int)
self.base = 0;
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ELMAIP, 23))
s.recv(256)
s.send("admin\r\n")
s.recv(256)
s.send(ELMAPWD + "\r\n")
s.recv(256)
self.handle = s
# get crate firmware version, to apply proper address in readreg/writereg
self.handle.send("version\r\n")
ver = self.handle.recv(256)
pos = ver.find("Software version")
if (pos == -1):
print("Unexpected response from \"version\" command, exiting...")
self.close()
sys.exit(2)
ver = float(ver[pos+17:pos+21])
self.ver = ver
def vv_write(self, byte_offset, value):
""" Write to the application FPGA via ELMA telnet
The byte offset will be aligned to D32
The value is a 32 bit integer
"""
try:
cm = "writereg %d %x %x\r\n" % (self.lun, byte_offset, value)
if (self.ver < 2.27):
rn = byte_offset/4 + 1
cm = "writereg %d %d %x\r\n" % (self.lun,rn,value)
#print "vv_write:Debug:cm:%s\n" % (cm)
self.handle.send(cm)
except Exception as e:
msg = "vv_write: No reply from register at address 0x%03x " % (byte_offset)
raise BusException(msg)
return self.handle.recv(256).find("Done")
def vv_read(self, byte_offset):
""" Read from the application FPGA via ELMA telnet
The byte offset will be aligned to D32
The value will contain the 32 bit integer read
"""
try:
cm = "readreg %d %x\r\n" % (self.lun, byte_offset)
if (self.ver < 2.27):
rn = byte_offset/4 + 1
cm = "readreg %d %d\r\n" % (self.lun,rn)
#print "vv_read:Debug:cm:%s\n" % (cm)
self.handle.send(cm)
orig = self.handle.recv(256)
rp = orig
rp = rp.split(" ")[3]
rp = rp.split("\n")[0]
rp = int(rp,16)
except Exception as e:
msg = "vv_read: No reply from register at address 0x%03x " % (byte_offset)
raise BusException(msg)
return rp
def vv_load(self):
""" Load the FPGA, its sort of a NO-OP in SKT class
"""
bid = self.vv_read(BIDR)
bid = binascii.unhexlify("%s" % "{0:x}".format(bid))
if bid in BIDR_ARR:
return 0
else:
raise BusException("Failed vv_load: FPGA: Bad board ID: %s" % bid)
return 2
def vv_init(self):
""" Init the library, its a NO-OP in SKT class
"""
return self.handle
def vv_close(self):
""" Close the socket
"""
self.handle.shutdown(SHUT_RDWR)
self.handle.close()
self.handle = 0
return 0
#!/usr/bin/python
import sys
from subprocess import *
from string import Template
sys.argv[1] = sys.argv[1].lower()
try:
with open("ubuntu/%s/pyts/ptsdefine.py" % (sys.argv[1]), "r+") as f:
buf = f.read()
buf = Template(buf)
buf = buf.substitute(BOARD=sys.argv[1], ELMAIP=sys.argv[2], ELMAPWD=sys.argv[3], ELMASLOT=sys.argv[4])
f.seek(0)
f.write(buf)
with open("ubuntu/%s/shell/get-fan-speeds" % (sys.argv[1]), "r+") as f:
buf = f.read()
buf = Template(buf)
buf = buf.substitute(ELMAIP=sys.argv[2], ELMAPWD=sys.argv[3])
f.seek(0)
f.write(buf)
with open("ubuntu/%s/shell/men-on" % (sys.argv[1]), "r+") as f:
buf = f.read()
buf = Template(buf)
buf = buf.substitute(ELMAIP=sys.argv[2], ELMAPWD=sys.argv[3])
f.seek(0)
f.write(buf)
with open("ubuntu/%s/shell/men-off" % (sys.argv[1]), "r+") as f:
buf = f.read()
buf = Template(buf)
buf = buf.substitute(ELMAIP=sys.argv[2], ELMAPWD=sys.argv[3])
f.seek(0)
f.write(buf)
except IndexError:
print("ERROR: Are you sure you give all the makefile variables as input?")
raise
#!/bin/bash
xc3sprog -c xpc flash_load.bit
xc3sprog -c xpc -I golden-v0.0_release-v1.0.bin:w:0:bin
#!/bin/bash
echo Get ELMA fan speeds and store them in log/fan-speeds
rm -f ../log/fan-speeds
snmpwalk -v2c -c $ELMAPWD $ELMAIP 1.3.6.1.4.1.37968.1.1.5.2.1.3 > ../log/fan-speeds
#!/bin/bash
echo Power OFF ELMA crate
snmpset -v2c -c $ELMAPWD $ELMAIP 1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 1
#!/bin/bash
echo Power ON ELMA crate
snmpset -v2c -c $ELMAPWD $ELMAIP 1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 0
#!/bin/bash
xc3sprog -c xpc pts.bit
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment