2 # GoodFET Client Library
4 # (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
6 # This code is being rewritten and refactored. You've been warned!
11 from GoodFET import GoodFET;
12 from intelhex import IntelHex;
14 import xml.dom.minidom, time;
16 class GoodFETCC(GoodFET):
17 """A GoodFET variant for use with Chipcon 8051 Zigbee SoC."""
23 smartrfpath="/opt/smartrf7";
24 def loadsymbols(self):
25 try: self.SRF_loadsymbols();
27 if self.verbose>0: print "SmartRF not found at %s." % self.smartrfpath;
28 def SRF_chipdom(self,chip="cc1110", doc="register_definition.xml"):
29 fn="%s/config/xml/%s/%s" % (self.smartrfpath,chip,doc);
30 #print "Opening %s" % fn;
31 return xml.dom.minidom.parse(fn)
33 def CMDrs(self,args=[]):
34 """Chip command to grab the radio state."""
36 self.SRF_radiostate();
38 print "Error printing radio state.";
39 print "SmartRF not found at %s." % self.smartrfpath;
40 def SRF_bitfieldstr(self,bf):
47 for e in bf.childNodes:
48 if e.localName=="Name" and e.childNodes: name= e.childNodes[0].nodeValue;
49 elif e.localName=="Start": start=e.childNodes[0].nodeValue;
50 elif e.localName=="Stop": stop=e.childNodes[0].nodeValue;
51 return " [%s:%s] %30s " % (start,stop,name);
52 def SRF_radiostate(self):
54 chip=self.CCversions.get(ident&0xFF00);
55 dom=self.SRF_chipdom(chip,"register_definition.xml");
56 for e in dom.getElementsByTagName("registerdefinition"):
57 for f in e.childNodes:
58 if f.localName=="DeviceName":
59 print "// %s RadioState" % (f.childNodes[0].nodeValue);
60 elif f.localName=="Register":
65 for g in f.childNodes:
66 if g.localName=="Name":
67 name=g.childNodes[0].nodeValue;
68 elif g.localName=="Address":
69 address=g.childNodes[0].nodeValue;
70 elif g.localName=="Description":
72 description=g.childNodes[0].nodeValue;
73 elif g.localName=="Bitfield":
74 bitfields+="%17s/* %-50s */\n" % ("",self.SRF_bitfieldstr(g));
75 #print "SFRX(%10s, %s); /* %50s */" % (name,address, description);
76 print "%-10s=0x%02x; /* %-50s */" % (
77 name,self.CCpeekdatabyte(eval(address)), description);
78 if bitfields!="": print bitfields.rstrip();
79 def RF_setfreq(self,frequency):
80 """Set the frequency in Hz."""
81 #FIXME CC1110 specific
84 freq=int(hz/396.728515625);
87 freq1=(freq&0xFF00)>>8;
88 freq2=(freq&0xFF0000)>>16;
90 self.pokebysym("FREQ2",freq2);
91 self.pokebysym("FREQ1",freq1);
92 self.pokebysym("FREQ0",freq0);
96 """Get the frequency in Hz."""
97 #FIXME CC1110 specific
99 #return (2400+self.peek(0x05))*10**6
100 #self.poke(0x05,chan);
102 #freq2=self.CCpeekdatabyte(0xdf09);
103 #freq1=self.CCpeekdatabyte(0xdf0a);
104 #freq0=self.CCpeekdatabyte(0xdf0b);
107 freq2=self.peekbysym("FREQ2");
108 freq1=self.peekbysym("FREQ1");
109 freq0=self.peekbysym("FREQ0");
110 freq=(freq2<<16)+(freq1<<8)+freq0;
114 hz=freq*396.728515625;
118 def RF_carrier(self):
119 """Hold a carrier wave on the present frequency."""
120 self.pokebysym("SYNC1",0xAA);
121 self.pokebysym("SYNC0",0xAA);
124 self.pokebyte(0xdfe1,0x03); #RFST=RFST_STX
126 print "Holding a carrier on %f MHz." % (self.RF_getfreq()/10**6);
128 #while ((MARCSTATE & MARCSTATE_MARC_STATE) != MARC_STATE_TX);
130 while( (state!=0x13)):
132 state=self.peekbysym("MARCSTATE")&0x1F;
133 print "state=%02x" % state;
137 def RF_getrssi(self):
138 """Returns the received signal strenght, with a weird offset."""
140 rssireg=self.symbols.get("RSSI");
141 return self.CCpeekdatabyte(rssireg);
143 if self.verbose>0: print "RSSI reg doesn't exist.";
145 #RSSI doesn't exist on 2.4GHz devices. Maybe RSSIL and RSSIH?
146 rssilreg=self.symbols.get("RSSIL");
147 rssil=self.CCpeekdatabyte(rssilreg);
148 rssihreg=self.symbols.get("RSSIL");
149 rssih=self.CCpeekdatabyte(rssihreg);
150 return (rssih<<8)|rssil;
152 if self.verbose>0: print "RSSIL/RSSIH regs don't exist.";
157 def SRF_loadsymbols(self):
158 ident=self.CCident();
159 chip=self.CCversions.get(ident&0xFF00);
160 dom=self.SRF_chipdom(chip,"register_definition.xml");
161 for e in dom.getElementsByTagName("registerdefinition"):
162 for f in e.childNodes:
163 if f.localName=="Register":
168 for g in f.childNodes:
169 if g.localName=="Name":
170 name=g.childNodes[0].nodeValue;
171 elif g.localName=="Address":
172 address=g.childNodes[0].nodeValue;
173 elif g.localName=="Description":
175 description=g.childNodes[0].nodeValue;
176 elif g.localName=="Bitfield":
177 bitfields+="%17s/* %-50s */\n" % ("",self.SRF_bitfieldstr(g));
178 #print "SFRX(%10s, %s); /* %50s */" % (name,address, description);
179 self.symbols.define(eval(address),name,description,"data");
185 self.writecmd(self.APP,0x86,0,self.data);
188 def CCreleasecpu(self):
189 """Resume the CPU."""
190 self.writecmd(self.APP,0x87,0,self.data);
194 #print "Status: %s" % self.CCstatusstr();
196 #Grab ident three times, should be equal.
197 ident1=self.CCident();
198 ident2=self.CCident();
199 ident3=self.CCident();
200 if(ident1!=ident2 or ident2!=ident3):
201 print "Error, repeated ident attempts unequal."
202 print "%04x, %04x, %04x" % (ident1, ident2, ident3);
204 #Single step, printing PC.
205 print "Tracing execution at startup."
206 for i in range(1,15):
208 byte=self.CCpeekcodebyte(i);
209 #print "PC=%04x, %02x" % (pc, byte);
212 print "Verifying that debugging a NOP doesn't affect the PC."
213 for i in range(1,15):
215 self.CCdebuginstr([0x00]);
216 if(pc!=self.CCgetPC()):
217 print "ERROR: PC changed during CCdebuginstr([NOP])!";
219 print "Checking pokes to XRAM."
220 for i in range(0xf000,0xf020):
221 self.CCpokedatabyte(i,0xde);
222 if(self.CCpeekdatabyte(i)!=0xde):
223 print "Error in XDATA at 0x%04x" % i;
225 #print "Status: %s." % self.CCstatusstr();
231 """Move the FET into the CC2430/CC2530 application."""
232 #print "Initializing Chipcon.";
233 self.writecmd(self.APP,0x10,0,self.data);
234 def CCrd_config(self):
235 """Read the config register of a Chipcon."""
236 self.writecmd(self.APP,0x82,0,self.data);
237 return ord(self.data[0]);
238 def CCwr_config(self,config):
239 """Write the config register of a Chipcon."""
240 self.writecmd(self.APP,0x81,1,[config&0xFF]);
241 def CClockchip(self):
242 """Set the flash lock bit in info mem."""
243 self.writecmd(self.APP, 0x9A, 0, None);
245 """Set the flash lock bit in info mem."""
249 CCversions={0x0100:"cc1110",
255 0xA500:"cc2530", #page 52 of SWRU191
258 CCpagesizes={0x01: 1024, #"CC1110",
259 0x11: 1024, #"CC1111",
260 0x85: 2048, #"CC2430",
261 0x89: 2048, #"CC2431",
262 0x81: 1024, #"CC2510",
263 0x91: 1024, #"CC2511",
264 0xA5: 2048, #"CC2530", #page 52 of SWRU191
265 0xB5: 2048, #"CC2531",
266 0xFF: 0 } #"CCmissing"};
267 def infostring(self):
268 return self.CCidentstr();
269 def CCidentstr(self):
270 ident=self.CCident();
271 chip=self.CCversions.get(ident&0xFF00);
272 pagesize=self.CCpagesizes.get(ident>0xFF);
274 return "%s/r%0.4x/ps0x%0.4x" % (chip, ident, pagesize);
276 return "%04x" % ident;
278 """Get a chipcon's ID."""
279 self.writecmd(self.APP,0x8B,0,None);
280 chip=ord(self.data[0]);
281 rev=ord(self.data[1]);
282 return (chip<<8)+rev;
283 def CCpagesize(self):
284 """Get a chipcon's ID."""
285 self.writecmd(self.APP,0x8B,0,None);
286 chip=ord(self.data[0]);
287 size=self.CCpagesizes.get(chip);
289 print "ERROR: Pagesize undefined.";
290 print "chip=%0.4x" %chip;
295 return self.CCgetPC();
297 """Get a chipcon's PC."""
298 self.writecmd(self.APP,0x83,0,None);
299 hi=ord(self.data[0]);
300 lo=ord(self.data[1]);
302 def CCcmd(self,phrase):
303 self.writecmd(self.APP,0x00,len(phrase),phrase);
304 val=ord(self.data[0]);
305 print "Got %02x" % val;
307 def CCdebuginstr(self,instr):
308 self.writecmd(self.APP,0x88,len(instr),instr);
309 return ord(self.data[0]);
310 def peekblock(self,adr,length,memory="vn"):
311 """Return a block of data."""
312 data=[adr&0xff, (adr&0xff00)>>8,
313 length&0xFF,(length&0xFF00)>>8];
314 self.writecmd(self.APP,0x91,4,data);
315 return [ord(x) for x in self.data]
316 def peek8(self,address, memory="code"):
317 if(memory=="code" or memory=="flash" or memory=="vn"):
318 return self.CCpeekcodebyte(address);
319 elif(memory=="data" or memory=="xdata" or memory=="ram"):
320 return self.CCpeekdatabyte(address);
321 elif(memory=="idata" or memory=="iram"):
322 return self.CCpeekirambyte(address);
323 print "%s is an unknown memory." % memory;
325 def CCpeekcodebyte(self,adr):
326 """Read the contents of code memory at an address."""
327 self.data=[adr&0xff, (adr&0xff00)>>8];
328 self.writecmd(self.APP,0x90,2,self.data);
329 return ord(self.data[0]);
330 def CCpeekdatabyte(self,adr):
331 """Read the contents of data memory at an address."""
332 self.data=[adr&0xff, (adr&0xff00)>>8];
333 self.writecmd(self.APP,0x91, 2, self.data);
334 return ord(self.data[0]);
335 def CCpeekirambyte(self,adr):
336 """Read the contents of IRAM at an address."""
337 self.data=[adr&0xff];
338 self.writecmd(self.APP,0x02, 1, self.data);
339 return ord(self.data[0]);
340 def CCpeekiramword(self,adr):
341 """Read the little-endian contents of IRAM at an address."""
342 return self.CCpeekirambyte(adr)+(
343 self.CCpeekirambyte(adr+1)<<8);
344 def CCpokeiramword(self,adr,val):
345 self.CCpokeirambyte(adr,val&0xff);
346 self.CCpokeirambyte(adr+1,(val>>8)&0xff);
347 def CCpokeirambyte(self,adr,val):
348 """Write the contents of IRAM at an address."""
349 self.data=[adr&0xff, val&0xff];
350 self.writecmd(self.APP,0x02, 2, self.data);
351 return ord(self.data[0]);
352 def pokebyte(self,adr,val,mem="data"):
353 self.CCpokedatabyte(adr,val);
354 def CCpokedatabyte(self,adr,val):
355 """Write a byte to data memory."""
356 self.data=[adr&0xff, (adr&0xff00)>>8, val];
357 self.writecmd(self.APP, 0x92, 3, self.data);
358 return ord(self.data[0]);
359 def CCchiperase(self):
360 """Erase all of the target's memory."""
361 self.writecmd(self.APP,0x80,0,None);
363 """Erase all of the target's memory."""
368 """Check the status."""
369 self.writecmd(self.APP,0x84,0,None);
370 return ord(self.data[0])
372 CCstatusbits={0x80 : "erase_busy",
376 0x08 : "halt_status",
381 CCconfigbits={0x20 : "soft_power_mode", #new for CC2530
384 0x02 : "timer_suspend",
385 0x01 : "sel_flash_info_page" #stricken from CC2530
389 """Check the status as a string."""
390 status=self.CCstatus();
395 str="%s %s" %(self.CCstatusbits[i],str);
399 """Start debugging."""
401 self.writecmd(self.APP,0x20,0,self.data);
402 ident=self.CCidentstr();
403 #print "Target identifies as %s." % ident;
404 #print "Status: %s." % self.status();
407 #Get SmartRF Studio regs if they exist.
411 """Stop debugging."""
412 self.writecmd(self.APP,0x21,0,self.data);
413 def CCstep_instr(self):
414 """Step one instruction."""
415 self.writecmd(self.APP,0x89,0,self.data);
416 def CCeraseflashbuffer(self):
417 """Erase the 2kB flash buffer"""
418 self.writecmd(self.APP,0x99);
419 def CCflashpage(self,adr):
420 """Flash 2kB a page of flash from 0xF000 in XDATA"""
425 print "Flashing buffer to 0x%06x" % adr;
426 self.writecmd(self.APP,0x95,4,data);
428 def setsecret(self,value):
429 """Set a secret word for later retreival. Used by glitcher."""
431 pagelen = self.CCpagesize(); #Varies by chip.
432 print "page=%04x, pagelen=%04x" % (page,pagelen);
434 self.CCeraseflashbuffer();
435 print "Setting secret to %x" % value;
436 self.CCpokedatabyte(0xF000,value);
437 self.CCpokedatabyte(0xF800,value);
438 print "Setting secret to %x==%x" % (value,
439 self.CCpeekdatabyte(0xf000));
441 print "code[0]=%x" % self.CCpeekcodebyte(0);
443 """Get a secret word. Used by glitcher."""
444 secret=self.CCpeekcodebyte(0);
445 #print "Got secret %02x" % secret;
448 def dump(self,file,start=0,stop=0xffff):
449 """Dump an intel hex file from code memory."""
450 print "Dumping code from %04x to %04x as %s." % (start,stop,file);
454 h[i]=self.CCpeekcodebyte(i);
456 print "Dumped %04x."%i;
457 h.write_hex_file(file); #buffer to disk.
459 h.write_hex_file(file);
461 def flash(self,file):
462 """Flash an intel hex file to code memory."""
463 print "Flashing %s" % file;
467 pagelen = self.CCpagesize(); #Varies by chip.
469 #print "page=%04x, pagelen=%04x" % (page,pagelen);
473 #Wipe the RAM buffer for the next flash page.
474 self.CCeraseflashbuffer();
475 for i in h._buf.keys():
476 while(i>=page+pagelen):
478 self.CCflashpage(page);
479 #client.CCeraseflashbuffer();
481 print "Flashed page at %06x" % page
484 #Place byte into buffer.
485 self.CCpokedatabyte(0xF000+i-page,
489 print "Buffering %04x toward %06x" % (i,page);
491 self.CCflashpage(page);
492 print "Flashed final page at %06x" % page;