test23.py 13.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!   /usr/bin/env   python
#    coding: utf8

# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 16/5/2012

# Import system modules
import sys
import time
import datetime
import os

# Add common modules and libraries location to path
sys.path.append('../../../')
sys.path.append('../../../gnurabbit/python/')
sys.path.append('../../../common/')
20
sys.path.append('../../fmceeprom/python/')
21 22 23

# Import common modules
from ptsexcept import *
24
from fmc_eeprom import *
25 26 27 28 29 30 31 32
import rr

# Import specific modules
from fmc_adc_spec import *
from fmc_adc import *


"""
33
test23: Write IPMI information and calibration data to FMC EEPROM.
34
        This is done using gensdbfs tool.
Matthieu Cattin's avatar
Matthieu Cattin committed
35
        Serial number and calibration data are taken from text files.
36 37

Note: Requires test00.py to run first to load the firmware!
Matthieu Cattin's avatar
Matthieu Cattin committed
38
      Requires test19.py to run before to get calibration data.
39 40 41 42 43 44 45
"""

def main (default_directory='.'):

    # Constants declaration
    TEST_NB = 23
    EXPECTED_BITSTREAM_TYPE = 0x1
46 47
    MANUFACTURER = "CERN"
    PRODUCT_NAME = "FmcAdc100m14b4cha"
48
    PART_NUMBER = "EDA-02063-V5-0"
49 50 51 52
    SERIAL_FILENAME = "../../../serial.txt"
    SERIAL_FILENAME = os.path.join(default_directory, SERIAL_FILENAME)
    CALIBR_FILENAME = "calibration_data.txt"
    CALIBR_FILENAME = os.path.join(default_directory, CALIBR_FILENAME)
53 54 55 56
    SDBFS_DIR = "sdbfs/"
    SDBFS_DIR = os.path.join(default_directory, SDBFS_DIR)
    IPMI_BIN_FILENAME = SDBFS_DIR + "ipmi.sdb"
    CALIBR_BIN_FILENAME = SDBFS_DIR + "calibration.sdb"
57 58
    EEPROM_BIN_FILENAME = "eeprom_content.out"
    EEPROM_BIN_FILENAME = os.path.join(default_directory, EEPROM_BIN_FILENAME)
59
    EEPROM_SIZE = 8192 # in Bytes
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92


    start_test_time = time.time()
    print "================================================================================"
    print "Test%02d start\n" % TEST_NB

    # SPEC object declaration
    print "Loading hardware access library and opening device.\n"
    spec = rr.Gennum()

    # Carrier object declaration (SPEC board specific part)
    try:
        carrier = CFmcAdc100mSpec(spec, EXPECTED_BITSTREAM_TYPE)
    except FmcAdc100mSpecOperationError as e:
        raise PtsCritical("Carrier init failed, test stopped: %s" % e)

    # Mezzanine object declaration (FmcAdc100m14b4cha board specific part)
    try:
        fmc = CFmcAdc100m(spec)
    except FmcAdc100mOperationError as e:
        raise PtsCritical("Mezzanine init failed, test stopped: %s" % e)


    ###########################################################################
    # Real test stuff here
    try:
        #==================================================
        # Read serial number from a file
        # This file must be written by the shell script launching pts
        f_serial = open(SERIAL_FILENAME, 'r+')
        serial = f_serial.readline()
        f_serial.close()
        serial = serial[:-1] # remove EOL char
93
        print "Board's serial number: %s\n" % serial
94 95 96

        #==================================================
        # Calculate number of minutes since 0:00 1/1/96
97
        current_date = datetime.datetime.now()
98
        ref_date = datetime.datetime(1996, 1, 1)
99 100 101 102
        diff_date = current_date - ref_date
        current_date_min = int(diff_date.total_seconds()//60)
        print("Current date/time: %s"%(str(current_date)))
        print(" -> 0x%06X = %d minutes (since 0:00 1/1/96)\n" % (current_date_min, current_date_min))
103 104

        #==================================================
105
        # Read calibration data from text file
106 107 108 109
        # This file must be written by the test performing the calibration
        f_calibr = open(CALIBR_FILENAME, 'r+')
        calibr_data = []
        for line in iter(f_calibr):
110 111
            calibr_data.append(0xFF & int(line, 16))
            calibr_data.append(0xFF & (int(line, 16) >> 8))
112
        f_calibr.close()
113

114 115 116
        #print "Raw calibration data:"
        #for data in calibr_data:
        #    print "0x%02X" % (data)
117

118 119 120 121 122 123 124 125
        #==================================================
        # Write calibration data to binary file
        # This file will be feed to gensdbfs
        f_bin_calibr = open(CALIBR_BIN_FILENAME, 'wb')
        for byte in calibr_data:
            f_bin_calibr.write(chr(byte))
        f_bin_calibr.close()

126
        ################################################################################
127 128 129
        # Check if a manufacturing date is present in the EEPROM.
        # If not, put the current date (it means it's the first time the test is run).
        # If a date is present, keep it.
130

131 132 133 134
        # EEPROM clear code used to test the test!
        #eeprom_data = [0x0] * EEPROM_SIZE
        #fmc.sys_i2c_eeprom_write(eeprom_data)

135
        # Read entire EEPROM
136
        #print "Read EEPROM content."
137 138
        eeprom_data_read = fmc.sys_i2c_eeprom_read(0, EEPROM_SIZE)

139
        # Write EEPROM data to binary file
140
        #print "Write EEPROM content to file (binary)."
141 142 143 144 145 146 147
        f_eeprom = open(EEPROM_BIN_FILENAME, "wb")
        for byte in eeprom_data_read:
            f_eeprom.write(chr(byte))
        f_eeprom.close()

        # Get manufacturing date from EEPROM data, if exists
        eeprom_data = open(EEPROM_BIN_FILENAME, "rb").read()
148 149 150 151 152
        mfg_date_min = ipmi_get_mfg_date(eeprom_data)
        ref_date = datetime.datetime(1996, 1, 1)
        mfg_date = ref_date + datetime.timedelta(minutes=mfg_date_min)
        print("Mfg date read from eeprom: %s"%(str(mfg_date)))
        print(" -> 0x%06X = %d minutes (since 0:00 1/1/96)\n"%(mfg_date_min, mfg_date_min))
153

154 155 156 157
        first_prod_date = datetime.datetime(2013, 3, 4)
        diff_date = first_prod_date - ref_date
        first_prod_date_min = int(diff_date.total_seconds()//60)

158
        # No manufacturing date present in EEPROM, put the current date
159 160 161 162 163 164
        if(mfg_date_min == 0 | mfg_date_min == 0xffffff):
            print("No manufacturing date found in the EEPROM => taking current date: %s\n" % str(current_date))
            mfg_date_min = current_date_min
        elif(mfg_date_min > current_date_min):
            print("Date found in the EEPROM is in the future => taking current date: %s\n" % str(current_date))
            mfg_date_min = current_date_min
165 166 167
        elif(mfg_date_min < first_prod_date_min):
            print("Date found in the EEPROM is older than the first production => taking current date: %s\n" % str(current_date))
            mfg_date_min = current_date_min
168
        else:
169
            print("Valid manufacturing date found in EEPROM: %s (will be preserved)\n" % str(mfg_date))
170 171 172

        #==================================================
        # Create Board Info Area
173 174
        # FRU field is used to store the date of generation of the eeprom content
        # This could be used later to determine if the content has to be udated (bug fix, ...)
175 176 177 178 179 180 181 182 183 184 185 186
        print("EEPROM content generation date: %s\n" % str(current_date))

        print("IPMI: Board Info Area")
        print(" - Mfg. Date/Time     : 0x%06X" % mfg_date_min)
        print(" - Board Manufacturer : %s" % MANUFACTURER)
        print(" - Board Product Name : %s" % PRODUCT_NAME)
        print(" - Board Serial Number: %s" % serial)
        print(" - Board Part Number  : %s" % PART_NUMBER)
        print(" - FRU File ID        : %s" % str(current_date))
        print("")
        fru = "%s" % str(current_date)
        bia = BoardInfoArea(mfg_date_min, MANUFACTURER, PRODUCT_NAME, serial, PART_NUMBER, fru)
187 188 189

        #==================================================
        # Multirecords Area
190
        print("IPMI: Multi-record area")
191

192
        # output number, vnom, vmin, vmax, ripple, imin, imax
193 194 195 196 197 198 199 200 201 202 203 204
        vnom=2.5; vmin=2.375; vmax=2.625; ripple=0.0; imin=0; imax=4000
        print(" - DC Load (VADJ): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcload0 = DCLoadRecord(0, vnom, vmin, vmax, ripple, imin, imax) # VADJ

        vnom=3.3; vmin=3.135; vmax=3.465; ripple=0.0; imin=0; imax=3000
        print(" - DC Load (P3V3): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcload1 = DCLoadRecord(1, vnom, vmin, vmax, ripple, imin, imax) # P3V3

        vnom=12.0; vmin=11.4; vmax=12.6; ripple=0.0; imin=0; imax=1000
        print(" - DC Load (P12V): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcload2 = DCLoadRecord(2, vnom, vmin, vmax, ripple, imin, imax) # P12V

205 206 207
        dcload = [ dcload0, dcload1, dcload2 ]

        # output number, vnom, vmin, vmax, ripple, imin, imax
208 209 210 211 212 213 214 215 216 217
        vnom=0.0; vmin=0.0; vmax=0.0; ripple=0.0; imin=0; imax=0
        print(" - DC Out (VIO_B_M2C): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcout0 = DCOutputRecord(3, vnom, vmin, vmax, ripple, imin, imax) # VIO_B_M2C

        print(" - DC Out (VREF_A_M2C): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcout1 = DCOutputRecord(4, vnom, vmin, vmax, ripple, imin, imax) # VREF_A_M2C

        print(" - DC Out (VREF_B_M2C): vnom=%2.3fV, vmin=%2.3fV, vmax=%2.3fV, ripple=%2.3fV, imin=%dmA, imax=%dmA"%(vnom, vmin, vmax, ripple, imin, imax))
        dcout2 = DCOutputRecord(5, vnom, vmin, vmax, ripple, imin, imax) # VREF_B_M2C

218 219 220 221 222 223 224 225 226 227 228 229 230
        dcout = [ dcout0, dcout1, dcout2 ]

        # module size  : 0=single width, 1=double width
        # P1 size      : 0=LPC, 1=HPC
        # P2 size      : 0=LPC, 1=HPC, 3=not fitted
        # clock dir    : 0=M2C, 1=C2M
        # nb sig P1 A  : number
        # nb sig P1 B  : number
        # nb sig P2 A  : number
        # nb sig P2 B  : number
        # nb GBT P1    : number
        # nb GBT P2    : number
        # max TCK freq : frequency in MHz
231 232 233 234
        size=0; p1_size=0; p2_size=3; clk_dir=0; sig_p1_a=68; sig_p1_b=0; sig_p2_a=0; sig_p2_b=0; gbt_p1=0; gbt_p2=0; tck=0
        print(" - OEM: Module Size=%d, P1 Connector Size=%d, P2 Connector Size=%d, Clock Direction=%d, \
P1 Bank A nb signal=%d, P1 Bank B nb signal=%d, P2 Bank A nb signal=%d, P2 Bank B nb signal=%d, P1 GBT nb=%d, P2 GBT nb=%d, TCK max freq=%d\n"%(size, p1_size, p2_size, clk_dir, sig_p1_a, sig_p1_b, sig_p2_a, sig_p2_b, gbt_p1, gbt_p2, tck))
        oem = OEMRecord(size, p1_size, p2_size, clk_dir, sig_p1_a, sig_p1_b, sig_p2_a, sig_p2_b, gbt_p1, gbt_p2, tck)
235 236

        #==================================================
237
        # Write ipmi content to a binary file
238
        print("Generate binary file with IPMI crap.\n")
239 240
        ipmi_open_file(IPMI_BIN_FILENAME)
        ipmi_set(bia, dcload, dcout, oem)
241 242 243
        ipmi_write()
        ipmi_close_file()

244
        #==================================================
245 246 247 248
        # Read impi content from binary file
        f_ipmi = open(IPMI_BIN_FILENAME, "rb")
        ipmi_data = []
        byte = f_ipmi.read(1) # reads one byte
249
        while byte:
250 251 252
            ipmi_data.append(ord(byte))
            byte = f_ipmi.read(1) # reads one byte
        f_ipmi.close()
253

254 255 256
        #print "Raw IPMI data:"
        #for add, data in enumerate(ipmi_data):
        #    print "0x%02X(%3d): 0x%02X" % (add, add, data)
257

258 259
        #==================================================
        # Generate eeprom image with gensdbfs
260
        cmd = "gensdbfs " + SDBFS_DIR + " " + EEPROM_BIN_FILENAME
261
        print("Generate eeprom image, cmd: %s\n"%(cmd))
262 263 264 265 266 267 268
        os.system(cmd)

        #==================================================
        # Erase EEPROM content
        print "Erase EEPROM content.\n"
        eeprom_data = [0x0] * EEPROM_SIZE
        fmc.sys_i2c_eeprom_write(eeprom_data)
269 270 271 272 273 274 275 276 277 278 279

        #==================================================
        # Read eeprom content from binary file
        f_bin_eeprom = open(EEPROM_BIN_FILENAME, "rb")
        eeprom_data = []
        byte = f_bin_eeprom.read(1) # reads one byte
        while byte:
            eeprom_data.append(ord(byte))
            byte = f_bin_eeprom.read(1) # reads one byte
        f_bin_eeprom.close()

280 281 282 283 284 285 286 287 288 289
        #==================================================
        # Dump EEPROM content to log
        print("Content to be written to the eeprom (length=0x%X (%d)):"%(len(eeprom_data), len(eeprom_data)))
        for i in range(len(eeprom_data)/16):
            print("0x%04X"%(i*16)),
            for j in range(16):
                print("%02X"%eeprom_data[(i*16)+j]),
            print("")
        print("")

290 291
        #==================================================
        # Write content to EEPROM via I2C
292
        print "Write EEPROM content.\n"
293 294
        if eeprom_data != []:
            fmc.sys_i2c_eeprom_write(eeprom_data)
295 296 297 298

        #==================================================
        # Read back EEPROM content via I2C
        eeprom_data_read = fmc.sys_i2c_eeprom_read(0, len(eeprom_data))
299
        mismatch = 0
300 301 302 303 304 305 306
        for i in range(len(eeprom_data)):
            wr_data = eeprom_data[i]
            rd_data = eeprom_data_read[i]
            if wr_data == rd_data:
                check = "OK"
            else:
                check = "FAILED"
307 308 309
                mismatch += 1
                print "0x%02X 0x%02X => %s" % (wr_data, rd_data, check)
            #print "0x%02X 0x%02X => %s" % (wr_data, rd_data, check)
310
        print "EEPROM content comparison => ",
311 312 313 314
        if(mismatch == 0):
            print "OK"
        else:
            print "FAILED"
315 316

    except FmcAdc100mOperationError as e:
317
        raise PtsError("Test failed: %s" % e)
318 319 320 321 322 323 324 325 326

    ###########################################################################

    print ""
    print "==> End of test%02d" % TEST_NB
    print "================================================================================"
    end_test_time = time.time()
    print "Test%02d elapsed time: %.2f seconds\n" % (TEST_NB, end_test_time-start_test_time)

327 328 329 330 331
    # Check if an error occured during EEPROM verification
    if(mismatch != 0):
        raise PtsError("EEPROM comparison failed: %d mismatch found. Check log for details." % mismatch)


332 333
if __name__ == '__main__' :
    main()