Index of glitches(time) in glitching databases.
[goodfet] / client / GoodFETARM.py
1 #!/usr/bin/env python
2 # GoodFET Client Library
3
4 # (C) 2009 Matthew Carpenter <matt at inguardians.com>
5 #
6 # Good luck with alpha / beta code.
7 # Contributions and bug reports welcome.
8 #
9
10 import sys, binascii, struct
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(0x33,HALTCPU,0,self.data)
69     def ARMreleasecpu(self):
70         """Resume the CPU."""
71         self.writecmd(0x33,RESUMECPU,0,self.data)
72     def ARMsetModeArm(self):
73         self.writecmd(0x33,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         #Single step, printing PC.
88         print "Tracing execution at startup."
89         for i in range(1,15):
90             pc=self.ARMgetPC()
91             byte=self.ARMpeekcodebyte(i)
92             #print "PC=%04x, %02x" % (pc, byte)
93             self.ARMstep_instr()
94         
95         print "Verifying that debugging a NOP doesn't affect the PC."
96         for i in range(1,15):
97             pc=self.ARMgetPC()
98             self.ARMdebuginstr([NOP])
99             if(pc!=self.ARMgetPC()):
100                 print "ERROR: PC changed during ARMdebuginstr([NOP])!"
101         
102         print "Checking pokes to XRAM."
103         for i in range(0xf000,0xf020):
104             self.ARMpokedatabyte(i,0xde)
105             if(self.ARMpeekdatabyte(i)!=0xde):
106                 print "Error in DATA at 0x%04x" % i
107         
108         #print "Status: %s." % self.ARMstatusstr()
109         #Exit debugger
110         self.stop()
111         print "Done."
112
113     def setup(self):
114         """Move the FET into the JTAG ARM application."""
115         #print "Initializing ARM."
116         self.writecmd(0x33,SETUP,0,self.data)
117     def ARMget_dbgstate(self):
118         """Read the config register of an ARM."""
119         self.writecmd(0x33,GET_DEBUG_STATE,0,self.data)
120         print "DEBUGGING get_dbgstate:  %s"%repr(self.data)
121         retval = struct.unpack("<L", self.data[:4])[0]
122         return retval
123     def ARMget_dbgctrl(self):
124         """Read the config register of an ARM."""
125         self.writecmd(0x33,GET_DEBUG_CTRL,0,self.data)
126         retval = struct.unpack("B", self.data)[0]
127         return retval
128     def ARMset_dbgctrl(self,config):
129         """Write the config register of an ARM."""
130         self.writecmd(0x33,SET_DEBUG_CTRL,1,[config&7])
131     def ARMlockchip(self):
132         """Set the flash lock bit in info mem."""
133         self.writecmd(0x33, LOCKCHIP, 0, [])
134     
135
136     def ARMidentstr(self):
137         ident=self.ARMident()
138         ver     = ident >> 28
139         partno  = (ident >> 12) & 0x10
140         mfgid   = ident & 0xfff
141         return "mfg: %x\npartno: %x\nver: %x\n(%x)" % (ver, partno, mfgid, ident); 
142     def ARMident(self):
143         """Get an ARM's ID."""
144         self.writecmd(0x33,GET_CHIP_ID,0,[])
145         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
146         return retval
147     def ARMgetPC(self):
148         """Get an ARM's PC."""
149         self.writecmd(0x33,GET_PC,0,[])
150         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
151         return retval
152     def ARMget_register(self, reg):
153         """Get an ARM's Register"""
154         self.writecmd(0x33,GET_REGISTER,1,[reg&0xff])
155         print "DEBUG:GET_REGISTER: %s"%repr(self.data)
156         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
157         return retval
158     def ARMset_register(self, reg, val):
159         """Get an ARM's Register"""
160         self.writecmd(0x33,GET_REGISTER,8,[reg,0,0,0,val>>24, (val>>16)&0xff, (val>>8)&0xff, val&0xff])
161         print "DEBUG:SET_REGISTER: %s"%repr(self.data)
162         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
163         return retval
164     def ARMget_registers(self):
165         """Get an ARM's Register"""
166         self.writecmd(0x33,GET_REGISTERS,0,[])
167         print "DEBUG:GET_REGISTER: %s"%repr(self.data)
168         #retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
169         return retval
170     def ARMset_registers(self, regs):
171         """Get an ARM's Register"""
172         regarry = []
173         for reg in regs:
174           regarray.merge([reg>>24, (reg>>16)&0xff, (reg>>8)&0xff, reg&0xff])
175         self.writecmd(0x33,GET_REGISTER,16*4,regarray)
176         print "DEBUG:SET_REGISTER: %s"%repr(self.data)
177         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
178         return retval
179     def ARMcmd(self,phrase):
180         self.writecmd(0x33,READ,len(phrase),phrase)
181         val=ord(self.data[0])
182         print "Got %02x" % val
183         return val
184     def ARMdebuginstr(self,instr):
185         if type (instr) == int:
186             instr = struct.pack("<L", instr)
187         self.writecmd(0x33,DEBUG_INSTR,len(instr),instr)
188         return (self.data[0])
189     def ARMpeekcodebyte(self,adr):
190         """Read the contents of code memory at an address."""
191         self.data=[adr&0xff, (adr&0xff00)>>8]
192         self.writecmd(0x33,PEEK,2,self.data)
193         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
194         return retval
195     def ARMpeekdatabyte(self,adr):
196         """Read the contents of data memory at an address."""
197         self.data=[adr&0xff, (adr&0xff00)>>8]
198         self.writecmd(0x33, PEEK, 2, self.data)
199         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
200         return retval
201     def ARMpokedatabyte(self,adr,val):
202         """Write a byte to data memory."""
203         self.data=[adr&0xff, (adr&0xff00)>>8, val]
204         self.writecmd(0x33, POKE, 3, self.data)
205         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
206         return retval
207     def ARMchiperase(self):
208         """Erase all of the target's memory."""
209         self.writecmd(0x33,CHIP_ERASE,0,[])
210     def ARMstatus(self):
211         """Check the status."""
212         self.writecmd(0x33,GET_DEBUG_STATE,0,[])
213         return ord(self.data[0])
214     ARMstatusbits={
215                   0x10 : "TBIT",
216                   0x08 : "cgenL",
217                   0x04 : "Interrupts Enabled (or not?)",
218                   0x02 : "DBGRQ",
219                   0x01 : "DGBACK"
220                   }
221     ARMctrlbits={
222                   0x04 : "disable interrupts",
223                   0x02 : "force dbgrq",
224                   0x01 : "force dbgack"
225                   }
226                   
227     def ARMstatusstr(self):
228         """Check the status as a string."""
229         status=self.ARMstatus()
230         str=""
231         i=1
232         while i<0x100:
233             if(status&i):
234                 str="%s %s" %(self.ARMstatusbits[i],str)
235             i*=2
236         return str
237     def start(self):
238         """Start debugging."""
239         self.writecmd(0x33,START,0,self.data)
240         #ident=self.ARMidentstr()
241         #print "Target identifies as %s." % ident
242         #print "Status: %s." % self.ARMstatusstr()
243         #self.ARMreleasecpu()
244         #self.ARMhaltcpu()
245         #print "Status: %s." % self.ARMstatusstr()
246         
247     def stop(self):
248         """Stop debugging."""
249         self.writecmd(0x33,STOP,0,self.data)
250     def ARMstep_instr(self):
251         """Step one instruction."""
252         self.writecmd(0x33,STEP_INSTR,0,self.data)
253     def ARMflashpage(self,adr):
254         """Flash 2kB a page of flash from 0xF000 in XDATA"""
255         data=[adr&0xFF,
256               (adr>>8)&0xFF,
257               (adr>>16)&0xFF,
258               (adr>>24)&0xFF]
259         print "Flashing buffer to 0x%06x" % adr
260         self.writecmd(0x33,MASS_FLASH_PAGE,4,data)
261
262     def writecmd(self, app, verb, count=0, data=[]):
263         """Write a command and some data to the GoodFET."""
264         self.serialport.write(chr(app))
265         self.serialport.write(chr(verb))
266         count = len(data)
267         #if data!=None:
268         #    count=len(data); #Initial count ignored.
269
270         #print "TX %02x %02x %04x" % (app,verb,count)
271
272         #little endian 16-bit length
273         self.serialport.write(chr(count&0xFF))
274         self.serialport.write(chr(count>>8))
275
276         #print "count=%02x, len(data)=%04x" % (count,len(data))
277
278         if count!=0:
279             if(isinstance(data,list)):
280                 for i in range(0,count):
281                     #print "Converting %02x at %i" % (data[i],i)
282                     data[i]=chr(data[i])
283             #print type(data)
284             outstr=''.join(data)
285             self.serialport.write(outstr)
286         if not self.besilent:
287             self.readcmd()
288
289