jtagarm7 interface improvements, including at91x40
authordodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Thu, 24 Jan 2013 18:03:38 +0000 (18:03 +0000)
committerdodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Thu, 24 Jan 2013 18:03:38 +0000 (18:03 +0000)
git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1409 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/GoodFETARM7.py
client/GoodFETAT91X40.py
client/goodfet.arm7
client/goodfet.at91x40 [new file with mode: 0755]
client/gplay-at91x40.py

index f7f0b94..86b3ca8 100644 (file)
@@ -9,7 +9,10 @@
 #  * flash manipulation (probably need to get the specific chip for this one)
 #  * set security (chip-specific)
 
-import sys, binascii, struct, time
+import sys
+import time
+import struct
+
 from GoodFET import GoodFET
 from intelhex import IntelHex
 
@@ -95,6 +98,7 @@ PM_svc = 0b10011
 PM_abt = 0b10111
 PM_und = 0b11011
 PM_sys = 0b11111
+
 proc_modes = {
     0:      ("UNKNOWN, MESSED UP PROCESSOR MODE","fsck", "This should Never happen.  MCU is in funky state!"),
     PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
@@ -187,6 +191,7 @@ PCOFF_BREAK = 4 * 4
 
 def debugstr(strng):
     print >>sys.stderr,(strng)
+
 def PSRdecode(psrval):
     output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
     for x in xrange(5,32):
@@ -195,11 +200,12 @@ def PSRdecode(psrval):
     return " ".join(output)
    
 fmt = [None, "B", "<H", None, "<L", None, None, None, "<Q"]
+
 def chop(val,byts):
     s = struct.pack(fmt[byts], val)
     return [ord(b) for b in s ]
         
-class GoodFETARM(GoodFET):
+class GoodFETARM7(GoodFET):
     """A GoodFET variant for use with ARM7TDMI microprocessor."""
     def __init__(self):
         GoodFET.__init__(self)
@@ -207,6 +213,7 @@ class GoodFETARM(GoodFET):
         self.current_dbgstate = 0xffffffff
         self.flags =            0xffffffff
         self.nothing =          0xffffffff
+        self.stored_regs = []
     def __del__(self):
         try:
             if (self.ARMget_dbgstate()&9) == 9:
@@ -267,7 +274,7 @@ class GoodFETARM(GoodFET):
         ver     = (ident >> 28)
         partno  = (ident >> 12) & 0xffff
         mfgid   = (ident >> 1)  & 0x7ff
-        return "Chip IDCODE: 0x%x\n\tver: %x\n\tpartno: %x\n\tmfgid: %x\n" % (ident, ver, partno, mfgid); 
+        return "Chip IDCODE:    0x%x\tver: %x\tpartno: %x\tmfgid: %x" % (ident, ver, partno, mfgid); 
     def ARMeice_write(self, reg, val):
         data = chop(val,4)
         data.extend([reg])
@@ -371,38 +378,58 @@ class GoodFETARM(GoodFET):
         self.ARMset_register(0,r0)
         return retval
     def ARMcapture_system_state(self, pcoffset):
+        self.c0Data, self.flags, self.c0Addr = self.ARMchain0(0)
         if self.ARMget_dbgstate() & DBG_TBIT:
             pcoffset += 8
         else:
             pcoffset += 4
         self.storedPC = self.ARMget_register(15) + pcoffset
         self.last_dbg_state = self.ARMget_dbgstate()
-    def ARMhaltcpu(self):
+        self.cpsr = self.ARMget_regCPSR()
+        print "ARMcapture_system_state: stored pc: 0x%x  last_dbg_state: 0x%x" % (self.storedPC, self.last_dbg_state)
+
+    #def ARMhaltcpu(self):
+    def halt(self):
         """Halt the CPU."""
-        if not(self.ARMget_dbgstate()&1):
-            self.ARMset_dbgctrl(2)
-            if (self.ARMwaitDBG() == 0):
-                raise Exception("Timeout waiting to enter DEBUG mode on HALT")
-            self.ARMset_dbgctrl(0)
-            self.ARMcapture_system_state(PCOFF_DBGRQ)
-            if self.last_dbg_state&0x10:
-                self.storedPC = self.THUMBgetPC()
-            else:
-                self.storedPC = self.ARMget_register(15)
-        self.storedPC, self.flags, self.nothing = self.ARMchain0(0)
+        if self.ARMget_dbgstate()&DBG_DBGACK:
+            if not len(self.stored_regs):
+                #print "stored regs: " + repr(self.stored_regs)
+                self.stored_regs = self.ARMget_registers()[:15]
+                print self.print_stored_registers()
+            return
+        print "halting cpu"
+        self.ARMset_dbgctrl(2)
+        if (self.ARMwaitDBG() == 0):
+            raise Exception("Timeout waiting to enter DEBUG mode on HALT")
+        self.ARMset_dbgctrl(0)
+
+        self.ARMcapture_system_state(PCOFF_DBGRQ)
+        print "storedPC: %x (%x)      flags: %x    nothing: %x" % (self.storedPC, self.c0Data, self.flags, self.c0Addr)
         if self.ARMget_dbgstate() & DBG_TBIT:
             self.ARMsetModeARM()
             if self.storedPC ^ 4:
                 self.ARMset_register(15,self.storedPC&0xfffffffc)
+        self.stored_regs = self.ARMget_registers()[:15]
+        #print "stored regs: " + repr(self.stored_regs)
+        #print self.print_stored_registers()
         print "CPSR: (%s) %s"%(self.ARMget_regCPSRstr())
-    halt = ARMhaltcpu
+    #halt = ARMhaltcpu
 
-    def ARMreleasecpu(self):
+    #def ARMreleasecpu(self):
+    def resume(self):
         """Resume the CPU."""
-        # restore registers FIXME: DO THIS
-        if self.ARMget_dbgstate()&1 == 0:
+        # FIXME: restore CPSR
+        # FIXME: true up PC to exactly where we left off...
+        if not self.ARMget_dbgstate()&DBG_DBGACK:
             return
-        currentPC, self.currentflags, nothing = self.ARMchain0(self.storedPC,self.flags)
+        print "resume"
+        if len(self.stored_regs):
+            #print self.print_stored_registers()
+            self.ARMset_registers(self.stored_regs, 0x7fff)
+        else:
+            print "skipping restore of stored registers due to empty list ?  WTFO?"
+
+        currentPC, self.currentflags, nothing = self.ARMchain0(self.storedPC,self.flags, self.c0Addr)
         if not(self.flags & F_TBIT):                                    # need to be in arm mode
             if self.currentflags & F_TBIT:                              # currently in thumb mode
                 self.ARMsetModeARM()
@@ -428,12 +455,16 @@ class GoodFETARM(GoodFET):
             self.ARM_nop(1)
             #print hex(self.storedPC)
             #print hex(self.ARMget_register(15))
-            print hex(self.ARMchain0(self.storedPC,self.flags)[0])
+            #print hex(self.ARMchain0(self.storedPC,self.flags)[0])
+            self.ARMchain0(self.storedPC,self.flags)[0]
             self.ARMdebuginstr(THUMB_INSTR_B_IMM | (0x7fc07fc),0)
             self.ARM_nop(0)
             self.ARMrestart()
 
-    resume = ARMreleasecpu
+        #print >>sys.stderr,"Debug Status:\t%s\n" % self.statusstr()
+        #print >>sys.stderr,"CPSR: (%s) %s"%(self.ARMget_regCPSRstr())
+
+    #resume = ARMreleasecpu
     
     def resettap(self):
         self.writecmd(0x13, RESETTAP, 0,[])
@@ -441,7 +472,7 @@ class GoodFETARM(GoodFET):
     def ARMsetModeARM(self):
         r0 = None
         if ((self.current_dbgstate & DBG_TBIT)):
-            debugstr("=== Switching to ARM mode ===")
+            #debugstr("=== Switching to ARM mode ===")
             self.ARM_nop(0)
             self.ARMdebuginstr(THUMB_INSTR_BX_PC,0)
             self.ARM_nop(0)
@@ -452,7 +483,7 @@ class GoodFETARM(GoodFET):
 
     def ARMsetModeThumb(self):                               # needs serious work and truing
         self.resettap()
-        debugstr("=== Switching to THUMB mode ===")
+        #debugstr("=== Switching to THUMB mode ===")
         if ( not (self.current_dbgstate & DBG_TBIT)):
             self.storedPC |= 1
             r0 = self.ARMget_register(0)
@@ -554,13 +585,29 @@ class GoodFETARM(GoodFET):
                 #print out
         return ''.join(out)        
 
+    def ARMprintChunk(self, adr, wordcount, verbose=False, width=8):
+        for string in self.ARMreprChunk(adr, wordcount, verbose=False, width=8):
+            sys.stdout.write(string)
+
+    def ARMreprChunk(self, adr, wordcount, verbose=False, width=8):
+        adr &= 0xfffffffc
+        endva = adr + (4*wordcount)
+        output = [ "Dwords from 0x%x through 0x%x" % (adr, endva) ]
+        idx = 0
+        for data in self.ARMreadChunk(adr, wordcount, verbose):
+            if (idx % width) == 0:
+                yield ( "\n0x%.8x\t" % (adr + (4*idx)) )
+            yield ( "%.8x   " % (data) )
+            idx += 1
+
+        yield("\n")
+
     def ARMreadChunk(self, adr, wordcount, verbose=True):
         """ Only works in ARM mode currently
         WARNING: Addresses must be word-aligned!
         """
         regs = self.ARMget_registers()
         self.ARMset_registers([0xdeadbeef for x in xrange(14)], 0xe)
-        #output = []
         count = wordcount
         while (wordcount > 0):
             if (verbose and wordcount%64 == 0):  sys.stderr.write(".")
@@ -579,14 +626,17 @@ class GoodFETARM(GoodFET):
             #print hex(adr)
         # FIXME: handle the rest of the wordcount here.
         self.ARMset_registers(regs,0xe)
-        #return output
-        
+
+    '''def ARMreadStream(self, adr, bytecount):
+        #data = [struct.unpack("<L", x) for x in self.ARMreadChunk(adr, (bytecount-1/4)+1)]
+        diff = adr % 4
+        address = adr - diff
+        data = [ struct.pack("<L", x) for x in self.ARMreadChunk(address, (bytecount-1/4)+1) ]
+        return "".join(data)[diff:bytecount]'''
+    
     ARMreadMem = ARMreadChunk
     peek = ARMreadMem
-    '''def ARMreadStream(self, adr, bytecount):
-        data = [struct.unpack("<L", x) for x in self.ARMreadChunk(adr, (bytecount-1/4)+1)]
-        return "".join(data)[:bytecount]
-       ''' 
+
     def ARMwriteChunk(self, adr, wordarray):         
         """ Only works in ARM mode currently
         WARNING: Addresses must be word-aligned!
@@ -696,13 +746,13 @@ class GoodFETARM(GoodFET):
         d1,b1,a1 = struct.unpack("<LQL",self.data)
         return (a1,b1,d1)
 
-    def start(self):
+    def start(self, ident=False):
         """Start debugging."""
         self.writecmd(0x13,START,0,self.data)
-        print >>sys.stderr,"Identifying Target:"
-        ident=self.ARMidentstr()
-        print >>sys.stderr,ident
-        print >>sys.stderr,"Debug Status:\t%s\n" % self.statusstr()
+        if ident:
+            print >>sys.stderr,"Identifying Target:"
+            print >>sys.stderr, self.ARMidentstr()
+            print >>sys.stderr,"Debug Status:\t%s\n" % self.statusstr()
 
     def stop(self):
         """Stop debugging."""
@@ -719,4 +769,209 @@ class GoodFETARM(GoodFET):
     #    print "Flashing buffer to 0x%06x" % adr
     #    self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
 
+    def print_registers(self):
+        return [ hex(x) for x in self.ARMget_registers() ]
+
+    def print_stored_registers(self):
+        return [ hex(x) for x in self.stored_regs ]
+
+
+
+######### command line stuff #########
+from intelhex import IntelHex16bit, IntelHex
+
+def arm7_syntax():
+    print "Usage: %s verb [objects]\n" % sys.argv[0]
+    print "%s info" % sys.argv[0]
+    print "%s dump $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s erase" % sys.argv[0]
+    print "%s eraseinfo" % sys.argv[0]
+    print "%s flash $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s verify $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s poke 0x$adr 0x$val" % sys.argv[0]
+    print "%s peek 0x$start [0x$stop]" % sys.argv[0]
+    print "%s reset" % sys.argv[0]
+    sys.exit()
+
+def arm7_main():
+    ''' this function should be called from command line app '''
+
+    #Initialize FET and set baud rate
+    client=GoodFETARM7()
+    client.serInit()
+
+    client.setup()
+    client.start()
+
+    arm7_cli_handler(client, sys.argv)
+
+def arm7_cli_handler(client, argv):
+    if(argv[1]=="info"):
+        client.halt()
+        print >>sys.stderr,"Identifying Target:"
+        print >>sys.stderr, self.ARMidentstr()
+        print >>sys.stderr,"Debug Status:\t%s\n" % self.statusstr()
+        client.resume()
+
+
+    if(argv[1]=="dump"):
+        f = sys.argv[2]
+        start=0x00000000
+        stop=0xFFFFFFFF
+        if(len(sys.argv)>3):
+            start=int(sys.argv[3],16)
+        if(len(sys.argv)>4):
+            stop=int(sys.argv[4],16)
+        
+        print "Dumping from %04x to %04x as %s." % (start,stop,f)
+        #h = IntelHex16bit(None)
+        # FIXME: get mcu state and return it to that state
+        client.halt()
+
+        try:
+            h = IntelHex(None)
+            i=start
+            while i<=stop:
+                #data=client.ARMreadMem(i, 48)
+                data=client.ARMreadChunk(i, 48, verbose=0)
+                print "Dumped %06x."%i
+                for dword in data:
+                    if i<=stop and dword != 0xdeadbeef:
+                        h.puts( i, struct.pack("<I", dword) )
+                    i+=4
+            # FIXME: get mcu state and return it to that state
+        except:
+            print "Unknown error during read. Writing results to output file."
+            print "Rename file with last address dumped %06x."%i
+            pass
+
+        client.resume()
+        h.write_hex_file(f)
+
+    '''
+    if(sys.argv[1]=="erase"):
+        print "Erasing main flash memory."
+        client.ARMmasserase()
+
+    if(sys.argv[1]=="eraseinfo"):
+        print "Erasing info memory."
+        client.ARMinfoerase()
+
+        
+    '''
+    if(sys.argv[1]=="ivt"):
+        client.halt()
+        client.ARMprintChunk(0x0,0x20)
+        client.resume()
+
+    if(sys.argv[1]=="regs"):
+        client.halt()
+        for i in range(0,16):
+            print "r%i=%04x" % (i,client.ARMget_register(i))
+        client.resume()
+
+    if(sys.argv[1]=="flash"):
+        f=sys.argv[2]
+        start=0
+        stop=0x10000
+        if(len(sys.argv)>3):
+            start=int(sys.argv[3],16)
+        if(len(sys.argv)>4):
+            stop=int(sys.argv[4],16)
+        
+        client.halt()
+        h = IntelHex16bit(f)
+        
+        #Should this be default?
+        #Makes flashing multiple images inconvenient.
+        #client.ARMmasserase()
+        
+        count=0; #Bytes in commit.
+        first=0
+        vals=[]
+        last=0;  #Last address committed.
+        for i in h._buf.keys():
+            if((count>0x40 or last+2!=i) and count>0 and i&1==0):
+                #print "%i, %x, %x" % (len(vals), last, i)
+                client.ARMpokeflashblock(first,vals)
+                count=0
+                first=0
+                last=0
+                vals=[]
+            if(i>=start and i<stop  and i&1==0):
+                val=h[i>>1]
+                if(count==0):
+                    first=i
+                last=i
+                count+=2
+                vals+=[val&0xff,(val&0xff00)>>8]
+                if(i%0x100==0):
+                    print "%04x" % i
+        if count>0: #last commit, ivt
+            client.ARMpokeflashblock(first,vals)
+        client.resume()
+
+    if(sys.argv[1]=="verify"):
+        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)
+        
+        client.halt()
+        h = IntelHex16bit(f)
+        for i in h._buf.keys():
+            if(i>=start and i<stop and i&1==0):
+                peek=client.peek(i)
+                if(h[i>>1]!=peek):
+                    print "ERROR at %04x, found %04x not %04x"%(i,peek,h[i>>1])
+                if(i%0x100==0):
+                    print "%04x" % i
+        client.resume()
+
+
+    if(sys.argv[1]=="peek"):
+        start = 0x0000
+        if(len(sys.argv)>2):
+            start=int(sys.argv[2],16)
+
+        stop = start+4
+        if(len(sys.argv)>3):
+            stop=int(sys.argv[3],16)
+
+        print "Peeking from %04x to %04x." % (start,stop)
+        client.halt()
+        for dword in client.ARMreadChunk(start, (stop-start)/4, verbose=0):
+            print "%.4x: %.8x" % (start, dword)
+            start += 4
+        client.resume()
+
+    if(sys.argv[1]=="poke"):
+        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 %06x to become %04x." % (start,val)
+        client.halt()
+        #???while client.ARMreadMem(start)[0]&(~val)>0:
+        client.ARMwriteChunk(start, [val])
+        print "Poked to %.8x" % client.ARMreadMem(start)[0]
+        client.resume()
+
+
+    if(sys.argv[1]=="reset"):
+        #Set PC to RESET vector's value.
+        
+        #client.ARMsetPC(0x00000000)
+        #client.ARMset_regCPSR(0)
+        #client.ARMreleasecpu()
+        client.ARMresettarget(1000)
+
+    #client.ARMreleasecpu()
+    #client.ARMstop()
 
index cb9c7a8..12803b5 100644 (file)
@@ -225,6 +225,17 @@ def ebi_csr_decode(reg):
     wse =  (reg>>5)&1
     nws =  (reg>>2)&7
     dbw =  (reg&3)
+    return [ addr, csen, bat, tdf, pages, wse, nws, dbw]
+
+def ebi_csr_decode_str(reg):
+    (addr,
+    csen,
+    bat,
+    tdf,
+    pages,
+    wse,
+    nws,
+    dbw) = ebi_csr_decode(reg)
     output = ["(register: %x)"%reg,
             "Base Address: %s"%hex(addr<<20),
             "Chip Select: %s"%("False","True")[csen],
@@ -251,21 +262,36 @@ mcr_ale = {
 def mcr_decode(mcr):
     validAddrBits,maxAddrSpace,validCS,codeLabel = mcr_ale[mcr&7]
     drp = mcr>>4
-    output = ["Valid Address Bits: %s"%validAddrBits,
-            "Maximum Address Space: %xMB"%maxAddrSpace,
+    #print hex(drp)
+    if drp and drp != 1:
+        drp = 2
+       return (validAddrBits, maxAddrSpace, validCS, codeLabel, drp)
+
+def mcr_decode_str(mcr):
+    ( validAddrBits, maxAddrSpace, validCS, codeLabel, drp) = mcr_decode(mcr)
+    output = [ 
+            "(register: %x)"%mcr,
+            "Valid Address Bits: %s"%validAddrBits,
+            "Maximum Address Space: 0x%x MB"%maxAddrSpace,
             "Valid Chip Select: %s"%validCS,
             "Code Label:  %s"%codeLabel,
-            ("Standard Read Protocol for all external memory devices enabled (EBI_DRP_STANDARD)","Early Read Protocol for all external memory devices enabled (EBI_DRP_EARLY)")[drp]
+            ("Standard Read Protocol for all external memory devices enabled (EBI_DRP_STANDARD)","Early Read Protocol for all external memory devices enabled (EBI_DRP_EARLY)","Invalid mcr")[drp]
             ]
     return "\n".join(output)
 
 def wd_omr_decode(omr):
-    return "\n".join(["External Signal: %s"%("disabled","enabled")[(omr>>3)&1],
-            "External Signal: %s"%("disabled","enabled")[(omr>>3)&1],
-            "Interrupt: %s"%("disabled","enabled")[(omr>>2)&1],
-            "Reset: %s"%("disabled","enabled")[(omr>>1)&1],
-            "Watch Dog: %s"%("disabled","enabled")[(omr)&1],
+       return (omr>>4, (omr>>3)&1, (omr>>2)&1, (omr>>1)&1, omr&1)
+
+def wd_omr_decode_str(omr):
+    ( okey, esig, int, rst, wdog ) = wd_omr_decode(omr)
+    return "\n".join([
+            "Overflow Access Key (OKEY): %x"%(okey),
+            "External Signal (EXTEN): %s"%("disabled","enabled")[esig],
+            "Interrupt (IRQEN): %s"%("disabled","enabled")[int],
+            "Reset (RSTEN): %s"%("disabled","enabled")[rst],
+            "Watch Dog (WDEN): %s"%("disabled","enabled")[wdog],
             ])
+
 def wd_cmr_decode(cmr):
     return "MCK/%d"%(8,32,128,1024)[(cmr>>2)&0xf]
 
@@ -273,16 +299,32 @@ def wd_cmr_decode(cmr):
 
 
 
-class GoodFETAT91X40(GoodFETARM):
+class GoodFETAT91X40(GoodFETARM7):
     def __init__(self):
-        GoodFETARM.__init__(self)
+        GoodFETARM7.__init__(self)
         self.usart0 = usart.USART(usart.USART0_BASE)
         self.usart1 = usart.USART(usart.USART1_BASE)
+
+    def halt(self, disableWD=True):
+        GoodFETARM7.halt(self)
+        if not disableWD: return
+
+        #Disable Watch Dog
+        self.disableWatchDog()
+
+    def resume(self, enableWD=False):
+        GoodFETARM7.resume(self)
+        if not enableWD: return
+
+        self.enableWatchDog()
+
     def getChipSelectReg(self, chipnum):
         addr = EBI_BASE + (chipnum*4)
         reg, = self.ARMreadChunk(addr,1)
         return reg
     def getChipSelectRegstr(self, chipnum):
+        return ebi_csr_decode_str(self.getChipSelectReg(chipnum))
+    def getChipSelectReglist(self, chipnum):
         return ebi_csr_decode(self.getChipSelectReg(chipnum))
     def setChipSelectReg(self, chipnum, value):
         addr = EBI_BASE + (chipnum*4)
@@ -302,7 +344,10 @@ class GoodFETAT91X40(GoodFETARM):
         mcr, = self.ARMreadMem(EBI_MCR)
         return mcr
     def getMemoryControlRegisterstr(self):
-        return mcr_decode(self.getMemoryControlRegister())
+        return mcr_decode_str(self.getMemoryControlRegister())
+    def getEBIMCR(self):
+        print "EBI Memory Control Register\n"
+        print self.getMemoryControlRegisterstr()
 
     def getInterruptSourceModeReg(self, regnum):
         regval = self.ARMreadMem(AIC_SMR[regnum][0])
@@ -380,17 +425,36 @@ class GoodFETAT91X40(GoodFETARM):
     def getWatchDogOverflowModeReg(self):
         return self.ARMreadMem(WD_OMR)
     def getWatchDogOverflowModeStr(self):
-        return wd_omr_decode(self.getWatchDogOverflowModeReg())
-    def setWatchDogOverflowModeReg(self, mode=0x2340):
-        self.ARMwriteMem(WD_OMR, mode)
+        return wd_omr_decode_str(self.getWatchDogOverflowModeReg()[0])
+    def setWatchDogOverflowModeReg(self, mode=0x00002340):
+        self.ARMwriteMem(WD_OMR, [mode])
     def getWatchDogClockModeReg(self):
-        return self.ARMreadMem(WD_CMR)
+        return self.ARMreadMem(WD_CMR)[0]
     def setWatchDogClockModeReg(self, mode=0x06e):
-        self.ARMwriteMem(WD_CMR, mode)
+        self.ARMwriteMem(WD_CMR, [mode])
     def setWatchDogControlReg(self, mode=0xC071):
-        self.ARMwriteMem(WD_CR, mode)
+        self.ARMwriteMem(WD_CR, [mode])
     def getWatchDogStatusReg(self):
-        return self.ARMreadMem(WD_SR)
+        return self.ARMreadMem(WD_SR)[0]
+    def disableWatchDog(self):
+        # 0x234 in OKEY enables writing and 0 in lowest nibble disables
+        self.setWatchDogOverflowModeReg()
+    def enableWatchDog(self):
+        # Initialize the WD Clock Mode Register
+        self.setWatchDogClockModeReg(mode=0x0000373c)
+        # Restart the timer
+        self.setWatchDogControlReg(mode=0x0000c071)
+        # Enable the watchdog
+        self.setWatchDogOverflowModeReg(mode=0x00002340)
+    def statWatchDog(self):
+        print "Status Watch Dog:"
+        print "Register Value: 0b%s" % '{0:032b}'.format(self.getWatchDogOverflowModeReg()[0])
+        print self.getWatchDogOverflowModeStr()
+        print "Clock Mode Reg: %x" % self.getWatchDogClockModeReg()
+        print "Status Reg: %x" % self.getWatchDogStatusReg()
+    def checkWatchDog(self):
+        return self.getWatchDogOverflowModeStr()
+        
 
     def getChipID(self):
         chipid = self.ARMreadMem(SF_CIDR,1)
@@ -439,4 +503,203 @@ class GoodFETAT91X40(GoodFETARM):
         for page in xrange(pagecount):
             pages.append(self.ARMreadChunk(addr+(pagesz*page), pagesz))
         return pages
-                                
+
+
+######### command line stuff #########
+
+from GoodFETARM7 import *
+
+def at91x40_main():
+    ''' this function should be called from command line app '''
+    #Initialize FET and set baud rate
+    client=GoodFETAT91X40()
+    client.serInit()
+
+    client.setup()
+    client.start()
+
+    at91x40_cli_handler(client, sys.argv)
+
+def at91x40_cli_handler(client, argv):
+
+    if(argv[1]=="chipRegStr"):
+        client.halt()
+        print "#####"
+        print client.getChipSelectRegstr(int(argv[2]))
+        print "#####"
+        client.resume()
+
+    if(argv[1]=="chipRegList"):
+        client.halt()
+        print "#####"
+        print client.getChipSelectReglist(int(argv[2]))
+        print "#####"
+        client.resume()
+
+    if(argv[1]=="chipRegValue"):
+        client.halt()
+        print "#####"
+        print "Chip Register Value:",hex(client.getChipSelectReg(int(argv[2])))
+        print "#####"
+
+    if(argv[1]=="ecdump"):
+        f = argv[2]
+        start=0x00000000
+        stop=0xFFFFFFFF
+        if(len(argv)>3):
+            start=int(argv[3],16)
+        if(len(argv)>4):
+            stop=int(argv[4],16)
+
+        ##############################3
+        # Error checking requires a special register
+        # Should an error occur while reading from the chip's memory
+        # These values will help to test if the chip is working and 
+        # the memory is mapped properly before continuing
+        # Use the chipRegStr verb to determine the value of the 
+        # Special Register when the chip is operating normally
+        # Example: ./goodfet.at91x40 chipRegValue 1
+        ##############################3
+        # user$ ./goodfet.at91x40 chipRegValue 1
+        # Identifying Target:
+        # # DEBUG 0x120
+        # Chip IDCODE: 0x1f0f0f0f
+        #     ver: 1
+        #     partno: f0f0
+        #     mfgid: 787
+        #
+        # Debug Status:   Interrupts Enabled (or not?) 
+        #
+        # #####
+        # Chip Register Value: 0x10000000
+        # #####
+        ##############################
+        special_reg_num=1
+        special_addr=0x010000000
+        if(len(argv)>5):
+            # Yes, this requires that you set the start and stop addresses
+            special_reg_num=int(argv[5])
+            special_addr=int(argv[6],16)
+        
+        print "Dumping from %04x to %04x as %s." % (start,stop,f)
+        #h = IntelHex16bit(None)
+        # FIXME: get mcu state and return it to that state
+        client.halt()
+
+        h = IntelHex(None)
+        i=start
+        while i<=stop:
+            err_cnt = 0
+            #data=client.ARMreadMem(i, 48)
+            try:
+                data=client.ARMreadChunk(i, 48, verbose=0)
+                print "Dumped %06x."%i
+                for dword in data:
+                    if i<=stop and dword != 0xdeadbeef:
+                        h.puts( i, struct.pack("<I", dword) )
+                        err_cnt = 0
+                    i+=4
+            # FIXME: get mcu state and return it to that state
+            except:
+                # Handle exceptions by counting errors after pausing to let ARM settle
+                err_cnt = 1
+                fail = 0
+                while err_cnt:
+                    time.sleep(.25)
+                    if err_cnt == 100:
+                        print "Unknown error occurred at least 100 times. Resync did not work. Writing incomplete data to file."
+                        fail = 1
+                        break
+                    else:
+                        try:
+                            print "Unknown error during read. Resync and retry."
+
+                            # If we error out several times then reset the chip and restart
+                            # This uses a special register value from a Chip Select Register
+                            # to test that the chip is in the operation state we expect
+                            if not ((err_cnt+1) % 2):
+                                reset_cnt = 0
+                                while True:
+                                    print "    Reset:",reset_cnt
+                                    check_addr = client.getChipSelectReg(special_reg_num)
+                                    print "    Special Addr:",hex(special_addr)
+                                    print "    Check Addr:",hex(check_addr)
+                                    if (special_addr == check_addr):
+                                        break
+                                    if reset_cnt == 10:
+                                        reset_cnt = 0
+                                        print "    Resetting Target"
+                                        client.ARMresettarget(1000)
+                                        client.halt()
+                                    reset_cnt += 1
+                                    time.sleep(.25)
+                            else:
+                                #Resync ARM and Watch Dog
+                                client.resume()
+                                client.halt()
+
+                            #Disable Watch Dog
+                            if client.checkWatchDog():
+                                client.disableWatchDog()
+                            err_cnt = 0
+                        except:
+                            err_cnt += 1
+                            pass
+                if fail:
+                    break
+
+        client.resume()
+        h.write_hex_file(f)
+
+
+
+    if(argv[1]=="memorymap"):
+        client.halt()
+        print client.getEBIMCR()
+        print ""
+        print client.getEBIMemoryMap()
+        client.resume()
+
+    if(argv[1]=="memorycontrolreg"):
+        client.halt()
+        print client.getEBIMCR()
+        client.resume()
+
+
+
+    if(argv[1]=="stat_watchdog"):
+        client.halt()
+        print "Watch Dog Status:"
+        print "--"
+        client.statWatchDog()
+        client.resume()
+
+    if(argv[1]=="test_disable_watchdog"):
+        client.halt()
+        print "Status Watch Dog:"
+        client.statWatchDog()
+        print "--"
+        print "Disabling Watchdog Timer:"
+        client.disableWatchDog()
+        time.sleep(2) # pause to settle
+        print "\nChecking:"
+        client.statWatchDog()
+        print "--"
+        print "Done. Resume may re-enable Watch Dog."
+        client.resume()
+
+    # anything we didn't provide from arm7:        
+    arm7_cli_handler(client, argv)
+
+    #client.ARMreleasecpu()
+    #client.ARMstop()
+
+
+if __name__ == "__main__":
+    if(len(sys.argv)==1):
+        at91x40_syntax()
+
+    else: 
+        at91x40_main()
+
+
index 97d2ea3..1727521 100755 (executable)
@@ -4,183 +4,14 @@ import sys
 import struct
 import binascii
 
-from GoodFETARM7 import GoodFETARM
+from GoodFETARM7 import *
 from intelhex import IntelHex16bit, IntelHex
 
+if __name__ == "__main__":
+    if(len(sys.argv)==1):
+        arm7_syntax()
 
-if(len(sys.argv)==1):
-    print "Usage: %s verb [objects]\n" % sys.argv[0]
-    # halt, resume... but need for flash and dump to leave it as it was
-    print "%s info" % sys.argv[0]
-    print "%s dump $foo.hex [0x$start 0x$stop]" % sys.argv[0]
-    print "%s erase" % sys.argv[0]
-    print "%s eraseinfo" % sys.argv[0]
-    print "%s flash $foo.hex [0x$start 0x$stop]" % sys.argv[0]
-    print "%s verify $foo.hex [0x$start 0x$stop]" % sys.argv[0]
-    print "%s poke 0x$adr 0x$val" % sys.argv[0]
-    print "%s peek 0x$start [0x$stop]" % sys.argv[0]
-    print "%s reset" % sys.argv[0]
-    sys.exit()
+    else: 
+        arm7_main()
 
-#Initialize FET and set baud rate
-client=GoodFETARM()
-client.serInit()
 
-client.setup()
-client.start()
-
-if(sys.argv[1]=="info"):
-    client.halt()
-    client.resume()
-
-
-if(sys.argv[1]=="dump"):
-    f = sys.argv[2]
-    start=0x00000000
-    stop=0xFFFFFFFF
-    if(len(sys.argv)>3):
-        start=int(sys.argv[3],16)
-    if(len(sys.argv)>4):
-        stop=int(sys.argv[4],16)
-    
-    print "Dumping from %04x to %04x as %s." % (start,stop,f)
-    #h = IntelHex16bit(None)
-    # FIXME: get mcu state and return it to that state
-    client.halt()
-
-    h = IntelHex(None)
-    i=start
-    while i<=stop:
-        #data=client.ARMreadMem(i, 48)
-        data=client.ARMreadChunk(i, 48, verbose=0)
-        print "Dumped %06x."%i
-        for dword in data:
-            if i<=stop and dword != 0xdeadbeef:
-                h.puts( i, struct.pack("<I", dword) )
-            i+=4
-    # FIXME: get mcu state and return it to that state
-    client.resume()
-    h.write_hex_file(f)
-
-'''
-if(sys.argv[1]=="erase"):
-    print "Erasing main flash memory."
-    client.ARMmasserase()
-
-if(sys.argv[1]=="eraseinfo"):
-    print "Erasing info memory."
-    client.ARMinfoerase()
-
-    
-'''
-if(sys.argv[1]=="ivt"):
-    client.ARMreprChunk(0xFFC0,0xFFFF)
-
-if(sys.argv[1]=="regs"):
-    for i in range(0,16):
-        print "r%i=%04x" % (i,client.ARMget_register(i))
-
-if(sys.argv[1]=="flash"):
-    f=sys.argv[2]
-    start=0
-    stop=0x10000
-    if(len(sys.argv)>3):
-        start=int(sys.argv[3],16)
-    if(len(sys.argv)>4):
-        stop=int(sys.argv[4],16)
-    
-    client.halt()
-    h = IntelHex16bit(f)
-    
-    #Should this be default?
-    #Makes flashing multiple images inconvenient.
-    #client.ARMmasserase()
-    
-    count=0; #Bytes in commit.
-    first=0
-    vals=[]
-    last=0;  #Last address committed.
-    for i in h._buf.keys():
-        if((count>0x40 or last+2!=i) and count>0 and i&1==0):
-            #print "%i, %x, %x" % (len(vals), last, i)
-            client.ARMpokeflashblock(first,vals)
-            count=0
-            first=0
-            last=0
-            vals=[]
-        if(i>=start and i<stop  and i&1==0):
-            val=h[i>>1]
-            if(count==0):
-                first=i
-            last=i
-            count+=2
-            vals+=[val&0xff,(val&0xff00)>>8]
-            if(i%0x100==0):
-                print "%04x" % i
-    if count>0: #last commit, ivt
-        client.ARMpokeflashblock(first,vals)
-    client.resume()
-
-if(sys.argv[1]=="verify"):
-    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)
-    
-    client.halt()
-    h = IntelHex16bit(f)
-    for i in h._buf.keys():
-        if(i>=start and i<stop and i&1==0):
-            peek=client.peek(i)
-            if(h[i>>1]!=peek):
-                print "ERROR at %04x, found %04x not %04x"%(i,peek,h[i>>1])
-            if(i%0x100==0):
-                print "%04x" % i
-    client.resume()
-
-
-if(sys.argv[1]=="peek"):
-    start = 0x0000
-    if(len(sys.argv)>2):
-        start=int(sys.argv[2],16)
-
-    stop = start+4
-    if(len(sys.argv)>3):
-        stop=int(sys.argv[3],16)
-
-    print "Peeking from %04x to %04x." % (start,stop)
-    client.halt()
-    for dword in client.ARMreadChunk(start, (stop-start)/4, verbose=0):
-        print "%.4x: %.8x" % (start, dword)
-        start += 4
-    client.resume()
-
-if(sys.argv[1]=="poke"):
-    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 %06x to become %04x." % (start,val)
-    client.halt()
-    #???while client.ARMreadMem(start)[0]&(~val)>0:
-    client.ARMwriteChunk(start, [val])
-    print "Poked to %.8x" % client.ARMreadMem(start)[0]
-    client.resume()
-
-
-if(sys.argv[1]=="reset"):
-    #Set PC to RESET vector's value.
-    
-    #client.ARMsetPC(0x00000000)
-    #client.ARMset_regCPSR(0)
-    #client.ARMreleasecpu()
-    client.ARMresettarget(1000)
-
-#client.ARMreleasecpu()
-#client.ARMstop()
diff --git a/client/goodfet.at91x40 b/client/goodfet.at91x40
new file mode 100755 (executable)
index 0000000..cb45500
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+
+import sys
+import struct
+import binascii
+import time
+
+from GoodFETAT91X40 import *
+from intelhex import IntelHex16bit, IntelHex
+
+#######################################
+#   GoodFET              AT91r40008  
+#     PIN                 PIN
+#
+#      1 <----- TDO ----> 90
+#      3 <----- TDI ----> 89
+#      5 <----- TMS ----> 88
+#      7 <----- TCK ----> 91
+#      9 <----- GND ----> GND
+#     11 <----- RST ----> 79
+#######################################
+
+
+def at91x40_syntax():
+    print "Usage: %s verb [objects]\n" % sys.argv[0]
+    print "%s info" % sys.argv[0]
+    print "%s dump $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s ecdump $foo.hex [0x$start 0x$stop]   - exception-handling dump" % sys.argv[0]
+    print "%s erase" % sys.argv[0]
+    print "%s eraseinfo" % sys.argv[0]
+    print "%s flash $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s verify $foo.hex [0x$start 0x$stop]" % sys.argv[0]
+    print "%s poke 0x$adr 0x$val" % sys.argv[0]
+    print "%s peek 0x$start [0x$stop]" % sys.argv[0]
+    print "%s stat_watchdog" % sys.argv[0]
+    print "%s test_disable_watchdog" % sys.argv[0]
+    print "%s reset" % sys.argv[0]
+    sys.exit()
+
+if __name__ == "__main__":
+    if(len(sys.argv)==1):
+        at91x40_syntax()
+
+    else: 
+        at91x40_main()
+
+
index cb54d4e..6f8d2c0 100755 (executable)
@@ -18,6 +18,7 @@ def init():
     print >>sys.stderr,"Starting JTAG ARM on goodfet...\n"
     client.start()
     print "STARTUP: %s\n"%repr(client.data)
+    client.disableWatchDog()
     #
 
 def print_registers():