Substantially reduced time required to verify program memory contents.
[goodfet] / client / GoodFET.py
index 077ee75..518cf47 100755 (executable)
@@ -6,6 +6,9 @@
 # This code is being rewritten and refactored.  You've been warned!
 
 import sys, time, string, cStringIO, struct, glob, serial, os;
+import sqlite3;
+
+fmt = ("B", "<H", None, "<L")
 
 def getClient(name="GoodFET"):
     import GoodFET, GoodFETCC, GoodFETAVR, GoodFETSPI, GoodFETMSP430;
@@ -13,27 +16,60 @@ def getClient(name="GoodFET"):
     elif name=="cc" or name=="chipcon": return GoodFETCC.GoodFETCC();
     elif name=="avr": return GoodFETAVR.GoodFETAVR();
     elif name=="spi": return GoodFETSPI.GoodFETSPI();
-    elif name=="msp430": return GoodFETSPI.GoodFETMSP430();
+    elif name=="msp430": return GoodFETMSP430.GoodFETMSP430();
     
     print "Unsupported target: %s" % name;
     sys.exit(0);
 
+class SymbolTable:
+    """GoodFET Symbol Table"""
+    db=sqlite3.connect(":memory:");
+    
+    def __init__(self, *args, **kargs):
+        self.db.execute("create table if not exists symbols(adr,name,memory,size,comment);");
+    def get(self,name):
+        self.db.commit();
+        c=self.db.cursor();
+        try:
+            c.execute("select adr,memory from symbols where name=?",(name,));
+            for row in c:
+                #print "Found it.";
+                sys.stdout.flush();
+                return row[0];
+            #print "No dice.";
+        except:# sqlite3.OperationalError:
+            #print "SQL error.";
+            return eval(name);
+        return eval(name);
+    def define(self,adr,name,comment="",memory="vn",size=16):
+        self.db.execute("insert into symbols(adr,name,memory,size,comment)"
+                        "values(?,?,?,?,?);", (
+                adr,name,memory,size,comment));
+        #print "Set %s=%s." % (name,adr);
 
 class GoodFET:
     """GoodFET Client Library"""
+
+    besilent=0;
+    app=0;
+    verb=0;
+    count=0;
+    data="";
+    verbose=False
     
     GLITCHAPP=0x71;
+    symbols=SymbolTable();
     
     def __init__(self, *args, **kargs):
         self.data=[0];
-    
-
     def getConsole(self):
         from GoodFETConsole import GoodFETConsole;
         return GoodFETConsole(self);
+    def name2adr(self,name):
+        return self.symbols.get(name);
     def timeout(self):
         print "timeout\n";
-    def serInit(self, port=None):
+    def serInit(self, port=None, timeout=None):
         """Open the serial port"""
         
         if port is None and os.environ.get("GOODFET")!=None:
@@ -53,12 +89,10 @@ class GoodFET:
             port,
             #9600,
             115200,
-            parity = serial.PARITY_NONE
+            parity = serial.PARITY_NONE,
+            timeout=timeout
             )
         
-        #This might cause problems, but it makes failure graceful.
-        #self.serialport._timeout = 5;
-        
         #Explicitly set RTS and DTR to halt board.
         self.serialport.setRTS(1);
         self.serialport.setDTR(1);
@@ -71,7 +105,8 @@ class GoodFET:
         #time.sleep(1);
         self.readcmd(); #Read the first command.
         if(self.verb!=0x7F):
-            print "Verb %02x is wrong.  Incorrect firmware?" % self.verb;
+            print "Verb %02x is wrong.  Incorrect firmware or bad Info guess?" % self.verb;
+            print "http://goodfet.sf.net/faq/";
         #print "Connected."
     def getbuffer(self,size=0x1c00):
         writecmd(0,0xC2,[size&0xFF,(size>>16)&0xFF]);
@@ -89,6 +124,9 @@ class GoodFET:
         #little endian 16-bit length
         self.serialport.write(chr(count&0xFF));
         self.serialport.write(chr(count>>8));
+
+        if self.verbose:
+            print "Tx: ( 0x%02x, 0x%02x, 0x%04x )" % ( app, verb, count )
         
         #print "count=%02x, len(data)=%04x" % (count,len(data));
         
@@ -101,34 +139,41 @@ class GoodFET:
             outstr=''.join(data);
             self.serialport.write(outstr);
         if not self.besilent:
-            self.readcmd();
-        
-    besilent=0;
-    app=0;
-    verb=0;
-    count=0;
-    data="";
+            return self.readcmd()
+        else:
+            return []
 
     def readcmd(self):
         """Read a reply from the GoodFET."""
-        while 1:
-            #print "Reading...";
-            self.app=ord(self.serialport.read(1));
-            #print "APP=%2x" % self.app;
-            self.verb=ord(self.serialport.read(1));
-            #print "VERB=%02x" % self.verb;
-            self.count=(
-                ord(self.serialport.read(1))
-                +(ord(self.serialport.read(1))<<8)
-                );
+        while 1:#self.serialport.inWaiting(): # Loop while input data is available
+            try:
+                #print "Reading...";
+                self.app=ord(self.serialport.read(1));
+                #print "APP=%2x" % self.app;
+                self.verb=ord(self.serialport.read(1));
+                #print "VERB=%02x" % self.verb;
+                self.count=(
+                    ord(self.serialport.read(1))
+                    +(ord(self.serialport.read(1))<<8)
+                    );
+
+                if self.verbose:
+                    print "Rx: ( 0x%02x, 0x%02x, 0x%04x )" % ( self.app, self.verb, self.count )
             
-            #Debugging string; print, but wait.
-            if self.app==0xFF and self.verb==0xFF:
-                print "# DEBUG %s" % self.serialport.read(self.count);
-                sys.stdout.flush();
-            else:
-                self.data=self.serialport.read(self.count);
-                return self.data;
+                #Debugging string; print, but wait.
+                if self.app==0xFF:
+                    if self.verb==0xFF:
+                        print "# DEBUG %s" % self.serialport.read(self.count)
+                           elif self.verb==0xFE:
+                        print "# DEBUG 0x%x" % struct.unpack(fmt[self.count-1], self.serialport.read(self.count))[0]
+                    sys.stdout.flush();
+                else:
+                    self.data=self.serialport.read(self.count);
+                    return self.data;
+            except TypeError:
+                print "Error: waiting for serial read timed out (most likely)."
+                sys.exit(-1)
+
     #Glitching stuff.
     def glitchApp(self,app):
         """Glitch into a device by its application."""
@@ -286,16 +331,27 @@ class GoodFET:
     def start(self):
         return;
     def test(self):
+        print "Unimplemented.";
         return;
     def status(self):
+        print "Unimplemented.";
         return;
     def halt(self):
+        print "Unimplemented.";
         return;
     def resume(self):
+        print "Unimplemented.";
         return;
+    def getpc(self):
+        print "Unimplemented.";
+        return 0xdead;
     def flash(self,file):
         """Flash an intel hex file to code memory."""
         print "Flash not implemented.";
+    def dump(self,file,start=0,stop=0xffff):
+        """Dump an intel hex file from code memory."""
+        print "Dump not implemented.";
+
     def peek32(self,address, memory="vn"):
         return (self.peek16(address,memory)+
                 (self.peek16(address+2,memory)<<16));
@@ -303,4 +359,6 @@ class GoodFET:
         return (self.peek8(address,memory)+
                 (self.peek8(address+1,memory)<<8));
     def peek8(self,address, memory="vn"):
-        return 0xde;
+        return self.peekbyte(address); #monitor
+    def loadsymbols(self):
+        return;