예제 #1
0
class Blaster:
    def __init__(self, debug=False):
        self.blaster = Ftdi()
        self.virtual = True
        self.blaster.LATENCY_MIN = 1
        self.blaster.open(0x09FB, 0x6001)
        self.blaster.write_data_set_chunksize(1)
        self._last = None  # Last deferred TDO bit
        self.debug = debug

    def readwritebit(self, tms, tdi):
        val = ENA + tms * TMS + tdi * TDI
        self.blaster._write(bytes([val]))
        val = ENA + tms * TMS + tdi * TDI + TCK + TDO
        self.blaster._write(bytes([val]))
        rd = self.blaster.read_data_bytes(1, attempt=3)
        tdo = ord(rd) & 1
        return tdo

    def writebit(self, tms, tdi):
        val = ENA + tms * TMS + tdi * TDI
        self.blaster._write(bytes([val]))
        val = ENA + tms * TMS + tdi * TDI + TCK
        self.blaster._write(bytes([val]))

    def shiftinoutval(self, length, val):
        outval = 0
        if (self.debug):
            print(">>Out{2:d}:0x{0:x}={0:0{1}b}".format(val, length, length))
        nbytes = length >> 3
        if nbytes > 63:
            raise Exception("length > 63 bytes")
        self.blaster._write(bytes([ENA]))
        valcmd = bytearray([BYTESHIFT | DORDWR | (nbytes & 0x3F)])
        txlen = (nbytes & 0x3F) << 3
        valbytes = (val & ((1 << txlen) - 1)).to_bytes(nbytes & 0x3F, 'little')
        valcmd.extend(valbytes)
        self.blaster._write(valcmd)
        rd = self.blaster.read_data_bytes(nbytes & 0x3F, attempt=3)
        rxlen = len(rd)
        outval += int.from_bytes(rd, 'little')
        val >>= txlen
        if (self.debug):
            print(">>Inbytes{2:d}:0x{0:x}={0:0{1}b}".format(
                outval, rxlen * 8, rxlen))
        length -= txlen

        for i in range(length):
            bit = val & 1
            tdo = self.readwritebit(0, bit)
            val >>= 1
            outval += (tdo << (i + rxlen * 8))
        if (self.debug):
            print(">>In{2:d}:0x{0:x}={0:0{1}b}".format(outval,
                                                       (length + nbytes * 8),
                                                       length))
        return outval

    def shiftinval(self, length, val):
        if (self.debug):
            print(">>Out{2:d}:0x{0:x}={0:0{1}b}".format(val, length, length))
        nbytes = length >> 3
        while nbytes > 0:
            self.blaster._write(bytes([ENA]))
            valcmd = bytearray([BYTESHIFT | (nbytes & 0x3F)])
            len = (nbytes & 0x3F) << 3
            valbytes = (val & ((1 << len) - 1)).to_bytes(
                nbytes & 0x3F, 'little')
            valcmd.extend(valbytes)
            self.blaster._write(valcmd)
            val >>= len
            nbytes -= nbytes & 0x3F
            length -= len
        for i in range(length):
            bit = val & 1
            tdo = self.writebit(0, bit)
            val >>= 1

    def write_tms(self, tms, should_read=False):
        """Change the TAP controller state"""
        if not isinstance(tms, BitSequence):
            raise JtagError('Expect a BitSequence')
        tdo = 0
        for val in tms:
            if (self._last is not None):
                if (should_read):
                    if (self.debug):
                        print(">>Tmsout:" + bin(self._last))
                    tdo = self.readwritebit(val, int(self._last))
                    if (self.debug):
                        print(">>Tmsin:" + bin(tdo))
                else:
                    if (self.debug):
                        print(">>Tmsout:" + bin(self._last))
                    self.writebit(val, int(self._last))
            else:
                self.writebit(val, 0)
            should_read = False
            self._last = None
        return BitSequence(tdo, 1)

    def reset(self):
        """Reset the attached TAP controller.
           sync sends the command immediately (no caching)
        """
        # we can either send a TRST HW signal or perform 5 cycles with TMS=1
        # to move the remote TAP controller back to 'test_logic_reset'state

        # TAP reset (even with HW reset, could be removed though)
        self.write_tms(BitSequence('11111'))

    def write(self, out, use_last=True):
        if not isinstance(out, BitSequence):
            return JtagError('Expect a BitSequence')
        if use_last:
            (out, self._last) = (out[:-1], bool(out[-1]))
        length = len(out)
        self.shiftinval(length, int(out))

    def writeread(self, out, use_last=True):
        if not isinstance(out, BitSequence):
            return JtagError('Expect a BitSequence')
        if use_last:
            (out, self._last) = (out[:-1], bool(out[-1]))
        length = len(out)
        bs = BitSequence(value=self.shiftinoutval(length, int(out)),
                         length=length)
        return bs

    def read(self, length):
        """Read out a sequence of bits from TDO"""
        bs = BitSequence(value=self.shiftinoutval(length, 0), length=length)
        return bs

    def close(self):
        self.blaster.close()