from __future__ import division
from builtins import str
from builtins import hex
from builtins import range
__author__ = 'lessju'
from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
from time import sleep
import logging
import os
[docs]
class TpmCpld(FirmwareBlock):
""" FirmwareBlock tests class """
@compatibleboards(BoardMake.TpmBoard)
@friendlyname('tpm_cpld')
@maxinstances(1)
def __init__(self, board, **kwargs):
""" TpmCpld initialiser
:param board: Pointer to board instance
"""
super(TpmCpld, self).__init__(board)
self.board_type = kwargs.get('board_type', 'XTPM')
self._cpld_fw_date_add = 0x30000000
#######################################################################################
[docs]
def get_version(self):
version = hex(self.board[self._cpld_fw_date_add])
return version
[docs]
def cpld_flash_read(self, bitfile="cpld_dump.bit"):
""" Read CPLD FLASH """
dump = []
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x74) #
self.cpld_efb_wr(0x08) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
time.sleep(0.001)
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x46)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
for n in range(9212):
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x73)
self.cpld_efb_wr(0x10)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
while self.board[0x90000000 + 0x72 * 4] & 0x8 == 0x8:
pass
for m in range(16):
while True:
rd = self.board[0x90000000 + 0x72 * 4]
if rd & 0x8 != 0:
pass
else:
break
dump.append(self.board[0x90000000 + 0x73 * 4])
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
if n % 1000 == 0:
logging.info("Reading CPLD config frame {}/9212".format(str(n)))
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x26)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
# Save flash contents to file
with open(bitfile, "wb") as f:
f.write(bytearray(dump))
return bytearray(dump)
[docs]
def cpld_flash_write(self, bitfile):
""" Write bitfile to CPLD FLASH """
logging.info("Writing {} to CPLD flash".format(bitfile))
with open(bitfile, "rb") as f:
dump = bytearray(f.read())
start_idx = -1
for n in range(len(dump) - 8):
if dump[n] == 0xFF and dump[n + 1] == 0xFF and dump[n + 2] == 0xBD and dump[n + 3] == 0xB3:
start_idx = n
break
if start_idx == -1:
logging.error("Invalid CPLD bitfile. Start word not found!")
return False
if start_idx > 0:
dump = dump[start_idx:]
dump = dump[:10] + dump[10 + 8:]
if len(dump) % 16 != 0:
dump = dump + bytearray([0xFF] * (16 - len(dump) % 16))
# Enable configuration access
logging.info("Enabling CPLD configuration access")
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x74) #
self.cpld_efb_wr(0x08) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
time.sleep(0.001)
# Erase flash
logging.info("Erasing Flash")
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x0E) #
self.cpld_efb_wr(0x04) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
# FLASH status check
while True:
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0xF0) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
rd = self.board[0x90000000 + 0x73 * 4]
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
if rd == 0:
break
else:
logging.info("CPLD status register: {}".format(hex(rd)))
time.sleep(0.2)
# Init Address
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x46)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
nof_frame = len(dump) // 16
idx = 0
logging.info("Write configuration flash")
for n in range(nof_frame):
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x70)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
for m in range(16):
self.cpld_efb_wr(dump[idx])
idx += 1
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
if n % 1000 == 0:
logging.info("Writing CPLD config frame {}/{}".format(n, nof_frame))
while True:
# status check
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0xF0) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
self.cpld_efb_wr(0x00) #
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
rd = self.board[0x90000000 + 0x73 * 4]
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
if rd == 0:
break
else:
logging.info("CPLD status register: {}".format(hex(rd)))
time.sleep(0.2)
# Program done
logging.info("Programming Done")
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x5E)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
time.sleep(0.01)
# disable configuration access
logging.info("Disable CPLD configuration access")
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x26)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
# Bypass
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.cpld_efb_wr(0xFF) #
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
# Verify bitstream
readback_dump = self.cpld_flash_read()
for n in range(len(dump)):
if readback_dump[n] != dump[n]:
logging.error("CPLD Verify Flash error! Address {}".format(str(n)))
logging.error("CPLD doesn't have a good bitstream, it will not boot!")
logging.error(
"Write a valid bistream into the Flash before rebooting, otherwise you will need to use then JTAG!")
os.remove("cpld_dump.bit")
return False
# Remove temporary file
os.remove("cpld_dump.bit")
# Refresh
self.board[0x90000000 + 0x70 * 4] = 0x80 # enable wishbone connection
self.cpld_efb_wr(0x79)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
self.cpld_efb_wr(0x00)
# This command will refresh the board so there will be no reply. Catch
# execption and ignore
try:
self.board[0x90000000 + 0x70 * 4] = 0x0 # disable wishbone connection
except:
pass
# Give the board some time to reset
sleep(1)
while self.board[0x90000000 + 0x72 * 4] & 0x20 == 0:
pass
# Check CPLD firmware version, if it's that of the golden firmware then
# this did not work properly (or bitfile is invalid)
if self.board[0x30000000] == 0xDEAD0001:
raise PluginError("TpmCpld: CPLD firmware download failed, golden firmware loaded")
logging.info("CPLD bitstream update done!")
return True
[docs]
def cpld_efb_wr(self, dat):
""" CPLD EFB write """
while self.board[0x90000000 + 0x72 * 4] & 0x10 == 0x10:
pass
self.board[0x90000000 + 0x71 * 4] = dat
[docs]
def eep_rd8(self, offset):
""" Read 8-bit value from EEP ROM """
i2c_data = offset & 0xFF
return self.board.tpm_i2c.read(i2c_add=0xA0,
nof_wr_byte=1,
nof_rd_byte=1,
wr_data=i2c_data)
[docs]
def eep_wr8(self, offset, data):
""" Write 8-bit value to EEP ROM """
i2c_data = (data & 0xFF) << 8 + (offset & 0xFF)
self.board.tpm_i2c.read(i2c_add=0xA0,
nof_wr_byte=2,
nof_rd_byte=0,
wr_data=i2c_data)
return
[docs]
def eep_rd32(self, offset):
""" Read 32-bit value from EEP ROM """
rd = 0
for n in range(4):
rd = rd << 8
rd = rd | self.eep_rd8(offset + n)
return rd
[docs]
def eep_wr32(self, offset, data):
""" Write 32-bit value to EEP ROM """
for n in range(4):
self.eep_wr8(offset + n, (data >> 8 * (3 - n)) & 0xFF)
return
##################### Superclass method implementations ###############################
[docs]
def initialise(self):
""" Initialise TpmCpld """
logging.info("TpmCpld has been initialised")
return True
[docs]
def status_check(self):
""" Perform status check
:return: Status
"""
logging.info("TpmCpld : Checking status")
return Status.OK
[docs]
def clean_up(self):
""" Perform cleanup
:return: Success
"""
logging.info("TpmCpld : Cleaning up")
return True