Source code for pyfabil.plugins.tpm_1_6.progflash

__author__ = 'Bubs'

from pyfabil.plugins.firmwareblock import FirmwareBlock
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
import logging
import time

FIFOSIZE = 1024
PAGESIZE = 256
SPICLK = 13000000


[docs] class FlasdhDev: def __init__(self, name="", description="", jedecID=0, pageSize = 0, sectorSize=0, sectorCount=0, slaveID=0): self.name = name self.description = description self.jedecID = jedecID self.pageSize = pageSize self.sectorSize = sectorSize self.sectorCount = sectorCount self.slaveID = slaveID
FlashDevice_CPLD = FlasdhDev(name="Flash_CPLD", description="macronix,mx25r32", jedecID=0xc22816, pageSize=256, sectorSize=64 * 1024, sectorCount=64, slaveID=0x00000000) FlashDevice_FPGA1 = FlasdhDev(name="Flash_FPGA1", description="micron,n25q256a", jedecID=0x20BA19, pageSize=256, sectorSize=64 * 1024, sectorCount=512, slaveID=0x00000001) FlashDevice_FPGA2 = FlasdhDev(name="Flash_FPGA2", description="micron,n25q256a", jedecID=0x20BA19, pageSize=256, sectorSize=64 * 1024, sectorCount=512, slaveID=0x00000002) FlashDevices=[FlashDevice_CPLD,FlashDevice_FPGA1,FlashDevice_FPGA2]
[docs] class Tpm_1_6_ProgFlash(FirmwareBlock): """ TPM Plugin for CPLD and FPGA SPI Flash bitfile storage/access class """ @compatibleboards(BoardMake.Tpm16Board) @friendlyname('tpm_progflash') @maxinstances(1) def __init__(self, board, **kwargs): """ SPI4Flash initialiser :param board: Pointer to board instance """ super(Tpm_1_6_ProgFlash, self).__init__(board) self._board_type = kwargs.get('board_type', 'XTPM') self.add4bytemode = False ####################################################################################### # ##################### SPI METHODS SECTION ###############################
[docs] def spi_chipselect(self,isactive): self.board["board.regfile.spi_cs.cs0"] = 1
[docs] def spi_resetfifo(self): self.board["board.regfile.spi_fifo_addr"] = 0
[docs] def spi_trigger(self,length): self.board["board.regfile.spi_tx_byte"] = length
[docs] def spi_config(self,spi_cs_ow): self.board["board.regfile.spi_cs.ow"] = spi_cs_ow
[docs] def spi_rx_available(self): tmp = self.board["board.regfile.spi_rx_byte"] return tmp
[docs] def spi_tx_remaining(self): tmp = self.board["board.regfile.spi_rx_byte"] return tmp
[docs] def spi_sync(self, slaveid, tx_buffer, cmd, length): _length = length self.spi_chipselect(False) if length >= 256: formatted_cmd = list(struct.unpack_from('I' * int(len(cmd) // 4), cmd)) tx_buffer = formatted_cmd + tx_buffer self.board["board.confspi.rxtx_buffer"] = tx_buffer[0: (260 // 4)] self.spi_trigger(260) while True: remaining = self.spi_tx_remaining() if remaining <= 0: break self.spi_resetfifo() ba = self.board.memory_map['board.confspi.rxtx_buffer'].address rxbuffer = self.board.read_address(ba, (260//4)) self.spi_chipselect(True) self.spi_resetfifo() return rxbuffer[1:] elif length<4: formatted_cmd = list(struct.unpack_from('I' * int(len(cmd) // 4), cmd)) tx_buffer = formatted_cmd + tx_buffer self.board["board.confspi.rxtx_buffer"] = tx_buffer[0: length * 4] self.spi_trigger(length) while True: remaining = self.spi_tx_remaining() if remaining <= 0: break self.spi_resetfifo() ba = self.board.memory_map['board.confspi.rxtx_buffer'].address rxbuffer = self.board.read_address(ba, 2) self.spi_chipselect(True) self.spi_resetfifo() return rxbuffer[0] else: formatted_cmd = list(struct.unpack_from('I' * int(len(cmd) // 4), cmd)) tx_buffer = formatted_cmd + tx_buffer self.board["board.confspi.rxtx_buffer"] = tx_buffer[0: length // 4] self.spi_trigger(length) while True: remaining = self.spi_tx_remaining() if remaining <= 0: break self.spi_resetfifo() ba = self.board.memory_map['board.confspi.rxtx_buffer'].address rxbuffer = self.board.read_address(ba, length//4) self.spi_chipselect(True) self.spi_resetfifo() if (cmd[0] & 0xff) == 0x9F: return rxbuffer
[docs] def spi_mux_selection(self, slaveid): self.board["board.regfile.spi_mux"] = slaveid
# ########## FLASH COMMAND METHODS SECTION ####################################
[docs] def SPITransaction(self, device, TxBuffer, cmd, size): return self.spi_sync(device.slaveID, TxBuffer, cmd, size)
[docs] def FlashDevice_readReg(self, device, reg): cmd = bytearray(4) tx_buffer = [0] * 4 cmd[0] = reg cmd[1] = 0 rx_buffer = self.SPITransaction(device, tx_buffer, cmd, 2) return (rx_buffer & 0xFF00) >> 8
[docs] def FlashDevice_writeReg(self, device, reg, value=None): cmd = bytearray(4) tx_buffer = [0] * 4 cmd[0] = reg if value is None: self.SPITransaction(device, tx_buffer, cmd, 1) else: cmd[1] = value self.SPITransaction(device, tx_buffer, cmd, 2)
[docs] def FlashDevice_prepareCommand(self, command, address, device): tx_buffer = bytearray(4) tx_buffer[0] = command tx_buffer[1] = (address >> 16) & 0xFF tx_buffer[2] = (address >> 8) & 0xFF tx_buffer[3] = address & 0xFF return tx_buffer
[docs] def FlashDevice_Enter4byteAddMode(self, device): self.add4bytemode = True self.FlashDevice_writeReg(device, 0x06) # write enable command self.FlashDevice_writeReg(device, 0xC5, 0xf) while True: sr = self.FlashDevice_readReg(device, 0xc8) if(sr & 0x01) == 1: break self.FlashDevice_writeReg(device, 0x06) # write enable command
[docs] def FlashDevice_Exit4byteAddMode(self, device): self.add4bytemode=False self.FlashDevice_writeReg(device, 0x06) # write enable command self.FlashDevice_writeReg(device, 0xC5, 0x0) while True: sr = self.FlashDevice_readReg(device, 0xc8) if(sr & 0x01) == 0: break self.FlashDevice_writeReg(device, 0x06) # write enable command
[docs] def FlashDevice_writeEnable(self, device): self.FlashDevice_writeReg(device, 0x06)
[docs] def FlashDevice_writeDisable(self, device): self.FlashDevice_writeReg(device, 0x04)
[docs] def FlashDevice_waitTillReady(self, device): while True: sr = self.FlashDevice_readReg(device, 0x05) if(sr & 0x01) == 0: break
[docs] def FlashDevice_readIdentification(self, device): tx_buffer = [0] * 32 cmd = bytearray(4) cmd[0] = 0x9F rx_buffer = self.SPITransaction(device, tx_buffer, cmd, 12) id = ((rx_buffer[0] & 0xFF000000) >> 24) | ((rx_buffer[0] & 0xFF0000) >> 8) | ((rx_buffer[0] & 0xFF00) << 8) return id
[docs] def FlashDevice_readPage(self, device, address, size): tx_buffer = [0] * 512 if size > device.pageSize: print("FlashDevice_readPage size > pageSize!") return -1 buffer = self.FlashDevice_prepareCommand(0x03, address, device) rx_buffer = self.SPITransaction(device, tx_buffer, buffer, size + 4) return rx_buffer
[docs] def FlashDevice_readsector(self, device, address): rxbuffer = [] page_size = device.pageSize num_of_pages = device.sectorSize // page_size for i in range(0, num_of_pages): rxbuff = self.FlashDevice_readPage(device, address+i*page_size, page_size) rxbuffer = rxbuffer+rxbuff return rxbuffer
[docs] def FlashDevice_eraseSector(self, device, address): self.FlashDevice_writeEnable(device) self.FlashDevice_waitTillReady(device) txBuffer = [0]*4 buff = self.FlashDevice_prepareCommand(0xD8, address, device) if device.slaveID != 0 and address >= 0x01000000: self.FlashDevice_Enter4byteAddMode(device) self.SPITransaction(device, txBuffer, buff, 4) self.FlashDevice_Exit4byteAddMode(device) else: self.SPITransaction(device, txBuffer, buff, 4) self.FlashDevice_waitTillReady(device)
[docs] def FlashDevice_erase(self, device, address, size): stop = address + size while True: self.FlashDevice_eraseSector(device, address) address += device.sectorSize if address >= stop: break self.FlashDevice_writeDisable(device)
[docs] def FlashDevice_chiperase(self, device): self.FlashDevice_writeEnable(device) self.FlashDevice_waitTillReady(device) self.FlashDevice_writeReg(device, 0xC7) self.FlashDevice_waitTillReady(device)
[docs] def FlashDevice_writePage(self, device, address, size, buffer): if size > device.pageSize: print("FlashDevice_writePage size > pageSize!") return -1 buff = self.FlashDevice_prepareCommand(0x02, address, device) self.FlashDevice_writeEnable(device) rxBuffer = self.SPITransaction(device, buffer, buff, size + 4) self.FlashDevice_waitTillReady(device)
[docs] def FlashDevice_writesector(self, device, address, buffer): page_size = device.pageSize page_offset = address & (device.pageSize - 1) num_of_pages=device.sectorSize // page_size for i in range (0,num_of_pages): self.FlashDevice_writePage(device, address + i * page_size, page_size, buffer[i * page_size // 4:i * page_size // 4 + page_size // 4])
# ########## BITSTREAM MANAGE METHODS SECTION ####################################
[docs] def loadBitstream(self, filename, sectorSize): print ("Open Bistream file %s" %filename) with open(filename, "rb") as f: dump = bytearray(f.read()) bitstreamSize = len(dump) sc = bitstreamSize // sectorSize if ((sc * sectorSize) != bitstreamSize): sc = sc + 1 print("Loading %s (%d bytes) = %d * %d bytes sectors" % (filename, bitstreamSize, sc, sectorSize)) s = sc * sectorSize tmp=bytearray(s) for i in range(0, bitstreamSize): tmp[i] = dump[i] for i in range(0, s-bitstreamSize): tmp[i+bitstreamSize] = 0xff return tmp, bitstreamSize, s
[docs] def saveBitstream(self, filename, memblock, bitstreamSize): f = open(filename, "wb") print ("Writing %d bytes to %s" % (bitstreamSize, filename)) l = len(memblock) data = bytearray(l*4) print ("lenght of array to be written: %d, in byte %d" % (l, l*4)) bytecount=0 for i in range(0, l): data[bytecount+0] = memblock[i] & 0xff data[bytecount+1] = (memblock[i] & 0xff00) >> 8 data[bytecount+2] = (memblock[i] & 0xff0000) >> 16 data[bytecount+3] = (memblock[i] & 0xff000000) >> 24 bytecount += 4 f.write(data[0:bitstreamSize]) f.close()
[docs] def firmwareProgram(self, flashdeviceindedx, bitstreamFilename, address, dumpFilename=None, erase_all=False, erase_size=None, add_len=False): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) sectorSize = device.sectorSize sectorSize_w = sectorSize//4 sectorOffset = address//sectorSize memblock1, bitstreamSize, size = self.loadBitstream(bitstreamFilename, sectorSize) if add_len: logging.debug("Prepending bitsream size in flash writing") lght = bytearray(4) lght[0] = (size & 0xff000000) >> 24 lght[1] = (size & 0xff0000) >> 16 lght[2] = (size & 0xff00) >> 8 lght[3] = (size & 0xff) memblock = lght+memblock1 size = size+4 else: memblock = memblock1 sector_num = (size//sectorSize) if erase_size != None: sector_erase_num = (erase_size//sectorSize) else: sector_erase_num = sector_num end_sector_offset = sector_num + sectorOffset # Read bitfile and cast as a list of unsigned integers formatted_bitstream = list(struct.unpack_from('I' * (len(memblock) // 4), memblock)) bufferD = [] remaining = size i = sectorOffset j = 0 ec = 0 if not erase_all: logging.info("Starting Erase from sector %d" % sector_erase_num) logging.info( "--- ERASING ------------------------------------------------------------------------------------") sect = sector_erase_num while True: print("Sector %03d @ %08X: Erasing" % (sect, sect * sectorSize)) self.FlashDevice_erase(device, sect * sectorSize, sectorSize) sect -= 1 if sect == 0: break else: logging.info("Starting Chip Erase ") logging.info( "--- ERASING ------------------------------------------------------------------------------------") self.FlashDevice_chiperase(device) logging.debug("Starting programming from sector %d" % (sectorOffset)) logging.debug( "--- PROGRAMMING ------------------------------------------------------------------------------------") sect = 0 upper_flash=False while (1): off = j * sectorSize logging.debug("Sector %03d @ %08X - bitstream offset %08X: " % (i, i * sectorSize, off)) # print "E ", # self.FlashDevice_erase(device, i * sectorSize, sectorSize) c = 0 # for k in range (0,sectorSize): # bufferO[k]=memblock[k+off] if upper_flash is False and (i * sectorSize) >= 0x1000000: upper_flash = True self.FlashDevice_Enter4byteAddMode(device) logging.info("W ", ) b=formatted_bitstream[(j * sectorSize_w):((j * sectorSize_w) + sectorSize_w)] self.FlashDevice_writesector(device, i * sectorSize, b ) logging.info("V") bufferI = self.FlashDevice_readsector(device, i * sectorSize) # bufferI=self.FlashDevice_read(device, i * sectorSize, sectorSize) bufferD = bufferD+bufferI # for k in range (0,sectorSize): # bufferD[k+off]=bufferI[k] c = 0 # formatted_data=list(struct.unpack_from('I' * (sectorSize / 4), bufferO)) for k in range (0, sectorSize//4): if b[k] != bufferI[k]: c += 1 print("Error detected in verify @ offset %x: expected %x, read %x" % (k, b[k], bufferI[k])) break if c != 0: retry = 2 counterr = 0 while retry > 0: logging.info("Error detected, retring to write sector") print("Sector %03d @ %08X: Erasing" % (i, i * sectorSize)) self.FlashDevice_erase(device, i * sectorSize, sectorSize) logging.info("W ") # b=formatted_bitstream[(j * sectorSize_w):((j * sectorSize_w) +sectorSize_w)] self.FlashDevice_writesector(device, i * sectorSize, b) logging.info("V") bufferI = self.FlashDevice_readsector(device, i * sectorSize) # bufferI=self.FlashDevice_read(device, i * sectorSize, sectorSize) bufferD = bufferD + bufferI counterr = 0 for k in range(0, sectorSize // 4): if b[k] != bufferI[k]: counterr += 1 logging.info("Error detected in verify @ offset %x: expected %x, read %x" % ( k, formatted_bitstream[(j * sectorSize_w) + k], bufferI[k])) retry -= 1 break if counterr == 0: break if counterr != 0 and retry == 0: logging.info("Impossible to write bitstream in flash device %d" % flashdeviceindedx) exit() ec += c j += 1 i += 1 sect += 1 if sect == sector_num: break logging.info( "----------------------------------------------------------------------------------------------------") if self.add4bytemode: upper_flash = False self.FlashDevice_Exit4byteAddMode(device) if dumpFilename is not None: self.saveBitstream(dumpFilename, bufferD, bitstreamSize) return ec
""" def firmwareVerify(self,flashdeviceindedx,bitstreamFilename,address,dumpFilename=None): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) sectorSize=device.sectorSize sectorOffset = address/sectorSize memblock,bitstreamSize,size = self.loadBitstream(bitstreamFilename, sectorSize) bufferO = bytearray(sectorSize) bufferD = []#bytearray(size) remaining = size i = sectorOffset j = 0 ec = 0 print("Starting verify from sector %d" %sectorOffset) print("--- VERIFYING ------------------------------------------------------------------------------------\n") while (remaining > 0): off = j * sectorSize print("Sector %03d @ %08X - bitstream offset %08X: " %(i, i * sectorSize, off)) c = 0 for k in range(0,sectorSize): bufferO[k]=memblock[k+off] print"V", bufferI=self.FlashDevice_read_sector(device, i * sectorSize, sectorSize) bufferD=bufferD+bufferI formatted_data=list(struct.unpack_from('I' * (sectorSize / 4), bufferO)) for k in range (0, sectorSize/4): if formatted_data[k] != bufferI[k]: c+=1 print("Error detected in verify @ offset %x: expected %x, read %x" %(k,formatted_data[k]),bufferI[k]) ec+=c remaining -= sectorSize j+=1 i+=1 print("----------------------------------------------------------------------------------------------------\n"); errorCount = ec if (dumpFilename!= None): self.saveBitstream(dumpFilename, bufferD, bitstreamSize) return errorCount """
[docs] def firmwareRead(self, flashdeviceindedx, address, size, dumpFilename): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) sectorSize = device.sectorSize sectorOffset = address//device.sectorSize remaining = 0 bitstream_sectorsize = size//sectorSize bitstream_sectorsize += 1 bufferD = [] # bytearray(bitstream_sectorsize*sectorSize) # remaining = size remaining = bitstream_sectorsize * sectorSize i = sectorOffset j = 0 ec = 0 upper_flash = False logging.info("Starting Reading from sector %d" % sectorOffset) logging.info("--- READING ------------------------------------------------------------------------------------") while remaining > 0: off = j * sectorSize print("Sector %03d @ %08X - bitstream offset %08X: R" % (i, i * sectorSize, off)) c = 0 if upper_flash is False and address >= 0x1000000: upper_flash = True self.FlashDevice_Enter4byteAddMode(device) bufferI = self.FlashDevice_readsector(device, i * sectorSize) # for k in range (0,sectorSize): # bufferD[k+off]=bufferI[k] bufferD = bufferD+bufferI remaining -= sectorSize j += 1 i += 1 logging.info( "----------------------------------------------------------------------------------------------------") if self.add4bytemode is True: self.FlashDevice_Exit4byteAddMode(device) if dumpFilename is not None: self.saveBitstream(dumpFilename, bufferD, size)
[docs] def DeviceGetInfo(self, flashdeviceindedx): device = FlashDevices[flashdeviceindedx] return device
[docs] def DeviceGetID(self, flashdeviceindedx): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) id = self.FlashDevice_readIdentification(device) return id
[docs] def DeviceErase(self, flashdeviceindedx, address, size): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) self.FlashDevice_erase(device, address, size)
[docs] def DeviceEraseChip(self, flashdeviceindedx): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) self.FlashDevice_chiperase(device)
[docs] def DeviceWrite(self, flashdeviceindedx, address, txbuff, size): device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) data_size = len(txbuff) sectorSize = 64*1024 sectorOffset = address // sectorSize sc = data_size // sectorSize if (sc * sectorSize) != data_size: sc = sc + 1 s = sc * sectorSize tmp=bytearray(s) for i in range(0, data_size): tmp[i] = txbuff[i] for i in range(0, s-data_size): tmp[i+data_size] = 0xff formatted_bitstream = list(struct.unpack_from('I' * (len(tmp) // 4), tmp)) i = sectorOffset j = 0 sector_num = sc sect = 0 while True: self.FlashDevice_writesector(device, i * sectorSize, formatted_bitstream[j * sectorSize // 4:(j * sectorSize // 4 + sectorSize // 4)]) i = i+1 j += 1 sect += 1 if sect == sector_num: break
[docs] def Prog_FPGA_From_flash(self, flashdeviceindedx, fpga): # Check if connected if self.board.status[Device.Board] != Status.OK: raise LibraryError("TPM needs to be connected in order to program FPGAs") # Check if enabled (hw_ver >= 1.5) if self.board.hw_rev >= self.board.tpm_hw_rev_1_5: if self.board["board.regfile.enable.fpga"] == 0: logging.info("FPGAs power disabled. Enabling") self.board["board.regfile.enable.fpga"] = 1 time.sleep(0.1) else: logging.info("FPGAs power already enabled.") if self.board.hw_rev >= self.board.tpm_hw_rev_1_5: required_cpld_version = 0 # @TODO 0x17041801 else: required_cpld_version = 0x17041801 cpld_version = self.board["board.regfile.date_code"] # cpld_version = self[0x30000000] if cpld_version < required_cpld_version or cpld_version & 0xF0 == 0xB0: logging.error("CPLD firmware version is too old. Required version is " + hex(required_cpld_version)) raise LibraryError("CPLD firmware version is too old. Required version is " + hex(required_cpld_version)) # Disable C2C stream # self.board['board.regfile.c2c_stream_enable'] = 0x0 # Select FPGAs to program self.board.smap_deselect_fpga([0, 1]) self.board['board.smap.global'] = 0x3 # Erase FPGAs SRAM self.board.erase_fpga() device = FlashDevices[flashdeviceindedx] self.spi_mux_selection(device.slaveID) self.FlashDevice_writeReg(device, 0x06) # write enable command txBuffer = bytearray(16) address = 0x00000000 txBuffer[1] = (address >> 16) & 0xFF txBuffer[2] = (address >> 8) & 0xFF txBuffer[3] = address & 0xFF # read from flash logging.debug("Read from flash") self.board["board.regfile.spi_fifo_addr"] = 0 txBuffer[0] = 0x03 for i in range(5, 16): txBuffer[i] = i & 0x00 formatted_cmd = list(struct.unpack_from('I' * (len(txBuffer) // 4), txBuffer)) self.board["board.confspi.rxtx_buffer"] = formatted_cmd[0:len(formatted_cmd)] self.spi_trigger(8) while True: remaining = self.spi_tx_remaining() if remaining <= 0: break self.spi_resetfifo() ba = self.board.memory_map['board.confspi.rxtx_buffer'].address rxbuffer_rd = self.board.read_address(ba, 2) # self.spi_chipselect(True) self.spi_resetfifo() lenght = ((rxbuffer_rd[1] & 0xff) << 24) | ((rxbuffer_rd[1] & 0xff00) << 8) | ( (rxbuffer_rd[1] & 0xff0000) >> 16) | ((rxbuffer_rd[1] & 0xff000000) >> 24) logging.debug("Bitstream lenght" + hex(lenght)) txBuffer[0] = 0x0B formatted_cmd = list(struct.unpack_from('I' * int(len(txBuffer) // 4), txBuffer)) self.board["board.confspi.rxtx_buffer"] = formatted_cmd[0:len(formatted_cmd)] self.spi_config(0) self.spi_trigger(4) self.board['board.regfile.spi_route'] = 1 start = time.time() self.spi_trigger(lenght) timeout = lenght*8//SPICLK+5 while True: if self.board.is_programmed(): break now = time.time() if now-start > timeout: break self.board['board.regfile.spi_route'] = 1 self.spi_config(1) if self.board.is_programmed(): return 0 else: return -1
""" def FlashDevice_read(self,device,address,size): page_size = 0 rxBuffer=[] #rxBuffer=bytearray(size+4) page_offset = address & (device.pageSize - 1) #/* do all the bytes fit onto one page? */ if (page_offset + size <= device.pageSize): rxBuffer=self.FlashDevice_readPage(device, address, size) return rxBuffer else: bytecount=0 #/* the size of data remaining on the first page */ page_size = device.pageSize - page_offset bytecount=bytecount+page_size rxbuff1=self.FlashDevice_readPage(device, address, page_size) #for k in range(0,bytecount): rxBuffer=rxbuff1 #/* write everything in nor->page_size chunks */ for i in range(page_size,size,page_size): page_size = size - i if (page_size > device.pageSize): page_size = device.pageSize rxbuff2=self.FlashDevice_readPage(device, address + i, page_size) rxBuffer=rxBuffer+rxbuff2 return rxBuffer """ # #################### Superclass method implementations #################################
[docs] def initialise(self): """ Initialise TpmMcu """ logging.info("TpmMcu has been initialised") return True
[docs] def status_check(self): """ Perform status check :return: Status """ logging.info("TpmMcu : Checking status") return Status.OK
[docs] def clean_up(self): """ Perform cleanup :return: Success """ logging.info("TpmMcu : Cleaning up") return True