def fetch_data(self): if len(self.bits_in_read_queue) > 0: length = self.bits_in_read_queue.popleft() bs = BitSequence() byte_count = length // 8 pos = 8 * byte_count bit_count = length - pos if byte_count: data = self._ftdi.read_data_bytes(byte_count, 4) if not data: raise JtagError('Unable to read data from FTDI') byteseq = BitSequence(bytes_=data, length=8 * byte_count) # print("RW IN %s" % byteseq) bs.append(byteseq) # print("pop %d bytes" % byte_count) if bit_count: data = self._ftdi.read_data_bytes(1, 4) if not data: raise JtagError('Unable to read data from FTDI') byte = data[0] # need to shift bits as they are shifted in from the MSB in FTDI byte >>= 8 - bit_count bitseq = BitSequence(byte, length=bit_count) bs.append(bitseq) # print("pop %d bits" % bit_count) if len(bs) != length: raise ValueError("Internal error") return bs return None
def read_access(self, address): error = False bs = BitSequence(1, msb=False, length=16) # Bits 15:0 -> Count=1 bs.append(BitSequence(address, msb=False, length=32)) # bits 47:16 -> 32-bit Address bs.append( BitSequence(ADV_DBG_IF_WB_CMD_BURST_READ_32, msb=False, length=4)) # Command bs.append(BitSequence(0, msb=True, length=1)) # Bit 52 self.jtag.write_dr(bs) # Now shift outputs self.jtag.change_state('shift_dr') # Read status bit seq = self.jtag.read(2) status = 0 while status == 0: status = self.jtag.read(1)[0] data = int(self.jtag.read(32)) crc = int(self.jtag.read(32)) # first word of a burst : crc_in = 0xFFFFFFFF expected_crc = self.compute_crc(data_in=data, length_bits=32, crc_in=0xFFFFFFFF) if crc != expected_crc: print( "-E- CRC error detected Data : {0:#010x}, CRC : {1:#010x} Computed CRC : {2:#010x}" .format(data, crc, expected_crc)) error = True self.jtag.go_idle() return data, error
def writeapb(self, adr, data): if self.currentir!=0x11: self.write_ir(BitSequence(value = 0x11, length=self._irlen)) self.currentir = 0x11 self._engine.write_dr(BitSequence(value = ((adr&0xffff)<<34)| ((data&0xffffffff)<<2)|(2), length = 41)) self._engine.go_idle() for i in range(2): self._engine.write_tms(BitSequence(value=0 ,length=5))
def writecmd(self, adr, data, size, write): adr = adr + self.adrofs; if(self.virtual): self._engine.write_dr(BitSequence(value = ((adr&0xffffffff)<<10)| ((data&0xffffffff)<<42)|(write<<74) + (size<<75), length = 77)) else: self._engine.write_ir(BitSequence(value = 0x2, length=self._irlen)) self._engine.write_dr(BitSequence(value = ((adr&0xffffffff)<<8)| ((data&0xffffffff)<<40)|(write<<72) + (size<<73), length = 75))
def resetdm(self): if self.currentir!= 0x10: self.write_ir(BitSequence(value = 0x10, length=self._irlen)) self.currentir = 0x10 self._engine.write_dr(BitSequence(value = (3<<16), length = 32)) self._engine.go_idle() self._engine.write_dr(BitSequence(value = 0, length = 32)) self._engine.go_idle() pass
def resetdm(self): if self.currentir!= 0x10: self.write_ir(BitSequence(value = 0x10, length=self._irlen)) self.currentir = 0x10 self._engine.write_dr(BitSequence(value = (3<<16), length = 32)) self._engine.go_idle() self._engine.write_dr(BitSequence(value = 0, length = 32)) self._engine.go_idle() self.writeapb(PulpOCD.DMCONTROLREG, (1<<PulpOCD.ACTIVEBIT)) self._engine.go_idle()
def test_conversion(self): bs = BitSequence(0xCA, msb=True, length=8) self.assertEqual('%02x' % bs.tobyte(False), '53') self.assertEqual('%02x' % bs.tobyte(True), 'ca') self.assertEqual(bs, BitSequence(bs.tobyte(True), msb=True, length=8)) self.assertRaises(BitSequenceError, BitZSequence.__int__, self.bzs5) self.assertRaises(BitSequenceError, BitZSequence.tobyte, self.bzs5) self.assertRaises(BitSequenceError, BitZSequence.tobytes, self.bzs5) bzs = BitZSequence(0xaa) self.assertEqual(int(bzs), 0xaa)
def shift_register(self, out, use_last=False): """Shift a BitSequence into the current register and retrieve the register output""" if not isinstance(out, BitSequence): return JtagError('Expect a BitSequence') length = len(out) if use_last: (out, self._last) = (out[:-1], int(out[-1])) byte_count = len(out) // 8 pos = 8 * byte_count bit_count = len(out) - pos if not byte_count and not bit_count: raise JtagError("Nothing to shift") if byte_count: blen = byte_count - 1 # print("RW OUT %s" % out[:pos]) cmd = array('B', (Ftdi.RW_BYTES_PVE_NVE_LSB, blen, (blen >> 8) & 0xff)) cmd.extend(out[:pos].tobytes(msby=True)) self._stack_cmd(cmd) # print("push %d bytes" % byte_count) if bit_count: # print("RW OUT %s" % out[pos:]) cmd = array('B', (Ftdi.RW_BITS_PVE_NVE_LSB, bit_count - 1)) cmd.append(out[pos:].tobyte()) self._stack_cmd(cmd) # print("push %d bits" % bit_count) self.sync( ) # we cannot skip sync here, because we expect data to be returned from MPSSE bs = BitSequence() byte_count = length // 8 pos = 8 * byte_count bit_count = length - pos if byte_count: data = self._ftdi.read_data_bytes(byte_count, 4) if not data: raise JtagError('Unable to read data from FTDI') byteseq = BitSequence(bytes_=data, length=8 * byte_count) # print("RW IN %s" % byteseq) bs.append(byteseq) # print("pop %d bytes" % byte_count) if bit_count: data = self._ftdi.read_data_bytes(1, 4) if not data: raise JtagError('Unable to read data from FTDI') byte = data[0] # need to shift bits as they are shifted in from the MSB in FTDI byte >>= 8 - bit_count bitseq = BitSequence(byte, length=bit_count) bs.append(bitseq) # print("pop %d bits" % bit_count) if len(bs) != length: raise ValueError("Internal error") return bs
def readrsp(self, adr): adr = adr + self.adrofs; self.writecmd(adr, 0, 2, 0) if(self.virtual): val = int(self._engine.readwrite_dr(BitSequence(value = 0x1, length=36))) val = val>>2 else: self._engine.write_ir(BitSequence(value = 0x3, length=self._irlen)) val = int(self._engine.read_dr(34)) val = (val>>2) & 0xffffffff return val
def readapb(self, adr): if self.currentir!=0x11: self.write_ir(BitSequence(value = 0x11, length=self._irlen)) self.currentir = 0x11 self._engine.write_dr(BitSequence(value = ((adr&0xffff)<<34)|(1), length = 50)) self._engine.go_idle() for i in range(8): self._engine.write_tms(BitSequence(value=0 ,length=7)) val = (int(self._engine.read_dr(50))>>2) & 0xffffffff return val
def shift_register(self, out, use_last=False): if len(out) == 0: return bytearray() if isinstance(out, tuple): out = BitSequence(bytes_=out[1])[:out[0]] elif isinstance(out, bytearray): out = BitSequence(bytes_=out) elif not isinstance(out, BitSequence): raise Exception('Expect a BitSequence') length = len(out) if use_last: (out, self._last) = (out[:-1], int(out[-1])) byte_count = len(out) // 8 pos = 8 * byte_count bit_count = len(out) - pos if not byte_count and not bit_count: raise Exception("Nothing to shift") if byte_count: blen = byte_count - 1 cmd = array('B', (Ftdi.RW_BYTES_PVE_NVE_LSB, blen, (blen >> 8) & 0xff)) cmd.extend(out[:pos].tobytes(msby=True)) self._stack_cmd(cmd) if bit_count: cmd = array('B', (Ftdi.RW_BITS_PVE_NVE_LSB, bit_count - 1)) cmd.append(out[pos:].tobyte()) self._stack_cmd(cmd) self._sync() bs = BitSequence() byte_count = length // 8 pos = 8 * byte_count bit_count = length - pos if byte_count: data = self._ftdi.read_data_bytes(byte_count, 4) if not data: raise Exception('Unable to read data from FTDI') byteseq = BitSequence(bytes_=data, length=8 * byte_count) bs.append(byteseq) if bit_count: data = self._ftdi.read_data_bytes(1, 4) if not data: raise Exception('Unable to read data from FTDI') byte = data[0] # need to shift bits as they are shifted in from the MSB in FTDI byte >>= 8 - bit_count bitseq = BitSequence(byte, length=bit_count) bs.append(bitseq) assert len(bs) == length return bytearray(bs.tobytes())
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): if(self.debug): print(">>Tmsout:" + bin(val)) if(should_read): tdo = self.readwritebit(val,1) if(self.debug): print(">>Tmsin:" + bin(tdo)) else: self.writebit(val, 1) else: if(should_read): tdo = self.readwritebit(val,0) if(self.debug): print(">>Tmsin:" + bin(tdo)) else: self.writebit(val, 0) should_read = False self._last = None return BitSequence(tdo, 1)
def reset(self, sync=False): """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 # do both for now if not self._ftdi: raise JtagError("FTDI controller terminated") if self._trst: # nTRST value = 0 cmd = array('B', (Ftdi.SET_BITS_LOW, value, self.direction)) self._stack_cmd(cmd) self.sync() time.sleep(0.1) # nTRST should be left to the high state value = JtagController.TRST_BIT cmd = array('B', (Ftdi.SET_BITS_LOW, value, self.direction)) self._stack_cmd(cmd) self.sync() time.sleep(0.1) # TAP reset (even with HW reset, could be removed though) self.write_tms(BitSequence('11111')) if sync: self.sync()
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 test_rotations(self): b = BitSequence('10101110') b.lsr(2) self.assertEqual(str(b), '8: 01011101') b.lsr(10) self.assertEqual(str(b), '8: 01010111') b.rsr(3) self.assertEqual(str(b), '8: 10111010')
def shift_register(self, length): if not self._sm.state_of('shift'): raise JtagError("Invalid state: %s" % self._sm.state()) if self._sm.state_of('capture'): bs = BitSequence(False) self._ctrl.write_tms(bs) self._sm.handle_events(bs) return self._ctrl.shift_register(length)
def detect_register_size(self): # Freely inpired from UrJTAG # Need to contact authors, or to replace this code to comply with # the GPL license (GPL vs. LGPL with Python is a bit fuzzy for me) if not self._engine._sm.state_of('shift'): raise JtagError("Invalid state: %s" % self._engine._sm.state()) if self._engine._sm.state_of('capture'): bs = BitSequence(False) self._engine._ctrl.write_tms(bs) self._engine._sm.handle_events(bs) MAX_REG_LEN = 1024 PATTERN_LEN = 8 stuck = None for length in range(1, MAX_REG_LEN): print_("Testing for length %d" % length) if length > 5: return zero = BitSequence(length=length) inj = BitSequence(length=length + PATTERN_LEN) inj.inc() ok = False for p in range(1, 1 << PATTERN_LEN): ok = False self._engine.write(zero, False) rcv = self._engine.shift_register(inj) try: tdo = rcv.invariant() except ValueError: tdo = None if stuck is None: stuck = tdo if stuck != tdo: stuck = None rcv >>= length if rcv == inj: ok = True else: break inj.inc() if ok: print_("Register detected length: %d" % length) return length if stuck is not None: raise JtagError('TDO seems to be stuck') raise JtagError('Unable to detect register length')
def write_access(self, address, data): bs = BitSequence(1, msb=False, length=16) # Bits 15:0 -> Count=1 bs.append(BitSequence(address, msb=False, length=32)) # bits 47:16 -> 32-bit Address bs.append( BitSequence(ADV_DBG_IF_WB_CMD_BURST_WRITE_32, msb=False, length=4)) # Command bs.append(BitSequence(0, msb=True, length=1)) # Bit 52 self.jtag.write_dr(bs) # High-speed mode - no status bit # Start bit bs = BitSequence(1, msb=False, length=1) bs.append(BitSequence(data, msb=False, length=32)) # Data # first word of a burst : crc_in = 0xFFFFFFFF crc = self.compute_crc(data_in=data, crc_in=0xFFFFFFFF, length_bits=32) bs.append(BitSequence(crc, msb=False, length=32)) # CRC self.jtag.change_state('shift_dr') self.jtag.write(bs) match = self.jtag.read(1) self.jtag.go_idle() return int(match) == 1
def write(self, out, use_last=True): """Write a sequence of bits to TDI""" if isinstance(out, str): if len(out) > 1: self._write_bytes_raw(out[:-1]) out = out[-1] out = BitSequence(bytes_=out) elif not isinstance(out, BitSequence): out = BitSequence(out) if use_last: (out, self._last) = (out[:-1], bool(out[-1])) byte_count = len(out) // 8 pos = 8 * byte_count bit_count = len(out) - pos if byte_count: self._write_bytes(out[:pos]) if bit_count: self._write_bits(out[pos:])
def readbus(self, adr): WORDSIZE = 2 self.writeapb(PulpOCD.SYSTEMBUSCONTROLREG, (WORDSIZE<<17) + (1<<PulpOCD.BUSREADONADDRBIT)) self.writeapb(PulpOCD.SYSTEMBUSADR0, adr) self._engine.go_idle() for i in range(9): self._engine.write_tms(BitSequence(value=0 ,length=7)) val = self.readapb(PulpOCD.SYSTEMBUSDATA0)# & (1<<((WORDSIZE + 1)*8) - 1) return val
def readreg(self, regnr): debugregnr = regnr + 0x1000 self.writeapb(PulpOCD.ABSTRACTCMDREG, debugregnr + PulpOCD.WORDSIZE + (1<<PulpOCD.REGTRANSFERBIT)) self._engine.go_idle() for i in range(9): self._engine.write_tms(BitSequence(value=0 ,length=7)) val = self.readapb(PulpOCD.ABSTRACTDATAREG) return val
def shift_register(self, out): if not self._sm.state_of('shift'): raise JtagError("Invalid state: %s" % self._sm.state()) if self._sm.state_of('capture'): bs = BitSequence(False) self._ctrl.write_tms(bs) self._sm.handle_events(bs) bs = self._ctrl.writeread(out, use_last=False) return bs
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 shift_register(self, out, use_last=False): """Shift a BitSequence into the current register and retrieve the register output""" 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.readsetdr(length, int(out)), length=length) return bs
def test_idcode_shift_register(self): """Read the IDCODE using the dedicated instruction with shift_and_update_register""" instruction = JTAG_INSTR['IDCODE'] self.jtag.change_state('shift_ir') retval = self.jtag.shift_and_update_register(instruction) print("retval: 0x%x" % int(retval)) self.jtag.go_idle() self.jtag.change_state('shift_dr') idcode = self.jtag.shift_and_update_register(BitSequence('0' * 32)) self.jtag.go_idle() print("IDCODE (idcode): 0x%08x" % int(idcode))
def readwrite_dr(self, out): """Read the data register from the TAP controller""" self.change_state('shift_dr') data = int(self._ctrl.writeread(out, use_last=True)) events = BitSequence('11') tdo = int(self.write_tms(events, should_read=True)) # (write_tms calls sync()) # update the current state machine's state self._sm.handle_events(events) data += tdo << (len(out) - 1) return data
def get_events(self, path): """Build up an event sequence from a state sequence, so that the resulting event sequence allows the JTAG state machine to advance from the first state to the last one of the input sequence""" events = [] for s, d in zip(path[:-1], path[1:]): for e, x in enumerate(s.exits): if x == d: events.append(e) if len(events) != len(path) - 1: raise JtagError("Invalid path") return BitSequence(events)
def read(self, length): """Read out a sequence of bits from TDO""" byte_count = length // 8 bit_count = length - 8 * byte_count bs = BitSequence() if byte_count: bytes = self._read_bytes(byte_count) bs.append(bytes) if bit_count: bits = self._read_bits(bit_count) bs.append(bits) return bs
def test_misc(self): ba = BitSequence(12, msb=True, length=16) bb = BitSequence(12, msb=True, length=14) l = [ba, bb] l.sort() self.assertEqual(str(l), "[00110000000000, 0011000000000000]") self.assertEqual(str(ba.tobytes()), "[48, 0]") self.assertEqual(str(ba.tobytes(True)), "[0, 12]") self.assertEqual(str(bb.tobytes(True)), "[0, 12]") b = BitSequence(length=254) b[0:4] = '1111' self.assertEqual(str(b), '254: 000000 00000000 00000000 00000000 ' \ '00000000 00000000 00000000 00000000 00000000 00000000 00000000 ' \ '00000000 00000000 00000000 00000000 00000000 00000000 00000000 ' \ '00000000 00000000 00000000 00000000 00000000 00000000 00000000 ' \ '00000000 00000000 00000000 00000000 00000000 00000000 00001111') self.assertEqual(str(b.tobytes()), '[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ' \ '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15]') b = BitSequence(bytes_=[0xa0, '\x0f', 0x77], msb=False, msby=False) self.assertEqual(str(['%02x' % x for x in b.tobytes(False)]), "['a0', '0f', '77']") b = BitSequence(bytes_=[0xa0, '\x0f', 0x77], msb=True, msby=True) self.assertEqual(str(['%02x' % x for x in b.tobytes(True)]), "['a0', '0f', '77']") b = BitSequence(length=3) b[6] = '1' self.assertEqual(str(b), '7: 1000000')
def test_bitwise_ops(self): self.assertEqual( int(BitSequence(0x01, length=8) | BitSequence(0x02, length=8)), 3) self.assertEqual( int(BitSequence(0x07, length=8) & BitSequence(0x02, length=8)), 2) self.assertEqual( int(BitZSequence(0x01, length=8) | BitSequence(0x02, length=8)), 3) self.assertEqual( int(BitSequence(0x07, length=8) & BitZSequence(0x02, length=8)), 2) self.assertRaises(BitSequenceError, BitZSequence.__or__, self.bzs4, self.bzs5) self.assertRaises(BitSequenceError, BitZSequence.__and__, self.bzs4, self.bzs5) self.assertEqual(repr(self.bzs6), '00000000100Z01') self.assertEqual(repr(self.bzs6 | self.bzs4), '11Z1Z010ZZ0Z01') self.assertEqual(repr(self.bzs6 & self.bzs4), '00Z0Z000ZZ0Z00') self.assertEqual(repr(self.bzs4 & self.bs7), '11Z1Z010ZZ0000') self.assertEqual(repr(self.bs7 & self.bzs4), '11Z1Z010ZZ0000') self.assertEqual(repr(self.bzs4 | self.bs7), '11Z1Z010ZZ1101') self.assertEqual(repr(self.bs7 | self.bzs4), '11Z1Z010ZZ1101') self.assertEqual(repr(self.bs7.invert()), '00000101010110') self.assertEqual(repr(self.bzs4.invert()), '00Z0Z101ZZ1011') self.assertLess(self.bs5, self.bs6) self.assertLessEqual(self.bs5, self.bs6) self.assertLess(self.bs6, self.bs5) self.assertLessEqual(self.bs6, self.bs5)