2 # GoodFET 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
25 # ARM7TDMI JTAG commands
31 GET_DEBUG_STATE = 0x85
43 READ_CODE_MEMORY = 0x91 # ??
44 WRITE_FLASH_PAGE = 0x92 # ??
45 READ_FLASH_PAGE = 0x93 # ??
46 MASS_ERASE_FLASH = 0x94 # ??
49 CHIP_ERASE = 0x97 # can do?
50 # Really ARM specific stuff
60 "at91sam7": {0:(0x100000, "Flash before remap, SRAM after remap"),
61 0x100000: (0x100000, "Internal Flash"),
62 0x200000: (0x100000, "Internal SRAM"),
66 from GoodFET import GoodFET
67 from intelhex import IntelHex
72 class GoodFETARM(GoodFET):
73 """A GoodFET variant for use with ARM7TDMI microprocessor."""
76 self.writecmd(0x13,HALTCPU,0,self.data)
77 def ARMreleasecpu(self):
79 self.writecmd(0x13,RESUMECPU,0,self.data)
80 def ARMsetModeArm(self):
81 self.writecmd(0x13,SET_MODE_ARM,0,self.data)
82 def ARMsetModeThumb(self):
83 self.writecmd(0x13,SET_MODE_THUMB,0,self.data)
87 print "Status: %s" % self.ARMstatusstr()
89 #Grab ident three times, should be equal.
90 ident1=self.ARMident()
91 ident2=self.ARMident()
92 ident3=self.ARMident()
93 if(ident1!=ident2 or ident2!=ident3):
94 print "Error, repeated ident attempts unequal."
95 print "%04x, %04x, %04x" % (ident1, ident2, ident3)
97 #Set and Check Registers
98 regs = [1024+x for x in range(0,15)]
100 for x in range(len(regs)):
101 self.ARMset_register(x, regs[x])
103 for x in range(len(regs)):
104 regr.append(self.ARMget_register(x))
106 for x in range(len(regs)):
107 if regs[x] != regr[x]:
108 print "Error, R%d fail: %x != %x"%(x,regs[x],regr[x])
115 #Single step, printing PC.
116 print "Tracing execution at startup."
119 byte=self.ARMpeekcodebyte(i)
120 #print "PC=%04x, %02x" % (pc, byte)
123 print "Verifying that debugging a NOP doesn't affect the PC."
124 for i in range(1,15):
126 self.ARMdebuginstr([NOP])
127 if(pc!=self.ARMgetPC()):
128 print "ERROR: PC changed during ARMdebuginstr([NOP])!"
130 print "Checking pokes to XRAM."
131 for i in range(0xf000,0xf020):
132 self.ARMpokedatabyte(i,0xde)
133 if(self.ARMpeekdatabyte(i)!=0xde):
134 print "Error in DATA at 0x%04x" % i
136 #print "Status: %s." % self.ARMstatusstr()
142 """Move the FET into the JTAG ARM application."""
143 #print "Initializing ARM."
144 self.writecmd(0x13,SETUP,0,self.data)
145 def ARMget_dbgstate(self):
146 """Read the config register of an ARM."""
147 self.writecmd(0x13,GET_DEBUG_STATE,0,self.data)
148 retval = struct.unpack("<L", self.data[:4])[0]
150 def ARMget_dbgctrl(self):
151 """Read the config register of an ARM."""
152 self.writecmd(0x13,GET_DEBUG_CTRL,0,self.data)
153 retval = struct.unpack("B", self.data)[0]
155 def ARMset_dbgctrl(self,config):
156 """Write the config register of an ARM."""
157 self.writecmd(0x13,SET_DEBUG_CTRL,1,[config&7])
158 #def ARMlockchip(self):
159 # """Set the flash lock bit in info mem."""
160 # self.writecmd(0x13, LOCKCHIP, 0, [])
163 def ARMidentstr(self):
164 ident=self.ARMident()
166 partno = (ident >> 12) & 0x10
167 mfgid = ident & 0xfff
168 return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident);
170 """Get an ARM's ID."""
171 self.writecmd(0x13,GET_CHIP_ID,0,[])
172 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
175 """Get an ARM's PC."""
176 self.writecmd(0x13,GET_PC,0,[])
177 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
179 def ARMget_register(self, reg):
180 """Get an ARM's Register"""
181 self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
182 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
184 def ARMset_register(self, reg, val):
185 """Get an ARM's Register"""
186 self.writecmd(0x13,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
187 #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
188 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
190 def ARMget_registers(self):
191 """Get ARM Registers"""
192 self.writecmd(0x13,GET_REGISTERS,0, [])
194 for x in range(0,len(self.data), 4):
195 retval.append(struct.unpack("<L", self.data[x:x+4])[0])
197 def ARMset_registers(self, regs):
198 """Set ARM Registers"""
201 regarry.extend([reg&0xff, (reg>>8)&0xff, (reg>>16)&0xff, reg>>24])
202 self.writecmd(0x13,SET_REGISTERS,16*4,regarry)
203 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
205 def ARMget_regCPSR(self):
206 """Get an ARM's Register"""
207 self.writecmd(0x13,GET_CPSR,0,[])
208 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
210 def ARMset_regCPSR(self, val):
211 """Get an ARM's Register"""
212 self.writecmd(0x13,SET_CPSR,4,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
213 def ARMcmd(self,phrase):
214 self.writecmd(0x13,READ,len(phrase),phrase)
215 val=ord(self.data[0])
216 print "Got %02x" % val
218 def ARMdebuginstr(self,instr):
219 if type (instr) == int:
220 instr = struct.pack("<L", instr)
221 self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
222 return (self.data[0])
223 def ARMpeekcodewords(self,adr,words):
224 """Read the contents of code memory at an address."""
225 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ]
226 self.writecmd(0x13,READ_CODE_MEMORY,8,self.data)
228 retval.append(self.serialport.read(words*4))
229 #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
230 return "".join(retval)
231 def ARMpeekdatabyte(self,adr):
232 """Read the contents of data memory at an address."""
233 self.data=[ adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff ]
234 self.writecmd(0x13, PEEK, 4, self.data)
235 #retval.append(self.serialport.read(words*4))
236 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
238 def ARMpokedatabyte(self,adr,val):
239 """Write a byte to data memory."""
240 self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff ]
241 self.writecmd(0x13, POKE, 8, self.data)
242 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
244 #def ARMchiperase(self):
245 # """Erase all of the target's memory."""
246 # self.writecmd(0x13,CHIP_ERASE,0,[])
248 """Check the status."""
249 self.writecmd(0x13,GET_DEBUG_STATE,0,[])
250 return ord(self.data[0])
254 0x04 : "Interrupts Enabled (or not?)",
259 0x04 : "disable interrupts",
260 0x02 : "force dbgrq",
261 0x01 : "force dbgack"
264 def ARMstatusstr(self):
265 """Check the status as a string."""
266 status=self.ARMstatus()
271 str="%s %s" %(self.ARMstatusbits[i],str)
275 """Start debugging."""
276 self.writecmd(0x13,START,0,self.data)
277 ident=self.ARMidentstr()
278 print "Target identifies as %s." % ident
279 print "Status: %s." % self.ARMstatusstr()
280 #self.ARMreleasecpu()
282 #print "Status: %s." % self.ARMstatusstr()
285 """Stop debugging."""
286 self.writecmd(0x13,STOP,0,self.data)
287 #def ARMstep_instr(self):
288 # """Step one instruction."""
289 # self.writecmd(0x13,STEP_INSTR,0,self.data)
290 #def ARMflashpage(self,adr):
291 # """Flash 2kB a page of flash from 0xF000 in XDATA"""
296 # print "Flashing buffer to 0x%06x" % adr
297 # self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
299 def writecmd(self, app, verb, count=0, data=[]):
300 """Write a command and some data to the GoodFET."""
301 self.serialport.write(chr(app))
302 self.serialport.write(chr(verb))
305 # count=len(data); #Initial count ignored.
307 #print "TX %02x %02x %04x" % (app,verb,count)
309 #little endian 16-bit length
310 self.serialport.write(chr(count&0xFF))
311 self.serialport.write(chr(count>>8))
313 #print "count=%02x, len(data)=%04x" % (count,len(data))
316 if(isinstance(data,list)):
317 for i in range(0,count):
318 #print "Converting %02x at %i" % (data[i],i)
322 self.serialport.write(outstr)
323 if not self.besilent: