#! /usr/bin/env python # coding: utf8 # Copyright CERN, 2011 # Author: Matthieu Cattin # 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/') sys.path.append('../../fmceeprom/python/') # Import common modules from ptsexcept import * from fmc_eeprom import * import rr # Import specific modules from fmc_adc_spec import * from fmc_adc import * """ test23: Write IPMI information and calibration data to FMC EEPROM. This is done using gensdbfs tool. Serial number and calibration data are taken from text files. Note: Requires test00.py to run first to load the firmware! Requires test19.py to run before to get calibration data. """ def main (default_directory='.'): # Constants declaration TEST_NB = 23 EXPECTED_BITSTREAM_TYPE = 0x1 MANUFACTURER = "CERN" PRODUCT_NAME = "FmcAdc100m14b4cha" PART_NUMBER = "EDA-02063-V5-0" 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) 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" EEPROM_BIN_FILENAME = "eeprom_content.out" EEPROM_BIN_FILENAME = os.path.join(default_directory, EEPROM_BIN_FILENAME) EEPROM_SIZE = 8192 # in Bytes 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 print "Board's serial number: %s\n" % serial #================================================== # Calculate number of minutes since 0:00 1/1/96 current_date = datetime.datetime.now() ref_date = datetime.datetime(1996, 1, 1) 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)) #================================================== # Read calibration data from text file # 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): calibr_data.append(0xFF & int(line, 16)) calibr_data.append(0xFF & (int(line, 16) >> 8)) f_calibr.close() #print "Raw calibration data:" #for data in calibr_data: # print "0x%02X" % (data) #================================================== # 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() ################################################################################ # 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. # EEPROM clear code used to test the test! #eeprom_data = [0x0] * EEPROM_SIZE #fmc.sys_i2c_eeprom_write(eeprom_data) # Read entire EEPROM #print "Read EEPROM content." eeprom_data_read = fmc.sys_i2c_eeprom_read(0, EEPROM_SIZE) # Write EEPROM data to binary file #print "Write EEPROM content to file (binary)." 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() 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)) 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) # No manufacturing date present in EEPROM, put the current date 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 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 else: print("Valid manufacturing date found in EEPROM: %s (will be preserved)\n" % str(mfg_date)) #================================================== # Create Board Info Area # 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, ...) 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) #================================================== # Multirecords Area print("IPMI: Multi-record area") # output number, vnom, vmin, vmax, ripple, imin, imax 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 dcload = [ dcload0, dcload1, dcload2 ] # output number, vnom, vmin, vmax, ripple, imin, imax 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 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 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) #================================================== # Write ipmi content to a binary file print("Generate binary file with IPMI crap.\n") ipmi_open_file(IPMI_BIN_FILENAME) ipmi_set(bia, dcload, dcout, oem) ipmi_write() ipmi_close_file() #================================================== # Read impi content from binary file f_ipmi = open(IPMI_BIN_FILENAME, "rb") ipmi_data = [] byte = f_ipmi.read(1) # reads one byte while byte: ipmi_data.append(ord(byte)) byte = f_ipmi.read(1) # reads one byte f_ipmi.close() #print "Raw IPMI data:" #for add, data in enumerate(ipmi_data): # print "0x%02X(%3d): 0x%02X" % (add, add, data) #================================================== # Generate eeprom image with gensdbfs cmd = "gensdbfs " + SDBFS_DIR + " " + EEPROM_BIN_FILENAME print("Generate eeprom image, cmd: %s\n"%(cmd)) os.system(cmd) #================================================== # Erase EEPROM content print "Erase EEPROM content.\n" eeprom_data = [0x0] * EEPROM_SIZE fmc.sys_i2c_eeprom_write(eeprom_data) #================================================== # 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() #================================================== # 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("") #================================================== # Write content to EEPROM via I2C print "Write EEPROM content.\n" if eeprom_data != []: fmc.sys_i2c_eeprom_write(eeprom_data) #================================================== # Read back EEPROM content via I2C eeprom_data_read = fmc.sys_i2c_eeprom_read(0, len(eeprom_data)) mismatch = 0 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" mismatch += 1 print "0x%02X 0x%02X => %s" % (wr_data, rd_data, check) #print "0x%02X 0x%02X => %s" % (wr_data, rd_data, check) print "EEPROM content comparison => ", if(mismatch == 0): print "OK" else: print "FAILED" except FmcAdc100mOperationError as e: raise PtsError("Test failed: %s" % e) ########################################################################### 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) # Check if an error occured during EEPROM verification if(mismatch != 0): raise PtsError("EEPROM comparison failed: %d mismatch found. Check log for details." % mismatch) if __name__ == '__main__' : main()