]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Merge of the latest Deluge T2.
authorrazvanm <razvanm>
Mon, 19 May 2008 21:25:08 +0000 (21:25 +0000)
committerrazvanm <razvanm>
Mon, 19 May 2008 21:25:08 +0000 (21:25 +0000)
22 files changed:
apps/tests/deluge/Blink/Makefile
apps/tests/deluge/Blink/burn
apps/tests/deluge/Blink/burn-net
tools/tinyos/misc/Makefile.am
tools/tinyos/misc/tinyos.py [deleted file]
tools/tinyos/misc/tos-build-deluge-image
tools/tinyos/misc/tos-deluge
tools/tinyos/misc/tos.py [new file with mode: 0644]
tos/lib/net/Deluge/Deluge.h
tos/lib/net/Deluge/DelugeC.nc
tos/lib/net/Deluge/DelugeManagerP.nc
tos/lib/net/Deluge/DelugeMetadataP.nc
tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc
tos/lib/net/Deluge/ReprogramGuard.nc [new file with mode: 0644]
tos/lib/net/Deluge/extra/NetProgC.nc
tos/lib/net/Deluge/extra/NetProgM.nc
tos/lib/net/Deluge/extra/micaz/ReprogramGuardC.nc [new file with mode: 0644]
tos/lib/net/Deluge/extra/micaz/ReprogramGuardP.nc [new file with mode: 0644]
tos/lib/net/Deluge/extra/telosb/ReprogramGuardC.nc [new file with mode: 0644]
tos/lib/net/Deluge/extra/telosb/ReprogramGuardP.nc [new file with mode: 0644]
tos/lib/net/Deluge/imgNum2volumeId.h [new file with mode: 0644]
tos/lib/tosboot/micaz/hardware.h

index 5a995f0bb36532f6e961d105464bab823cf64983..6f7acb3916edea0d19bff17972bcdbb21ce1b42c 100644 (file)
@@ -1,6 +1,7 @@
 COMPONENT=BlinkAppC
 TINYOS_NP=BNP
 
-CFLAGS += -DDELUGE_BASESTATION
+#CFLAGS += -DDELUGE_BASESTATION
+#CFLAGS += -DDELUGE_LIGHT_BASESTATION
 
 include $(MAKERULES)
index f0aaddce5862c2dd080e1f04320304ff5efea1f7..1e82f5d3b23859ce8d8440fff2b1bf7f5985b89d 100755 (executable)
@@ -18,17 +18,24 @@ if [[ ! -x ${TOS_DELUGE} ]] ; then
     TOS_DELUGE=../../../../tools/tinyos/misc/tos-deluge
 fi 
 
-if [ $# -ne 2 ]; then
-  echo "Usage: $0 <port> <platform>"
+if [[ $# -ne 2 && $# -ne 3 ]]; then
+  echo "Usage: $0 <port> [<comm_port>] <platform>"
   echo "  <port>       /dev/ttyUSB0"
-  echo "  <platform>   micaz or telosb"
+  echo "  <comm_port>  /dev/ttyUSB1"
+  echo "  <platform>   micaz, telosb or iris"
   exit 2
 fi
 
-PORT=$1
+PPORT=$1
+CPORT=$1
 PLATFORM=$2
 
-if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' ]; then
+if [ $# -eq 3 ]; then
+ CPORT=$2
+ PLATFORM=$3
+fi
+
+if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' -a ${PLATFORM} != 'iris' ]; then
   echo "\"${PLATFORM}\" is not a supported platform"
   exit 2
 fi
@@ -44,12 +51,16 @@ make clean
 echo ============================ Compile and load Blink ============================
 if [ $PLATFORM == 'micaz' ]
 then
-  CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PORT}
+  CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PPORT}
 elif [ $PLATFORM == 'telosb' ]
 then
-  CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install bsl,${PORT}
+  CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install bsl,${PPORT}
+elif [ $PLATFORM == 'iris' ]
+then
+  CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PPORT}
 fi
 
+
 echo '           +-------------------------------------------------------+'
 echo '           |                                                       |'
 echo '           | At this point the first led (red) should be blinking. |'
@@ -63,7 +74,7 @@ echo  ============================= Compile a new Blink ========================
 CFLAGS=-DBLINK_REVERSE\ -DDELUGE_BASESTATION make ${PLATFORM}
 
 echo =============================== Upload the image ===============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
+${TOS_DELUGE} ${CPORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
 
 echo '       +----------------------------------------------------------------+'
 echo '       |                                                                |'
@@ -80,4 +91,4 @@ echo '       +----------------------------------------------------------------+'
 read
 
 echo =========================== Reboot the base station ============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -r 1 
+${TOS_DELUGE} ${CPORT} ${PLATFORM} -r 1 
index 0d94b40c9634dbcd14a855343f9b2d6e1310cb5f..cc14666103f45bec4c182d6d0994cfee0e61a281 100755 (executable)
@@ -7,7 +7,7 @@ fi
 
 if [ $# -ne 2 ]; then
   echo "Usage: $0 <platform> <number of motes>"
-  echo "  <platform>         micaz or telosb"
+  echo "  <platform>         micaz, telosb or iris"
   echo "  <number of motes>  how many motes will be used in the test"
   exit 2
 fi
@@ -15,7 +15,7 @@ fi
 PLATFORM=$1
 NO_MOTES=$2
 
-if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' ]; then
+if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' -a ${PLATFORM} != 'iris' ]; then
   echo "\"${PLAFTORM}\" is not a supported platform"
   exit 2
 fi
@@ -28,29 +28,35 @@ fi
 
 echo ================================ Compile Blink =================================
 make clean
-CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM}
 ID=0
 
 function burn_one() {
     ID=`expr $ID + 1`
-    echo -n ">>> Please plug mote $ID and type the port to continue: "
+    echo -n ">>> Please plug mote $ID and type the programming port to continue: "
     read PORT
 
     if [ ${PLATFORM} == 'micaz' ]
     then
-       CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} reinstall,$ID mib510,${PORT}
+       CFLAGS=$1 make ${PLATFORM} install,$ID mib510,${PORT}
     elif [ ${PLATFORM} == 'telosb' ]
     then
-       CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} reinstall,$ID bsl,${PORT}
+       CFLAGS=$1 make ${PLATFORM} install,$ID bsl,${PORT}
+    elif [ ${PLATFORM} == 'iris' ]
+    then
+       CFLAGS=$1 make ${PLATFORM} install,$ID mib510,${PORT}
     fi
-    
 }
 
-while [[ ${NO_MOTES} > 0 ]]
+while [[ ${NO_MOTES} > 1 ]]
 do
-  burn_one
+  burn_one -DDELUGE_LIGHT_BASESTATION
   NO_MOTES=`expr ${NO_MOTES} - 1`
 done
+echo ">>> Note: this last mote will be the basestation! <<<"
+burn_one -DDELUGE_BASESTATION
+echo -n ">>> Please plug mote $ID and type the communication port to continue: "
+read PORT
+BASESTATION_PORT=$PORT
 
 echo '   +------------------------------------------------------------------------+'
 echo '   |                                                                        |'
@@ -62,10 +68,10 @@ echo '   +----------------------------------------------------------------------
 read
 
 echo ============================= Compile a new Blink ==============================
-CFLAGS=-DBLINK_REVERSE\ -DDELUGE_BASESTATION make ${PLATFORM} 
+CFLAGS=-DBLINK_REVERSE\ -DDELUGE_LIGHT_BASESTATION make ${PLATFORM} 
 
 echo ========= Upload the new image to the external flash of the last mote ==========
-${TOS_DELUGE} ${PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
+${TOS_DELUGE} ${BASESTATION_PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
 
 echo '            +-----------------------------------------------------+'
 echo '            |                                                     |'
@@ -76,11 +82,10 @@ echo '            |                                                     |'
 echo '            |              Press ENTER to continue...             |'
 echo '            |                                                     |'
 echo '            +-----------------------------------------------------+'
-
 read
 
 echo ============================= Start dissemination ==============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -dr 1
+${TOS_DELUGE} ${BASESTATION_PORT} ${PLATFORM} -dr 1
 
 echo '         +------------------------------------------------------------+'
 echo '         |                                                            |'
index 276314be167fd27a9fb6f39a0a327a7dc461f7d3..8dfc65b573c2e1dd13b12859d3ed97c4bef06f0a 100644 (file)
@@ -34,4 +34,4 @@ bin_SCRIPTS = tos-ident-flags \
 bin_PROGRAMS = tos-serial-debug
 
 pythondir = $(bindir)
-python_DATA = tinyos.py
+python_DATA = tos.py
diff --git a/tools/tinyos/misc/tinyos.py b/tools/tinyos/misc/tinyos.py
deleted file mode 100644 (file)
index c33a8db..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-"""A library that implements the T2 serial communication.
-
-This library has two parts: one that deals with sending and receiving
-packets using the serial format from T2 (TEP113) and a second one that
-tries to simplifies the work with arbitrary packets.
-
-"""
-
-import sys, struct, time, serial, socket, operator
-from Queue import Queue
-
-__version__ = "$Id$"
-
-__all__ = ['Serial', 'GenericPacket', 'RawPacket',
-           'AckFrame', 'DataFrame', 'NoAckDataFrame',
-           'ActiveMessage']
-
-_seqno = 1
-
-def list2hex(v):
-    return " ".join(["%02x" % p for p in v])
-
-class Serial:
-    """
-    A Serial object offers a way to send and data using a HDLC-like
-    formating.
-    """
-    
-    HDLC_FLAG_BYTE = 0x7e
-    HDLC_CTLESC_BYTE = 0x7d
-    
-    TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
-    TOS_SERIAL_CC1000_ID = 1
-    TOS_SERIAL_802_15_4_ID = 2
-    TOS_SERIAL_UNKNOWN_ID = 255
-    
-    SERIAL_PROTO_ACK = 67
-    SERIAL_PROTO_PACKET_ACK = 68
-    SERIAL_PROTO_PACKET_NOACK = 69
-    SERIAL_PROTO_PACKET_UNKNOWN = 255
-  
-    _debug = False   # Debug mode
-    
-    def __init__(self, port, baudrate, flush=True):
-       self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
-       self._queue = Queue()
-       self._ts = None
-       self._seqno = 0
-
-       self._s.flushInput()
-       start = time.time();
-       if flush:
-           print "Flushing the serial port",
-           while time.time() - start < 1:
-               p = self.sniff()
-               sys.stdout.write(".")
-           if not self._debug:
-               sys.stdout.write("\n")
-
-    def _format_packet(self, payload):
-        f = NoAckDataFrame(payload)
-        if f.protocol == self.SERIAL_PROTO_ACK:
-            rpacket = AckFrame(payload)
-            return "Ack seqno: %d" % (rpacket.seqno)
-        else:
-            rpacket = ActiveMessage(f.data)
-            return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
-                   (rpacket.destination, rpacket.source,
-                    rpacket.length, rpacket.group, rpacket.type,
-                    list2hex(rpacket.data))
-
-    def crc16(self, base_crc, frame_data):
-        crc = base_crc
-        for b in frame_data:
-            crc = crc ^ (b << 8)
-            for i in range(0, 8):
-                if crc & 0x8000 == 0x8000:
-                    crc = (crc << 1) ^ 0x1021
-                else:
-                    crc = crc << 1
-                crc = crc & 0xffff
-        return crc
-    
-    def _encode(self, val, dim):
-        output = []
-        for i in range(dim):
-            output.append(val & 0xFF)
-            val = val >> 8
-        return output
-    
-    def _decode(self, v):
-        r = long(0)
-        for i in v[::-1]:
-            r = (r << 8) + i
-        return r
-    
-    def _get_byte(self):
-        try:
-            r = struct.unpack("B", self._s.read())[0]
-            return r
-        except struct.error:
-            # Serial port read timeout
-            raise socket.timeout
-    
-    def _put_bytes(self, data):
-        #print "DEBUG: _put_bytes:", data
-        for b in data:
-            self._s.write(struct.pack('B', b))
-    
-    def _unescape(self, packet):
-        r = []
-        esc = False
-        for b in packet:
-            if esc:
-                r.append(b ^ 0x20)
-                esc = False
-            elif b == self.HDLC_CTLESC_BYTE:
-                esc = True
-            else:
-                r.append(b)
-        return r
-    
-    def _escape(self, packet):
-        r = []
-        for b in packet:
-            if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
-                r.append(self.HDLC_CTLESC_BYTE)
-                r.append(b ^ 0x20)
-            else:
-                r.append(b)
-        return r
-    
-    # Returns the next incoming serial packet
-    def sniff(self, skip_queue = False):
-        """Wait for a packet and return it as a RawPacket."""
-        
-        if (not skip_queue and not self._queue.empty()):
-            print "DEBUG: sniff_packet: return a packet from the queue(%d)." % self._queue.qsize()
-            return self._queue.get()
-        try:
-            d = self._get_byte()
-            ts = time.time()
-            while d != self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                ts = time.time()
-            packet = [d]
-            d = self._get_byte()
-            if d == self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                ts = time.time()
-            else:
-                packet.append(d)
-            while d != self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                packet.append(d)
-            if self._debug == True:
-                print "sniff: unescaped", packet
-            packet = self._unescape(packet)
-            
-            crc = self.crc16(0, packet[1:-3])
-            packet_crc = self._decode(packet[-3:-1])
-            
-            if self._debug:
-                if crc != packet_crc:
-                    print "Warning: wrong CRC! %s" % packet
-                if self._ts == None:
-                    self._ts = ts
-                else:
-                    print "%.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
-                self._ts = ts
-            return RawPacket(ts, packet[1:-3], crc == packet_crc)
-        except socket.timeout:
-            return None
-
-    def sniff_am(self, skip_queue = False, timeout=0):
-        """Wait for a packet and return it as a ActiveMessage."""
-        
-        start = time.time();
-        p = None
-        done = False
-        while not done:
-            while p == None:
-                if timeout == 0 or time.time() - start < timeout:
-                    p = self.sniff(skip_queue)
-                else:
-                    return None
-            if p.crc:
-                done = True
-        return ActiveMessage(NoAckDataFrame(p.data).data)
-
-    
-    # Sends data with the specified AM group ID and AM ID. To have a "reliable"
-    # transfer, num_tries defines how many times to retry before giving up
-    def write(self, payload, num_tries=3):
-        """
-        Write a packet. If the payload argument is a list, it is
-        assumed to be exactly the payload. Otherwise the payload is
-        assume to be a GenericPacket and the real payload is obtain
-        by calling the .payload().
-        """
-        
-        global _seqno
-        if type(payload) != type([]):
-            # Assume this will be derived from GenericPacket
-            payload = payload.payload()
-        _seqno = (_seqno + 1) % 100
-        packet = DataFrame();
-        packet.protocol = self.SERIAL_PROTO_PACKET_ACK
-        packet.seqno = _seqno
-        packet.dispatch = 0
-        packet.data = payload
-        packet = packet.payload()
-        crc = self.crc16(0, packet)
-        packet.append(crc & 0xff)
-        packet.append((crc >> 8) & 0xff)
-        packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
-
-        for i in range(num_tries):
-            self._put_bytes(packet)
-            if self._debug == True:
-                print "Send:", packet
-            
-            # Waits for ACK
-            for j in range(3):
-                p = self.sniff(skip_queue = True)
-                if p != None:
-                    ack = AckFrame(p.data)
-                    if ack.protocol == self.SERIAL_PROTO_ACK:
-                        if ack.seqno != _seqno:
-                            print ">" * 40, "Wrong ACK!", ack.seqno, _seqno, "<" * 40
-                        return True
-                    else:
-                        if self._debug == True:
-                            print "write_packet: put a packet in the queue(%d)." % (self._queue.qsize())
-                        self._queue.put(p)
-                        
-        return False
-    
-    def debug(self, debug):
-        self._debug = debug
-
-
-
-class GenericPacket:
-    """ GenericPacket """
-
-    def _decode(self, v):
-        r = long(0)
-        for i in v:
-            r = (r << 8) + i
-        return r
-    
-    def _encode(self, val, dim):
-        output = []
-        for i in range(dim):
-            output.append(int(val & 0xFF))
-            val = val >> 8
-        output.reverse()
-        return output
-    
-    def __init__(self, desc, packet = None):
-        offset = 0
-        boffset = 0
-        sum = 0
-        for i in range(len(desc)-1, -1, -1):
-            (n, t, s) = desc[i]
-            if s == None:
-                if sum > 0:
-                    desc[i] = (n, t, -sum)
-                break
-            sum += s
-        self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
-        self.__dict__['_names'] = [n for (n, t, s) in desc]
-        self.__dict__['_values'] = []
-        if type(packet) == type([]):
-            for (t, s) in self._schema:
-                if t == 'int':
-                    self._values.append(self._decode(packet[offset:offset + s]))
-                    offset += s
-                elif t == 'bint':
-                    doffset = 8 - (boffset + s)
-                    self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
-                    boffset += s
-                    if boffset == 8:
-                        offset += 1
-                        boffset = 0
-                elif t == 'string':
-                    self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
-                    offset += s
-                elif t == 'blob':
-                    if s:
-                        if s > 0:
-                            self._values.append(packet[offset:offset + s])
-                            offset += s
-                        else:
-                            self._values.append(packet[offset:s])
-                            offset = len(packet) + s
-                    else:
-                        self._values.append(packet[offset:])
-        elif type(packet) == type(()):
-            for i in packet:
-                self._values.append(i)
-        else:
-            for v in self._schema:
-                self._values.append(None)
-
-    def __repr__(self):
-        return self._values.__repr__()
-
-    def __str__(self):
-        r = ""
-        for i in range(len(self._names)):
-            r += "%s: %s " % (self._names[i], self._values[i])
-        for i in range(len(self._names), len(self._values)):
-            r += "%s" % self._values[i]
-        return r
-#        return self._values.__str__()
-
-    # Implement the map behavior
-    def __getitem__(self, key):
-        return self.__getattr__(key)
-
-    def __setitem__(self, key, value):
-        self.__setattr__(key, value)
-
-    def __len__(self):
-        return len(self._values)
-
-    def keys(self):
-        return self._names
-
-    def values(self):
-        return self._names
-
-    # Implement the struct behavior
-    def __getattr__(self, name):
-        #print "DEBUG: __getattr__", name
-        if type(name) == type(0):
-            return self._names[name]
-        else:
-            return self._values[self._names.index(name)]
-
-    def __setattr__(self, name, value):
-        if type(name) == type(0):
-            self._values[name] = value
-        else:
-            self._values[self._names.index(name)] = value
-
-    def __ne__(self, other):
-        if other.__class__ == self.__class__:
-            return self._values != other._values
-        else:
-            return True
-
-    def __eq__(self, other):
-        if other.__class__ == self.__class__:
-            return self._values == other._values
-        else:
-            return False
-
-    def __nonzero__(self):
-        return True;
-
-    # Custom
-    def names(self):
-        return self._names
-
-    def sizes(self):
-        return self._schema
-
-    def payload(self):
-        r = []
-        boffset = 0
-        for i in range(len(self._schema)):
-            (t, s) = self._schema[i]
-            if t == 'int':
-                r += self._encode(self._values[i], s)
-                boffset = 0
-            elif t == 'bint':
-                doffset = 8 - (boffset + s)
-                if boffset == 0:
-                    r += [self._values[i] << doffset]
-                else:
-                    r[-1] |= self._values[i] << doffset
-                boffset += s
-                if boffset == 8:
-                    boffset = 0
-            elif self._values[i] != []:
-                r += self._values[i]
-        for i in self._values[len(self._schema):]:
-            r += i
-        return r
-
-
-class RawPacket(GenericPacket):
-    def __init__(self, ts = None, data = None, crc = None):
-        GenericPacket.__init__(self,
-                               [('ts' , 'int', 4),
-                                ('crc', 'int', 1),
-                                ('data', 'blob', None)],
-                               None)
-        self.ts = ts;
-        self.data = data
-        self.crc = crc
-        
-
-class AckFrame(GenericPacket):
-    def __init__(self, payload = None):
-        GenericPacket.__init__(self,
-                               [('protocol',  'int', 1),
-                                ('seqno',  'int', 1)],
-                               payload)
-
-class DataFrame(GenericPacket):
-    def __init__(self, payload = None):
-        if payload != None and type(payload) != type([]):
-            # Assume is a GenericPacket
-            payload = payload.payload()
-        GenericPacket.__init__(self,
-                               [('protocol',  'int', 1),
-                                ('seqno',  'int', 1),
-                                ('dispatch',  'int', 1),
-                                ('data', 'blob', None)],
-                               payload)
-
-class NoAckDataFrame(GenericPacket):
-    def __init__(self, payload = None):
-        if payload != None and type(payload) != type([]):
-            # Assume is a GenericPacket
-            payload = payload.payload()
-        GenericPacket.__init__(self,
-                               [('protocol',  'int', 1),
-                                ('dispatch',  'int', 1),
-                                ('data', 'blob', None)],
-                               payload)
-
-class ActiveMessage(GenericPacket):
-    def __init__(self, gpacket = None, am_id = 0x00, dest = 0xFFFF):
-        if type(gpacket) == type([]):
-            payload = gpacket
-        else:
-            # Assume this will be derived from GenericPacket
-            payload = None
-        GenericPacket.__init__(self,
-                               [('destination', 'int', 2),
-                                ('source',   'int', 2),
-                                ('length',   'int', 1),
-                                ('group',    'int', 1),
-                                ('type',     'int', 1),
-                                ('data',     'blob', None)],
-                               payload)
-        if payload == None:
-            self.destination = dest
-            self.source = 0x0000
-            self.group = 0x00
-            self.type = am_id
-            self.data = gpacket.payload()
-            self.length = len(self.data)
-
index 085424011b42e7cccfec016c81ff3a3b68e7e435..3095167aeeed9ad4c37b26a5700c52c0c9ec4691 100755 (executable)
@@ -20,8 +20,8 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 # THE POSSIBILITY OF SUCH DAMAGE.
 
-# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
 # @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
 
 import sys, struct, operator
 from xml.dom.minidom import parse
@@ -147,8 +147,8 @@ for line in image.split():
             all.append((start_addr, section))
             if rectype == 0x03:
                 # This last record updates the first 4 bytes which
-                # holds some some low level configuration. They are
-                # the same all the time so I guess that's why they are
+                # holds some low level configuration. They are the
+                # same all the time so I guess that's why they are
                 # skipped.
                 break
             section = []
@@ -173,6 +173,7 @@ for (addr, data) in all:
   all_data += encode(addr, 4) + \
               encode(len(data), 4) + \
               data
+all_data += encode(0, 4) + encode(0, 4) # Add the marker for the end of an image
 padding = [0] * (DELUGE_BYTES_PER_PAGE - len(all_data) % DELUGE_BYTES_PER_PAGE)
 if len(padding) < DELUGE_BYTES_PER_PAGE:
   all_data += padding
index 4e71e0c528a935f36cd8e025941172500dc66b99..a6c99785b13590f02b0c2215703c0b847508f125 100755 (executable)
@@ -24,7 +24,7 @@
 # @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
 
 import sys, stat, struct, subprocess, time
-import tinyos
+import tos
 from datetime import datetime
 import os.path 
 
@@ -36,7 +36,8 @@ FM_AMID = 0xAB
 DM_AMID = 0xAC
 SERIAL_DATA_LENGTH = 28 - 1 - 1 - 2 - 2
 BAUDRATES = {'micaz': 57600,
-             'telosb': 115200}
+             'telosb': 115200,
+             'iris': 57600}
 
 # Commands for FlashManager
 FM_CMD_ERASE     = 0
@@ -63,54 +64,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',  2),
+                             ('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
@@ -129,13 +130,15 @@ def crc16(data):
 
 def handleResponse(success, msg):
     if success == True:
-        packet = s.sniff_am()
+        packet = am.read(timeout=1)
         while packet and packet.type == 100:
             print "".join([chr(i) for i in packet.data])
-            packet = s.sniff_am()
+            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
@@ -146,8 +149,8 @@ def handleResponse(success, msg):
 
 def ident():
     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):
+        packet = am.read()
         reply = SerialReplyPacket(packet.data)
         if reply.error == ERROR_SUCCESS:
             return ShortIdent(reply.data)
@@ -161,8 +164,8 @@ def read(imgNum, offset, length):
         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)
@@ -182,12 +185,12 @@ def read(imgNum, offset, length):
 
 def erase(imgNum):
     sreqpkt = FMReqPacket((FM_CMD_ERASE, 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 erase the flash volume")
 
 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):
@@ -214,13 +217,13 @@ def write(imgNum, data):
         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
@@ -300,11 +303,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):
@@ -333,32 +337,32 @@ def ping(imgNum):
 
 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():
@@ -402,7 +406,8 @@ if len(sys.argv) >= 4:
             
     # Initializes serial port communication
     try:
-        s = tinyos.Serial(sys.argv[1], baudrate, flush=False)
+        s = tos.Serial(sys.argv[1], baudrate, flush=True, debug=False)
+        am = tos.AM(s)
     except:
         print "ERROR: Unable to initialize serial port connection to", sys.argv[1]
         sys.exit(-1)
diff --git a/tools/tinyos/misc/tos.py b/tools/tinyos/misc/tos.py
new file mode 100644 (file)
index 0000000..e01e7ec
--- /dev/null
@@ -0,0 +1,575 @@
+# Copyright (c) 2008 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>
+
+"""A library that implements the T2 serial communication.
+
+This library has two parts: one that deals with sending and receiving
+packets using the serial format from T2 (TEP113) and a second one that
+tries to simplifies the work with arbitrary packets.
+
+"""
+
+import sys, struct, time, serial, socket, operator, thread
+from Queue import Queue
+from threading import Lock, Condition
+
+__version__ = "$Id$"
+
+__all__ = ['Serial', 'AM',
+           'Packet', 'RawPacket',
+           'AckFrame', 'DataFrame', 'NoAckDataFrame',
+           'ActiveMessage']
+
+def list2hex(v):
+    return " ".join(["%02x" % p for p in v])
+
+class Serial:
+    """
+    A Serial object offers a way to send and data using a HDLC-like
+    formating.
+    """
+    
+    HDLC_FLAG_BYTE = 0x7e
+    HDLC_CTLESC_BYTE = 0x7d
+    
+    TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
+    TOS_SERIAL_CC1000_ID = 1
+    TOS_SERIAL_802_15_4_ID = 2
+    TOS_SERIAL_UNKNOWN_ID = 255
+    
+    SERIAL_PROTO_ACK = 67
+    SERIAL_PROTO_PACKET_ACK = 68
+    SERIAL_PROTO_PACKET_NOACK = 69
+    SERIAL_PROTO_PACKET_UNKNOWN = 255
+  
+    def __init__(self, port, baudrate, flush=False, debug=False, qsize=10):
+        self._debug = debug
+        self._in_queue = Queue(qsize)
+        self._out_lock = Lock()
+        self._out_ack = Condition()
+        self._seqno = 0
+        self._ack = None
+        self._write_counter = 0
+        self._write_counter_failures = 0
+        self._read_counter = 0
+        self._ts = None
+
+        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
+        self._s.flushInput()
+        start = time.time();
+        if flush:
+            print >>sys.stdout, "Flushing the serial port",
+            while time.time() - start < 1:
+                p = self._read()
+                sys.stdout.write(".")
+            if not self._debug:
+                sys.stdout.write("\n")
+        self._s.close()
+        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=None)
+
+        thread.start_new_thread(self.run, ())
+
+    def run(self):
+        
+        while True:
+            p = self._read()
+            self._read_counter += 1
+            if self._debug:
+                print "Serial:run: got a packet(%d): %s" % (self._read_counter, p)
+            ack = AckFrame(p.data)
+            if ack.protocol == self.SERIAL_PROTO_ACK:
+                if not self._ack:
+                    self._ack = ack
+                if self._debug:
+                    print "Serial:run: got an ack:", ack
+                self._ack = ack
+                # Wake up the writer
+                self._out_ack.acquire()
+                self._out_ack.notify()
+                self._out_ack.release()
+            else:
+                ampkt = ActiveMessage(NoAckDataFrame(p.data).data)
+                if ampkt.type == 100:
+                    for t in "".join([chr(i) for i in ampkt.data]).strip('\n\0').split('\n'):
+                        print "PRINTF:", t.strip('\n')
+                else:
+                    if self._in_queue.full():
+                        print "Warning: Buffer overflow"
+                        self._in_queue.get()
+                    self._in_queue.put(p, block=False)
+
+
+    # Returns the next incoming serial packet
+    def _read(self):
+        """Wait for a packet and return it as a RawPacket."""
+        
+        try:
+            d = self._get_byte()
+            ts = time.time()
+            while d != self.HDLC_FLAG_BYTE:
+                d = self._get_byte()
+                ts = time.time()
+            packet = [d]
+            d = self._get_byte()
+            if d == self.HDLC_FLAG_BYTE:
+                d = self._get_byte()
+                ts = time.time()
+            else:
+                packet.append(d)
+            while d != self.HDLC_FLAG_BYTE:
+                d = self._get_byte()
+                packet.append(d)
+            if self._debug == True:
+                print "Serial:_read: unescaped", packet
+            packet = self._unescape(packet)
+            
+            crc = self._crc16(0, packet[1:-3])
+            packet_crc = self._decode(packet[-3:-1])
+            
+            if crc != packet_crc:
+                print "Warning: wrong CRC! %x != %x %s" % (crc, packet_crc, ["%2x" % i for i in packet])
+            if self._debug:
+                if self._ts == None:
+                    self._ts = ts
+                else:
+                    print "Serial:_read: %.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
+                self._ts = ts
+            return RawPacket(ts, packet[1:-3], crc == packet_crc)
+        except socket.timeout:
+            return None
+
+
+    def read(self, timeout=0):
+        start = time.time();
+        done = False
+        while not done:
+            p = None
+            while p == None:
+                if timeout == 0 or time.time() - start < timeout:
+                    p = self._in_queue.get()
+                else:
+                    return None
+            if p.crc:
+                done = True
+            else:
+                p = None
+        # In the current TinyOS the packets from the mote are always NoAckDataFrame
+        return NoAckDataFrame(p.data)
+
+    def write(self, payload):
+        """
+        Write a packet. If the payload argument is a list, it is
+        assumed to be exactly the payload. Otherwise the payload is
+        assume to be a Packet and the real payload is obtain by
+        calling the .payload().
+        """
+        
+        if type(payload) != type([]):
+            # Assume this will be derived from Packet
+            payload = payload.payload()
+        self._out_lock.acquire()
+        self._seqno = (self._seqno + 1) % 100
+        packet = DataFrame();
+        packet.protocol = self.SERIAL_PROTO_PACKET_ACK
+        packet.seqno = self._seqno
+        packet.dispatch = 0
+        packet.data = payload
+        packet = packet.payload()
+        crc = self._crc16(0, packet)
+        packet.append(crc & 0xff)
+        packet.append((crc >> 8) & 0xff)
+        packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
+
+        while True:
+            self._put_bytes(packet)
+            self._write_counter += 1
+            if self._debug == True:
+                print "Send(%d/%d): %s" % (self._write_counter, self._write_counter_failures, packet)
+                print "Wait for ack %d ..." % (self._seqno)
+            self._out_ack.acquire()
+            self._out_ack.wait(0.2)
+            if self._debug:
+                print "Wait for ack %d done. Latest ack:" % (self._seqno), self._ack
+            self._out_ack.release()
+            if self._ack and self._ack.seqno == self._seqno:
+                if self._debug:
+                    print "The packet was acked."
+                self._out_lock.release()
+                if self._debug:
+                    print "Returning from Serial.write..."
+                return True
+            else:
+                self._write_counter_failures += 1
+                if self._debug:
+                    print "The packet was not acked. Try again."
+            # break # make only one sending attempt
+        self._out_lock.release()
+        return False
+
+
+    def _format_packet(self, payload):
+        f = NoAckDataFrame(payload)
+        if f.protocol == self.SERIAL_PROTO_ACK:
+            rpacket = AckFrame(payload)
+            return "Ack seqno: %d" % (rpacket.seqno)
+        else:
+            rpacket = ActiveMessage(f.data)
+            return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
+                   (rpacket.destination, rpacket.source,
+                    rpacket.length, rpacket.group, rpacket.type,
+                    list2hex(rpacket.data))
+
+    def _crc16(self, base_crc, frame_data):
+        crc = base_crc
+        for b in frame_data:
+            crc = crc ^ (b << 8)
+            for i in range(0, 8):
+                if crc & 0x8000 == 0x8000:
+                    crc = (crc << 1) ^ 0x1021
+                else:
+                    crc = crc << 1
+                crc = crc & 0xffff
+        return crc
+    
+    def _encode(self, val, dim):
+        output = []
+        for i in range(dim):
+            output.append(val & 0xFF)
+            val = val >> 8
+        return output
+    
+    def _decode(self, v):
+        r = long(0)
+        for i in v[::-1]:
+            r = (r << 8) + i
+        return r
+    
+    def _get_byte(self):
+        try:
+            r = struct.unpack("B", self._s.read())[0]
+            return r
+        except struct.error:
+            # Serial port read timeout
+            raise socket.timeout
+    
+    def _put_bytes(self, data):
+        #print "DEBUG: _put_bytes:", data
+        for b in data:
+            self._s.write(struct.pack('B', b))
+    
+    def _unescape(self, packet):
+        r = []
+        esc = False
+        for b in packet:
+            if esc:
+                r.append(b ^ 0x20)
+                esc = False
+            elif b == self.HDLC_CTLESC_BYTE:
+                esc = True
+            else:
+                r.append(b)
+        return r
+    
+    def _escape(self, packet):
+        r = []
+        for b in packet:
+            if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
+                r.append(self.HDLC_CTLESC_BYTE)
+                r.append(b ^ 0x20)
+            else:
+                r.append(b)
+        return r
+    
+    def debug(self, debug):
+        self._debug = debug
+
+
+class SFClient:
+    def __init__(self, host, port, qsize=10):
+        self._in_queue = Queue(qsize)
+        self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self._s.connect((host, port))
+        data = self._s.recv(2)
+        if data != 'U ':
+            print "Wrong handshake"
+        self._s.send("U ")
+        print "Connected"
+        thread.start_new_thread(self.run, ())
+
+    def run(self):
+        while True:
+            length = ord(self._s.recv(1))
+            data = self._s.recv(length)
+            data = [ord(c) for c in data][1:]
+            #print "Recv %d bytes" % (length), ActiveMessage(data)
+            if self._in_queue.full():
+                print "Warning: Buffer overflow"
+                self._in_queue.get()
+            p = RawPacket()
+            p.crc = 1
+            p.data = data
+            self._in_queue.put(p, block=False)
+
+    def read(self, timeout=0):
+        return self._in_queue.get()
+
+    def write(self, payload):
+        print "SFClient: write:", payload
+        if type(payload) != type([]):
+            # Assume this will be derived from Packet
+            payload = payload.payload()
+        payload = [0] + payload
+        self._s.send(chr(len(payload)))
+        self._s.send(''.join([chr(c) for c in payload]))
+        return True
+
+class AM:
+    def __init__(self, s):
+        self._s = s
+
+    def read(self, timeout=0):
+        return ActiveMessage(self._s.read().data)
+
+    def write(self, packet, amid):
+        return self._s.write(ActiveMessage(packet, amid=amid))
+
+
+class Packet:
+    """
+    The Packet class offers a handy way to build pack and unpack
+    binary data based on a given pattern.
+    """
+
+    def _decode(self, v):
+        r = long(0)
+        for i in v:
+            r = (r << 8) + i
+        return r
+    
+    def _encode(self, val, dim):
+        output = []
+        for i in range(dim):
+            output.append(int(val & 0xFF))
+            val = val >> 8
+        output.reverse()
+        return output
+    
+    def __init__(self, desc, packet = None):
+        offset = 0
+        boffset = 0
+        sum = 0
+        for i in range(len(desc)-1, -1, -1):
+            (n, t, s) = desc[i]
+            if s == None:
+                if sum > 0:
+                    desc[i] = (n, t, -sum)
+                break
+            sum += s
+        self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
+        self.__dict__['_names'] = [n for (n, t, s) in desc]
+        self.__dict__['_values'] = []
+        if type(packet) == type([]):
+            for (t, s) in self._schema:
+                if t == 'int':
+                    self._values.append(self._decode(packet[offset:offset + s]))
+                    offset += s
+                elif t == 'bint':
+                    doffset = 8 - (boffset + s)
+                    self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
+                    boffset += s
+                    if boffset == 8:
+                        offset += 1
+                        boffset = 0
+                elif t == 'string':
+                    self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
+                    offset += s
+                elif t == 'blob':
+                    if s:
+                        if s > 0:
+                            self._values.append(packet[offset:offset + s])
+                            offset += s
+                        else:
+                            self._values.append(packet[offset:s])
+                            offset = len(packet) + s
+                    else:
+                        self._values.append(packet[offset:])
+        elif type(packet) == type(()):
+            for i in packet:
+                self._values.append(i)
+        else:
+            for v in self._schema:
+                self._values.append(None)
+
+    def __repr__(self):
+        return self._values.__repr__()
+
+    def __str__(self):
+        r = ""
+        for i in range(len(self._names)):
+            r += "%s: %s " % (self._names[i], self._values[i])
+        for i in range(len(self._names), len(self._values)):
+            r += "%s" % self._values[i]
+        return r
+#        return self._values.__str__()
+
+    # Implement the map behavior
+    def __getitem__(self, key):
+        return self.__getattr__(key)
+
+    def __setitem__(self, key, value):
+        self.__setattr__(key, value)
+
+    def __len__(self):
+        return len(self._values)
+
+    def keys(self):
+        return self._names
+
+    def values(self):
+        return self._names
+
+    # Implement the struct behavior
+    def __getattr__(self, name):
+        #print "DEBUG: __getattr__", name
+        if type(name) == type(0):
+            return self._names[name]
+        else:
+            return self._values[self._names.index(name)]
+
+    def __setattr__(self, name, value):
+        if type(name) == type(0):
+            self._values[name] = value
+        else:
+            self._values[self._names.index(name)] = value
+
+    def __ne__(self, other):
+        if other.__class__ == self.__class__:
+            return self._values != other._values
+        else:
+            return True
+
+    def __eq__(self, other):
+        if other.__class__ == self.__class__:
+            return self._values == other._values
+        else:
+            return False
+
+    def __nonzero__(self):
+        return True;
+
+    # Custom
+    def names(self):
+        return self._names
+
+    def sizes(self):
+        return self._schema
+
+    def payload(self):
+        r = []
+        boffset = 0
+        for i in range(len(self._schema)):
+            (t, s) = self._schema[i]
+            if t == 'int':
+                r += self._encode(self._values[i], s)
+                boffset = 0
+            elif t == 'bint':
+                doffset = 8 - (boffset + s)
+                if boffset == 0:
+                    r += [self._values[i] << doffset]
+                else:
+                    r[-1] |= self._values[i] << doffset
+                boffset += s
+                if boffset == 8:
+                    boffset = 0
+            elif self._values[i] != []:
+                r += self._values[i]
+        for i in self._values[len(self._schema):]:
+            r += i
+        return r
+
+
+class RawPacket(Packet):
+    def __init__(self, ts = None, data = None, crc = None):
+        Packet.__init__(self,
+                        [('ts' ,  'int', 4),
+                         ('crc',  'int', 1),
+                         ('data', 'blob', None)],
+                        None)
+        self.ts = ts;
+        self.data = data
+        self.crc = crc
+        
+class AckFrame(Packet):
+    def __init__(self, payload = None):
+        Packet.__init__(self,
+                        [('protocol', 'int', 1),
+                         ('seqno',    'int', 1)],
+                        payload)
+
+class DataFrame(Packet):
+    def __init__(self, payload = None):
+        if payload != None and type(payload) != type([]):
+            # Assume is a Packet
+            payload = payload.payload()
+        Packet.__init__(self,
+                        [('protocol',  'int', 1),
+                         ('seqno',     'int', 1),
+                         ('dispatch',  'int', 1),
+                         ('data',      'blob', None)],
+                        payload)
+
+class NoAckDataFrame(Packet):
+    def __init__(self, payload = None):
+        if payload != None and type(payload) != type([]):
+            # Assume is a Packet
+            payload = payload.payload()
+        Packet.__init__(self,
+                        [('protocol',  'int', 1),
+                         ('dispatch',  'int', 1),
+                         ('data',      'blob', None)],
+                        payload)
+
+class ActiveMessage(Packet):
+    def __init__(self, gpacket = None, amid = 0x00, dest = 0xFFFF):
+        if type(gpacket) == type([]):
+            payload = gpacket
+        else:
+            # Assume this will be derived from Packet
+            payload = None
+        Packet.__init__(self,
+                        [('destination', 'int', 2),
+                         ('source',   'int', 2),
+                         ('length',   'int', 1),
+                         ('group',    'int', 1),
+                         ('type',     'int', 1),
+                         ('data',     'blob', None)],
+                        payload)
+        if payload == None:
+            self.destination = dest
+            self.source = 0x0000
+            self.group = 0x00
+            self.type = amid
+            self.data = []
+            if gpacket:
+                self.data = gpacket.payload()
+            self.length = len(self.data)
+
index 6ef74f584231a46a9c87259c6f0bbb37ea66efd6..fc2cfc504640f490dabe16803a04e6d7e033bba2 100644 (file)
@@ -44,6 +44,9 @@ typedef nx_struct DelugeIdent {
 enum {
   DELUGE_INVALID_UID = 0xffffffff,
   DELUGE_NUM_VOLUMES = 4, 
+  DELUGE_KEY = 0xDE00,
+  DELUGE_AM_FLASH_VOL_MANAGER = 0xAB,
+  DELUGE_AM_DELUGE_MANAGER = 0xAC,
 };
 
 enum {
index 20532b56e3b012fa68d2346bde4cbeba6f341e33..78d550fce9bde4113299c034013b2b70ba12c285 100644 (file)
@@ -53,7 +53,7 @@ implementation
 
   ObjectTransferC.Leds = Leds;
   
-  components new DisseminatorC(DelugeCmd, 0xDE00);
+  components new DisseminatorC(DelugeCmd, DELUGE_KEY);
   components DisseminationC;
   components ActiveMessageC;
   components NetProgC, DelugeP;
@@ -67,7 +67,9 @@ implementation
 
   DelugeP.Boot -> MainC;
   DelugeP.Leds = Leds;  
+#ifndef DELUGE_BASESTATION
   DelugeP.DisseminationValue -> DisseminatorC;
+#endif
   DelugeP.DisseminationStdControl -> DisseminationC;
   DelugeP.ObjectTransfer -> ObjectTransferC;
   DelugeP.NetProg -> NetProgC;
@@ -78,10 +80,13 @@ implementation
   DelugeP.DelugeVolumeManager -> DelugeVolumeManagerClientC;
   DelugeP.Resource -> BlockStorageLockClientC;
 
-#ifdef DELUGE_BASESTATION
+#if defined(DELUGE_BASESTATION) || defined(DELUGE_LIGHT_BASESTATION)
   components SerialStarterC;
-  components new FlashVolumeManagerC(0xAB);
-  components new DelugeManagerC(0xAC);
+  components new FlashVolumeManagerC(DELUGE_AM_FLASH_VOL_MANAGER);
+#endif
+
+#ifdef DELUGE_BASESTATION
+  components new DelugeManagerC(DELUGE_AM_DELUGE_MANAGER);
 
   DelugeManagerC.DisseminationUpdate -> DisseminatorC;
 #endif
index 342d8ca21cfc6462209e83d9fa38aa2ec255282d..4a25388fa3afd3f2973816557ececb39a3204fcb 100644 (file)
@@ -24,6 +24,8 @@
  * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
  */
 
+#include "imgNum2volumeId.h"
+
 generic module DelugeManagerP()
 {
   uses {
@@ -55,12 +57,6 @@ implementation
 
   message_t serialMsg;
   DelugeCmd delugeCmd;
-  uint8_t imgNum2volumeId[] = {
-    VOLUME_GOLDENIMAGE,
-    VOLUME_DELUGE1,
-    VOLUME_DELUGE2,
-    VOLUME_DELUGE3
-  };
 
   void sendReply(error_t error)
   {
@@ -77,9 +73,10 @@ implementation
   {
     SerialReqPacket *request = (SerialReqPacket *)payload;
     memset(&delugeCmd, 0, sizeof(DelugeCmd));
-
     call stop();
     delugeCmd.type = request->cmd;
+    // Converts the image number that the user wants to the real image number
+    request->imgNum = imgNum2volumeId(request->imgNum);
 
     switch (request->cmd) {
     case DELUGE_CMD_STOP:
@@ -90,21 +87,21 @@ implementation
       break;
     case DELUGE_CMD_ONLY_DISSEMINATE:
     case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM:
-      if (request->imgNum < DELUGE_NUM_VOLUMES &&
+      if (request->imgNum != NON_DELUGE_VOLUME &&
          (call Resource.isOwner() || 
           call Resource.immediateRequest() == SUCCESS)) {
-       call DelugeMetadata.read(imgNum2volumeId[request->imgNum]);
+       call DelugeMetadata.read(request->imgNum);
       } else {
        sendReply(FAIL);
       }
       break;
     case DELUGE_CMD_REPROGRAM:
-      if (!(request->imgNum < DELUGE_NUM_VOLUMES)) {
+    case DELUGE_CMD_REBOOT:
+      if (request->imgNum == NON_DELUGE_VOLUME) {
        sendReply(FAIL);
        break;
       }
-    case DELUGE_CMD_REBOOT:
-      delugeCmd.imgNum = imgNum2volumeId[request->imgNum];
+      delugeCmd.imgNum = request->imgNum;
       call DelayTimer.startOneShot(1024);
       sendReply(SUCCESS);
       break;
index 6c2fa37573ca9e8f852203a6da521d2923f91a25..f10b3144b1c0481de8c390bbde06a3d0f1f4b159 100644 (file)
@@ -24,6 +24,8 @@
  * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
  */
 
+#include "imgNum2volumeId.h"
+
 module DelugeMetadataP
 {
   provides interface DelugeMetadata[uint8_t client];
@@ -48,16 +50,17 @@ implementation
   
   DelugeIdent ident;
   uint8_t state;
-  uint8_t currentImage;
+  uint8_t currentVolume;
+  uint8_t currentImageIdx;
   uint8_t currentPage;
   nx_uint16_t currentCrc;
   uint8_t currentClient;
 
   void nextImage()
   {
-    if (currentImage < DELUGE_NUM_VOLUMES) {
+    if (currentImageIdx < DELUGE_NUM_VOLUMES) {
       state = S_READ_IDENT;
-      call BlockRead.read[currentImage](0, &ident, sizeof(ident));
+      call BlockRead.read[currentVolume](0, &ident, sizeof(ident));
     } else {
       signal storageReady();
       state = S_READY;
@@ -82,7 +85,8 @@ implementation
     // CRC and check it against the corresponding value from the CRCs
     // block.
     state = S_READ_IDENT;
-    currentImage = 0;
+    currentImageIdx = 0;
+    currentVolume = _imgNum2volumeId[currentImageIdx];
     nextImage();    
   }
 
@@ -110,16 +114,16 @@ implementation
         if (ident.uidhash != DELUGE_INVALID_UID) {
           currentPage = 0;
           state = S_READ_CRC;
-          call BlockRead.read[currentImage](calcCrcAddr(), &currentCrc, sizeof(currentCrc));
+          call BlockRead.read[currentVolume](calcCrcAddr(), &currentCrc, sizeof(currentCrc));
         } else {
-          currentImage++;
+          currentImageIdx++;
           nextImage();
         }
       }
       break;
     case S_READ_CRC:
       state = S_CRC;
-      call BlockRead.computeCrc[currentImage](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0);
+      call BlockRead.computeCrc[currentVolume](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0);
       break;
     }
   }
@@ -131,14 +135,15 @@ implementation
       if (crc != currentCrc) {
 //     printf("%04x %04x\n", crc, currentCrc);
         // invalidate the image by erasing it
-        call BlockWrite.erase[currentImage]();
+        call BlockWrite.erase[currentVolume]();
       } else {
         currentPage++;
         if (currentPage < ident.numPgs) {
           state = S_READ_CRC;
-          call BlockRead.read[currentImage](calcCrcAddr(), &currentCrc, sizeof(currentCrc));
+          call BlockRead.read[currentVolume](calcCrcAddr(), &currentCrc, sizeof(currentCrc));
         } else {
-          currentImage++;
+          currentImageIdx++;
+         currentVolume = _imgNum2volumeId[currentImageIdx];
           nextImage();
         }
       }
@@ -157,7 +162,8 @@ implementation
       signal BlockWrite.eraseDone[imgNum](error);
       break;
     case S_CRC:
-      currentImage++;
+      currentImageIdx++;
+      currentVolume = _imgNum2volumeId[currentImageIdx];
       nextImage();
       break;
     }
index 56558c4214a17c8b14bf11c143a016a5e005de59..06420ce4a02ab4037f13cd7937738a9cf2d6eb98 100644 (file)
@@ -24,6 +24,8 @@
  * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
  */
 
+#include "imgNum2volumeId.h"
+
 generic module FlashVolumeManagerP()
 {
   uses {
@@ -88,13 +90,6 @@ implementation
     nx_uint16_t nodeid;
   };
 
-  uint8_t imgNum2volumeId[] = {
-    VOLUME_GOLDENIMAGE,
-    VOLUME_DELUGE1,
-    VOLUME_DELUGE2,
-    VOLUME_DELUGE3
-  };
-  
   void sendReply(error_t error, storage_len_t len)
   {
     SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket));
@@ -186,9 +181,9 @@ implementation
     }
 
     // Converts the image number that the user wants to the real image number
-    imgNum = request->imgNum < DELUGE_NUM_VOLUMES ? imgNum2volumeId[request->imgNum] : 0xFF;
+    imgNum = imgNum2volumeId(request->imgNum);
     
-    if (imgNum != 0xFF) {
+    if (imgNum != NON_DELUGE_VOLUME) {
       error = SUCCESS;
       // We ask for a reservation only for erase and write.
       switch (request->cmd) {
@@ -259,10 +254,9 @@ implementation
   {
     // Release the resource.
     if (state == S_IDLE && call Resource.isOwner()) {
-      call Leds.led1Off();
       call Resource.release();
     }
-    if (state == S_IDLE && !call ArbiterInfo.inUse()) {
+    if (state == S_IDLE) {
       call Leds.led1Off();
     }
   }
diff --git a/tos/lib/net/Deluge/ReprogramGuard.nc b/tos/lib/net/Deluge/ReprogramGuard.nc
new file mode 100644 (file)
index 0000000..df3ca41
--- /dev/null
@@ -0,0 +1,5 @@
+interface ReprogramGuard
+{
+  command error_t okToProgram();
+  event void okToProgramDone(bool ok);
+}
index 8a4c6c1288ca9113a4b2ea5c8cc9ecd183d3be02..462ff7da4883f412557da2857805b3ff19a52304 100644 (file)
@@ -40,14 +40,16 @@ configuration NetProgC {
 
 implementation {
 
-  components MainC, InternalFlashC as IFlash, CrcP, NetProgM;
+  components MainC, InternalFlashC as IFlash, CrcP;
+  components NetProgM, ReprogramGuardC;
 
   NetProg = NetProgM;
 
   MainC.SoftwareInit -> NetProgM.Init;
   NetProgM.IFlash -> IFlash;
   NetProgM.Crc -> CrcP;
-  
+  NetProgM.ReprogramGuard -> ReprogramGuardC;
+
   components LedsC;
   NetProgM.Leds -> LedsC;
   
index 478bad262cde8339f8da0ba8e4d749db98265993..7567ad1ad809ead008d6e76de7d3f186708f90f5 100644 (file)
@@ -42,11 +42,14 @@ module NetProgM {
     interface Leds;
     interface CC2420Config;
     async command void setAmAddress(am_addr_t a);
+    interface ReprogramGuard;
   }
 }
 
 implementation {
 
+  uint32_t reprogramImgAddr;
+
   command error_t Init.init()
   {
     BootArgs bootArgs;
@@ -81,13 +84,24 @@ implementation {
   }
   
   command error_t NetProg.programImageAndReboot(uint32_t imgAddr)
+  {
+    reprogramImgAddr = imgAddr;
+    return call ReprogramGuard.okToProgram();
+  }
+
+  event void ReprogramGuard.okToProgramDone(bool ok)
   {
     BootArgs bootArgs;
 
+    if (!ok) {
+      // The voltage is too low. Nothing to do.
+      return;
+    }
+
     atomic {
       call IFlash.read((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs));
       
-      bootArgs.imageAddr = imgAddr;
+      bootArgs.imageAddr = reprogramImgAddr;
       bootArgs.gestureCount = 0xff;
       bootArgs.noReprogram = FALSE;
       bootArgs.address = TOS_NODE_ID;
@@ -97,11 +111,7 @@ implementation {
       // reboot
       netprog_reboot();
     }
-
-    // couldn't reboot
-    return FAIL;
   }
 
   event void CC2420Config.syncDone(error_t error) {}
-
 }
diff --git a/tos/lib/net/Deluge/extra/micaz/ReprogramGuardC.nc b/tos/lib/net/Deluge/extra/micaz/ReprogramGuardC.nc
new file mode 100644 (file)
index 0000000..9f25e50
--- /dev/null
@@ -0,0 +1,13 @@
+configuration ReprogramGuardC
+{
+  provides interface ReprogramGuard;
+}
+
+implementation
+{
+  components ReprogramGuardP;
+  components new VoltageC();
+  
+  ReprogramGuard = ReprogramGuardP;
+  ReprogramGuardP.Voltage -> VoltageC;
+}
diff --git a/tos/lib/net/Deluge/extra/micaz/ReprogramGuardP.nc b/tos/lib/net/Deluge/extra/micaz/ReprogramGuardP.nc
new file mode 100644 (file)
index 0000000..c5dc0c8
--- /dev/null
@@ -0,0 +1,23 @@
+module ReprogramGuardP
+{
+  provides interface ReprogramGuard;
+  uses interface Read<uint16_t> as Voltage;
+}
+
+implementation
+{
+  enum {
+    VTHRESH = 0x1CF, // 2.7V
+  };
+
+  command error_t ReprogramGuard.okToProgram()
+  {
+    return call Voltage.read();
+  }
+
+  event void Voltage.readDone(error_t result, uint16_t val)
+  {
+    signal ReprogramGuard.okToProgramDone(result == SUCCESS && val < VTHRESH);
+  }
+  
+}
diff --git a/tos/lib/net/Deluge/extra/telosb/ReprogramGuardC.nc b/tos/lib/net/Deluge/extra/telosb/ReprogramGuardC.nc
new file mode 100644 (file)
index 0000000..9f25e50
--- /dev/null
@@ -0,0 +1,13 @@
+configuration ReprogramGuardC
+{
+  provides interface ReprogramGuard;
+}
+
+implementation
+{
+  components ReprogramGuardP;
+  components new VoltageC();
+  
+  ReprogramGuard = ReprogramGuardP;
+  ReprogramGuardP.Voltage -> VoltageC;
+}
diff --git a/tos/lib/net/Deluge/extra/telosb/ReprogramGuardP.nc b/tos/lib/net/Deluge/extra/telosb/ReprogramGuardP.nc
new file mode 100644 (file)
index 0000000..1ffb1e9
--- /dev/null
@@ -0,0 +1,23 @@
+module ReprogramGuardP
+{
+  provides interface ReprogramGuard;
+  uses interface Read<uint16_t> as Voltage;
+}
+
+implementation
+{
+  enum {
+    VTHRESH = 0xE66, // 2.7V
+  };
+
+  command error_t ReprogramGuard.okToProgram()
+  {
+    return call Voltage.read();
+  }
+
+  event void Voltage.readDone(error_t result, uint16_t val)
+  {
+    signal ReprogramGuard.okToProgramDone(result == SUCCESS && val > VTHRESH);
+  }
+  
+}
diff --git a/tos/lib/net/Deluge/imgNum2volumeId.h b/tos/lib/net/Deluge/imgNum2volumeId.h
new file mode 100644 (file)
index 0000000..0c3170b
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __IMGNUM2VOLUMEID_H__
+#define __IMGNUM2VOLUMEID_H__
+
+uint8_t _imgNum2volumeId[] = {
+  VOLUME_GOLDENIMAGE,
+  VOLUME_DELUGE1,
+  VOLUME_DELUGE2,
+  VOLUME_DELUGE3
+};
+
+enum {
+  NON_DELUGE_VOLUME = 0xFF
+};
+
+uint8_t imgNum2volumeId(uint8_t imgNum)
+{
+  return imgNum < DELUGE_NUM_VOLUMES ? _imgNum2volumeId[imgNum] : NON_DELUGE_VOLUME;
+}
+
+#endif
index 8f7a1c7f3003923073c03441c964df7dc07132f2..01fc2d1d4ebfa83f03c852edaba8d164ba990616 100644 (file)
 typedef uint32_t in_flash_addr_t;
 typedef uint32_t ex_flash_addr_t;
 
-void wait( uint16_t t ) {
-  for ( ; t; t-- );
+static inline void wait( uint16_t dt ) {
+  /* In most cases (constant arg), the test is elided at compile-time */
+  if (dt)
+    /* loop takes 8 cycles. this is 1uS if running on an internal 8MHz
+       clock, and 1.09uS if running on the external crystal. */
+    asm volatile (
+      "1:       sbiw    %0,1\n"
+      " adiw    %0,1\n"
+      " sbiw    %0,1\n"
+      " brne    1b" : "+w" (dt));
 }
 
 // LED assignments