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