Python library and plaything for ARM JTAG
authordodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Sat, 13 Mar 2010 06:29:25 +0000 (06:29 +0000)
committerdodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Sat, 13 Mar 2010 06:29:25 +0000 (06:29 +0000)
git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@406 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/GoodFETARM.py [new file with mode: 0644]
client/gplay-arm.py [new file with mode: 0755]

diff --git a/client/GoodFETARM.py b/client/GoodFETARM.py
new file mode 100644 (file)
index 0000000..67b4a3a
--- /dev/null
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+# GoodFET Client Library
+# 
+# (C) 2009 Matthew Carpenter <matt at inguardians.com>
+#
+# Good luck with alpha / beta code.
+# Contributions and bug reports welcome.
+#
+
+import sys, binascii, struct
+
+#Global Commands
+READ  = 0x00
+WRITE = 0x01
+PEEK  = 0x02
+POKE  = 0x03
+SETUP = 0x10
+START = 0x20
+STOP  = 0x21
+CALL  = 0x30
+EXEC  = 0x31
+NOK   = 0x7E
+OK    = 0x7F
+
+# ARM7TDMI JTAG commands
+GET_DEBUG_CTRL      = 0x80
+SET_DEBUG_CTRL      = 0x81
+GET_PC              = 0x82
+SET_PC              = 0x83
+GET_CHIP_ID         = 0x84
+GET_DEBUG_STATE     = 0x85
+GET_WATCHPOINT      = 0x86
+SET_WATCHPOINT      = 0x87
+GET_REGISTER        = 0x88
+SET_REGISTER        = 0x89
+GET_REGISTERS       = 0x8a
+SET_REGISTERS       = 0x8b
+HALTCPU             = 0x8c
+RESUMECPU           = 0x8d
+DEBUG_INSTR         = 0x8e      #
+STEP_INSTR          = 0x8f      #
+STEP_REPLACE        = 0x90      #
+READ_CODE_MEMORY    = 0x91      # ??
+WRITE_FLASH_PAGE    = 0x92      # ??
+READ_FLASH_PAGE     = 0x93      # ??
+MASS_ERASE_FLASH    = 0x94      # ??
+PROGRAM_FLASH       = 0x95
+LOCKCHIP            = 0x96      # ??
+CHIP_ERASE          = 0x97      # can do?
+# Really ARM specific stuff
+GET_CPSR            = 0x98
+SET_CPSR            = 0x99
+GET_SPSR            = 0x9a
+SET_SPSR            = 0x9b
+SET_MODE_THUMB      = 0x9c
+SET_MODE_ARM        = 0x9d
+
+from GoodFET import GoodFET
+from intelhex import IntelHex
+
+
+
+
+class GoodFETARM(GoodFET):
+    """A GoodFET variant for use with ARM7TDMI microprocessor."""
+    def ARMhaltcpu(self):
+        """Halt the CPU."""
+        self.writecmd(0x33,HALTCPU,0,self.data)
+    def ARMreleasecpu(self):
+        """Resume the CPU."""
+        self.writecmd(0x33,RESUMECPU,0,self.data)
+    def ARMsetModeArm(self):
+        self.writecmd(0x33,SET_MODE_ARM,0,self.data)
+    def ARMtest(self):
+        self.ARMreleasecpu()
+        self.ARMhaltcpu()
+        #print "Status: %s" % self.ARMstatusstr()
+        
+        #Grab ident three times, should be equal.
+        ident1=self.ARMident()
+        ident2=self.ARMident()
+        ident3=self.ARMident()
+        if(ident1!=ident2 or ident2!=ident3):
+            print "Error, repeated ident attempts unequal."
+            print "%04x, %04x, %04x" % (ident1, ident2, ident3)
+        
+        #Single step, printing PC.
+        print "Tracing execution at startup."
+        for i in range(1,15):
+            pc=self.ARMgetPC()
+            byte=self.ARMpeekcodebyte(i)
+            #print "PC=%04x, %02x" % (pc, byte)
+            self.ARMstep_instr()
+        
+        print "Verifying that debugging a NOP doesn't affect the PC."
+        for i in range(1,15):
+            pc=self.ARMgetPC()
+            self.ARMdebuginstr([NOP])
+            if(pc!=self.ARMgetPC()):
+                print "ERROR: PC changed during ARMdebuginstr([NOP])!"
+        
+        print "Checking pokes to XRAM."
+        for i in range(0xf000,0xf020):
+            self.ARMpokedatabyte(i,0xde)
+            if(self.ARMpeekdatabyte(i)!=0xde):
+                print "Error in DATA at 0x%04x" % i
+        
+        #print "Status: %s." % self.ARMstatusstr()
+        #Exit debugger
+        self.stop()
+        print "Done."
+
+    def setup(self):
+        """Move the FET into the JTAG ARM application."""
+        #print "Initializing ARM."
+        self.writecmd(0x33,SETUP,0,self.data)
+    def ARMget_dbgstate(self):
+        """Read the config register of an ARM."""
+        self.writecmd(0x33,GET_DEBUG_STATE,0,self.data)
+        print "DEBUGGING get_dbgstate:  %s"%repr(self.data)
+        retval = struct.unpack("<L", self.data[:4])[0]
+        return retval
+    def ARMget_dbgctrl(self):
+        """Read the config register of an ARM."""
+        self.writecmd(0x33,GET_DEBUG_CTRL,0,self.data)
+        retval = struct.unpack("B", self.data)[0]
+        return retval
+    def ARMset_dbgctrl(self,config):
+        """Write the config register of an ARM."""
+        self.writecmd(0x33,SET_DEBUG_CTRL,1,[config&7])
+    def ARMlockchip(self):
+        """Set the flash lock bit in info mem."""
+        self.writecmd(0x33, LOCKCHIP, 0, [])
+    
+
+    def ARMidentstr(self):
+        ident=self.ARMident()
+        ver     = ident >> 28
+        partno  = (ident >> 12) & 0x10
+        mfgid   = ident & 0xfff
+        return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident); 
+    def ARMident(self):
+        """Get an ARM's ID."""
+        self.writecmd(0x33,GET_CHIP_ID,0,[])
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMgetPC(self):
+        """Get an ARM's PC."""
+        self.writecmd(0x33,GET_PC,0,[])
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMget_register(self, reg):
+        """Get an ARM's Register"""
+        self.writecmd(0x33,GET_REGISTER,1,[reg&0xff])
+        print "DEBUG:GET_REGISTER: %s"%repr(self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMset_register(self, reg, val):
+        """Get an ARM's Register"""
+        self.writecmd(0x33,GET_REGISTER,8,[reg,0,0,0,val>>24, (val>>16)&0xff, (val>>8)&0xff, val&0xff])
+        print "DEBUG:SET_REGISTER: %s"%repr(self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMget_registers(self):
+        """Get an ARM's Register"""
+        self.writecmd(0x33,GET_REGISTERS,0,[])
+        print "DEBUG:GET_REGISTER: %s"%repr(self.data)
+        #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMset_registers(self, regs):
+        """Get an ARM's Register"""
+        regarry = []
+        for reg in regs:
+          regarray.merge([reg>>24, (reg>>16)&0xff, (reg>>8)&0xff, reg&0xff])
+        self.writecmd(0x33,GET_REGISTER,16*4,regarray)
+        print "DEBUG:SET_REGISTER: %s"%repr(self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMcmd(self,phrase):
+        self.writecmd(0x33,READ,len(phrase),phrase)
+        val=ord(self.data[0])
+        print "Got %02x" % val
+        return val
+    def ARMdebuginstr(self,instr):
+        if type (instr) == int:
+            instr = struct.pack("<L", instr)
+        self.writecmd(0x33,DEBUG_INSTR,len(instr),instr)
+        return (self.data[0])
+    def ARMpeekcodebyte(self,adr):
+        """Read the contents of code memory at an address."""
+        self.data=[adr&0xff, (adr&0xff00)>>8]
+        self.writecmd(0x33,PEEK,2,self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMpeekdatabyte(self,adr):
+        """Read the contents of data memory at an address."""
+        self.data=[adr&0xff, (adr&0xff00)>>8]
+        self.writecmd(0x33, PEEK, 2, self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMpokedatabyte(self,adr,val):
+        """Write a byte to data memory."""
+        self.data=[adr&0xff, (adr&0xff00)>>8, val]
+        self.writecmd(0x33, POKE, 3, self.data)
+        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return retval
+    def ARMchiperase(self):
+        """Erase all of the target's memory."""
+        self.writecmd(0x33,CHIP_ERASE,0,[])
+    def ARMstatus(self):
+        """Check the status."""
+        self.writecmd(0x33,GET_DEBUG_STATE,0,[])
+        return ord(self.data[0])
+    ARMstatusbits={
+                  0x10 : "TBIT",
+                  0x08 : "cgenL",
+                  0x04 : "Interrupts Enabled (or not?)",
+                  0x02 : "DBGRQ",
+                  0x01 : "DGBACK"
+                  }
+    ARMctrlbits={
+                  0x04 : "disable interrupts",
+                  0x02 : "force dbgrq",
+                  0x01 : "force dbgack"
+                  }
+                  
+    def ARMstatusstr(self):
+        """Check the status as a string."""
+        status=self.ARMstatus()
+        str=""
+        i=1
+        while i<0x100:
+            if(status&i):
+                str="%s %s" %(self.ARMstatusbits[i],str)
+            i*=2
+        return str
+    def start(self):
+        """Start debugging."""
+        self.writecmd(0x33,START,0,self.data)
+        #ident=self.ARMidentstr()
+        #print "Target identifies as %s." % ident
+        #print "Status: %s." % self.ARMstatusstr()
+        #self.ARMreleasecpu()
+        #self.ARMhaltcpu()
+        #print "Status: %s." % self.ARMstatusstr()
+        
+    def stop(self):
+        """Stop debugging."""
+        self.writecmd(0x33,STOP,0,self.data)
+    def ARMstep_instr(self):
+        """Step one instruction."""
+        self.writecmd(0x33,STEP_INSTR,0,self.data)
+    def ARMflashpage(self,adr):
+        """Flash 2kB a page of flash from 0xF000 in XDATA"""
+        data=[adr&0xFF,
+              (adr>>8)&0xFF,
+              (adr>>16)&0xFF,
+              (adr>>24)&0xFF]
+        print "Flashing buffer to 0x%06x" % adr
+        self.writecmd(0x33,MASS_FLASH_PAGE,4,data)
+
+    def writecmd(self, app, verb, count=0, data=[]):
+        """Write a command and some data to the GoodFET."""
+        self.serialport.write(chr(app))
+        self.serialport.write(chr(verb))
+        count = len(data)
+        #if data!=None:
+        #    count=len(data); #Initial count ignored.
+
+        #print "TX %02x %02x %04x" % (app,verb,count)
+
+        #little endian 16-bit length
+        self.serialport.write(chr(count&0xFF))
+        self.serialport.write(chr(count>>8))
+
+        #print "count=%02x, len(data)=%04x" % (count,len(data))
+
+        if count!=0:
+            if(isinstance(data,list)):
+                for i in range(0,count):
+                    #print "Converting %02x at %i" % (data[i],i)
+                    data[i]=chr(data[i])
+            #print type(data)
+            outstr=''.join(data)
+            self.serialport.write(outstr)
+        if not self.besilent:
+            self.readcmd()
+
+
diff --git a/client/gplay-arm.py b/client/gplay-arm.py
new file mode 100755 (executable)
index 0000000..44f5d04
--- /dev/null
@@ -0,0 +1,348 @@
+#!/usr/bin/env ipython
+import sys, struct, binascii
+from GoodFETARM import *
+from intelhex import IntelHex
+
+
+data = []
+
+client=GoodFETARM();
+def init():
+    #Initailize FET and set baud rate
+    client.serInit()
+    #
+    #Connect to target
+    client.setup()
+    client.start()
+    print "STARTUP: "+repr(client.data)
+    #
+
+def test1():
+    global data
+    print "\n\nTesting JTAG for ARM\n"
+    client.writecmd(0x33,0xd0,4,[0x40,0x40,0x40,0x40]); print "loopback:   \t %s"%repr(client.data)                  # loopback
+    data.append(client.data)
+    client.writecmd(0x33,0xd1,2,[1,0]); print "scanchain1:\t %s"%repr(client.data)               # set scan chain
+    data.append(client.data)
+    client.writecmd(0x33,0xd2,0,[]); print "debug state:\t %s"%repr(client.data)                  # get dbg state
+    data.append(client.data)
+    client.writecmd(0x33,0xd3,0,[0,0,0xa0,0xe1]); print "exec_nop: \t %s"%repr(client.data)     # execute instruction
+    data.append(client.data)
+    client.writecmd(0x33,0xd3,0,[0,0,0x8e,0xe5]); print "exec_stuff: \t %s"%repr(client.data)     # execute instruction
+    data.append(client.data)
+    client.writecmd(0x33,0xd3,0,[0,0,0xa0,0xe1]); print "exec_nop: \t %s"%repr(client.data)     # execute instruction
+    data.append(client.data)
+    client.writecmd(0x33,0xd3,0,[0,0,0xa0,0xe1]); print "exec_nop: \t %s"%repr(client.data)     # execute instruction
+    data.append(client.data)
+    client.writecmd(0x33,0xd3,0,[0,0,0xa0,0xe1]); print "exec_nop: \t %s"%repr(client.data)     # execute instruction
+    data.append(client.data)
+    client.writecmd(0x33,0xd6,0,[]); print "shift_dr_32: \t %s"%repr(client.data)                  # dr_shift32
+    data.append(client.data)
+    client.writecmd(0x33,0xd5,8,[3, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40]); print "set_register:\t %s"%repr(client.data)                  # set register
+    data.append(client.data)
+    client.writecmd(0x33,0xd4,1,[3]); print "get_register:\t %s"%repr(client.data)                  # get register
+    data.append(client.data)
+    client.writecmd(0x33,0xd7,0,[]); print "chain1:      \t %s"%repr(client.data)                  # chain1
+    data.append(client.data)
+    client.writecmd(0x33,0xd8,0,[]); print "read_chain2: \t %s"%repr(client.data)                  # read chain2
+    data.append(client.data)
+    client.writecmd(0x33,0xd9,0,[]); print "idcode:      \t %s"%repr(client.data)                  # read idcode
+    data.append(client.data)
+    client.writecmd(0x33,0xf0,2,[4,4,1,1]); print "f0:       \t %s"%repr(client.data)   # read idcode
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x0,4,4,4,4,4,4,4]); print "verb(0):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x2,4,4,4,4,4,4,4]); print "verb(2):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x3,4,4,4,4,4,4,4]); print "verb(3):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x4,4,4,4,4,4,4,4]); print "verb(4):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x5,4,4,4,4,4,4,4]); print "verb(5):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x7,4,4,4,4,4,4,4]); print "verb(7):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0x9,4,4,4,4,4,4,4]); print "verb(9):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0xc,4,4,4,4,4,4,4]); print "verb(c):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0xe,0,0,0,0,0,0xa0,0xe1]); print "verb(e):     \t %s"%repr(client.data)
+    data.append(client.data)
+    client.writecmd(0x33,0xdb,8,[0xf,4,4,4,4,4,4,4]); print "verb(f):     \t %s"%repr(client.data)
+    data.append(client.data)
+
+def test2():
+    global data
+    print "\n\nTesting JTAG for ARM\n"
+    print "IDCODE:      %x"%client.ARMident()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "Debug CTRL:  %x"%client.ARMget_dbgctrl()
+    client.writecmd(0x33,0xda,0,[])
+    print "TEST CHAIN0: %s"%repr(client.data)
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "IDCODE:      %x"%client.ARMident()
+    #print "Debug State: %x"%client.ARMget_dbgstate ()
+    client.writecmd(0x33,0xd0,4,[0xf7,0xf7,0xf7,0xf7])
+    print "Loopback:   \t %s"%repr(client.data)                  # loopback
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "IDCODE:      %x"%client.ARMident()
+    print "GetPC: %x"%client.ARMgetPC()
+    print "IDCODE:      %x"%client.ARMident()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "IDCODE:      %x"%client.ARMident()
+    print "set_register(3,0x41414141):  %x"%client.ARMset_register(3,0x41414141)
+    print "IDCODE:      %x"%client.ARMident()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "IDCODE:      %x"%client.ARMident()
+    print "get_register(3):             %x"%client.ARMget_register(3)
+    print "IDCODE:      %x"%client.ARMident()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    print "IDCODE:      %x"%client.ARMident()
+
+def test3():
+    print "IDCODE:      %x"%client.ARMident()
+    print "Debug State: %x"%client.ARMget_dbgstate ()
+    client.writecmd(0x33,0xd0,4,[0xf7,0xf7,0xf7,0xf7])
+    print "Loopback:   \t %s"%repr(client.data)                  # loopback
+    client.writecmd(0x33,0xd5,8,[0,0,0,0,0xf7,0xf7,0xf7,0xf7])
+    print "test_set_reg:   \t %s"%repr(client.data)            
+    client.writecmd(0x33,0xd4,1,[0])
+    print "test_get_reg:   \t %s"%repr(client.data)           
+    print "set_register(3,0x41414141):  %x"%client.ARMset_register(3,0x41414141)
+    print "get_register(3):             %x"%client.ARMget_register(3)
+    client.writecmd(0x33,0xd4,1,[0])
+    print "test_get_reg:   \t %s"%repr(client.data)           
+
+init()
+print "Don't forget to 'client.stop()' if you want to exit cleanly"
+
+
+
+"""
+  case 0xD0: // loopback test
+    cmddatalong[0] = 0x12345678;
+  case 0xD1: // Set Scan Chain
+    cmddatalong[0] = jtagarm7tdmi_scan_n(cmddataword[0]);
+  case 0xD2: //
+    cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
+  case 0xD3:
+    cmddatalong[0] = jtagarm7tdmi_exec(cmddatalong[0]);
+  case 0xD4:
+    cmddatalong[0] = jtagarm7tdmi_get_register(cmddata[0]);
+  case 0xD5:
+    cmddatalong[0] = jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
+  case 0xD6:
+    cmddatalong[0] = jtagarm7tdmi_dr_shift32(cmddatalong[0]);
+  case 0xD7:
+    cmddatalong[0] = jtagarm7tdmi_chain1(cmddatalong[0], 0);
+  case 0xD8:
+    cmddatalong[0] = jtagarm7tdmi_chain2_read(cmddata[0], 32);
+"""
+
+"""
+if(sys.argv[1]=="test"):
+    client.CCtest();
+if(sys.argv[1]=="deadtest"):
+    for i in range(1,10):
+        print "IDENT as %s" % client.CCidentstr();
+if(sys.argv[1]=="dumpcode"):
+    f = sys.argv[2];
+    start=0x0000;
+    stop=0xFFFF;
+    if(len(sys.argv)>3):
+        start=int(sys.argv[3],16);
+    if(len(sys.argv)>4):
+        stop=int(sys.argv[4],16);
+    
+    print "Dumping code from %04x to %04x as %s." % (start,stop,f);
+    h = IntelHex(None);
+    i=start;
+    while i<=stop:
+        h[i]=client.CCpeekcodebyte(i);
+        if(i%0x100==0):
+            print "Dumped %04x."%i;
+        i+=1;
+    h.write_hex_file(f);
+if(sys.argv[1]=="dumpdata"):
+    f = sys.argv[2];
+    start=0xE000;
+    stop=0xFFFF;
+    if(len(sys.argv)>3):
+        start=int(sys.argv[3],16);
+    if(len(sys.argv)>4):
+        stop=int(sys.argv[4],16);
+    
+    print "Dumping data from %04x to %04x as %s." % (start,stop,f);
+    h = IntelHex(None);
+    i=start;
+    while i<=stop:
+        h[i]=client.CCpeekdatabyte(i);
+        if(i%0x100==0):
+            print "Dumped %04x."%i;
+        i+=1;
+    h.write_hex_file(f);
+if(sys.argv[1]=="status"):
+    print "Status: %s" %client.CCstatusstr();
+if(sys.argv[1]=="erase"):
+    print "Status: %s" % client.CCstatusstr();
+    client.CCchiperase();
+    print "Status: %s" %client.CCstatusstr();
+
+if(sys.argv[1]=="peekinfo"):
+    print "Select info flash."
+    client.CCwr_config(1);
+    print "Config is %02x" % client.CCrd_config();
+    
+    start=0x0000;
+    if(len(sys.argv)>2):
+        start=int(sys.argv[2],16);
+    stop=start;
+    if(len(sys.argv)>3):
+        stop=int(sys.argv[3],16);
+    print "Peeking from %04x to %04x." % (start,stop);
+    while start<=stop:
+        print "%04x: %02x" % (start,client.CCpeekcodebyte(start));
+        start=start+1;
+if(sys.argv[1]=="poke"):
+    client.CCpokeirambyte(int(sys.argv[2],16),
+                          int(sys.argv[3],16));
+if(sys.argv[1]=="randtest"):
+    #Seed RNG
+    client.CCpokeirambyte(0xBD,0x01); #RNDH=0x01
+    client.CCpokeirambyte(0xB4,0x04); #ADCCON1=0x04
+    client.CCpokeirambyte(0xBD,0x01); #RNDH=0x01
+    client.CCpokeirambyte(0xB4,0x04); #ADCCON1=0x04
+    
+    #Dump values
+    for foo in range(1,10):
+        print "%02x" % client.CCpeekirambyte(0xBD); #RNDH
+        client.CCpokeirambyte(0xB4,0x04); #ADCCON1=0x04
+        client.CCreleasecpu();
+        client.CChaltcpu();
+    print "%02x" % client.CCpeekdatabyte(0xDF61); #CHIP ID
+if(sys.argv[1]=="adctest"):
+    # ADCTest 0xDF3A 0xDF3B
+    print "ADC TEST %02x%02x" % (
+        client.CCpeekdatabyte(0xDF3A),
+        client.CCpeekdatabyte(0xDF3B));
+if(sys.argv[1]=="config"):
+    print "Config is %02x" % client.CCrd_config();
+
+if(sys.argv[1]=="flash"):
+     f=sys.argv[2];
+     start=0;
+     stop=0xFFFF;
+     if(len(sys.argv)>3):
+         start=int(sys.argv[3],16);
+     if(len(sys.argv)>4):
+         stop=int(sys.argv[4],16);
+   
+     h = IntelHex(f);
+     page = 0x0000;
+     pagelen = 2048; #2kB pages in 32-bit words
+     bcount = 0;
+     
+     print "Wiping Flash."
+     #Wipe all of flash.
+     #client.CCchiperase();
+     #Wipe the RAM buffer for the next flash page.
+     #client.CCeraseflashbuffer();
+     for i in h._buf.keys():
+         while(i>page+pagelen):
+             if bcount>0:
+                 client.CCflashpage(page);
+                 #client.CCeraseflashbuffer();
+                 bcount=0;
+                 print "Flashed page at %06x" % page
+             page+=pagelen;
+             
+         #Place byte into buffer.
+         client.CCpokedatabyte(0xF000+i-page,
+                               h[i]);
+         bcount+=1;
+         if(i%0x100==0):
+                print "Buffering %04x toward %06x" % (i,page);
+     #last page
+     client.CCflashpage(page);
+     print "Flashed final page at %06x" % page;
+     
+if(sys.argv[1]=="lock"):
+    print "Status: %s" %client.CCstatusstr();
+    client.CClockchip();
+    print "Status: %s" %client.CCstatusstr();
+if(sys.argv[1]=="flashpage"):
+    target=0;
+    if(len(sys.argv)>2):
+        target=int(sys.argv[2],16);
+    print "Writing a page of flash from 0xF000 in XDATA"
+    client.CCflashpage(target);
+if(sys.argv[1]=="erasebuffer"):
+    print "Erasing flash buffer.";
+    client.CCeraseflashbuffer();
+
+if(sys.argv[1]=="writedata"):
+    f=sys.argv[2];
+    start=0;
+    stop=0xFFFF;
+    if(len(sys.argv)>3):
+        start=int(sys.argv[3],16);
+    if(len(sys.argv)>4):
+        stop=int(sys.argv[4],16);
+    
+    h = IntelHex(f);
+    
+    for i in h._buf.keys():
+        if(i>=start and i<=stop):
+            client.CCpokedatabyte(i,h[i]);
+            if(i%0x100==0):
+                print "%04x" % i;
+#if(sys.argv[1]=="flashtest"):
+#    client.CCflashtest();
+if(sys.argv[1]=="peekdata"):
+    start=0x0000;
+    if(len(sys.argv)>2):
+        start=int(sys.argv[2],16);
+    stop=start;
+    if(len(sys.argv)>3):
+        stop=int(sys.argv[3],16);
+    print "Peeking from %04x to %04x." % (start,stop);
+    while start<=stop:
+        print "%04x: %02x" % (start,client.CCpeekdatabyte(start));
+        start=start+1;
+if(sys.argv[1]=="peek"):
+    start=0x0000;
+    if(len(sys.argv)>2):
+        start=int(sys.argv[2],16);
+    stop=start;
+    if(len(sys.argv)>3):
+        stop=int(sys.argv[3],16);
+    print "Peeking from %04x to %04x." % (start,stop);
+    while start<=stop:
+        print "%04x: %02x" % (start,client.CCpeekirambyte(start));
+        start=start+1;
+
+if(sys.argv[1]=="peekcode"):
+    start=0x0000;
+    if(len(sys.argv)>2):
+        start=int(sys.argv[2],16);
+    stop=start;
+    if(len(sys.argv)>3):
+        stop=int(sys.argv[3],16);
+    print "Peeking from %04x to %04x." % (start,stop);
+    while start<=stop:
+        print "%04x: %02x" % (start,client.CCpeekcodebyte(start));
+        start=start+1;
+if(sys.argv[1]=="pokedata"):
+    start=0x0000;
+    val=0x00;
+    if(len(sys.argv)>2):
+        start=int(sys.argv[2],16);
+    if(len(sys.argv)>3):
+        val=int(sys.argv[3],16);
+    print "Poking %04x to become %02x." % (start,val);
+    client.CCpokedatabyte(start,val);
+
+client.stop();
+"""