Formatting in glitch.c
[goodfet] / client / GoodFETARM.py
1 #!/usr/bin/env python
2 # GoodFET Client Library
3
4 #
5 # Good luck with alpha / beta code.
6 # Contributions and bug reports welcome.
7 #
8
9 import sys, binascii, struct
10 import atlasutils.smartprint as asp
11
12 #Global Commands
13 READ  = 0x00
14 WRITE = 0x01
15 PEEK  = 0x02
16 POKE  = 0x03
17 SETUP = 0x10
18 START = 0x20
19 STOP  = 0x21
20 CALL  = 0x30
21 EXEC  = 0x31
22 NOK   = 0x7E
23 OK    = 0x7F
24
25 # ARM7TDMI JTAG commands
26 GET_DEBUG_CTRL      = 0x80
27 SET_DEBUG_CTRL      = 0x81
28 GET_PC              = 0x82
29 SET_PC              = 0x83
30 GET_CHIP_ID         = 0x84
31 GET_DEBUG_STATE     = 0x85
32 GET_WATCHPOINT      = 0x86
33 SET_WATCHPOINT      = 0x87
34 GET_REGISTER        = 0x88
35 SET_REGISTER        = 0x89
36 GET_REGISTERS       = 0x8a
37 SET_REGISTERS       = 0x8b
38 HALTCPU             = 0x8c
39 RESUMECPU           = 0x8d
40 DEBUG_INSTR         = 0x8e      #
41 STEP_INSTR          = 0x8f      #
42 STEP_REPLACE        = 0x90      #
43 READ_CODE_MEMORY    = 0x91      # ??
44 WRITE_FLASH_PAGE    = 0x92      # ??
45 READ_FLASH_PAGE     = 0x93      # ??
46 MASS_ERASE_FLASH    = 0x94      # ??
47 PROGRAM_FLASH       = 0x95
48 LOCKCHIP            = 0x96      # ??
49 CHIP_ERASE          = 0x97      # can do?
50 # Really ARM specific stuff
51 GET_CPSR            = 0x98
52 SET_CPSR            = 0x99
53 GET_SPSR            = 0x9a
54 SET_SPSR            = 0x9b
55 SET_MODE_THUMB      = 0x9c
56 SET_MODE_ARM        = 0x9d
57
58 from GoodFET import GoodFET
59 from intelhex import IntelHex
60
61
62
63
64 class GoodFETARM(GoodFET):
65     """A GoodFET variant for use with ARM7TDMI microprocessor."""
66     def ARMhaltcpu(self):
67         """Halt the CPU."""
68         self.writecmd(0x13,HALTCPU,0,self.data)
69     def ARMreleasecpu(self):
70         """Resume the CPU."""
71         self.writecmd(0x13,RESUMECPU,0,self.data)
72     def ARMsetModeArm(self):
73         self.writecmd(0x13,SET_MODE_ARM,0,self.data)
74     def ARMtest(self):
75         #self.ARMreleasecpu()
76         #self.ARMhaltcpu()
77         print "Status: %s" % self.ARMstatusstr()
78         
79         #Grab ident three times, should be equal.
80         ident1=self.ARMident()
81         ident2=self.ARMident()
82         ident3=self.ARMident()
83         if(ident1!=ident2 or ident2!=ident3):
84             print "Error, repeated ident attempts unequal."
85             print "%04x, %04x, %04x" % (ident1, ident2, ident3)
86         
87         #Set and Check Registers
88         regs = [1024+x for x in range(0,15)]
89         regr = []
90         for x in range(len(regs)):
91             self.ARMset_register(x, regs[x])
92
93         for x in range(len(regs)):
94             regr.append(self.ARMget_register(x))
95         
96         for x in range(len(regs)):
97             if regs[x] != regr[x]:
98                 print "Error, R%d fail: %x != %x"%(x,regs[x],regr[x])
99
100         return
101
102
103
104
105         #Single step, printing PC.
106         print "Tracing execution at startup."
107         for i in range(15):
108             pc=self.ARMgetPC()
109             byte=self.ARMpeekcodebyte(i)
110             #print "PC=%04x, %02x" % (pc, byte)
111             self.ARMstep_instr()
112         
113         print "Verifying that debugging a NOP doesn't affect the PC."
114         for i in range(1,15):
115             pc=self.ARMgetPC()
116             self.ARMdebuginstr([NOP])
117             if(pc!=self.ARMgetPC()):
118                 print "ERROR: PC changed during ARMdebuginstr([NOP])!"
119         
120         print "Checking pokes to XRAM."
121         for i in range(0xf000,0xf020):
122             self.ARMpokedatabyte(i,0xde)
123             if(self.ARMpeekdatabyte(i)!=0xde):
124                 print "Error in DATA at 0x%04x" % i
125         
126         #print "Status: %s." % self.ARMstatusstr()
127         #Exit debugger
128         self.stop()
129         print "Done."
130
131     def setup(self):
132         """Move the FET into the JTAG ARM application."""
133         #print "Initializing ARM."
134         self.writecmd(0x13,SETUP,0,self.data)
135     def ARMget_dbgstate(self):
136         """Read the config register of an ARM."""
137         self.writecmd(0x13,GET_DEBUG_STATE,0,self.data)
138         retval = struct.unpack("<L", self.data[:4])[0]
139         return retval
140     def ARMget_dbgctrl(self):
141         """Read the config register of an ARM."""
142         self.writecmd(0x13,GET_DEBUG_CTRL,0,self.data)
143         retval = struct.unpack("B", self.data)[0]
144         return retval
145     def ARMset_dbgctrl(self,config):
146         """Write the config register of an ARM."""
147         self.writecmd(0x13,SET_DEBUG_CTRL,1,[config&7])
148     def ARMlockchip(self):
149         """Set the flash lock bit in info mem."""
150         self.writecmd(0x13, LOCKCHIP, 0, [])
151     
152
153     def ARMidentstr(self):
154         ident=self.ARMident()
155         ver     = ident >> 28
156         partno  = (ident >> 12) & 0x10
157         mfgid   = ident & 0xfff
158         return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident); 
159     def ARMident(self):
160         """Get an ARM's ID."""
161         self.writecmd(0x13,GET_CHIP_ID,0,[])
162         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
163         return retval
164     def ARMgetPC(self):
165         """Get an ARM's PC."""
166         self.writecmd(0x13,GET_PC,0,[])
167         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
168         return retval
169     def ARMget_register(self, reg):
170         """Get an ARM's Register"""
171         self.writecmd(0x13,GET_REGISTER,1,[reg&0xff])
172         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
173         return retval
174     def ARMset_register(self, reg, val):
175         """Get an ARM's Register"""
176         self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0,val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24])
177         #self.writecmd(0x13,SET_REGISTER,8,[reg,0,0,0, (val>>16)&0xff, val>>24, val&0xff, (val>>8)&0xff])
178         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
179         return retval
180     def ARMget_registers(self):
181         """Get ARM Registers"""
182         self.writecmd(0x13,GET_REGISTERS,0, [])
183         retval = []
184         for x in range(0,len(self.data), 4):
185           retval.append(struct.unpack("<L", self.data[x:x+4])[0])
186         return retval
187     def ARMset_registers(self, regs):
188         """Set ARM Registers"""
189         regarry = []
190         for reg in regs:
191           regarry.extend([reg&0xff, (reg>>8)&0xff, (reg>>16)&0xff, reg>>24])
192         self.writecmd(0x13,SET_REGISTERS,16*4,regarry)
193         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
194         return retval
195     def ARMcmd(self,phrase):
196         self.writecmd(0x13,READ,len(phrase),phrase)
197         val=ord(self.data[0])
198         print "Got %02x" % val
199         return val
200     def ARMdebuginstr(self,instr):
201         if type (instr) == int:
202             instr = struct.pack("<L", instr)
203         self.writecmd(0x13,DEBUG_INSTR,len(instr),instr)
204         return (self.data[0])
205     def ARMpeekcodebyte(self,adr):
206         """Read the contents of code memory at an address."""
207         self.data=[adr&0xff, (adr&0xff00)>>8]
208         self.writecmd(0x13,PEEK,2,self.data)
209         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
210         return retval
211     def ARMpeekdatabyte(self,adr):
212         """Read the contents of data memory at an address."""
213         self.data=[adr&0xff, (adr&0xff00)>>8]
214         self.writecmd(0x13, PEEK, 2, self.data)
215         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
216         return retval
217     def ARMpokedatabyte(self,adr,val):
218         """Write a byte to data memory."""
219         self.data=[adr&0xff, (adr&0xff00)>>8, val]
220         self.writecmd(0x13, POKE, 3, self.data)
221         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
222         return retval
223     def ARMchiperase(self):
224         """Erase all of the target's memory."""
225         self.writecmd(0x13,CHIP_ERASE,0,[])
226     def ARMstatus(self):
227         """Check the status."""
228         self.writecmd(0x13,GET_DEBUG_STATE,0,[])
229         return ord(self.data[0])
230     ARMstatusbits={
231                   0x10 : "TBIT",
232                   0x08 : "cgenL",
233                   0x04 : "Interrupts Enabled (or not?)",
234                   0x02 : "DBGRQ",
235                   0x01 : "DGBACK"
236                   }
237     ARMctrlbits={
238                   0x04 : "disable interrupts",
239                   0x02 : "force dbgrq",
240                   0x01 : "force dbgack"
241                   }
242                   
243     def ARMstatusstr(self):
244         """Check the status as a string."""
245         status=self.ARMstatus()
246         str=""
247         i=1
248         while i<0x100:
249             if(status&i):
250                 str="%s %s" %(self.ARMstatusbits[i],str)
251             i*=2
252         return str
253     def start(self):
254         """Start debugging."""
255         self.writecmd(0x13,START,0,self.data)
256         #ident=self.ARMidentstr()
257         #print "Target identifies as %s." % ident
258         #print "Status: %s." % self.ARMstatusstr()
259         #self.ARMreleasecpu()
260         #self.ARMhaltcpu()
261         #print "Status: %s." % self.ARMstatusstr()
262         
263     def stop(self):
264         """Stop debugging."""
265         self.writecmd(0x13,STOP,0,self.data)
266     def ARMstep_instr(self):
267         """Step one instruction."""
268         self.writecmd(0x13,STEP_INSTR,0,self.data)
269     def ARMflashpage(self,adr):
270         """Flash 2kB a page of flash from 0xF000 in XDATA"""
271         data=[adr&0xFF,
272               (adr>>8)&0xFF,
273               (adr>>16)&0xFF,
274               (adr>>24)&0xFF]
275         print "Flashing buffer to 0x%06x" % adr
276         self.writecmd(0x13,MASS_FLASH_PAGE,4,data)
277
278     def writecmd(self, app, verb, count=0, data=[]):
279         """Write a command and some data to the GoodFET."""
280         self.serialport.write(chr(app))
281         self.serialport.write(chr(verb))
282         count = len(data)
283         #if data!=None:
284         #    count=len(data); #Initial count ignored.
285
286         #print "TX %02x %02x %04x" % (app,verb,count)
287
288         #little endian 16-bit length
289         self.serialport.write(chr(count&0xFF))
290         self.serialport.write(chr(count>>8))
291
292         #print "count=%02x, len(data)=%04x" % (count,len(data))
293
294         if count!=0:
295             if(isinstance(data,list)):
296                 for i in range(0,count):
297                     #print "Converting %02x at %i" % (data[i],i)
298                     data[i]=chr(data[i])
299             #print type(data)
300             outstr=''.join(data)
301             self.serialport.write(outstr)
302         if not self.besilent:
303             self.readcmd()
304
305