From 62b84950912c1c033c401fb0b2a1efaceec78280 Mon Sep 17 00:00:00 2001 From: razvanm Date: Mon, 19 May 2008 21:25:08 +0000 Subject: [PATCH] Merge of the latest Deluge T2. --- apps/tests/deluge/Blink/Makefile | 3 +- apps/tests/deluge/Blink/burn | 29 +- apps/tests/deluge/Blink/burn-net | 31 +- tools/tinyos/misc/Makefile.am | 2 +- tools/tinyos/misc/tos-build-deluge-image | 7 +- tools/tinyos/misc/tos-deluge | 131 ++--- tools/tinyos/misc/{tinyos.py => tos.py} | 454 +++++++++++------- tos/lib/net/Deluge/Deluge.h | 3 + tos/lib/net/Deluge/DelugeC.nc | 13 +- tos/lib/net/Deluge/DelugeManagerP.nc | 21 +- tos/lib/net/Deluge/DelugeMetadataP.nc | 28 +- .../FlashVolumeManager/FlashVolumeManagerP.nc | 16 +- tos/lib/net/Deluge/ReprogramGuard.nc | 5 + tos/lib/net/Deluge/extra/NetProgC.nc | 6 +- tos/lib/net/Deluge/extra/NetProgM.nc | 20 +- .../net/Deluge/extra/micaz/ReprogramGuardC.nc | 13 + .../net/Deluge/extra/micaz/ReprogramGuardP.nc | 23 + .../Deluge/extra/telosb/ReprogramGuardC.nc | 13 + .../Deluge/extra/telosb/ReprogramGuardP.nc | 23 + tos/lib/net/Deluge/imgNum2volumeId.h | 20 + tos/lib/tosboot/micaz/hardware.h | 12 +- 21 files changed, 567 insertions(+), 306 deletions(-) rename tools/tinyos/misc/{tinyos.py => tos.py} (54%) create mode 100644 tos/lib/net/Deluge/ReprogramGuard.nc create mode 100644 tos/lib/net/Deluge/extra/micaz/ReprogramGuardC.nc create mode 100644 tos/lib/net/Deluge/extra/micaz/ReprogramGuardP.nc create mode 100644 tos/lib/net/Deluge/extra/telosb/ReprogramGuardC.nc create mode 100644 tos/lib/net/Deluge/extra/telosb/ReprogramGuardP.nc create mode 100644 tos/lib/net/Deluge/imgNum2volumeId.h diff --git a/apps/tests/deluge/Blink/Makefile b/apps/tests/deluge/Blink/Makefile index 5a995f0b..6f7acb39 100644 --- a/apps/tests/deluge/Blink/Makefile +++ b/apps/tests/deluge/Blink/Makefile @@ -1,6 +1,7 @@ COMPONENT=BlinkAppC TINYOS_NP=BNP -CFLAGS += -DDELUGE_BASESTATION +#CFLAGS += -DDELUGE_BASESTATION +#CFLAGS += -DDELUGE_LIGHT_BASESTATION include $(MAKERULES) diff --git a/apps/tests/deluge/Blink/burn b/apps/tests/deluge/Blink/burn index f0aaddce..1e82f5d3 100755 --- a/apps/tests/deluge/Blink/burn +++ b/apps/tests/deluge/Blink/burn @@ -18,17 +18,24 @@ if [[ ! -x ${TOS_DELUGE} ]] ; then TOS_DELUGE=../../../../tools/tinyos/misc/tos-deluge fi -if [ $# -ne 2 ]; then - echo "Usage: $0 " +if [[ $# -ne 2 && $# -ne 3 ]]; then + echo "Usage: $0 [] " echo " /dev/ttyUSB0" - echo " micaz or telosb" + echo " /dev/ttyUSB1" + echo " 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 diff --git a/apps/tests/deluge/Blink/burn-net b/apps/tests/deluge/Blink/burn-net index 0d94b40c..cc146661 100755 --- a/apps/tests/deluge/Blink/burn-net +++ b/apps/tests/deluge/Blink/burn-net @@ -7,7 +7,7 @@ fi if [ $# -ne 2 ]; then echo "Usage: $0 " - echo " micaz or telosb" + echo " micaz, telosb or iris" echo " 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 ' | |' diff --git a/tools/tinyos/misc/Makefile.am b/tools/tinyos/misc/Makefile.am index 276314be..8dfc65b5 100644 --- a/tools/tinyos/misc/Makefile.am +++ b/tools/tinyos/misc/Makefile.am @@ -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/tos-build-deluge-image b/tools/tinyos/misc/tos-build-deluge-image index 08542401..3095167a 100755 --- a/tools/tinyos/misc/tos-build-deluge-image +++ b/tools/tinyos/misc/tos-build-deluge-image @@ -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 # @author Razvan Musaloiu-E. +# @author Chieh-Jan Mike Liang 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 diff --git a/tools/tinyos/misc/tos-deluge b/tools/tinyos/misc/tos-deluge index 4e71e0c5..a6c99785 100755 --- a/tools/tinyos/misc/tos-deluge +++ b/tools/tinyos/misc/tos-deluge @@ -24,7 +24,7 @@ # @author Chieh-Jan Mike Liang 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/tinyos.py b/tools/tinyos/misc/tos.py similarity index 54% rename from tools/tinyos/misc/tinyos.py rename to tools/tinyos/misc/tos.py index c33a8dbe..e01e7ecd 100644 --- a/tools/tinyos/misc/tinyos.py +++ b/tools/tinyos/misc/tos.py @@ -1,3 +1,25 @@ +# 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. + """A library that implements the T2 serial communication. This library has two parts: one that deals with sending and receiving @@ -6,17 +28,17 @@ tries to simplifies the work with arbitrary packets. """ -import sys, struct, time, serial, socket, operator +import sys, struct, time, serial, socket, operator, thread from Queue import Queue +from threading import Lock, Condition __version__ = "$Id$" -__all__ = ['Serial', 'GenericPacket', 'RawPacket', +__all__ = ['Serial', 'AM', + 'Packet', 'RawPacket', 'AckFrame', 'DataFrame', 'NoAckDataFrame', 'ActiveMessage'] -_seqno = 1 - def list2hex(v): return " ".join(["%02x" % p for p in v]) @@ -39,23 +61,170 @@ class Serial: 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 __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) @@ -69,7 +238,7 @@ class Serial: rpacket.length, rpacket.group, rpacket.type, list2hex(rpacket.data)) - def crc16(self, base_crc, frame_data): + def _crc16(self, base_crc, frame_data): crc = base_crc for b in frame_data: crc = crc ^ (b << 8) @@ -130,119 +299,65 @@ class Serial: 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 debug(self, debug): + self._debug = debug - 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 +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 GenericPacket + # Assume this will be derived from Packet 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] + payload = [0] + payload + self._s.send(chr(len(payload))) + self._s.send(''.join([chr(c) for c in payload])) + return True - 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 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 GenericPacket: - """ GenericPacket """ + +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) @@ -392,68 +507,69 @@ class GenericPacket: return r -class RawPacket(GenericPacket): +class RawPacket(Packet): def __init__(self, ts = None, data = None, crc = None): - GenericPacket.__init__(self, - [('ts' , 'int', 4), - ('crc', 'int', 1), - ('data', 'blob', None)], - 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(GenericPacket): +class AckFrame(Packet): def __init__(self, payload = None): - GenericPacket.__init__(self, - [('protocol', 'int', 1), - ('seqno', 'int', 1)], - payload) + Packet.__init__(self, + [('protocol', 'int', 1), + ('seqno', 'int', 1)], + payload) -class DataFrame(GenericPacket): +class DataFrame(Packet): def __init__(self, payload = None): if payload != None and type(payload) != type([]): - # Assume is a GenericPacket + # Assume is a Packet payload = payload.payload() - GenericPacket.__init__(self, - [('protocol', 'int', 1), - ('seqno', 'int', 1), - ('dispatch', 'int', 1), - ('data', 'blob', None)], - payload) - -class NoAckDataFrame(GenericPacket): + 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 GenericPacket + # Assume is a Packet 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): + 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 GenericPacket + # Assume this will be derived from Packet payload = None - GenericPacket.__init__(self, - [('destination', 'int', 2), - ('source', 'int', 2), - ('length', 'int', 1), - ('group', 'int', 1), - ('type', 'int', 1), - ('data', 'blob', None)], - payload) + 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 = am_id - self.data = gpacket.payload() + self.type = amid + self.data = [] + if gpacket: + self.data = gpacket.payload() self.length = len(self.data) diff --git a/tos/lib/net/Deluge/Deluge.h b/tos/lib/net/Deluge/Deluge.h index 6ef74f58..fc2cfc50 100644 --- a/tos/lib/net/Deluge/Deluge.h +++ b/tos/lib/net/Deluge/Deluge.h @@ -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 { diff --git a/tos/lib/net/Deluge/DelugeC.nc b/tos/lib/net/Deluge/DelugeC.nc index 20532b56..78d550fc 100644 --- a/tos/lib/net/Deluge/DelugeC.nc +++ b/tos/lib/net/Deluge/DelugeC.nc @@ -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 diff --git a/tos/lib/net/Deluge/DelugeManagerP.nc b/tos/lib/net/Deluge/DelugeManagerP.nc index 342d8ca2..4a25388f 100644 --- a/tos/lib/net/Deluge/DelugeManagerP.nc +++ b/tos/lib/net/Deluge/DelugeManagerP.nc @@ -24,6 +24,8 @@ * @author Chieh-Jan Mike Liang */ +#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; diff --git a/tos/lib/net/Deluge/DelugeMetadataP.nc b/tos/lib/net/Deluge/DelugeMetadataP.nc index 6c2fa375..f10b3144 100644 --- a/tos/lib/net/Deluge/DelugeMetadataP.nc +++ b/tos/lib/net/Deluge/DelugeMetadataP.nc @@ -24,6 +24,8 @@ * @author Chieh-Jan Mike Liang */ +#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(), ¤tCrc, sizeof(currentCrc)); + call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, 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(), ¤tCrc, sizeof(currentCrc)); + call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, 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; } diff --git a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc index 56558c42..06420ce4 100644 --- a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc +++ b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc @@ -24,6 +24,8 @@ * @author Razvan Musaloiu-E. */ +#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 index 00000000..df3ca418 --- /dev/null +++ b/tos/lib/net/Deluge/ReprogramGuard.nc @@ -0,0 +1,5 @@ +interface ReprogramGuard +{ + command error_t okToProgram(); + event void okToProgramDone(bool ok); +} diff --git a/tos/lib/net/Deluge/extra/NetProgC.nc b/tos/lib/net/Deluge/extra/NetProgC.nc index 8a4c6c12..462ff7da 100644 --- a/tos/lib/net/Deluge/extra/NetProgC.nc +++ b/tos/lib/net/Deluge/extra/NetProgC.nc @@ -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; diff --git a/tos/lib/net/Deluge/extra/NetProgM.nc b/tos/lib/net/Deluge/extra/NetProgM.nc index 478bad26..7567ad1a 100644 --- a/tos/lib/net/Deluge/extra/NetProgM.nc +++ b/tos/lib/net/Deluge/extra/NetProgM.nc @@ -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 index 00000000..9f25e503 --- /dev/null +++ b/tos/lib/net/Deluge/extra/micaz/ReprogramGuardC.nc @@ -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 index 00000000..c5dc0c89 --- /dev/null +++ b/tos/lib/net/Deluge/extra/micaz/ReprogramGuardP.nc @@ -0,0 +1,23 @@ +module ReprogramGuardP +{ + provides interface ReprogramGuard; + uses interface Read 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 index 00000000..9f25e503 --- /dev/null +++ b/tos/lib/net/Deluge/extra/telosb/ReprogramGuardC.nc @@ -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 index 00000000..1ffb1e9a --- /dev/null +++ b/tos/lib/net/Deluge/extra/telosb/ReprogramGuardP.nc @@ -0,0 +1,23 @@ +module ReprogramGuardP +{ + provides interface ReprogramGuard; + uses interface Read 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 index 00000000..0c3170ba --- /dev/null +++ b/tos/lib/net/Deluge/imgNum2volumeId.h @@ -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 diff --git a/tos/lib/tosboot/micaz/hardware.h b/tos/lib/tosboot/micaz/hardware.h index 8f7a1c7f..01fc2d1d 100644 --- a/tos/lib/tosboot/micaz/hardware.h +++ b/tos/lib/tosboot/micaz/hardware.h @@ -80,8 +80,16 @@ 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 -- 2.39.2