2 # GoodFET ARM Client Library
5 # Good luck with alpha / beta code.
6 # Contributions and bug reports welcome.
11 raise Exception("DEPRECATED. USE GoodFETARM7")
13 import sys, binascii, struct, time
14 import atlasutils.smartprint as asp
15 from GoodFET import GoodFET
16 from intelhex import IntelHex
19 "at91sam7": {0:(0x100000, "Flash before remap, SRAM after remap"),
20 0x100000: (0x100000, "Internal Flash"),
21 0x200000: (0x100000, "Internal SRAM"),
39 # ARM7TDMI JTAG commands
45 GET_DEBUG_STATE = 0x85
59 CHIP_ERASE = 0x97 # can do?
60 # Really ARM specific stuff
88 PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
89 PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"),
90 PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"),
91 PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"),
92 PM_irq: ("Abort Processor Mode", "irq", "Implements virtual memory and/or memory protection"),
93 PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"),
94 PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"),
106 "nImprDataAbort_int",
134 ARM_INSTR_NOP = 0xe1a00000L
135 ARM_INSTR_BX_R0 = 0xe12fff10L
136 ARM_INSTR_STR_Rx_r14 = 0xe58f0000L # from atmel docs
137 ARM_READ_REG = ARM_INSTR_STR_Rx_r14
138 ARM_INSTR_LDR_Rx_r14 = 0xe59f0000L # from atmel docs
139 ARM_WRITE_REG = ARM_INSTR_LDR_Rx_r14
140 ARM_INSTR_LDR_R1_r0_4 = 0xe4901004L
141 ARM_READ_MEM = ARM_INSTR_LDR_R1_r0_4
142 ARM_INSTR_STR_R1_r0_4 = 0xe4801004L
143 ARM_WRITE_MEM = ARM_INSTR_STR_R1_r0_4
144 ARM_INSTR_MRS_R0_CPSR = 0xe10f0000L
145 ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
146 ARM_INSTR_STMIA_R14_r0_rx = 0xE88E0000L # add up to 65k to indicate which registers...
147 ARM_STORE_MULTIPLE = ARM_INSTR_STMIA_R14_r0_rx
148 ARM_INSTR_SKANKREGS = 0xE88F7fffL
149 ARM_INSTR_CLOBBEREGS = 0xE89F7fffL
151 ARM_INSTR_B_PC = 0xea000000L
152 ARM_INSTR_BX_PC = 0xe1200010L # need to set r0 to the desired address
153 THUMB_INSTR_STR_R0_r0 = 0x60006000L
154 THUMB_INSTR_MOV_R0_PC = 0x46b846b8L
155 THUMB_INSTR_BX_PC = 0x47784778L
156 THUMB_INSTR_NOP = 0x1c001c00L
159 ARM7TDMI_IR_EXTEST = 0x0
160 ARM7TDMI_IR_SCAN_N = 0x2
161 ARM7TDMI_IR_SAMPLE = 0x3
162 ARM7TDMI_IR_RESTART = 0x4
163 ARM7TDMI_IR_CLAMP = 0x5
164 ARM7TDMI_IR_HIGHZ = 0x7
165 ARM7TDMI_IR_CLAMPZ = 0x9
166 ARM7TDMI_IR_INTEST = 0xC
167 ARM7TDMI_IR_IDCODE = 0xE
168 ARM7TDMI_IR_BYPASS = 0xF
171 def PSRdecode(psrval):
172 output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
173 for x in xrange(5,32):
175 output.append(PSR_bits[x])
176 return " ".join(output)
178 fmt = [None, "B", "<H", None, "<L", None, None, None, "<Q"]
180 s = struct.pack(fmt[byts], val)
181 return [ord(b) for b in s ]
183 class GoodFETARM(GoodFET):
184 """A GoodFET variant for use with ARM7TDMI microprocessor."""
185 def ARMhaltcpu(self):
187 self.writecmd(0x13,HALTCPU,0,self.data)
188 print "CPSR: (%s) %s"%(self.ARMget_regCPSRstr())
190 def ARMreleasecpu(self):
191 """Resume the CPU."""
192 self.writecmd(0x13,RESUMECPU,0,self.data)
193 def ARMsetModeArm(self, restart=0):
194 self.writecmd(0x13,SET_MODE_ARM,0,[restart])
195 def ARMsetModeThumb(self, restart=0):
196 self.writecmd(0x13,SET_MODE_THUMB,0,[restart])
198 #self.ARMreleasecpu()
200 print "Status: %s" % self.ARMstatusstr()
202 #Grab ident three times, should be equal.
203 ident1=self.ARMident()
204 ident2=self.ARMident()
205 ident3=self.ARMident()
206 if(ident1!=ident2 or ident2!=ident3):
207 print "Error, repeated ident attempts unequal."
208 print "%04x, %04x, %04x" % (ident1, ident2, ident3)
210 #Set and Check Registers
211 regs = [1024+x for x in range(0,15)]
213 for x in range(len(regs)):
214 self.ARMset_register(x, regs[x])
216 for x in range(len(regs)):
217 regr.append(self.ARMget_register(x))
219 for x in range(len(regs)):
220 if regs[x] != regr[x]:
221 print "Error, R%d fail: %x != %x"%(x,regs[x],regr[x])
228 #Single step, printing PC.
229 print "Tracing execution at startup."
232 byte=self.ARMpeekcodebyte(i)
233 #print "PC=%04x, %02x" % (pc, byte)
236 print "Verifying that debugging a NOP doesn't affect the PC."
237 for i in range(1,15):
239 self.ARMdebuginstr([NOP])
240 if(pc!=self.ARMgetPC()):
241 print "ERROR: PC changed during ARMdebuginstr([NOP])!"
243 print "Checking pokes to XRAM."
244 for i in range(0xf000,0xf020):
245 self.ARMpokedatabyte(i,0xde)
246 if(self.ARMpeekdatabyte(i)!=0xde):
247 print "Error in DATA at 0x%04x" % i
249 #print "Status: %s." % self.ARMstatusstr()
255 """Move the FET into the JTAG ARM application."""
256 #print "Initializing ARM."
257 self.writecmd(0x13,SETUP,0,self.data)
258 def ARMget_dbgstate(self):
259 """Read the config register of an ARM."""
260 self.writecmd(0x13,GET_DEBUG_STATE,0,self.data)
261 retval = struct.unpack("<L", self.data[:4])[0]
263 def ARMget_dbgctrl(self):
264 """Read the config register of an ARM."""
265 self.writecmd(0x13,GET_DEBUG_CTRL,0,self.data)
266 retval = struct.unpack("B", self.data)[0]
268 def ARMset_dbgctrl(self,config):
269 """Write the config register of an ARM."""
270 self.writecmd(0x13,SET_DEBUG_CTRL,1,[config&7])
271 def ARMlockchip(self):
272 """Set the flash lock bit in info mem.
273 Chip-Specific. Not implemented"""
274 #self.writecmd(0x13, LOCKCHIP, 0, [])
275 raise Exception("Unimplemented: lockchip. This is chip specific and must be implemented for each chip.")
278 def ARMidentstr(self):
279 ident=self.ARMident()
281 partno = (ident >> 12) & 0x10
282 mfgid = ident & 0xfff
283 return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident);
285 """Get an ARM's ID."""
286 self.writecmd(0x13,GET_CHIP_ID,0,[])
287 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
289 def ARMsetPC(self, val):
290 """Set an ARM's PC. Note: real PC gets all wonky in debug mode, this changes the "saved" PC which is used when exiting debug mode"""
291 self.writecmd(0x13,SET_PC,0,chop(val,4))
293 """Get an ARM's PC. Note: real PC gets all wonky in debug mode, this is the "saved" PC"""
294 self.writecmd(0x13,GET_PC,0,[])
295 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
297 def ARMget_register(self, reg):
298 """Get an ARM's Register"""
299 self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
300 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
302 def ARMset_register(self, reg, val):
303 """Get an ARM's Register"""
304 self.writecmd(0x13,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
305 #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
306 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
308 def ARMget_registers(self):
309 """Get ARM Registers"""
310 regs = [ self.ARMget_register(x) for x in range(15) ]
311 regs.append(self.ARMgetPC()) # make sure we snag the "static" version of PC
313 def ARMset_registers(self, regs, mask):
314 """Set ARM Registers"""
317 self.ARMset_register(x,regs.pop())
318 if (1<<15) & mask: # make sure we set the "static" version of PC or changes will be lost
319 self.ARMsetPC(regs.pop())
320 def ARMget_regCPSRstr(self):
321 psr = self.ARMget_regCPSR()
322 return hex(psr), PSRdecode(psr)
323 def ARMget_regCPSR(self):
324 """Get an ARM's Register"""
325 self.writecmd(0x13,GET_CPSR,0,[])
326 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
328 def ARMset_regCPSR(self, val):
329 """Get an ARM's Register"""
330 self.writecmd(0x13,SET_CPSR,4,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
331 def ARMcmd(self,phrase):
332 self.writecmd(0x13,READ,len(phrase),phrase)
333 val=ord(self.data[0])
334 print "Got %02x" % val
336 def ARMdebuginstr(self,instr,bkpt):
337 if type (instr) == int or type(instr) == long:
338 instr = struct.pack("<L", instr)
339 instr = [int("0x%x"%ord(x),16) for x in instr]
341 self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
343 def ARM_nop(self, bkpt):
344 return self.ARMdebuginstr(ARM_INSTR_NOP, bkpt)
345 def ARMset_IR(self, IR, noretidle=0):
346 self.writecmd(0x13,SET_IR,2, [IR, LSB|noretidle])
348 def ARMshiftDR(self, data, bits, flags):
349 self.writecmd(0x13,SHIFT_DR,8,[bits&0xff, flags&0xff, 0, 0, data&0xff,(data>>8)&0xff,(data>>16)&0xff,(data>>24)&0xff])
351 def ARMwaitDBG(self, timeout=0xff):
352 self.writecmd(0x13,WAIT_DBG,2,[timeout&0xf,timeout>>8])
354 def ARMrestart(self):
355 #self.ARMset_IR(ARM7TDMI_IR_BYPASS)
356 self.ARMset_IR(ARM7TDMI_IR_RESTART)
357 def ARMset_watchpoint0(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
359 self.data.extend(chop(addr,4))
360 self.data.extend(chop(addrmask,4))
361 self.data.extend(chop(data,4))
362 self.data.extend(chop(datamask,4))
363 self.data.extend(chop(ctrl,4))
364 self.data.extend(chop(ctrlmask,4))
365 self.writecmd(0x13,SETWATCH0,24,self.data)
367 def ARMset_watchpoint1(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
369 self.data.extend(chop(addr,4))
370 self.data.extend(chop(addrmask,4))
371 self.data.extend(chop(data,4))
372 self.data.extend(chop(datamask,4))
373 self.data.extend(chop(ctrl,4))
374 self.data.extend(chop(ctrlmask,4))
375 self.writecmd(0x13,SETWATCH1,24,self.data)
377 def ARMreadMem(self, adr, wrdcount):
379 r0 = self.ARMget_register(0); # store R0 and R1
380 r1 = self.ARMget_register(1);
381 #print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR())
382 for word in range(adr, adr+(wrdcount*4), 4):
384 self.ARMset_register(0, word); # write address into R0
386 self.ARMset_register(1, 0xdeadbeef)
392 self.ARMdebuginstr(ARM_READ_MEM, 0); # push LDR R1, [R0], #4 into instruction pipeline (autoincrements for consecutive reads)
400 print hex(self.ARMget_register(1))
403 # FIXME: this may end up changing te current debug-state. should we compare to current_dbgstate?
404 #print repr(self.data[4])
405 if (len(self.data)>4 and self.data[4] == '\x00'):
406 print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
407 raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
410 retval.append( self.ARMget_register(1) ) # read memory value from R1 register
411 #print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1)))
412 self.ARMset_register(1, r1); # restore R0 and R1
413 self.ARMset_register(0, r0);
416 def ARMwriteMem(self, adr, wordarray):
417 r0 = self.ARMget_register(0); # store R0 and R1
418 r1 = self.ARMget_register(1);
419 #print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR())
420 for word in xrange(adr, adr+len(string), 4):
421 self.ARMset_register(0, word); # write address into R0
424 self.ARMdebuginstr(ARM_WRITE_MEM, 0); # push STR R1, [R0], #4 into instruction pipeline (autoincrements for consecutive writes)
428 print hex(self.ARMget_register(1))
431 # FIXME: this may end up changing te current debug-state. should we compare to current_dbgstate?
432 #print repr(self.data[4])
433 if (len(self.data)>4 and self.data[4] == '\x00'):
434 print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
435 raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
438 retval.append( self.ARMget_register(1) ) # read memory value from R1 register
439 #print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1)))
440 self.ARMset_register(1, r1); # restore R0 and R1
441 self.ARMset_register(0, r0);
444 def ARMpeekcodewords(self,adr,words):
445 """Read the contents of code memory at an address."""
446 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ]
447 self.writecmd(0x13,READ_CODE_MEMORY,8,self.data)
449 retval.append(self.serialport.read(words*4))
450 #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
451 return "".join(retval)
452 def ARMpeekdatabyte(self,adr):
453 """Read the contents of data memory at an address."""
454 self.data=[ adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff ]
455 self.writecmd(0x13, PEEK, 4, self.data)
456 #retval.append(self.serialport.read(words*4))
457 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
459 def ARMpokedatabyte(self,adr,val):
460 """Write a byte to data memory."""
461 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff ]
462 self.writecmd(0x13, POKE, 8, self.data)
463 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
465 #def ARMchiperase(self):
466 # """Erase all of the target's memory."""
467 # self.writecmd(0x13,CHIP_ERASE,0,[])
469 """Check the status."""
470 self.writecmd(0x13,GET_DEBUG_STATE,0,[])
471 return ord(self.data[0])
475 0x04 : "Interrupts Enabled (or not?)",
480 0x04 : "disable interrupts",
481 0x02 : "force dbgrq",
482 0x01 : "force dbgack"
485 def ARMstatusstr(self):
486 """Check the status as a string."""
487 status=self.ARMstatus()
492 str="%s %s" %(self.ARMstatusbits[i],str)
495 def ARMchain0(self, address, bits, data):
496 bulk = chop(address,4)
497 bulk.extend(chop(bits,8))
498 bulk.extend(chop(data,4))
500 self.writecmd(0x13,CHAIN0,16,bulk)
501 d1,b1,a1 = struct.unpack("<LQL",self.data)
504 """Start debugging."""
505 self.writecmd(0x13,START,0,self.data)
506 ident=self.ARMidentstr()
507 print "Target identifies as %s." % ident
508 print "Debug Status: %s." % self.ARMstatusstr()
509 #print "System State: %x." % self.ARMget_regCPSRstr()
510 #self.ARMreleasecpu()
514 """Stop debugging."""
515 self.writecmd(0x13,STOP,0,self.data)
516 #def ARMstep_instr(self):
517 # """Step one instruction."""
518 # self.writecmd(0x13,STEP_INSTR,0,self.data)
519 #def ARMflashpage(self,adr):
520 # """Flash 2kB a page of flash from 0xF000 in XDATA"""
525 # print "Flashing buffer to 0x%06x" % adr
526 # self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
528 def writecmd(self, app, verb, count=0, data=[]):
529 """Write a command and some data to the GoodFET."""
530 self.serialport.write(chr(app))
531 self.serialport.write(chr(verb))
534 # count=len(data); #Initial count ignored.
536 #print "TX %02x %02x %04x" % (app,verb,count)
538 #little endian 16-bit length
539 self.serialport.write(chr(count&0xFF))
540 self.serialport.write(chr(count>>8))
542 #print "count=%02x, len(data)=%04x" % (count,len(data))
545 if(isinstance(data,list)):
546 for i in range(0,count):
547 #print "Converting %02x at %i" % (data[i],i)
551 self.serialport.write(outstr)
552 if not self.besilent: