yay! it worked!
authordodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Tue, 6 Jul 2010 14:42:49 +0000 (14:42 +0000)
committerdodge-this <dodge-this@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Tue, 6 Jul 2010 14:42:49 +0000 (14:42 +0000)
jtag arm was pretty much always working.  i simply wanted too much out of it.
i forgot to contemplate that debugging through jtag *is shellcoding* and needs
to be treated as if it is fragile... because it is.

writing to a register involves ldr rX [rY]
turns out, when rY is not word aligned, the contents of the data is shifted in funky ways...
weirder still, the rotating differed between r0-7 and r8-15.

solution?  use PC.  ldr rX, [r15] means the highest likelihood of having word-aligned register.
change PC at your own peril.  make sure it is word-aligned.

and all is well.

initial testing of reading from memory seems promising.  although, debugging in the process doesn't work *at all* because the python handler includes the debug messages as part of the data.

need to true up reading memory, writing memory, reading code, and reading/writing PSRs.

yay!

git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@657 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/GoodFETARM.py
client/gplay-arm.py
firmware/apps/jtag/jtagarm7tdmi.c
firmware/include/jtagarm7tdmi.h

index 4d25bd7..3305820 100644 (file)
@@ -173,7 +173,7 @@ class GoodFETARM(GoodFET):
         return retval
     def ARMset_register(self, reg, val):
         """Get an ARM's Register"""
         return retval
     def ARMset_register(self, reg, val):
         """Get an ARM's Register"""
-        self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0,val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
+        self.writecmd(0x13,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
         #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
         return retval
         #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
         return retval
@@ -202,15 +202,17 @@ class GoodFETARM(GoodFET):
             instr = struct.pack("<L", instr)
         self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
         return (self.data[0])
             instr = struct.pack("<L", instr)
         self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
         return (self.data[0])
-    def ARMpeekcodebyte(self,adr):
+    def ARMpeekcodebyte(self,adr,words):
         """Read the contents of code memory at an address."""
         """Read the contents of code memory at an address."""
-        self.data=[adr&0xff, (adr&0xff00)>>8]
+        self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ]
         self.writecmd(0x13,PEEK,2,self.data)
         self.writecmd(0x13,PEEK,2,self.data)
-        retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
-        return retval
+        retval = []
+        retval.append(self.serialport.read(words*4))
+        #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
+        return "".join(retval)
     def ARMpeekdatabyte(self,adr):
         """Read the contents of data memory at an address."""
     def ARMpeekdatabyte(self,adr):
         """Read the contents of data memory at an address."""
-        self.data=[adr&0xff, (adr&0xff00)>>8]
+        self.data=[adr&0xff, (adr&0xff00)>>8, (adr&0xff0000)>>16, (adr&0xff000000)>>24]
         self.writecmd(0x13, PEEK, 2, self.data)
         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
         return retval
         self.writecmd(0x13, PEEK, 2, self.data)
         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
         return retval
index 80a4b34..f216a1f 100755 (executable)
@@ -9,14 +9,24 @@ data = []
 client=GoodFETARM();
 def init():
     #Initailize FET and set baud rate
 client=GoodFETARM();
 def init():
     #Initailize FET and set baud rate
+    print >>sys.stderr,"Connecting to goodfet..."
     client.serInit()
     #
     #Connect to target
     client.serInit()
     #
     #Connect to target
+    print >>sys.stderr,"Setting up JTAG ARM on goodfet..."
     client.setup()
     client.setup()
+    print >>sys.stderr,"Starting JTAG ARM on goodfet..."
     client.start()
     print "STARTUP: "+repr(client.data)
     #
 
     client.start()
     print "STARTUP: "+repr(client.data)
     #
 
+def print_registers():
+    return [ hex(client.ARMget_register(x)) for x in range(15) ]
+
+def regwratchet(num,hi=13,lo=0):
+    for x in xrange(lo,hi+1):
+        client.ARMset_register(x,num)
+
 def test1():
     global data
     print "\n\nTesting JTAG for ARM\n"
 def test1():
     global data
     print "\n\nTesting JTAG for ARM\n"
@@ -204,16 +214,34 @@ def test6(start=0,end=15):
             print "Debug State: %x"%client.ARMget_dbgstate ()
         seed += 1
 
             print "Debug State: %x"%client.ARMget_dbgstate ()
         seed += 1
 
-def test7(start=0,end=15):
+def test7(start=0,end=14):
     global results,seed
     results = [[] for x in range(end)]
     while True:
         #print "IDCODE:      %x"%client.ARMident()
         #print "Debug State: %x"%client.ARMget_dbgstate ()
     global results,seed
     results = [[] for x in range(end)]
     while True:
         #print "IDCODE:      %x"%client.ARMident()
         #print "Debug State: %x"%client.ARMget_dbgstate ()
-        for x in range(end,start, -1):
+        for x in range(end,start-1, -1):
             num = client.ARMset_register(x,seed+x)
             time.sleep(1)
             print "set_register(%d,0x%x):  %x"%(x,seed+x,num)
             num = client.ARMset_register(x,seed+x)
             time.sleep(1)
             print "set_register(%d,0x%x):  %x"%(x,seed+x,num)
+        for y in range(10):
+          for x in range(start,endi+1):
+            num = client.ARMget_register(x)
+            time.sleep(1)
+            print "get_register(%d):             %x"%(x,num)
+            results[x].append(num)
+        seed += 1
+
+def readtest(start=0,end=14):
+    global results,seed
+    results = [[] for x in range(end)]
+    while True:
+        #print "IDCODE:      %x"%client.ARMident()
+        #print "Debug State: %x"%client.ARMget_dbgstate ()
+        for x in range(end,start, -1):
+            num = client.ARMget_register(x)
+            time.sleep(1)
+            print "get_register(%d):  %x"%(x,num)
         for y in range(10):
           for x in range(start,end,2):
             num = client.ARMget_register(x)
         for y in range(10):
           for x in range(start,end,2):
             num = client.ARMget_register(x)
index 8c4bfc4..cf708ae 100644 (file)
@@ -124,10 +124,10 @@ void jtag_reset_to_runtest_idle() {
 }
 
 void jtag_arm_tcktock() {
 }
 
 void jtag_arm_tcktock() {
-  delay(100);  // FIXME: Should never wait this long...
+  delay(1);  // FIXME: Should never wait this long...
   CLRTCK; 
   PLEDOUT^=PLEDPIN; 
   CLRTCK; 
   PLEDOUT^=PLEDPIN; 
-  delay(100);  // FIXME: Should never wait this long...
+  delay(1);  // FIXME: Should never wait this long...
   SETTCK; 
   PLEDOUT^=PLEDPIN;
 }
   SETTCK; 
   PLEDOUT^=PLEDPIN;
 }
@@ -396,9 +396,9 @@ unsigned long jtagarm7tdmi_setMode_ARM(){               // PROVEN
 //! shifter for writing to chain2 (EmbeddedICE). 
 unsigned long eice_write(unsigned char reg, unsigned long data){
   unsigned long retval, temp;
 //! shifter for writing to chain2 (EmbeddedICE). 
 unsigned long eice_write(unsigned char reg, unsigned long data){
   unsigned long retval, temp;
-  debugstr("eice_write");
-  debughex(reg);
-  debughex32(data);
+  //debugstr("eice_write");
+  //debughex(reg);
+  //debughex32(data);
   jtagarm7tdmi_scan_intest(2);
   // Now shift in the 32 bits
   SHIFT_DR;
   jtagarm7tdmi_scan_intest(2);
   // Now shift in the 32 bits
   SHIFT_DR;
@@ -417,8 +417,8 @@ unsigned long eice_write(unsigned char reg, unsigned long data){
 //! shifter for reading from chain2 (EmbeddedICE).
 unsigned long eice_read(unsigned char reg){               // PROVEN
   unsigned long temp, retval;
 //! shifter for reading from chain2 (EmbeddedICE).
 unsigned long eice_read(unsigned char reg){               // PROVEN
   unsigned long temp, retval;
-  debugstr("eice_read");
-  debughex(reg);
+  //debugstr("eice_read");
+  //debughex(reg);
   jtagarm7tdmi_scan_intest(2);
 
   // send in the register address - 5 bits LSB
   jtagarm7tdmi_scan_intest(2);
 
   // send in the register address - 5 bits LSB
@@ -431,7 +431,7 @@ unsigned long eice_read(unsigned char reg){               // PROVEN
   SHIFT_DR;
   // Now shift out the 32 bits
   retval = jtagarmtransn(0L, 32, LSB, END, RETIDLE);   // atmel arm jtag docs pp.10-11: LSB first
   SHIFT_DR;
   // Now shift out the 32 bits
   retval = jtagarmtransn(0L, 32, LSB, END, RETIDLE);   // atmel arm jtag docs pp.10-11: LSB first
-  debughex32(retval);
+  //debughex32(retval);
   return(retval);   // atmel arm jtag docs pp.10-11: LSB first
   
 }
   return(retval);   // atmel arm jtag docs pp.10-11: LSB first
   
 }
@@ -501,43 +501,59 @@ void jtagarm7tdmi_disable_watchpoint1(){
 //! Push an instruction into the CPU pipeline
 //  NOTE!  Must provide EXECNOPARM for parameter if no parm is required.
 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
 //! Push an instruction into the CPU pipeline
 //  NOTE!  Must provide EXECNOPARM for parameter if no parm is required.
 unsigned long jtagarm7tdmi_exec(unsigned long instr, unsigned long parameter, unsigned char systemspeed) {
-  unsigned long retval;
+  unsigned long retval,waitcount=0xff;
 
   debughex32(jtagarm7tdmi_nop( 0));
   debughex32(jtagarm7tdmi_nop(systemspeed));
   debughex32(jtagarm7tdmi_instr_primitive(instr, 0));      // write 32-bit instruction code into DR
   debughex32(jtagarm7tdmi_nop( 0));
 
   debughex32(jtagarm7tdmi_nop( 0));
   debughex32(jtagarm7tdmi_nop(systemspeed));
   debughex32(jtagarm7tdmi_instr_primitive(instr, 0));      // write 32-bit instruction code into DR
   debughex32(jtagarm7tdmi_nop( 0));
-  debughex32(jtagarm7tdmi_nop( 0));
-  debughex32(jtagarm7tdmi_instr_primitive(parameter, 0));  // inject long
-  retval = jtagarm7tdmi_nop( 0);
-  debughex32(retval);
-  debughex32(jtagarm7tdmi_nop( 0));
-  debughex32(jtagarm7tdmi_nop( 0));
+  if (systemspeed){
+    jtagarm7tdmi_restart();                   // SHIFT_IR with RESTART instruction
 
 
+    // Poll the Debug Status Register for DBGACK and nMREQ to be HIGH
+    while ((jtagarm7tdmi_get_dbgstate() & 9L) == 0  && waitcount > 0){
+      delay(1);
+      waitcount --;
+    }
+    if (waitcount == 0)
+      return (-1);
+    retval = 0x12345678;
+  } else {
+    debughex32(jtagarm7tdmi_nop( 0));
+    debughex32(jtagarm7tdmi_instr_primitive(parameter, 0));  // inject long
+    retval = jtagarm7tdmi_nop( 0);
+    debughex32(retval);
+    debughex32(jtagarm7tdmi_nop( 0));
+    debughex32(jtagarm7tdmi_nop( 0));
+  }
   return(retval);
 }
 
 //! Retrieve a 32-bit Register value
 unsigned long jtagarm7tdmi_get_register(unsigned long reg) {
   return(retval);
 }
 
 //! Retrieve a 32-bit Register value
 unsigned long jtagarm7tdmi_get_register(unsigned long reg) {
-  unsigned long retval = 0L, instr, reg2;
+  unsigned long retval=0L, instr, reg2=0L;
   reg2 = (reg&0xfL)<<16;
   // push nop into pipeline - clean out the pipeline...
   instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG;   // STR Rx, [R14] 
   instr ^= reg2;
   //instr = (unsigned long)(((unsigned long)reg<<12) | ARM_READ_REG); 
   //debugstr("Reading:");
   reg2 = (reg&0xfL)<<16;
   // push nop into pipeline - clean out the pipeline...
   instr = (unsigned long)(reg<<12L) | (unsigned long)ARM_READ_REG;   // STR Rx, [R14] 
   instr ^= reg2;
   //instr = (unsigned long)(((unsigned long)reg<<12) | ARM_READ_REG); 
   //debugstr("Reading:");
-  debughex32(instr);
+  //debughex32(instr);
 
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_instr_primitive(instr, 0);
 
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_instr_primitive(instr, 0);
-  debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - fetched
-  debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - decoded
-  debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - executed 
+  //debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - fetched
+  //debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - decoded
+  //debughex32(jtagarm7tdmi_nop( 0));                // push nop into pipeline - executed 
+  jtagarm7tdmi_nop( 0);
+  jtagarm7tdmi_nop( 0);
+  jtagarm7tdmi_nop( 0);
   retval = jtagarm7tdmi_nop( 0);                        // recover 32-bit word
   retval = jtagarm7tdmi_nop( 0);                        // recover 32-bit word
-  debughex32(retval);
-  debughex32(jtagarm7tdmi_nop( 0));
+  //debughex32(retval);
+  //debughex32(jtagarm7tdmi_nop( 0));
+  jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   return retval;
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
   return retval;
@@ -545,29 +561,33 @@ unsigned long jtagarm7tdmi_get_register(unsigned long reg) {
 
 //! Set a 32-bit Register value
 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) {
 
 //! Set a 32-bit Register value
 void jtagarm7tdmi_set_register(unsigned long reg, unsigned long val) {
-  unsigned long instr, reg2;
+  unsigned long instr, reg2=0;
   reg2 = (reg&0xfL)<<16;
   instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); //  LDR Rx, [R14]
   reg2 = (reg&0xfL)<<16;
   instr = (unsigned long)(((unsigned long)reg<<12L) | ARM_WRITE_REG); //  LDR Rx, [R14]
-  instr ^= reg2;
+  //instr ^= reg2;
   //instr |= (unsigned long)((((unsigned long)reg)&0x7)<<8)<<8;
   //debugstr("Writing:");
   //instr |= (unsigned long)((((unsigned long)reg)&0x7)<<8)<<8;
   //debugstr("Writing:");
-  debughex32(instr);
+  //debughex32(instr);
   //debughex32(val);
   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
   jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
   //debughex32(val);
   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
   jtagarm7tdmi_nop( 0);            // push nop into pipeline - clean out the pipeline...
   jtagarm7tdmi_instr_primitive(instr, 0); // push instr into pipeline - fetch
-  jtagarm7tdmi_nop( 0);            // push nop into pipeline - decode
-  jtagarm7tdmi_nop( 0);            // push nop into pipeline - execute
   
   
-  //jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
-  jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
-  //jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
-  jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
-  jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
-
   if (reg == ARM_REG_PC){
   if (reg == ARM_REG_PC){
+  //jtagarm7tdmi_nop( 0);            // push nop into pipeline - execute
+    jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
+    jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
+    jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
     jtagarm7tdmi_nop( 0);
     jtagarm7tdmi_nop( 0);
     jtagarm7tdmi_nop( 0);
     jtagarm7tdmi_nop( 0);
+  } else {
+  jtagarm7tdmi_nop( 0);            // push nop into pipeline - decode
+  jtagarm7tdmi_nop( 0);            // push nop into pipeline - execute
+    //jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
+    jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
+    //jtagarm7tdmi_instr_primitive(val, 0); // push 32-bit word on data bus
+    jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
+    jtagarm7tdmi_nop( 0);            // push nop into pipeline - executed 
   }
   jtagarm7tdmi_nop( 0);
 }
   }
   jtagarm7tdmi_nop( 0);
 }
@@ -821,7 +841,6 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len
     debughex32(jtagarm7tdmi_haltcpu());
     //jtagarm7tdmi_resettap();
     cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
     debughex32(jtagarm7tdmi_haltcpu());
     //jtagarm7tdmi_resettap();
     cmddatalong[0] = jtagarm7tdmi_get_dbgstate();
-    
     txdata(app,verb,0x4);
     break;
   case JTAGARM7TDMI_READMEM:
     txdata(app,verb,0x4);
     break;
   case JTAGARM7TDMI_READMEM:
@@ -832,7 +851,7 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len
     txhead(app,verb,len);
     
        jtagarm7tdmi_resettap();
     txhead(app,verb,len);
     
        jtagarm7tdmi_resettap();
-       delay(10);
+       delay(1);
        
     for(i=0;i<blocks;i++){
          val=jtagarm7tdmi_readmem(at);
        
     for(i=0;i<blocks;i++){
          val=jtagarm7tdmi_readmem(at);
@@ -902,14 +921,11 @@ void jtagarm7tdmihandle(unsigned char app, unsigned char verb, unsigned long len
        jtagarm7tdmi_resettap();
     val = cmddata[0];
     cmddatalong[0] = jtagarm7tdmi_get_register(val);
        jtagarm7tdmi_resettap();
     val = cmddata[0];
     cmddatalong[0] = jtagarm7tdmi_get_register(val);
-    //debughex32(cmddatalong[0]);
     txdata(app,verb,4);
     break;
     txdata(app,verb,4);
     break;
-  case JTAGARM7TDMI_SET_REGISTER:           // FIXME: NOT AT ALL CORRECT, THIS IS TESTING CODE ONLY
+  case JTAGARM7TDMI_SET_REGISTER:
        jtagarm7tdmi_resettap();
        jtagarm7tdmi_resettap();
-    debughex32(cmddatalong[1]);
-    jtagarm7tdmi_set_register(cmddata[0], cmddatalong[1]);
-    cmddatalong[0] = cmddatalong[1];
+    jtagarm7tdmi_set_register(cmddatalong[1], cmddatalong[0]);
     txdata(app,verb,4);
     break;
   case JTAGARM7TDMI_GET_REGISTERS:
     txdata(app,verb,4);
     break;
   case JTAGARM7TDMI_GET_REGISTERS:
index d90b25f..7eab988 100644 (file)
@@ -171,9 +171,9 @@ The least significant bit of the instruction register is scanned in and scanned
 //      http://www.atmel.com/dyn/resources/prod_documents/DDI0029G_7TDMI_R3_trm.pdf
 #define EXECNOPARM                  0xe1a00000L
 #define ARM_INSTR_NOP               0xe1a00000L
 //      http://www.atmel.com/dyn/resources/prod_documents/DDI0029G_7TDMI_R3_trm.pdf
 #define EXECNOPARM                  0xe1a00000L
 #define ARM_INSTR_NOP               0xe1a00000L
-#define ARM_INSTR_STR_Rx_r14        0xe58e0000L // from atmel docs
+#define ARM_INSTR_STR_Rx_r14        0xe58f0000L // from atmel docs
 #define ARM_READ_REG                ARM_INSTR_STR_Rx_r14
 #define ARM_READ_REG                ARM_INSTR_STR_Rx_r14
-#define ARM_INSTR_LDR_Rx_r14        0xe59e0000L // from atmel docs
+#define ARM_INSTR_LDR_Rx_r14        0xe59f0000L // from atmel docs
 #define ARM_WRITE_REG               ARM_INSTR_LDR_Rx_r14
 #define ARM_INSTR_LDR_R1_r0_4       0xe4901004L
 #define ARM_READ_MEM                ARM_INSTR_LDR_R1_r0_4
 #define ARM_WRITE_REG               ARM_INSTR_LDR_Rx_r14
 #define ARM_INSTR_LDR_R1_r0_4       0xe4901004L
 #define ARM_READ_MEM                ARM_INSTR_LDR_R1_r0_4