2 # GoodFET ARM Client Library
5 # Good luck with alpha / beta code.
6 # Contributions and bug reports welcome.
9 import sys, binascii, struct
10 import atlasutils.smartprint as asp
11 from GoodFET import GoodFET
12 from intelhex import IntelHex
15 "at91sam7": {0:(0x100000, "Flash before remap, SRAM after remap"),
16 0x100000: (0x100000, "Internal Flash"),
17 0x200000: (0x100000, "Internal SRAM"),
35 # ARM7TDMI JTAG commands
41 GET_DEBUG_STATE = 0x85
55 CHIP_ERASE = 0x97 # can do?
56 # Really ARM specific stuff
77 PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
78 PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"),
79 PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"),
80 PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"),
81 PM_irq: ("Abort Processor Mode", "irq", "Implements virtual memory and/or memory protection"),
82 PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"),
83 PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"),
123 ARM_INSTR_NOP = 0xe1a00000L
124 ARM_INSTR_BX_R0 = 0xe12fff10L
125 ARM_INSTR_STR_Rx_r14 = 0xe58f0000L # from atmel docs
126 ARM_READ_REG = ARM_INSTR_STR_Rx_r14
127 ARM_INSTR_LDR_Rx_r14 = 0xe59f0000L # from atmel docs
128 ARM_WRITE_REG = ARM_INSTR_LDR_Rx_r14
129 ARM_INSTR_LDR_R1_r0_4 = 0xe4901004L
130 ARM_READ_MEM = ARM_INSTR_LDR_R1_r0_4
131 ARM_INSTR_STR_R1_r0_4 = 0xe4801004L
132 ARM_WRITE_MEM = ARM_INSTR_STR_R1_r0_4
133 ARM_INSTR_MRS_R0_CPSR = 0xe10f0000L
134 ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
135 ARM_INSTR_STMIA_R14_r0_rx = 0xE88E0000L # add up to 65k to indicate which registers...
136 ARM_STORE_MULTIPLE = ARM_INSTR_STMIA_R14_r0_rx
137 ARM_INSTR_SKANKREGS = 0xE88F7fffL
138 ARM_INSTR_CLOBBEREGS = 0xE89F7fffL
140 ARM_INSTR_B_PC = 0xea000000L
141 ARM_INSTR_BX_PC = 0xe1200010L # need to set r0 to the desired address
142 THUMB_INSTR_STR_R0_r0 = 0x60006000L
143 THUMB_INSTR_MOV_R0_PC = 0x46b846b8L
144 THUMB_INSTR_BX_PC = 0x47784778L
145 THUMB_INSTR_NOP = 0x1c001c00L
148 ARM7TDMI_IR_EXTEST = 0x0
149 ARM7TDMI_IR_SCAN_N = 0x2
150 ARM7TDMI_IR_SAMPLE = 0x3
151 ARM7TDMI_IR_RESTART = 0x4
152 ARM7TDMI_IR_CLAMP = 0x5
153 ARM7TDMI_IR_HIGHZ = 0x7
154 ARM7TDMI_IR_CLAMPZ = 0x9
155 ARM7TDMI_IR_INTEST = 0xC
156 ARM7TDMI_IR_IDCODE = 0xE
157 ARM7TDMI_IR_BYPASS = 0xF
160 def PSRdecode(psrval):
161 output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
162 for x in xrange(5,32):
164 output.append(PSR_bits[x])
165 return " ".join(output)
167 fmt = [None, "B", "<H", None, "<L", None, None, None, "<Q"]
169 s = struct.pack(fmt[byts], val)
170 return [ord(b) for b in s ]
172 class GoodFETARM(GoodFET):
173 """A GoodFET variant for use with ARM7TDMI microprocessor."""
174 def ARMhaltcpu(self):
176 self.writecmd(0x13,HALTCPU,0,self.data)
177 print "CPSR: (%s) %s"%(self.ARMget_regCPSRstr())
178 def ARMreleasecpu(self):
179 """Resume the CPU."""
180 self.writecmd(0x13,RESUMECPU,0,self.data)
181 def ARMsetModeArm(self, restart=0):
182 self.writecmd(0x13,SET_MODE_ARM,0,[restart])
183 def ARMsetModeThumb(self, restart=0):
184 self.writecmd(0x13,SET_MODE_THUMB,0,[restart])
186 #self.ARMreleasecpu()
188 print "Status: %s" % self.ARMstatusstr()
190 #Grab ident three times, should be equal.
191 ident1=self.ARMident()
192 ident2=self.ARMident()
193 ident3=self.ARMident()
194 if(ident1!=ident2 or ident2!=ident3):
195 print "Error, repeated ident attempts unequal."
196 print "%04x, %04x, %04x" % (ident1, ident2, ident3)
198 #Set and Check Registers
199 regs = [1024+x for x in range(0,15)]
201 for x in range(len(regs)):
202 self.ARMset_register(x, regs[x])
204 for x in range(len(regs)):
205 regr.append(self.ARMget_register(x))
207 for x in range(len(regs)):
208 if regs[x] != regr[x]:
209 print "Error, R%d fail: %x != %x"%(x,regs[x],regr[x])
216 #Single step, printing PC.
217 print "Tracing execution at startup."
220 byte=self.ARMpeekcodebyte(i)
221 #print "PC=%04x, %02x" % (pc, byte)
224 print "Verifying that debugging a NOP doesn't affect the PC."
225 for i in range(1,15):
227 self.ARMdebuginstr([NOP])
228 if(pc!=self.ARMgetPC()):
229 print "ERROR: PC changed during ARMdebuginstr([NOP])!"
231 print "Checking pokes to XRAM."
232 for i in range(0xf000,0xf020):
233 self.ARMpokedatabyte(i,0xde)
234 if(self.ARMpeekdatabyte(i)!=0xde):
235 print "Error in DATA at 0x%04x" % i
237 #print "Status: %s." % self.ARMstatusstr()
243 """Move the FET into the JTAG ARM application."""
244 #print "Initializing ARM."
245 self.writecmd(0x13,SETUP,0,self.data)
246 def ARMget_dbgstate(self):
247 """Read the config register of an ARM."""
248 self.writecmd(0x13,GET_DEBUG_STATE,0,self.data)
249 retval = struct.unpack("<L", self.data[:4])[0]
251 def ARMget_dbgctrl(self):
252 """Read the config register of an ARM."""
253 self.writecmd(0x13,GET_DEBUG_CTRL,0,self.data)
254 retval = struct.unpack("B", self.data)[0]
256 def ARMset_dbgctrl(self,config):
257 """Write the config register of an ARM."""
258 self.writecmd(0x13,SET_DEBUG_CTRL,1,[config&7])
259 #def ARMlockchip(self):
260 # """Set the flash lock bit in info mem."""
261 # self.writecmd(0x13, LOCKCHIP, 0, [])
264 def ARMidentstr(self):
265 ident=self.ARMident()
267 partno = (ident >> 12) & 0x10
268 mfgid = ident & 0xfff
269 return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident);
271 """Get an ARM's ID."""
272 self.writecmd(0x13,GET_CHIP_ID,0,[])
273 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
275 def ARMsetPC(self, val):
276 """Set an ARM's PC."""
277 self.writecmd(0x13,SET_PC,0,chop(val,4))
279 """Get an ARM's PC."""
280 self.writecmd(0x13,GET_PC,0,[])
281 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
283 def ARMget_register(self, reg):
284 """Get an ARM's Register"""
285 self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
286 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
288 def ARMset_register(self, reg, val):
289 """Get an ARM's Register"""
290 self.writecmd(0x13,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
291 #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
292 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
294 def ARMget_registers(self):
295 """Get ARM Registers"""
296 regs = [ self.ARMget_register(x) for x in range(15) ]
297 regs.append(self.ARMgetPC()) # make sure we snag the "static" version of PC
299 def ARMset_registers(self, regs, mask):
300 """Set ARM Registers"""
303 self.ARMset_register(x,regs.pop())
304 if (1<<15) & mask: # make sure we set the "static" version of PC or changes will be lost
305 self.ARMsetPC(regs.pop())
306 def ARMget_regCPSRstr(self):
307 psr = self.ARMget_regCPSR()
308 return hex(psr), PSRdecode(psr)
309 def ARMget_regCPSR(self):
310 """Get an ARM's Register"""
311 self.writecmd(0x13,GET_CPSR,0,[])
312 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
314 def ARMset_regCPSR(self, val):
315 """Get an ARM's Register"""
316 self.writecmd(0x13,SET_CPSR,4,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
317 def ARMcmd(self,phrase):
318 self.writecmd(0x13,READ,len(phrase),phrase)
319 val=ord(self.data[0])
320 print "Got %02x" % val
322 def ARMdebuginstr(self,instr,bkpt):
323 if type (instr) == int or type(instr) == long:
324 instr = struct.pack("<L", instr)
325 instr = [int("0x%x"%ord(x),16) for x in instr]
327 self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
329 def ARM_nop(self, bkpt):
330 return self.ARMdebuginstr(ARM_INSTR_NOP, bkpt)
331 def ARMset_IR(self, IR):
332 self.writecmd(0x13,SET_IR,1, [IR])
334 def ARMshiftDR(self, data, bits, LSB, END, RETIDLE):
335 self.writecmd(0x13,SHIFT_DR,8,[bits&0xff, LSB&0xff, END&0xff, RETIDLE&0xff, data&0xff,(data>>8)&0xff,(data>>16)&0xff,(data>>24)&0xff])
337 def ARMwaitDBG(self, timeout=0xff):
338 self.writecmd(0x13,WAIT_DBG,2,[timeout&0xf,timeout>>8])
340 def ARMrestart(self):
341 self.ARMset_IR(ARM7TDMI_IR_RESTART)
342 def ARMset_watchpoint0(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
344 self.data.extend(chop(addr,4))
345 self.data.extend(chop(addrmask,4))
346 self.data.extend(chop(data,4))
347 self.data.extend(chop(datamask,4))
348 self.data.extend(chop(ctrl,4))
349 self.data.extend(chop(ctrlmask,4))
350 self.writecmd(0x13,SETWATCH0,24,self.data)
352 def ARMset_watchpoint1(self, addr, addrmask, data, datamask, ctrl, ctrlmask):
354 self.data.extend(chop(addr,4))
355 self.data.extend(chop(addrmask,4))
356 self.data.extend(chop(data,4))
357 self.data.extend(chop(datamask,4))
358 self.data.extend(chop(ctrl,4))
359 self.data.extend(chop(ctrlmask,4))
360 self.writecmd(0x13,SETWATCH1,24,self.data)
362 def ARMreadMem(self, adr, wrdcount):
364 r0 = self.ARMget_register(0); # store R0 and R1
365 r1 = self.ARMget_register(1);
366 print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR())
367 for word in range(adr, adr+(wrdcount*4), 4):
368 self.ARMset_register(0, word); # write address into R0
371 self.ARMdebuginstr(ARM_READ_MEM, 0); # push LDR R1, [R0], #4 into instruction pipeline (autoincrements for consecutive reads)
375 print self.ARMget_register(1)
378 # FIXME: this may end up changing te current debug-state. should we compare to current_dbgstate?
379 #print repr(self.data[4])
380 if (len(self.data)>4 and self.data[4] == '\x00'):
381 print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
382 raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE")
385 retval.append( self.ARMget_register(1) ) # read memory value from R1 register
386 print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1)))
387 self.ARMset_register(1, r1); # restore R0 and R1
388 self.ARMset_register(0, r0);
391 def ARMpeekcodewords(self,adr,words):
392 """Read the contents of code memory at an address."""
393 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ]
394 self.writecmd(0x13,READ_CODE_MEMORY,8,self.data)
396 retval.append(self.serialport.read(words*4))
397 #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
398 return "".join(retval)
399 def ARMpeekdatabyte(self,adr):
400 """Read the contents of data memory at an address."""
401 self.data=[ adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff ]
402 self.writecmd(0x13, PEEK, 4, self.data)
403 #retval.append(self.serialport.read(words*4))
404 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
406 def ARMpokedatabyte(self,adr,val):
407 """Write a byte to data memory."""
408 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff ]
409 self.writecmd(0x13, POKE, 8, self.data)
410 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
412 #def ARMchiperase(self):
413 # """Erase all of the target's memory."""
414 # self.writecmd(0x13,CHIP_ERASE,0,[])
416 """Check the status."""
417 self.writecmd(0x13,GET_DEBUG_STATE,0,[])
418 return ord(self.data[0])
422 0x04 : "Interrupts Enabled (or not?)",
427 0x04 : "disable interrupts",
428 0x02 : "force dbgrq",
429 0x01 : "force dbgack"
432 def ARMstatusstr(self):
433 """Check the status as a string."""
434 status=self.ARMstatus()
439 str="%s %s" %(self.ARMstatusbits[i],str)
443 """Start debugging."""
444 self.writecmd(0x13,START,0,self.data)
445 ident=self.ARMidentstr()
446 print "Target identifies as %s." % ident
447 print "Debug Status: %s." % self.ARMstatusstr()
448 #print "System State: %x." % self.ARMget_regCPSRstr()
449 #self.ARMreleasecpu()
453 """Stop debugging."""
454 self.writecmd(0x13,STOP,0,self.data)
455 #def ARMstep_instr(self):
456 # """Step one instruction."""
457 # self.writecmd(0x13,STEP_INSTR,0,self.data)
458 #def ARMflashpage(self,adr):
459 # """Flash 2kB a page of flash from 0xF000 in XDATA"""
464 # print "Flashing buffer to 0x%06x" % adr
465 # self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
467 def writecmd(self, app, verb, count=0, data=[]):
468 """Write a command and some data to the GoodFET."""
469 self.serialport.write(chr(app))
470 self.serialport.write(chr(verb))
473 # count=len(data); #Initial count ignored.
475 #print "TX %02x %02x %04x" % (app,verb,count)
477 #little endian 16-bit length
478 self.serialport.write(chr(count&0xFF))
479 self.serialport.write(chr(count>>8))
481 #print "count=%02x, len(data)=%04x" % (count,len(data))
484 if(isinstance(data,list)):
485 for i in range(0,count):
486 #print "Converting %02x at %i" % (data[i],i)
490 self.serialport.write(outstr)
491 if not self.besilent: