]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tools/tinyos/misc/tos-deluge
Workaround the erase problems with AT45DB
[tinyos-2.x.git] / tools / tinyos / misc / tos-deluge
index 88e6dccbcbcf6e2ee116e7c11f99bbef2479e848..7a215a0e474cd82ced693d022feef1351ea33016 100755 (executable)
@@ -1,19 +1,44 @@
 #!/usr/bin/env python
 
-import sys, stat, struct, subprocess, time
-import tinyos
+# Copyright (c) 2007 Johns Hopkins University.
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose, without fee, and without written
+# agreement is hereby granted, provided that the above copyright
+# notice, the (updated) modification history and the author appear in
+# all copies of this source code.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+
+import sys, stat, struct, subprocess, time, os.path
+try:
+    import tos
+except ImportError:
+    import posix
+    sys.path = [os.path.join(posix.environ['TOSROOT'], 'support', 'sdk', 'python')] + sys.path
+    import tos
 from datetime import datetime
-import os.path 
 
 # Path to the python script that builds Deluge image from XML
-PATH_PY_BUILD_IMAGE  = './tos-build-deluge-image'
+PATH_PY_BUILD_IMAGE  = os.path.join(os.path.dirname(sys.argv[0]), 'tos-build-deluge-image')
 
 # TinyOS serial communication parameters
-FM_AMID = 0xAB
-DM_AMID = 0xAC
+FM_AMID = 0x53
+DM_AMID = 0x54
 SERIAL_DATA_LENGTH = 28 - 1 - 1 - 2 - 2
-BAUDRATES = {'micaz': 57600,
-             'telosb': 115200}
 
 # Commands for FlashManager
 FM_CMD_ERASE     = 0
@@ -40,54 +65,54 @@ DELUGE_MAX_PAGES    = 128
 DELUGE_IDENT_OFFSET = 0
 DELUGE_IDENT_SIZE   = 128
 
-class FMReqPacket(tinyos.GenericPacket):
+class FMReqPacket(tos.Packet):
     def __init__(self, packet = None):
-        tinyos.GenericPacket.__init__(self,
-                                      [('cmd',    'int',  1),
-                                       ('imgNum', 'int',  1),
-                                       ('offset', 'int',  2),
-                                       ('length', 'int',  2),
-                                       ('data',   'blob', None)],
-                                      packet)
-
-class DMReqPacket(tinyos.GenericPacket):
+        tos.Packet.__init__(self,
+                            [('cmd',    'int',  1),
+                             ('imgNum', 'int',  1),
+                             ('offset', 'int',  4),
+                             ('length', 'int',  2),
+                             ('data',   'blob', None)],
+                            packet)
+
+class DMReqPacket(tos.Packet):
     def __init__(self, packet = None):
-        tinyos.GenericPacket.__init__(self,
-                                      [('cmd',    'int',  1),
-                                       ('imgNum', 'int',  1)],
-                                      packet)
+        tos.Packet.__init__(self,
+                            [('cmd',    'int',  1),
+                             ('imgNum', 'int',  1)],
+                            packet)
 
-class SerialReplyPacket(tinyos.GenericPacket):
+class SerialReplyPacket(tos.Packet):
    def __init__(self, packet = None):
-       tinyos.GenericPacket.__init__(self,
-                                     [('error', 'int',  1),
-                                      ('data',  'blob', None)],
-                                     packet)
+       tos.Packet.__init__(self,
+                           [('error', 'int',  1),
+                            ('data',  'blob', None)],
+                           packet)
 
-class Ident(tinyos.GenericPacket):
+class Ident(tos.Packet):
     def __init__(self, packet = None):
-        tinyos.GenericPacket.__init__(self,
-                                      [('uidhash',  'int', 4),
-                                       ('size',     'int', 4),
-                                       ('pages',    'int', 1),
-                                       ('reserved', 'int', 1),
-                                       ('crc',      'int', 2),
-                                       ('appname', 'string', 16),
-                                       ('username', 'string', 16),
-                                       ('hostname', 'string', 16),
-                                       ('platform', 'string', 16),
-                                       ('timestamp','int', 4),
-                                       ('userhash', 'int', 4)],
-                                      packet)
-
-class ShortIdent(tinyos.GenericPacket):
+        tos.Packet.__init__(self,
+                            [('uidhash',  'int', 4),
+                             ('size',     'int', 4),
+                             ('pages',    'int', 1),
+                             ('reserved', 'int', 1),
+                             ('crc',      'int', 2),
+                             ('appname', 'string', 16),
+                             ('username', 'string', 16),
+                             ('hostname', 'string', 16),
+                             ('platform', 'string', 16),
+                             ('timestamp','int', 4),
+                             ('userhash', 'int', 4)],
+                            packet)
+
+class ShortIdent(tos.Packet):
     def __init__(self, packet = None):
-        tinyos.GenericPacket.__init__(self,
-                                      [('appname',  'string', 16),
-                                       ('timestamp','int', 4),
-                                       ('uidhash',  'int', 4),
-                                       ('nodeid',   'int', 2)],
-                                      packet)
+        tos.Packet.__init__(self,
+                            [('appname',  'string', 16),
+                             ('timestamp','int', 4),
+                             ('uidhash',  'int', 4),
+                             ('nodeid',   'int', 2)],
+                            packet)
 
 
 # Computes 16-bit CRC
@@ -101,30 +126,32 @@ def crc16(data):
             else:
                 crc = crc << 1
             crc = crc & 0xffff
-    
+
     return crc
 
 def handleResponse(success, msg):
     if success == True:
-        packet = s.sniff_am()
+        packet = am.read(timeout=2)
         while packet and packet.type == 100:
-            print "".join([chr(i) for i in p.data])
-            packet = s.sniff_am()
+            print "".join([chr(i) for i in packet.data])
+            packet = am.read()
+        if not packet:
+            print "No response"
+            return False
         reply = SerialReplyPacket(packet.data)
         if reply.error == ERROR_SUCCESS:
-            print reply
             return True
         else:
             print msg, reply
             return False
-        
+
     print "ERROR: Unable to send the command"
     return False
 
-def ident():
+def ident(timeout=None):
     sreqpkt = FMReqPacket((FM_CMD_IDENT, 0, 0, 0, []))
-    if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
-        packet = s.sniff_am()
+    if am.write(sreqpkt, FM_AMID, timeout=timeout):
+        packet = am.read(timeout=timeout)
         reply = SerialReplyPacket(packet.data)
         if reply.error == ERROR_SUCCESS:
             return ShortIdent(reply.data)
@@ -132,14 +159,14 @@ def ident():
 
 def read(imgNum, offset, length):
     r = []
-    
+
     sreqpkt = FMReqPacket((FM_CMD_READ, imgNum, offset, length, []))
     while True:
         if sreqpkt.length > SERIAL_DATA_LENGTH:
             sreqpkt.length = SERIAL_DATA_LENGTH
-        
-        if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
-            packet = s.sniff_am()
+
+        if am.write(sreqpkt, FM_AMID):
+            packet = am.read()
             reply = SerialReplyPacket(packet.data)
             if reply.error == ERROR_SUCCESS:
                 r.extend(reply.data)
@@ -149,7 +176,7 @@ def read(imgNum, offset, length):
         else:
             r = None
             break
-        
+
         sreqpkt.offset += sreqpkt.length
         if sreqpkt.offset >= (offset + length):
             break
@@ -158,13 +185,27 @@ def read(imgNum, offset, length):
     return r
 
 def erase(imgNum):
+    # Note: the normal erase doesn't work properly on AT45DB. A
+    # workaround is to do the normal erase (to make happy STM45P)
+    # and then overwrite the metadata (to make happy AT45DB).
+
     sreqpkt = FMReqPacket((FM_CMD_ERASE, imgNum, 0, 0, []))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID))
-    return handleResponse(success, "ERROR: Unable to erase the flash volume")
+    success = am.write(sreqpkt, FM_AMID)
+    result = handleResponse(success, "ERROR: Unable to erase the flash volume")
+    if result: return True;
+
+    print 'Attempt the workaround for AT45DB...'
+    sreqpkt = FMReqPacket((FM_CMD_WRITE, imgNum, 0, 0, []))
+    sreqpkt.data = [0xFF] * DELUGE_IDENT_SIZE
+    sreqpkt.length = DELUGE_IDENT_SIZE
+    success = am.write(sreqpkt, FM_AMID)
+    result = handleResponse(success, "ERROR: Unable to erase the flash volume")
+    if not result: return False;
+    return sync(imgNum)
 
 def sync(imgNum):
     sreqpkt = FMReqPacket((FM_CMD_SYNC, imgNum, 0, 0, []))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID))
+    success = am.write(sreqpkt, FM_AMID)
     return handleResponse(success, "ERROR: Unable to sync the flash volume")
 
 def write(imgNum, data):
@@ -173,37 +214,37 @@ def write(imgNum, data):
     total_length = length   # For progress bar
     next_tick = 100         # For progress bar
     start_time = time.time()
-    
+
     print "[0%        25%         50%         75%         100%]\r[",
+
     sreqpkt.offset = 0
     while length > 0:
         if ((length * 100) / total_length) < next_tick:
             next_tick = next_tick - 2
             sys.stdout.write('-')
             sys.stdout.flush()
-    
+
         # Calculates the payload size for the current packet
         if length >= SERIAL_DATA_LENGTH:
             sreqpkt.length = SERIAL_DATA_LENGTH
         else:
             sreqpkt.length = length
         sreqpkt.data = data[sreqpkt.offset:sreqpkt.offset+sreqpkt.length]
-        
+
         # Sends over serial to the mote
-        if not s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
+        if not am.write(sreqpkt, FM_AMID):
             print
             print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset
             return False
-        
+
         # Waiting for confirmation
-        packet = s.sniff_am()
+        packet = am.read()
         reply = SerialReplyPacket(packet.data)
         if reply.error != ERROR_SUCCESS:
             print
             print "ERROR: Unable to write to the flash volume (file offset: %d)" % sreqpkt.offset
             return False
-            
+
         length -= sreqpkt.length
         sreqpkt.offset += sreqpkt.length
 
@@ -211,7 +252,7 @@ def write(imgNum, data):
     elasped_time = time.time() - start_time
     print "\r%s bytes in %.2f seconds (%.4f bytes/s)" % (total_length, elasped_time, int(total_length) / (elasped_time))
     return True
-    
+
 # Checks for valid CRC and timestamp
 def verifyIdent(i):
     if i != None:
@@ -260,7 +301,7 @@ def inject(imgNum, tos_image_xml):
     except:
         print "ERROR: Unable to find the image building utility, \"%s\"" % PATH_PY_BUILD_IMAGE
         return False
-  
+
     # Gets status information of stored image
     i = getIdent(imgNum)
     if ident:
@@ -277,11 +318,12 @@ def inject(imgNum, tos_image_xml):
     cmd = [PATH_PY_BUILD_IMAGE, "-i", str(imgNum), tos_image_xml]
     print "Create image:", ' '.join(cmd)
     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    print p.stderr.read(),
+    (out, err) = p.communicate(None)
+    print err,
     print "--------------------------------------------------"
-    
+
     # Writes the new binary image
-    image = [struct.unpack("B", c)[0] for c in p.stdout.read()]
+    image = [struct.unpack("B", c)[0] for c in out]
     if len(image) > 0 and erase(imgNum):
         if write(imgNum, image):
             if sync(imgNum):
@@ -289,7 +331,7 @@ def inject(imgNum, tos_image_xml):
                 print "Replace image with:"
                 print formatIdent(getIdent(imgNum))
                 print "--------------------------------------------------"
-    
+
     return False
 
 def ping(imgNum):
@@ -304,43 +346,45 @@ def ping(imgNum):
         print formatIdent(i)
         print "--------------------------------------------------"
         return True
-        
+
     print "--------------------------------------------------"
     return False
 
 def boot():
     sreqpkt = DMReqPacket((DM_CMD_BOOT, 0))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to boot the mote")
 
 def reprogram(imgNum):
     sreqpkt = DMReqPacket((DM_CMD_REPROGRAM, imgNum))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to reprogram the mote")
 
 def disseminate(imgNum):
     sreqpkt = DMReqPacket((DM_CMD_ONLY_DISSEMINATE, imgNum))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to disseminate")
 
 def disseminateAndReboot(imgNum):
     sreqpkt = DMReqPacket((DM_CMD_DISSEMINATE_AND_REPROGRAM, imgNum))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to disseminate-and-reboot")
 
 def stop():
     sreqpkt = DMReqPacket((DM_CMD_STOP, 0))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to initiate the stop")
 
 def localstop():
     sreqpkt = DMReqPacket((DM_CMD_LOCAL_STOP, 0))
-    success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+    success = am.write(sreqpkt, DM_AMID)
     return handleResponse(success, "ERROR: Unable to initiate the local stop")
 
 def print_usage():
-    print "Usage: %s <device_port> <baud_rate> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
-    print "  <baud_rate>      Either the platform name (micaz or telosv) or a baudrate value"
+    print "Usage: %s <source> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
+    print "  <source> can be:"
+    print "     serial@PORT:SPEED   Serial ports"
+    print "     network@HOST:PORT   MIB600"
     print "  -p --ping        Provide status of the image in the external flash"
     print "  -i --inject      Inject a compiled TinyOS application"
     print "                   [options]: tos_image.xml file path"
@@ -359,72 +403,57 @@ def checkImgNum():
     global imgNum
     # Checks for valid image number format
     try:
-        imgNum = int(sys.argv[4])
+        imgNum = int(sys.argv[3])
     except:
         print "ERROR: Image number is not valid"
         sys.exit(-1)
     return imgNum
 
 # ======== MAIN ======== #
-if len(sys.argv) >= 4:
+if len(sys.argv) >= 3:
+
+    am = tos.AM()
 
-    if sys.argv[2] in BAUDRATES:
-        baudrate = BAUDRATES[sys.argv[2]]
-    else:
-        try:
-            baudrate = int(sys.argv[2])
-        except:
-            print "ERROR: Wrong baudrate"
-            sys.exit(-1)
-            
-    # Initializes serial port communication
     try:
-        s = tinyos.Serial(sys.argv[1], baudrate, flush=False)
-    except:
-        print "ERROR: Unable to initialize serial port connection to", sys.argv[1]
+        print "Checking if node is a Deluge T2 base station ..."
+        ident(timeout=5)
+    except tos.Timeout:
+        print "ERROR: Timeout. Is the node a Deluge T2 base station?"
         sys.exit(-1)
 
-    if sys.argv[3] in ["-p", "--ping"]:
+    if sys.argv[2] in ["-p", "--ping"]:
         checkImgNum()
         print "Pinging node ..."
-        ping(imgNum) 
-    elif sys.argv[3] in ["-i", "--inject"] and len(sys.argv) == 6:
+        ping(imgNum)
+    elif sys.argv[2] in ["-i", "--inject"] and len(sys.argv) == 5:
         checkImgNum()
         print "Pinging node ..."
-        inject(imgNum, sys.argv[5])
-    elif sys.argv[3] in ["-e", "--erase"]:
+        inject(imgNum, sys.argv[4])
+    elif sys.argv[2] in ["-e", "--erase"]:
         checkImgNum()
         if erase(imgNum):
             print "Image number %d erased" % imgNum
-    elif sys.argv[3] in ["-b", "--boot"]:
+    elif sys.argv[2] in ["-b", "--boot"]:
         if boot():
             print "Command sent"
-    elif sys.argv[3] in ["-r", "--reprogram"]:
+    elif sys.argv[2] in ["-r", "--reprogram"]:
         checkImgNum()
         if reprogram(imgNum):
             print "Command sent"
-    elif sys.argv[3] in ["-d", "--disseminate"]:
+    elif sys.argv[2] in ["-d", "--disseminate"]:
         checkImgNum()
         if disseminate(imgNum):
             print "Command sent"
-    elif sys.argv[3] in ["-dr", "--disseminate-and-reboot"]:
+    elif sys.argv[2] in ["-dr", "--disseminate-and-reboot"]:
         checkImgNum()
         if disseminateAndReboot(imgNum):
             print "Command sent"
-    elif sys.argv[3] in ["-s", "--stop"]:
+    elif sys.argv[2] in ["-s", "--stop"]:
         if stop():
             print "Command sent"
-    elif sys.argv[3] in ["-ls", "--local-stop"]:
+    elif sys.argv[2] in ["-ls", "--local-stop"]:
         if localstop():
             print "Command sent"
-
-
-#     elif sys.argv[3] in ["-b", "--reprogram_bs"]:
-#         if op_reprog_bs(imgNum):
-#             print "Command sent"
-#     elif sys.argv[3] in ["-s", "--reset"]:
-#         if op_reset(imgNum):
-#             print "Successfully reset image versioning information"
     else:
         print_usage()
 
@@ -433,32 +462,3 @@ else:
 
 sys.exit()
 
-# Testing ------------------------------------------------------------
-
-s = tinyos.Serial('/dev/ttyUSB0', 115200, flush=False)
-# print "ident: 0x%x" % ident()
-# r = read(0, 0, 10)
-# print "read:", len(r), r
-
-# erase(0)
-# write(0, [i % 256 for i in range(20*1024)])
-# r = read(0, 0, 10)
-# print "read:", len(r), r
-
-# inject(0, 'build/telosb/tos_image.xml')
-ping(0)
-
-# print formatDescription(getMetadata(0), getIdent(0))
-# print getMetadata(0)
-# print getIdent(0)
-
-# print verifyDescription(getMetadata(0), getIdent(0))
-
-# print formatShortIdent(ident())
-
-# def encode(val, dim):
-#   output = []
-#   for i in range(dim):
-#       output.append(val & 0xFF)
-#       val = val >> 8
-#   return output