#!/bin/env python3 import sys import serial import struct from smbus import SMBus from time import sleep from bitarray import bitarray from jtag import * def rev(s): return s[::-1] def h2b(s): return ''.join([format(int(_,16),"04b") for _ in s]) def b2h(s): return ''.join([format(int(''.join(_),2),"X") for _ in zip(*[iter(s)]*4)]) devid = { "00000000000000000000000000000000" : "", "00000001001010111001000001000011" : "MXO2-640HC", "00000001001010111010000001000011" : "MXO2-1200HC", "00000001001010111011000001000011" : "MXO2-2000HC" } sbits = [ ( 0, 1, "TRAN"), ( 1, 3, ["CFG", "SRAM", "EFUSE", "?", "?", "?", "?", "?", "?"]), ( 4, 1, "JTAG"), ( 5, 1, "PWDPROT"), ( 6, 1, "OTP"), ( 7, 1, "DECRYPT"), ( 8, 1, "DONE"), ( 9, 1, "ISC"), (10, 1, "WRITE"), (11, 1, "READ"), (12, 1, "BUSY"), (13, 1, "FAIL"), (14, 1, "FEAOTP"), (15, 1, "DONLY"), (16, 1, "PWDEN"), (17, 1, "UFMOTP"), (18, 1, "ASSP"), (19, 1, "SDMEN"), (20, 1, "EPREAM"), (21, 1, "PREAM"), (22, 1, "SPIFAIL"), (23, 3, ["BSE", "OK", "ID", "CMD", "CRC", "PRMB", "ABRT", "OVFL", "SDM"]), (26, 1, "EEXEC"), (27, 1, "EIO"), (28, 1, "INVCMD"), (29, 1, "ESED"), (30, 1, "BYPASS"), (31, 1, "FTM") ] def status(jtag, debug=True): jtag.sir(rev(h2b("3C"))) # shift in READ_STATUS (0x3C) status = jtag.tdo(32) # read status hr = [] for (sbit, blen, name) in sbits: bits = rev(status)[sbit:sbit+blen] if blen == 1: if bits == "1": hr.append(name) else: bval = int(bits, 2) hr.append("%s=%s" % (name[0], name[bval+1])) if debug: print("status %s [%s] %s" % (b2h(status), status, " ".join(hr))) def waitnotbusy(jtag, debug=True): if debug: print("waitnotbusy ", end="") while True: jtag.sir(rev(h2b("F0"))) # shift in LSC_CHECK_BUSY (0xF0) busy = jtag.tdo(8) # read byte if busy.endswith("0"): if debug: print(".") break else: if debug: print(".", end="") i2c = SMBus(2) with open(sys.argv[1]) as f: cont = f.readlines() # i2c.write_byte(0x38, 0x01) # TDO_W input # i2c.write_byte(0x3A, 0xFF) # all pullups # i2c.write_byte(0x39, 0x00) jtag = JTag(i2c) jtag.sir(rev(h2b("E0"))) # shift in IDCODE (0xE0) idcode = jtag.tdo(32) # read idcode dev = devid[idcode] print("found %s [%s]" % (dev, idcode)) jtag.sir(rev(h2b("79"))) # shift in REFRESH (0x79) jtag.runtest(2) status(jtag) jtag.sir(rev(h2b("C6"))) # shift in ISC ENABLE (0xC6) jtag.tdi(rev(h2b("00"))) jtag.runtest(2) status(jtag) jtag.sir(rev(h2b("0E"))) # shift in ISC ERASE (0x0E) jtag.tdi(rev(h2b("01"))) jtag.idle(2) waitnotbusy(jtag) status(jtag) data = "" scan = False for line in cont: if line[0] == '*': scan = False # break # skip zeros if line[0] == 'L': scan = True if scan and line[0] in "01": data += rev(line.strip()) print(len(data)) jtag.sir(rev(h2b("7A"))) # shift in LSC_BITSTREAM_BURST (0x7A) jtag.tdi(data) status(jtag) jtag.sir(rev(h2b("C0"))) # shift in USERCODE (0xC0) usercode = jtag.tdo(32) # read usercode print("usercode %s [%s]" % (b2h(usercode), usercode)) jtag.sir(rev(h2b("26"))) # shift in ISC DISABLE (0x26) jtag.idle(2) status(jtag) jtag.reset() # i2c.write_byte(0x39, 0x00)