def read_flash(self, filename, loAddr, hiAddr, doStart): self.flashpin(1) # release uC hold on flash chip # create the output file outf = open(filename, "wb") # download the USER instruction to the FPGA to enable the JTAG circuitry self.initTAP() self.assert_state("Shift-IR") self.sendbs(self.USER1) # go to the SHIFT-DR state where the Flash interface circuitry can be controlled self.go_states(1,1,0,0) # -> UpdateIR -> SelectDRScan -> CaptureDR -> ShiftDR self.assert_state("Shift-DR") # download the instruction that gets the interface capabilities from the FPGA self.sendbs(INSTR_CAPABILITIES) # readback the capabilities of the interface self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR data = self.sendrecvbs(Bitstream(TDO_LENGTH, 0)) # check the capabilities to see if Flash reads are supported flashIntfcAlreadyLoaded = self.has_capability(data, CAPABLE_FLASH_READ_BIT) if self.verbose: print "CAPABILITIES = 0x%08x" % data # only download the Flash interface if this is the first upload of data from the Flash. # Otherwise the interface should already be in place. if doStart and not flashIntfcAlreadyLoaded: # configure the FPGA with the Flash interface circuit. print "Loading the FPGA with the Flash interface circuit" if not self.configure(self.board[2]): print "Error configuring FPGA with Flash programming circuit!" return False # download the USER instruction to the FPGA to enable the JTAG circuitry # that will be used to access the Flash self.initTAP() self.assert_state("Shift-IR") self.sendbs(self.USER1) # go to the SHIFT-DR state where the Flash interface circuitry can be controlled self.go_states(1,1,0,0) # -> UpdateIR -> SelectDRScan -> CaptureDR -> ShiftDR self.assert_state("Shift-DR") # download the instruction that gets the Flash organization from the FPGA self.sendbs(INSTR_FLASH_SIZE) # readback the widths of the Flash address and data buses self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") data = self.sendrecvbs(Bitstream(24, 0)) data = Bitstream(24, data) w256 = [(b << (i & 7)) for (i, b) in enumerate(data)] sizes = array.array('B', [sum(w256[i:i+8]) for i in range(0, len(w256), 8)]) dataWidth = sizes[0] addrWidth = sizes[1] blockAddrWidth = sizes[2] # address width of the block RAM that holds data to be written to Flash # stride is the number of byte addresses that are contained in each Flash word address stride = dataWidth / 8 # stride is 1,2,4 for data bus width of 8, 16 or 32 # address mask zeroes the lower bits of the byte address for alignment to the Flash word size addrMask = ~(stride - 1) if self.verbose: print "dataWidth =", dataWidth print "addrWidth =", addrWidth print "stride =", stride print "addrMask =", addrMask print "blockAddrWidth =", blockAddrWidth # check address and length of the upload byte address range to make sure it aligns with Flash word size if (hiAddr-loAddr+1) % stride: print "Cannot upload an odd number of bytes from multibyte-wide Flash!" return False if loAddr & ~addrMask: print "Cannot upload from multibyte-wide Flash using an odd byte-starting address!" return False print "Reading Flash contents into", filename # read blocks Flash and save them into the output file wordAddr = loAddr / stride # address of word in Flash numBytes = hiAddr - loAddr + 1 # number of bytes to upload to the hex file numWords = numBytes / stride # number of Flash words to upload if self.verbose: print "wordAddr = 0x%08x" % wordAddr print "numBytes =", numBytes print "numWords =", numWords # partition the word address into bytes and store in the operand storage area addr = Bitstream(addrWidth, wordAddr) # store the number of words that will be uploaded from Flash into the upload instruction operands cnt = Bitstream(addrWidth, numWords) # send the Flash upload instruction and the Flash address and upload length ##payload = cnt + addr + INSTR_FLASH_READ self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") ##self.sendrecvbs(payload) for d in INSTR_FLASH_READ: self.do_bit(tms = 0, tdi = d) for d in addr: self.do_bit(tms = 0, tdi = d) for (is_lastbit, d) in islast(cnt): self.do_bit(tms = is_lastbit, tdi = d) # now upload the data words from Flash self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") t = time.time() data = self.sendrecvbs(Bitstream(8 * numBytes, 0)) t = time.time() - t if self.verbose: print "Time to upload", 8 * numBytes, "bits =", elapsed(t) print "Transfer rate =", 8 * numBytes / t, "bps" # convert uploaded data from bitstream into a byte string data = Bitstream(8 * numBytes, data) w256 = [(b << (i & 7)) for (i, b) in enumerate(data)] databytes = array.array('B', [sum(w256[i:i+8]) for i in range(0, len(w256), 8)]) #.tostring() outf.write(databytes) outf.close() # close-up the output file self.flashpin(0) return True
def write_flash(self, bs, loAddr, doStart): self.flashpin(1) # release uC hold on Flash chip # download the USER instruction to the FPGA to enable the JTAG circuitry self.initTAP() self.assert_state("Shift-IR") self.sendbs(self.USER1) # go to the SHIFT-DR state where the Flash interface circuitry can be controlled self.go_states(1,1,0,0) # -> UpdateIR -> SelectDRScan -> CaptureDR -> ShiftDR self.assert_state("Shift-DR") # download the instruction that gets the interface capabilities from the FPGA self.sendbs(INSTR_CAPABILITIES) # readback the capabilities of the interface self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") data = self.sendrecvbs(Bitstream(TDO_LENGTH, 0)) # check the capabilities to see if Flash writes are supported flashIntfcAlreadyLoaded = self.has_capability(data, CAPABLE_FLASH_WRITE_BIT) # only download the Flash interface if this is the first download of data to the Flash. # otherwise the interface should already be in place. if doStart and not flashIntfcAlreadyLoaded: # configure the FPGA with the Flash interface circuit. print "Loading the FPGA with the Flash interface circuit" if not self.configure(self.board[2]): print "Error downloading Flash interface circuit!!" return False print # download the USER instruction to the FPGA to enable the JTAG circuitry # that will be used to access the Flash self.initTAP() self.assert_state("Shift-IR") self.sendbs(self.USER1) # go to the SHIFT-DR state where the Flash interface circuitry can be controlled self.go_states(1,1,0,0) self.assert_state("Shift-DR") # download the instruction that gets the Flash organization from the FPGA self.sendbs(INSTR_FLASH_SIZE) # readback the widths of the Flash address and data buses self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") data = self.sendrecvbs(Bitstream(24, 0)) data = Bitstream(24, data) w256 = [(b << (i & 7)) for (i, b) in enumerate(data)] sizes = array.array('B', [sum(w256[i:i+8]) for i in range(0, len(w256), 8)]) # convert to byte array dataWidth = sizes[0] addrWidth = sizes[1] blockAddrWidth = sizes[2] # address width of the block RAM that holds data to be written to Flash blockSize = 1 << blockAddrWidth blockAddrMask = ~(blockSize - 1) # stride is the number of byte addresses that are contained in each Flash word address stride = dataWidth / 8 # stride is 1,2,4 for data bus width of 8, 16 or 32 # address mask zeroes the lower bits of the byte address for alignment to the Flash word size addrMask = ~(stride - 1) if self.verbose: print "dataWidth =", dataWidth print "addrWidth =", addrWidth print "stride =", stride print "addrMask =", addrMask print "blockSize =", blockSize if doStart: # erase the flash chip print "Erasing Flash", sys.stdout.flush() self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") self.sendbs(INSTR_FLASH_ERASE) while True: self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") data = self.sendrecvbs(Bitstream(TDO_LENGTH, 0)) if self.verbose: print "erase result = 0x%08x" % data time.sleep(0.5) # simple progress indicator print ".", sys.stdout.flush() if data == OP_INPROGRESS: continue if data == OP_FAILED: print "Flash erase failed!!" return False break print # download to Flash print "Downloading data", sys.stdout.flush() address = loAddr # start byte address count = 0 # count of bytes written # load the whole file into a byte string for easier access #bits = bs.tostring() m = array.array('B', bs.tostring()) bits = array.array('B', [reverse_bits[c] for c in m.tolist()]).tostring() while count < len(bits): # fill buffer with next block from file buf = bits[count:count+blockSize] numBytes = len(buf) if numBytes % stride: # better pad the buffer with a few 0xFF bytes and proceed anyway... print "Cannot download an odd number of bytes to multibyte-wide Flash!" return False if address & ~addrMask: print "Cannot download to multibyte-wide Flash using an odd byte-starting address!" return False # download the buffer if self.verbose: print "address = 0x%08x" % address print "numBytes =", numBytes # store the number of words that will be downloaded to Flash into the download instruction operands numWords = numBytes / stride cnt = Bitstream(addrWidth, numWords) # adjust the byte starting address for the Flash word size wordAddr = address / stride # partition the word address into bytes and store in the operand storage area addr = Bitstream(addrWidth, wordAddr) # send the Flash download instruction and the Flash address and download length ##payload = cnt + addr + INSTR_FLASH_PGM self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") ##self.sendrecvbs(payload) #self.sendbs(INSTR_FLASH_PGM) #self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR #self.assert_state("Shift-DR") #self.sendbs(addr) #self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR #self.assert_state("Shift-DR") #self.sendbs(cnt) for d in INSTR_FLASH_PGM: self.do_bit(tms = 0, tdi = d) for d in addr: self.do_bit(tms = 0, tdi = d) for (is_lastbit, d) in islast(cnt): self.do_bit(tms = is_lastbit, tdi = d) # now download the data words to block RAM data = BitstreamString(buf) # len = 8 * numBytes self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") t = time.time() self.sendbs(data) t = time.time() - t if self.verbose: print "Time to download", 8 * numBytes, "bits =", elapsed(t) print "Transfer rate =", 8 * numBytes / t, "bps" # wait until the block RAM contents are programmed into the Flash while True: self.go_states(0,1,0) # -> PauseDR -> Exit2DR -> ShiftDR self.assert_state("Shift-DR") data = self.sendrecvbs(Bitstream(TDO_LENGTH, 0)) if self.verbose: print "block write result = 0x%08x" % data if data == OP_INPROGRESS: continue if data == OP_FAILED: print "Download failed!!" return False break # simple progress bar print ".", sys.stdout.flush() # compute the address for the next block address += numBytes count += numBytes print self.flashpin(0) return True