X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2FGoodFET.py;h=952ae98f10332a2e3e1f00f582c44c1ea011ab1d;hp=054f6481d68b2558c50d6399759a24806b52ce49;hb=92560226caf1a463eb144324978b0a390327e09e;hpb=fbc2cacf6365782c314b4c512ce73b7dd24e5b91 diff --git a/client/GoodFET.py b/client/GoodFET.py index 054f648..952ae98 100755 --- a/client/GoodFET.py +++ b/client/GoodFET.py @@ -7,7 +7,7 @@ # Rewrite cleanly as soon as is convenient. import sys, time, string, cStringIO, struct -sys.path.append("/usr/lib/tinyos") +#sys.path.append("/usr/lib/tinyos") import serial @@ -20,7 +20,8 @@ class GoodFET: """Open the serial port""" self.serialport = serial.Serial( port, - 9600, + #9600, + 115200, parity = serial.PARITY_NONE ) #Drop DTR, which is !RST, low to begin the app. @@ -29,12 +30,11 @@ class GoodFET: self.serialport.flushOutput() #Read and handle the initial command. - time.sleep(1); + #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): """Write a command and some data to the GoodFET.""" self.serialport.write(chr(app)); @@ -69,7 +69,23 @@ class GoodFET: self.data=[address&0xff,address>>8,value]; self.writecmd(0,0x03,3,self.data); return ord(self.data[0]); - + def setBaud(self,baud): + rates=[9600, 9600, 19200, 38400]; + self.data=[baud]; + print "Changing FET baud." + self.serialport.write(chr(0x00)); + self.serialport.write(chr(0x80)); + self.serialport.write(chr(1)); + self.serialport.write(chr(baud)); + + print "Changed host baud." + self.serialport.setBaudrate(rates[baud]); + time.sleep(1); + self.serialport.flushInput() + self.serialport.flushOutput() + + print "Baud is now %i." % rates[baud]; + return; def monitortest(self): """Self-test several functions through the monitor.""" print "Performing monitor self-test."; @@ -83,37 +99,186 @@ class GoodFET: print "Self-test complete."; - def spisetup(self): + def SPIsetup(self): """Moved the FET into the SPI application.""" - self.writecmd(1,0x10,0,self.data); #SPI/SETUP + self.writecmd(0x01,0x10,0,self.data); #SPI/SETUP #self.readcmd(); - def spitrans8(self,byte): + def SPItrans8(self,byte): """Read and write 8 bits by SPI.""" - self.data=[byte]; - self.writecmd(1,0,1,self.data); #SPI exchange - #self.readcmd(); + data=self.SPItrans([byte]); + return ord(data[0]); + + def SPItrans(self,data): + """Exchange data by SPI.""" + self.data=data; + self.writecmd(0x01,0x00,len(data),data); + return self.data; + + JEDECmanufacturers={0xFF: "MISSING", + 0xEF: "Winbond"}; + JEDECdevices={0xEF3014: "W25X80L", + 0xEF3013: "W25X40L", + 0xEF3012: "W25X20L", + 0xEF3011: "W25X10L"}; + def SPIjedec(self): + """Grab an SPI Flash ROM's JEDEC bytes.""" + data=[0x9f, 0, 0, 0]; + data=self.SPItrans(data); + #print "Manufacturer: %02x\nType: %02x\nCapacity: %02x" % (ord(data[1]),ord(data[2]),ord(data[3])); + self.JEDECmanufacturer=ord(data[1]); + self.JEDECtype=ord(data[2]); + self.JEDECcapacity=ord(data[3]); + self.JEDECdevice=(ord(data[1])<<16)+(ord(data[2])<<8)+ord(data[3]); + return data; + def SPIpeek(self,adr): + """Grab a byte from an SPI Flash ROM.""" + data=[0x03, + (adr&0xFF0000)>>16, + (adr&0xFF00)>>8, + adr&0xFF, + 0]; + self.SPItrans(data); + return ord(self.data[4]); + def SPIpeekblock(self,adr): + """Grab a byte from an SPI Flash ROM.""" + data=[(adr&0xFF0000)>>16, + (adr&0xFF00)>>8, + adr&0xFF]; - if self.app!=1 or self.verb!=0: - print "Error in SPI transaction; app=%02x, verb=%02x" % (self.app, self.verb); - return ord(self.data[0]); + self.writecmd(0x01,0x02,3,data); + return self.data; + + def SPIjedecmanstr(self): + """Grab the JEDEC manufacturer string. Call after SPIjedec().""" + man=self.JEDECmanufacturers[self.JEDECmanufacturer]; + if man==0: + man="UNKNOWN"; + return man; + + def SPIjedecstr(self): + """Grab the JEDEC manufacturer string. Call after SPIjedec().""" + man=self.JEDECmanufacturers[self.JEDECmanufacturer]; + if man==0: + man="UNKNOWN"; + device=self.JEDECdevices[self.JEDECdevice]; + if device==0: + device="???" + return "%s %s" % (man,device); def MSP430setup(self): """Move the FET into the MSP430 JTAG application.""" print "Initializing MSP430."; self.writecmd(0x11,0x10,0,self.data); + + + + 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[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 MSP430peek(self,adr): """Read the contents of memory at an address.""" self.data=[adr&0xff, (adr&0xff00)>>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]; self.writecmd(0x11,0x03,4,self.data); return;# ord(self.data[0])+(ord(self.data[1])<<8); - def MSP430start(self): """Start debugging.""" self.writecmd(0x11,0x20,0,self.data); + 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); @@ -123,7 +288,12 @@ class GoodFET: 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]; @@ -138,15 +308,13 @@ class GoodFET: """Set the instruction fetch mode.""" self.writecmd(0x11,0xC1,0,self.data); return self.data[0]; + def MSP430ident(self): + """Grab self-identification word from 0x0FF0 as big endian.""" + i=self.MSP430peek(0x0ff0); + return ((i&0xFF00)>>8)+((i&0xFF)<<8) def MSP430test(self): """Test MSP430 JTAG. Requires that a chip be attached.""" - #self.MSP430setup(); - #self.MSP430start(); - self.MSP430haltcpu(); - - ident=self.MSP430peek(0x0ff0); - print "Target identifies as %04x." % ident; - if ident==0xffff: + if self.MSP430ident()==0xffff: print "Is anything connected?"; print "Testing RAM."; temp=self.MSP430peek(0x0200); @@ -155,8 +323,27 @@ class GoodFET: print "Poke of 0x0200 did not set to 0xDEAD properly."; return; self.MSP430poke(0x0200,temp); #restore old value. - self.MSP430releasecpu(); - + def MSP430flashtest(self): + self.MSP430masserase(); + i=0x2500; + while(i<0xFFFF): + if(self.MSP430peek(i)!=0xFFFF): + print "ERROR: Unerased flash at %04x."%i; + self.MSP430writeflash(i,0xDEAD); + i+=2; + def MSP430masserase(self): + """Erase MSP430 flash memory.""" + self.writecmd(0x11,0xE3,0,None); + def MSP430writeflash(self,adr,val): + """Write a word of flash memory.""" + if(self.MSP430peek(adr)!=0xFFFF): + print "FLASH ERROR: %04x not clear." % adr; + data=[adr&0xFF,(adr&0xFF00)>>8,val&0xFF,(val&0xFF00)>>8]; + self.writecmd(0x11,0xE1,4,data); + rval=ord(self.data[0])+(ord(self.data[1])<<8); + if(val!=rval): + print "FLASH WRITE ERROR AT %04x. Found %04x, wrote %04x." % (adr,rval,val); + def MSP430dumpbsl(self): self.MSP430dumpmem(0xC00,0xfff); def MSP430dumpallmem(self): @@ -166,4 +353,40 @@ class GoodFET: while i