X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2FGoodFET.py;h=ca84e574a0364e87a1cfb9e26d50cdfb7a686101;hp=14728c73c3c5288bf5fe8f741f76249aa4b8d13c;hb=fa7c4f1b34ed53c88a678f947eb4b34c6e9807b4;hpb=3f38402660946d2792fd9a9974f3ffa670a123e8 diff --git a/client/GoodFET.py b/client/GoodFET.py index 14728c7..ca84e57 100755 --- a/client/GoodFET.py +++ b/client/GoodFET.py @@ -6,18 +6,31 @@ # This code is ugly as sin, for bootstrapping the firmware only. # Rewrite cleanly as soon as is convenient. -import sys, time, string, cStringIO, struct -sys.path.append("/usr/lib/tinyos") -import serial +import sys, time, string, cStringIO, struct, glob, serial, os; class GoodFET: + """GoodFET Client Library""" def __init__(self, *args, **kargs): self.data=[0]; def timeout(self): - print "timout\n"; - def serInit(self, port): + print "timeout\n"; + def serInit(self, port=None): """Open the serial port""" + + if port is None and os.environ.get("GOODFET")!=None: + glob_list = glob.glob(os.environ.get("GOODFET")); + if len(glob_list) > 0: + port = glob_list[0]; + if port is None: + glob_list = glob.glob("/dev/tty.usbserial*"); + if len(glob_list) > 0: + port = glob_list[0]; + if port is None: + glob_list = glob.glob("/dev/ttyUSB*"); + if len(glob_list) > 0: + port = glob_list[0]; + self.serialport = serial.Serial( port, #9600, @@ -33,9 +46,9 @@ class GoodFET: #time.sleep(1); self.readcmd(); #Read the first command. if(self.verb!=0x7F): - print "Verb is wrong. Incorrect firmware?"; - - def writecmd(self, app, verb, count, data): + print "Verb %02x is wrong. Incorrect firmware?" % self.verb; + #print "Connected." + def writecmd(self, app, verb, count=0, data=[], blocks=1): """Write a command and some data to the GoodFET.""" self.serialport.write(chr(app)); self.serialport.write(chr(verb)); @@ -44,14 +57,15 @@ class GoodFET: if count!=0: for d in data: self.serialport.write(chr(d)); - self.readcmd(); #Uncomment this later, to ensure a response. - def readcmd(self): + + self.readcmd(blocks); #Uncomment this later, to ensure a response. + def readcmd(self,blocks=1): """Read a reply from the GoodFET.""" self.app=ord(self.serialport.read(1)); self.verb=ord(self.serialport.read(1)); self.count=ord(self.serialport.read(1)); - if self.count>0: - self.data=self.serialport.read(self.count); + self.data=self.serialport.read(self.count*blocks); + return self.data; #print "READ %02x %02x %02x " % (self.app, self.verb, self.count); #Monitor stuff @@ -69,8 +83,30 @@ class GoodFET: self.data=[address&0xff,address>>8,value]; self.writecmd(0,0x03,3,self.data); return ord(self.data[0]); + def dumpmem(self,begin,end): + i=begin; + while i>8]; self.writecmd(0x11,0x02,2,self.data); return ord(self.data[0])+(ord(self.data[1])<<8); - def CCpeekcodebyte(self,adr): - """Read the contents of code memory at an address.""" - self.data=[adr&0xff, (adr&0xff00)>>8]; - self.writecmd(0x30,0x90,2,self.data); - return ord(self.data[0]); - def CCpeekdatabyte(self,adr): - """Read the contents of data memory at an address.""" - self.data=[adr&0xff, (adr&0xff00)>>8]; - self.writecmd(0x30,0x91, 2, self.data); - return ord(self.data[0]); - def CCpokedatabyte(self,adr,val): - """Write a byte to data memory.""" - self.data=[adr&0xff, (adr&0xff00)>>8, val]; - self.writecmd(0x30, 0x92, 3, self.data); - return ord(self.data[0]); - def CCchiperase(self): - """Erase all of the target's memory.""" - self.writecmd(0x30,0x80,0,None); - def CCstatus(self): - """Check the status.""" - self.writecmd(0x30,0x84,0,None); - return ord(self.data[0]) - CCstatusbits={0x80 : "erased", - 0x40 : "pcon_idle", - 0x20 : "halted", - 0x10 : "pm0", - 0x08 : "halted", - 0x04 : "locked", - 0x02 : "oscstable", - 0x01 : "overflow"}; - def CCstatusstr(self): - """Check the status as a string.""" - status=self.CCstatus(); - str=""; - i=1; - while i<0x100: - if(status&i): - str="%s %s" %(self.CCstatusbits[i],str); - i*=2; - return str; def MSP430poke(self,adr,val): """Read the contents of memory at an address.""" self.data=[adr&0xff, (adr&0xff00)>>8, val&0xff, (val&0xff00)>>8]; @@ -208,36 +195,12 @@ class GoodFET: ident=self.MSP430ident(); print "Target identifies as %04x." % ident; - def CCstart(self): - """Start debugging.""" - self.writecmd(0x30,0x20,0,self.data); - ident=self.CCidentstr(); - print "Target identifies as %s." % ident; - print "Status: %s." % self.CCstatusstr(); - self.CCreleasecpu(); - self.CChaltcpu(); - print "Status: %s." % self.CCstatusstr(); - def CCstop(self): - """Stop debugging.""" - self.writecmd(0x30,0x21,0,self.data); - def CCstep_instr(self): - """Step one instruction.""" - self.writecmd(0x30,0x89,0,self.data); - def MSP430stop(self): - """Stop debugging.""" - self.writecmd(0x11,0x21,0,self.data); def MSP430haltcpu(self): """Halt the CPU.""" self.writecmd(0x11,0xA0,0,self.data); def MSP430releasecpu(self): """Resume the CPU.""" self.writecmd(0x11,0xA1,0,self.data); - def CChaltcpu(self): - """Halt the CPU.""" - self.writecmd(0x30,0x86,0,self.data); - def CCreleasecpu(self): - """Resume the CPU.""" - self.writecmd(0x30,0x87,0,self.data); def MSP430shiftir8(self,ins): """Shift the 8-bit Instruction Register.""" data=[ins]; @@ -297,10 +260,123 @@ class GoodFET: while i>16, + (adr&0xFF00)>>8, + adr&0xFF, + 0]; + self.SPItrans(data); + return ord(self.data[4]); + def SPIpeekblock(self,adr,blocks=1): + """Grab a few block from an SPI Flash ROM. Block size is unknown""" + data=[(adr&0xFF0000)>>16, + (adr&0xFF00)>>8, + adr&0xFF, + blocks]; + + self.writecmd(0x01,0x02,4,data,blocks); + return self.data; + + def SPIpokebyte(self,adr,val): + self.SPIpokebytes(adr,[val]); + def SPIpokebytes(self,adr,data): + #self.SPIwriteenable(); + adranddata=[(adr&0xFF0000)>>16, + (adr&0xFF00)>>8, + adr&0xFF + ]+data; + self.writecmd(0x01,0x03, + len(adranddata),adranddata); + + def SPIchiperase(self): + """Mass erase an SPI Flash ROM.""" + self.writecmd(0x01,0x81,0,[]); + def SPIwriteenable(self): + """SPI Flash Write Enable""" + data=[0x06]; + self.SPItrans(data); + + def SPIjedecmanstr(self): + """Grab the JEDEC manufacturer string. Call after SPIjedec().""" + man=self.JEDECmanufacturers.get(self.JEDECmanufacturer) + if man==0: + man="UNKNOWN"; + return man; + + def SPIjedecstr(self): + """Grab the JEDEC manufacturer string. Call after SPIjedec().""" + man=self.JEDECmanufacturers.get(self.JEDECmanufacturer); + if man==0: + man="UNKNOWN"; + device=self.JEDECdevices.get(self.JEDECdevice); + if device==0: + device="???" + return "%s %s" % (man,device); +class GoodFETCC(GoodFET): + """A GoodFET variant for use with Chipcon 8051 Zigbe SoC.""" + def CChaltcpu(self): + """Halt the CPU.""" + self.writecmd(0x30,0x86,0,self.data); + def CCreleasecpu(self): + """Resume the CPU.""" + self.writecmd(0x30,0x87,0,self.data); def CCtest(self): self.CCreleasecpu(); self.CChaltcpu(); - print "Status: %s" % self.CCstatusstr(); + #print "Status: %s" % self.CCstatusstr(); #Grab ident three times, should be equal. ident1=self.CCident(); @@ -311,26 +387,117 @@ class GoodFET: print "%04x, %04x, %04x" % (ident1, ident2, ident3); #Single step, printing PC. - #print "Tracing execution at startup." + print "Tracing execution at startup." for i in range(1,15): pc=self.CCgetPC(); byte=self.CCpeekcodebyte(i); - print "PC=%04x, %02x" % (pc, byte); + #print "PC=%04x, %02x" % (pc, byte); self.CCstep_instr(); - #print "Verifying that debugging a NOP doesn't affect the PC." + print "Verifying that debugging a NOP doesn't affect the PC." for i in range(1,15): pc=self.CCgetPC(); self.CCdebuginstr([0x00]); if(pc!=self.CCgetPC()): print "ERROR: PC changed during CCdebuginstr([NOP])!"; - for i in range(0xE500,0xE600): - byte=self.CCpeekdatabyte(i); - print "data %04x: %02x" % (i,byte); - self.CCpokedatabyte(i,i&0xFF); - byte=self.CCpeekdatabyte(i); - print "data %04x: %02x" % (i,byte); - print "Status: %s." % self.CCstatusstr(); + + + #print "Status: %s." % self.CCstatusstr(); #Exit debugger self.CCstop(); print "Done."; + + def CCsetup(self): + """Move the FET into the CC2430/CC2530 application.""" + #print "Initializing Chipcon."; + self.writecmd(0x30,0x10,0,self.data); + def CCrd_config(self): + """Read the config register of a Chipcon.""" + self.writecmd(0x30,0x82,0,self.data); + return ord(self.data[0]); + def CCwr_config(self,config): + """Write the config register of a Chipcon.""" + self.writecmd(0x30,0x81,1,[config&0xFF]); + + CCversions={0x0100:"CC1110", + 0x8500:"CC2430", + 0x8900:"CC2431", + 0x8100:"CC2510", + 0x9100:"CC2511", + 0xFF00:"CCmissing"}; + def CCidentstr(self): + ident=self.CCident(); + chip=self.CCversions.get(ident&0xFF00); + return "%s/r%02x" % (chip, ident&0xFF); + def CCident(self): + """Get a chipcon's ID.""" + self.writecmd(0x30,0x8B,0,None); + chip=ord(self.data[0]); + rev=ord(self.data[1]); + return (chip<<8)+rev; + def CCgetPC(self): + """Get a chipcon's PC.""" + self.writecmd(0x30,0x83,0,None); + hi=ord(self.data[0]); + lo=ord(self.data[1]); + return (hi<<8)+lo; + def CCdebuginstr(self,instr): + self.writecmd(0x30,0x88,len(instr),instr); + return ord(self.data[0]); + def CCpeekcodebyte(self,adr): + """Read the contents of code memory at an address.""" + self.data=[adr&0xff, (adr&0xff00)>>8]; + self.writecmd(0x30,0x90,2,self.data); + return ord(self.data[0]); + def CCpeekdatabyte(self,adr): + """Read the contents of data memory at an address.""" + self.data=[adr&0xff, (adr&0xff00)>>8]; + self.writecmd(0x30,0x91, 2, self.data); + return ord(self.data[0]); + def CCpokedatabyte(self,adr,val): + """Write a byte to data memory.""" + self.data=[adr&0xff, (adr&0xff00)>>8, val]; + self.writecmd(0x30, 0x92, 3, self.data); + return ord(self.data[0]); + def CCchiperase(self): + """Erase all of the target's memory.""" + self.writecmd(0x30,0x80,0,None); + def CCstatus(self): + """Check the status.""" + self.writecmd(0x30,0x84,0,None); + return ord(self.data[0]) + CCstatusbits={0x80 : "erased", + 0x40 : "pcon_idle", + 0x20 : "halted", + 0x10 : "pm0", + 0x08 : "halted", + 0x04 : "locked", + 0x02 : "oscstable", + 0x01 : "overflow"}; + def CCstatusstr(self): + """Check the status as a string.""" + status=self.CCstatus(); + str=""; + i=1; + while i<0x100: + if(status&i): + str="%s %s" %(self.CCstatusbits[i],str); + i*=2; + return str; + def CCstart(self): + """Start debugging.""" + self.writecmd(0x30,0x20,0,self.data); + ident=self.CCidentstr(); + print "Target identifies as %s." % ident; + #print "Status: %s." % self.CCstatusstr(); + self.CCreleasecpu(); + self.CChaltcpu(); + #print "Status: %s." % self.CCstatusstr(); + + def CCstop(self): + """Stop debugging.""" + self.writecmd(0x30,0x21,0,self.data); + def CCstep_instr(self): + """Step one instruction.""" + self.writecmd(0x30,0x89,0,self.data); +