JTAGARM7 is back up and running, folks! Tested Halt/Release, Get/Set Registers,...
[goodfet] / client / goodfet.bsl
index 3a8aa79..b51fce2 100755 (executable)
@@ -14,7 +14,7 @@
 # JTAG programmer.
 
 import sys, time, string, cStringIO, struct
-sys.path.append("/usr/lib/tinyos")
+#sys.path.append("/usr/lib/tinyos")  #We no longer require TinyOS.
 import serial, os, glob
 
 #forked from TinyOS Telos version.
@@ -200,12 +200,14 @@ deviceids = {
     0xf449: F4x,
     0x1232: F1x,
     0xf26f: F2x, #for GoodFET20
+    0xf227: F2x, #for GoodFET30
 }
 
 #GoodFET firmware
 firmware = {
     0xf16c: "http://goodfet.sourceforge.net/dist/msp430x1612.hex",
     0xf26f: "http://goodfet.sourceforge.net/dist/msp430x2618.hex",
+    0xf227: "http://goodfet.sourceforge.net/dist/msp430x2274.hex"
 }
 
 class BSLException(Exception):
@@ -258,7 +260,9 @@ class LowLevel:
     ERR_CMD_FAILED          = "Command failed, is not defined or is not allowed"
     ERR_BSL_SYNC            = "Bootstrap loader synchronization error"
     ERR_FRAME_NUMBER        = "Frame sequence number error."
-
+    
+    z1 = 0;
+    
     def calcChecksum(self, data, length):
         """Calculates a checksum of "data"."""
         checksum = 0
@@ -282,9 +286,9 @@ class LowLevel:
         #used for some hardware
         self.invertRST = 0
         self.invertTEST = 0
-       self.swapRSTTEST = 0
-       self.telosLatch = 0
-       self.telosI2C = 0
+        self.swapRSTTEST = 0
+        self.telosLatch = 0
+        self.telosI2C = 0
         
         self.protocolMode = self.MODE_BSL
         self.BSLMemAccessWarning = 0                #Default: no warning.
@@ -310,8 +314,10 @@ class LowLevel:
             timeout = self.timeout
         )
         if DEBUG: sys.stderr.write("using serial port %r\n" % self.serialport.portstr)
-        self.SetRSTpin()                        #enable power
-        self.SetTESTpin()                       #enable power
+        
+        if not self.z1:
+            self.SetRSTpin()                        #enable power
+            self.SetTESTpin()                       #enable power
         self.serialport.flushInput()
         self.serialport.flushOutput()
 
@@ -488,22 +494,22 @@ class LowLevel:
         self.serialport.setDTR(not level)
 
     def telosI2CStart(self):
-       self.telosSetSDA(1)
-       self.telosSetSCL(1)
-       self.telosSetSDA(0)
+        self.telosSetSDA(1)
+        self.telosSetSCL(1)
+        self.telosSetSDA(0)
 
     def telosI2CStop(self):
-       self.telosSetSDA(0)
-       self.telosSetSCL(1)
-       self.telosSetSDA(1)
+        self.telosSetSDA(0)
+        self.telosSetSCL(1)
+        self.telosSetSDA(1)
 
     def telosI2CWriteBit(self, bit):
-       self.telosSetSCL(0)
-       self.telosSetSDA(bit)
+        self.telosSetSCL(0)
+        self.telosSetSDA(bit)
         time.sleep(2e-6)
-       self.telosSetSCL(1)
+        self.telosSetSCL(1)
         time.sleep(1e-6)
-       self.telosSetSCL(0)
+        self.telosSetSCL(0)
 
     def telosI2CWriteByte(self, byte):
         self.telosI2CWriteBit( byte & 0x80 );
@@ -517,36 +523,115 @@ class LowLevel:
         self.telosI2CWriteBit( 0 );  # "acknowledge"
 
     def telosI2CWriteCmd(self, addr, cmdbyte):
-       self.telosI2CStart()
+        self.telosI2CStart()
         self.telosI2CWriteByte( 0x90 | (addr << 1) )
-       self.telosI2CWriteByte( cmdbyte )
-       self.telosI2CStop()
+        self.telosI2CWriteByte( cmdbyte )
+        self.telosI2CStop()
+    def writepicROM(self, address, data):
+        ''' Writes data to @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(0)
+        recbuf = 0
+        for i in range(7,-1,-1):
+            s = ((data >> i) & 0x01)
+            #print s
+            if i < 1:
+                r = not self.picROMclock(s, True)
+            else:
+                r = not self.picROMclock(s)
+            recbuf = (recbuf << 1) + r
+
+        self.picROMclock(0, True)
+        #k = 1
+        #while not self.serial.getCTS():
+        #    pass 
+        #time.sleep(0.1)
+        return recbuf
+
+    def readpicROM(self, address):
+        ''' reads a byte from @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(1)
+        recbuf = 0
+        r = 0
+        for i in range(7,-1,-1):
+            r = self.picROMclock(0)
+            recbuf = (recbuf << 1) + r
+        self.picROMclock(r)
+        #time.sleep(0.1)
+        return recbuf
+        
+    def picROMclock(self, masterout, slow = False):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        #time.sleep(0.02)
+        self.serialport.setDTR(0)
+        if slow:
+            time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def picROMfastclock(self, masterout):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        self.serialport.setDTR(0)
+        time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def bslResetZ1(self, invokeBSL=0):
+        '''
+        Applies BSL entry sequence on RST/NMI and TEST/VPP pins
+        Parameters:
+            invokeBSL = 1: complete sequence
+            invokeBSL = 0: only RST/NMI pin accessed
+            
+        By now only BSL mode is accessed
+        '''
+        
+        if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
+        if invokeBSL:
+            #sys.stderr.write("in Z1 bsl reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFF)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 bsl reset done...\n")
+        else:
+            #sys.stderr.write("in Z1 reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFE)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 reset done...\n")
 
     def telosBReset(self,invokeBSL=0):
-
-       # "BSL entry sequence at dedicated JTAG pins"
+        # "BSL entry sequence at dedicated JTAG pins"
         # rst !s0: 0 0 0 0 1 1
-       # tck !s1: 1 0 1 0 0 1
+        # tck !s1: 1 0 1 0 0 1
         #   s0|s1: 1 3 1 3 2 0
 
-       # "BSL entry sequence at shared JTAG pins"
+        # "BSL entry sequence at shared JTAG pins"
         # rst !s0: 0 0 0 0 1 1
-       # tck !s1: 0 1 0 1 1 0
+        # tck !s1: 0 1 0 1 1 0
         #   s0|s1: 3 1 3 1 0 2
 
-       if invokeBSL:
-         self.telosI2CWriteCmd(0,1)
-         self.telosI2CWriteCmd(0,3)
-         self.telosI2CWriteCmd(0,1)
-         self.telosI2CWriteCmd(0,3)
-         self.telosI2CWriteCmd(0,2)
-         self.telosI2CWriteCmd(0,0)
-       else:
-         self.telosI2CWriteCmd(0,3)
-         self.telosI2CWriteCmd(0,2)
-       self.telosI2CWriteCmd(0,0)
+        if invokeBSL:
+            self.telosI2CWriteCmd(0,1)
+            self.telosI2CWriteCmd(0,3)
+            self.telosI2CWriteCmd(0,1)
+            self.telosI2CWriteCmd(0,3)
+            self.telosI2CWriteCmd(0,2)
+            self.telosI2CWriteCmd(0,0)
+        else:
+            self.telosI2CWriteCmd(0,3)
+            self.telosI2CWriteCmd(0,2)
+
+        # This line was not defined inside the else: block, not sure where it
+        # should be however
+        self.telosI2CWriteCmd(0,0)
         time.sleep(0.250)       #give MSP430's oscillator time to stabilize
-       self.serialport.flushInput()  #clear buffers
+        self.serialport.flushInput()  #clear buffers
 
     def bslReset(self, invokeBSL=0):
         """Applies BSL entry sequence on RST/NMI and TEST/VPP pins
@@ -557,21 +642,27 @@ class LowLevel:
         RST is inverted twice on boot loader hardware
         TEST is inverted (only once)
         Need positive voltage on DTR, RTS for power-supply of hardware"""
-       if self.telosI2C:
-         self.telosBReset(invokeBSL)
-         return
+        if self.telosI2C:
+            self.telosBReset(invokeBSL)
+            return
+        
+        if self.z1:
+            if DEBUG > 1: sys.stderr.write("* entering bsl with z1\n")
+            self.bslResetZ1(invokeBSL)
+            return
+    
 
         if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
         self.SetRSTpin(1)       #power suply
         self.SetTESTpin(1)      #power suply
         time.sleep(0.250)       #charge capacitor on boot loader hardware
 
-       if self.telosLatch:
-         self.SetTESTpin(0)
-         self.SetRSTpin(0)
-         self.SetTESTpin(1)
-
+        if self.telosLatch:
+            self.SetTESTpin(0)
+            self.SetRSTpin(0)
+            self.SetTESTpin(1)
         self.SetRSTpin(0)       #RST  pin: GND
+
         if invokeBSL:
             self.SetTESTpin(1)  #TEST pin: GND
             self.SetTESTpin(0)  #TEST pin: Vcc
@@ -983,8 +1074,12 @@ class BootStrapLoader(LowLevel):
         """start BSL, download patch if desired and needed, adjust SP if desired"""
         sys.stderr.write("Invoking BSL...\n")
         sys.stderr.flush()
+        
+        #for '30, invertTEST=0, else =1
         if bslreset:
             self.bslReset(1)                        #Invoke the boot loader.
+        
+        
         self.txPasswd(self.passwd)                  #transmit password
 
         #Read actual bootstrap loader version.
@@ -1130,19 +1225,29 @@ class BootStrapLoader(LowLevel):
             raise BSLException, "programming without data not possible"
     def actionFromweb(self):
         """Grab GoodFET firmware from the web, then flash it."""
-        print "%x" % self.dev_id;
-        print "%s" % firmware[self.dev_id];
-        fn="/tmp/fw.hex"
-        os.system("curl %s >%s" % (firmware[self.dev_id],fn))
+        # print "Grabbing %x firmware." % self.dev_id;
+        print "%s" % firmware[self.dev_id];
+        # fn="/tmp/.goodfet.hex"
+        os.system("curl %s >%s" % (firmware[self.dev_id],fn))
         
-        fw=Memory(fn);
-        #fw.loadIhex(open(fn,"rb"));
+        # fw=Memory(fn);
+        # #fw.loadIhex(open(fn,"rb"));
+        
+        # sys.stderr.write("Program ...\n")
+        # sys.stderr.flush()
+        # self.programData(fw, self.ACTION_PROGRAM | self.ACTION_VERIFY)
+        # sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
+        # sys.stderr.flush()
+        
+        
+        print """
+The --fromweb feature is temporarily disabled, pending a rewrite.
+Please grab a copy of the appropriate .hex from
+http://goodfet.sf.net/dist/ and flash it like so:
+
+goodfet.bsl -e -p foo.hex        
+"""
         
-        sys.stderr.write("Program ...\n")
-        sys.stderr.flush()
-        self.programData(fw, self.ACTION_PROGRAM | self.ACTION_VERIFY)
-        sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
-        sys.stderr.flush()
         
     def actionVerify(self):
         """Verify programmed data"""
@@ -1275,7 +1380,13 @@ General options:
                         --swap-reset-test, and --telos-latch
   --telosb              Implies options --swap-reset-test, --telos-i2c,
                         --no-BSL-download, and --speed=38400
+  --apimote             Implies --swap-reset-test
+  --goodfet10
+  --goodfet20
+  --goodfet30
+  --goodthopter         Same as GF30.
   --tmote               Identical operation to --telosb
+  --z1                  Bootstrap a Z1
   --no-BSL-download     Do not download replacement BSL (disable automatic)
   --force-BSL-download  Download replacement BSL even if not needed (the one
                         in the device would have the required features)
@@ -1348,7 +1459,7 @@ def hexify(line, bytes, width=16):
         )
 
 #Main:
-def main():
+def main(itest=1):
     global DEBUG
     import getopt
     filetype    = None
@@ -1373,7 +1484,20 @@ def main():
     dumpinfo    = 0
     
     bsl.invertRST = 1
-    bsl.invertTEST = 1
+    bsl.invertTEST = itest
+    
+    if(os.environ.get("board")=='telosb' or 
+       os.environ.get("board")=='telosbbt' or
+       os.environ.get("platform")=='telosb'):
+        bsl.swapRSTTEST = 1
+        bsl.telosI2C = 1
+        mayuseBSL = 0
+    if(os.environ.get("board")=='z1' or 
+       os.environ.get("board")=='zolertiaz1'):
+        bsl.z1 = 1
+    if(os.environ.get("board")=='apimote' or os.environ.get("board")=='apimote1'):
+        bsl.swapRSTTEST = 1;
+    
     
     if comPort is None and os.environ.get("GOODFET")!=None:
         glob_list = glob.glob(os.environ.get("GOODFET"));
@@ -1387,8 +1511,17 @@ def main():
         glob_list = glob.glob("/dev/ttyUSB*");
         if len(glob_list) > 0:
             comPort = glob_list[0];
-    
-    
+    if os.name=='nt':
+            from scanwin32 import winScan;
+            scan=winScan();
+            for order,comport,desc,hwid in sorted(scan.comports()):
+                try:
+                    if hwid.index('FTDI')==0:
+                        comPort=comport;
+                        #print "Using FTDI port %s" % port
+                except:
+                    #Do nothing.
+                    a=1;
     sys.stderr.write("MSP430 Bootstrap Loader Version: %s\n" % VERSION)
 
     try:
@@ -1400,9 +1533,13 @@ def main():
              "upload=", "download=", "size=", "hex", "bin",
              "intelhex", "titext", "notimeout", "bsl=", "speed=",
              "bslversion", "f1x", "f2x", "f4x", "invert-reset", "invert-test",
-            "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb",
+             "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb",
              "tmote","no-BSL-download", "force-BSL-download", "slow",
-             "dumpivt", "dumpinfo", "fromweb"]
+             "dumpivt", "dumpinfo", "fromweb",
+             "goodfet40", "goodfet30",  "goodthopter", "goodfet20", "goodfet10",
+             "z1",
+             "nhbadge", "nhbadgeb", "goodfet"
+            ]
         )
     except getopt.GetoptError:
         # print help information and exit:
@@ -1542,16 +1679,39 @@ def main():
             bsl.invertTEST = 1
             bsl.swapRSTTEST = 1
             bsl.telosLatch = 1
+        elif o in ("--goodfet10", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--goodfet20", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--goodfet30", "--goodfet31", "--goodthopter" ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 0
+        elif o in ("--goodfet40", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--goodfet", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--apimote",):
+            bsl.swapRSTTEST = 1;
+        elif o in ("--nhbadge", "--nhbadgeb" ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
         elif o in ("--telosb", ):
             bsl.swapRSTTEST = 1
             bsl.telosI2C = 1
             mayuseBSL = 0
-           speed = 38400
+            speed = 38400
         elif o in ("--tmote", ):
             bsl.swapRSTTEST = 1
             bsl.telosI2C = 1
             mayuseBSL = 0
-           speed = 38400
+            speed = 38400
+        elif o in ("--z1", ):
+            bsl.z1 = 1
+            speed = 38400
         elif o in ("--no-BSL-download", ):
             mayuseBSL = 0
         elif o in ("--force-BSL-download", ):
@@ -1700,7 +1860,7 @@ def main():
 
 if __name__ == '__main__':
     try:
-        main()
+        main(1)
     except SystemExit:
         raise               #let pass exit() calls
     except KeyboardInterrupt:
@@ -1709,5 +1869,6 @@ if __name__ == '__main__':
         sys.exit(1)         #set errorlevel for script usage
     except Exception, msg:  #every Exception is caught and displayed
         if DEBUG: raise     #show full trace in debug mode
-        sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
-        sys.exit(1)         #set errorlevel for script usage
+        #sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
+        #sys.exit(1)         #set errorlevel for script usage
+        main(0);