From b7a6e00b7d75a7f29401c2aeeb2e19cbd622d678 Mon Sep 17 00:00:00 2001 From: dodge-this Date: Tue, 6 Jul 2010 14:42:49 +0000 Subject: [PATCH] yay! it worked! 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 | 14 +++-- client/gplay-arm.py | 32 ++++++++++- firmware/apps/jtag/jtagarm7tdmi.c | 96 ++++++++++++++++++------------- firmware/include/jtagarm7tdmi.h | 4 +- 4 files changed, 96 insertions(+), 50 deletions(-) diff --git a/client/GoodFETARM.py b/client/GoodFETARM.py index 4d25bd7..3305820 100644 --- a/client/GoodFETARM.py +++ b/client/GoodFETARM.py @@ -173,7 +173,7 @@ class GoodFETARM(GoodFET): 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(">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) - retval = struct.unpack(">8] + self.data=[adr&0xff, (adr&0xff00)>>8, (adr&0xff0000)>>16, (adr&0xff000000)>>24] self.writecmd(0x13, PEEK, 2, self.data) retval = struct.unpack(">sys.stderr,"Connecting to goodfet..." client.serInit() # #Connect to target + print >>sys.stderr,"Setting up JTAG ARM on goodfet..." client.setup() + print >>sys.stderr,"Starting JTAG ARM on goodfet..." 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" @@ -204,16 +214,34 @@ def test6(start=0,end=15): 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 () - 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) + 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) diff --git a/firmware/apps/jtag/jtagarm7tdmi.c b/firmware/apps/jtag/jtagarm7tdmi.c index 8c4bfc4..cf708ae 100644 --- a/firmware/apps/jtag/jtagarm7tdmi.c +++ b/firmware/apps/jtag/jtagarm7tdmi.c @@ -124,10 +124,10 @@ void jtag_reset_to_runtest_idle() { } void jtag_arm_tcktock() { - delay(100); // FIXME: Should never wait this long... + delay(1); // FIXME: Should never wait this long... CLRTCK; PLEDOUT^=PLEDPIN; - delay(100); // FIXME: Should never wait this long... + delay(1); // FIXME: Should never wait this long... 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; - 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; @@ -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; - debugstr("eice_read"); - debughex(reg); + //debugstr("eice_read"); + //debughex(reg); 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 - debughex32(retval); + //debughex32(retval); 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) { - 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_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) { - 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:"); - debughex32(instr); + //debughex32(instr); 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 - debughex32(retval); - debughex32(jtagarm7tdmi_nop( 0)); + //debughex32(retval); + //debughex32(jtagarm7tdmi_nop( 0)); + jtagarm7tdmi_nop( 0); 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) { - 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] - instr ^= reg2; + //instr ^= reg2; //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 - 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){ + //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); + } 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); } @@ -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(); - 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(); - delay(10); + delay(1); for(i=0;i