예제 #1
0
파일: xula.py 프로젝트: jlublin/xula-py
    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
예제 #2
0
파일: xula.py 프로젝트: jlublin/xula-py
    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