From: razvanm Date: Mon, 14 Jan 2008 04:22:01 +0000 (+0000) Subject: Super Duper update to Deluge T2. The manual and the testing scripts are temporary... X-Git-Tag: release_tinyos_2_1_0_0~608 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=e014c5d251e1706ee383c01597ed49173c00c8f3 Super Duper update to Deluge T2. The manual and the testing scripts are temporary out-of-date. Some of the improvements are: - simplified images (ident and metadata were merged) - network-order representation of fields - new version of tinyos.py - improved sharing of volumes. --- diff --git a/support/make/bnp.extra b/support/make/bnp.extra index c4f5b4c9..3270fb01 100644 --- a/support/make/bnp.extra +++ b/support/make/bnp.extra @@ -8,7 +8,7 @@ TOSBOOT_DIR ?= $(TOSDIR)/lib/tosboot/build ifeq ($(TINYOS_NP),BNP) CFLAGS += -DDELUGE - CFLAGS += -I$(TOSDIR)/lib/net -I$(TOSDIR)/lib/net/drip -I$(DELUGE_DIR) -I$(DELUGE_DIR)/FlashVolumeManager + CFLAGS += -I$(TOSDIR)/lib/net -I$(TOSDIR)/lib/net/drip -I$(DELUGE_DIR) -I$(DELUGE_DIR)/FlashVolumeManager -I$(DELUGE_DIR)/BlockStorageManager ifneq ($(filter telosb tmote,$(TARGETS)),) CFLAGS += -I$(DELUGE_EXTRA) -I$(DELUGE_EXTRA)/msp430 -I$(DELUGE_EXTRA)/telos -I$(DELUGE_EXTRA)/telosb diff --git a/tools/tinyos/misc/tinyos.py b/tools/tinyos/misc/tinyos.py index cf521e5f..c33a8dbe 100644 --- a/tools/tinyos/misc/tinyos.py +++ b/tools/tinyos/misc/tinyos.py @@ -1,33 +1,31 @@ -import struct, time, serial, socket - -# Copyright (c) 2007 Johns Hopkins University. -# All rights reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose, without fee, and without written -# agreement is hereby granted, provided that the above copyright -# notice, the (updated) modification history and the author appear in -# all copies of this source code. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, -# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. - -# @author Chieh-Jan Mike Liang -# @author Razvan Musaloiu-E. - -############################################################################### -# TinyOS 2 Python Serial Module -############################################################################### +"""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 @@ -40,33 +38,37 @@ class Serial: SERIAL_PROTO_PACKET_ACK = 68 SERIAL_PROTO_PACKET_NOACK = 69 SERIAL_PROTO_PACKET_UNKNOWN = 255 + + _debug = False # Debug mode - __s = None # An instance of serial.Serial object - __debug = False # Debug mode - - __baud_rate = {} - - def __init__(self, port, baudrate): - __baud_rate = {'telos': 115200, 'telosb': 115200, - 'tmote': 115200, 'micaz': 57600, - 'mica2': 57600, 'mica2dot': 19200, - 'eyes': 115200, 'intelmote2': 115200} - - # Converts baud rate from platform name to value, if necessary - try: - baudrate = int(baudrate) - except: - baudrate = __baud_rate.get(baudrate) - - if not baudrate == None: - self.__s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5) + 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: - raise ValueError, 'Invalid baud rate' - - def __format_packet(self, packet): - return " ".join(["%02x" % p for p in packet]) + " | " + \ - " ".join(["%d" % p for p in packet]) - + 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: @@ -79,32 +81,33 @@ class Serial: crc = crc & 0xffff return crc - def __encode(self, val, dim): + def _encode(self, val, dim): output = [] for i in range(dim): output.append(val & 0xFF) val = val >> 8 return output - def __decode(self, v): + def _decode(self, v): r = long(0) for i in v[::-1]: r = (r << 8) + i return r - def __get_byte(self): + def _get_byte(self): try: - r = struct.unpack("B", self.__s.read())[0] + 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): + def _put_bytes(self, data): + #print "DEBUG: _put_bytes:", data for b in data: - self.__s.write(struct.pack('B', b)) + self._s.write(struct.pack('B', b)) - def __unescape(self, packet): + def _unescape(self, packet): r = [] esc = False for b in packet: @@ -117,7 +120,7 @@ class Serial: r.append(b) return r - def __escape(self, packet): + def _escape(self, packet): r = [] for b in packet: if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE: @@ -128,101 +131,126 @@ class Serial: return r # Returns the next incoming serial packet - def sniff_packet(self): + 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() + d = self._get_byte() ts = time.time() while d != self.HDLC_FLAG_BYTE: - d = self.__get_byte() + d = self._get_byte() ts = time.time() packet = [d] - d = self.__get_byte() + d = self._get_byte() if d == self.HDLC_FLAG_BYTE: - d = self.__get_byte() + d = self._get_byte() ts = time.time() else: packet.append(d) while d != self.HDLC_FLAG_BYTE: - d = self.__get_byte() + d = self._get_byte() packet.append(d) - un_packet = self.__unescape(packet) + if self._debug == True: + print "sniff: unescaped", packet + packet = self._unescape(packet) - crc = self.crc16(0, un_packet[1:-3]) - packet_crc = self.__decode(un_packet[-3:-1]) + crc = self.crc16(0, packet[1:-3]) + packet_crc = self._decode(packet[-3:-1]) - if self.__debug == True: + if self._debug: if crc != packet_crc: - print "Warning: wrong CRC!" - print "Recv:", self.__format_packet(un_packet) - return (ts, un_packet) + 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 - - # Filters and returns the next incoming serial packet with - # specified AM group ID and AM ID - def read_packet(self, am_group, am_id): - packet = None + + def sniff_am(self, skip_queue = False, timeout=0): + """Wait for a packet and return it as a ActiveMessage.""" - while True: - packet = self.sniff_packet() - if not packet == None and len(packet[1]) >= 10: - if (packet[1])[8] == am_group and (packet[1])[9] == am_id: - break - - return packet + 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_packet(self, am_group, am_id, data, num_tries=10): + 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): - # The first byte after SERIAL_PROTO_PACKET_ACK is a sequence - # number that will be send back by the mote to ack the receive of - # the data. - packet = [self.SERIAL_PROTO_PACKET_ACK, 0, self.TOS_SERIAL_ACTIVE_MESSAGE_ID, - 0xff, 0xff, - 0, 0, - len(data), am_group, am_id] + data - 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] - - self.__put_bytes(packet) - if self.__debug == True: - print "Send:", self.__format_packet(packet) + self._put_bytes(packet) + if self._debug == True: + print "Send:", packet # Waits for ACK for j in range(3): - while True: - packet = self.sniff_packet() - if packet == None: - break - elif (packet[1])[1] == self.SERIAL_PROTO_ACK: + 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) - # Debug messages - if self.__debug == True: - if i == (num_tries - 1): - print "Failed to send the packet!" - else: - print "Timeout waiting for ACK... Retry" - return False - # Sets whether debugging message will in this module will be printed - def set_debug(self, debug): - self.__debug = debug + def debug(self, debug): + self._debug = debug + + class GenericPacket: """ GenericPacket """ - def __decode(self, v): + def _decode(self, v): r = long(0) for i in v: r = (r << 8) + i return r - def __encode(self, val, dim): + def _encode(self, val, dim): output = [] for i in range(dim): output.append(int(val & 0xFF)) @@ -231,21 +259,44 @@ class GenericPacket: 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'] = [] - offset = 10 if type(packet) == type([]): for (t, s) in self._schema: if t == 'int': - self._values.append(self.__decode(packet[offset:offset + s])) + 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< 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:-3]) + self._values.append(packet[offset:]) elif type(packet) == type(()): for i in packet: self._values.append(i) @@ -257,7 +308,13 @@ class GenericPacket: return self._values.__repr__() def __str__(self): - return self._values.__str__() + 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): @@ -277,6 +334,7 @@ class GenericPacket: # Implement the struct behavior def __getattr__(self, name): + #print "DEBUG: __getattr__", name if type(name) == type(0): return self._names[name] else: @@ -288,6 +346,21 @@ class GenericPacket: 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 @@ -297,10 +370,90 @@ class GenericPacket: 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) - else: + 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) + diff --git a/tools/tinyos/misc/tos-build-deluge-image b/tools/tinyos/misc/tos-build-deluge-image index 1219fa46..08542401 100755 --- a/tools/tinyos/misc/tos-build-deluge-image +++ b/tools/tinyos/misc/tos-build-deluge-image @@ -31,7 +31,6 @@ DELUGE_PKT_PAYLOAD_SIZE = 23 DELUGE_BYTES_PER_PAGE = DELUGE_PKTS_PER_PAGE * DELUGE_PKT_PAYLOAD_SIZE DELUGE_MAX_PAGES = 128 -DELUGE_METADATA_SIZE = 16 DELUGE_IDENT_SIZE = 128 def sencode(s, dim): @@ -40,19 +39,15 @@ def sencode(s, dim): return s[:dim] return s + [0] * (dim - len(s)) +# Encode to big endian def encode(val, dim): output = [] for i in range(dim): output.append(val & 0xFF) val = val >> 8 + output.reverse() return output -def decode(v): - r = long(0) - for i in v[::-1]: - r = (r << 8) + i - return r - def int2byte(v): return "".join([struct.pack("B", i) for i in v]) @@ -69,8 +64,11 @@ def crc16(data): return crc def pages(data): - return (len(data) / DELUGE_BYTES_PER_PAGE) + \ - (len(data) % DELUGE_BYTES_PER_PAGE != 0) + l = len(data) - 2*DELUGE_MAX_PAGES + if l % DELUGE_BYTES_PER_PAGE != 0: + sys.stderr.write("ERROR: Bug in padding!") + sys.exit() + return l / DELUGE_BYTES_PER_PAGE def align(data): mod = len(data) % DELUGE_BYTES_PER_PAGE @@ -78,50 +76,35 @@ def align(data): return data return data + [0] * (DELUGE_BYTES_PER_PAGE - mod) -def deluge_metadata(data, img_num): - uid = ident['uid_hash'] - num_pages = pages(data) - image_number = img_num - crc = crc16([image_number] + [num_pages]) - completed_pages = num_pages - return encode(uid, 4) + \ - encode(version, 2) + \ - [image_number] + \ - [num_pages] + \ - encode(crc, 2) + \ - [completed_pages] + \ - [0] + \ - encode(len(data) + 16, 2) + \ - ([0] * 2) - -def deluge_ident(): - tmp = sencode(ident['program_name'], 16) + \ - sencode(ident['user_id'], 16) + \ - sencode(ident['hostname'], 16) + \ - sencode(ident['platform'], 16) + \ +def deluge_ident(data): + tmp = encode(ident['uidhash'], 4) + \ encode(ident['size'], 4) + \ - encode(ident['unix_time'], 4) + \ - encode(ident['user_hash'], 4) + \ - encode(ident['uid_hash'], 4) + [pages(data), 0] + crc = crc16(tmp) + tmp += encode(crc, 2) + \ + sencode(ident['appname'], 16) + \ + sencode(ident['username'], 16) + \ + sencode(ident['hostname'], 16) + \ + sencode(ident['platform'], 16) + \ + encode(ident['timestamp'], 4) + \ + encode(ident['userhash'], 4) return tmp + [0] * (DELUGE_IDENT_SIZE - len(tmp)) def deluge_crc(data): crc = [0] * DELUGE_MAX_PAGES - crc[0] = crc16(data[2*DELUGE_MAX_PAGES:DELUGE_BYTES_PER_PAGE]) - #sys.stderr.write("crc[0] = 0x%x\n" % (crc[0])) - j = 1 - for i in range(DELUGE_BYTES_PER_PAGE, len(data)-1, DELUGE_BYTES_PER_PAGE): + j = 0 + sys.stderr.write("CRCs:\n ") + for i in range(0, len(data)-1, DELUGE_BYTES_PER_PAGE): crc[j] = crc16(data[i:i+DELUGE_BYTES_PER_PAGE]) - #sys.stderr.write("crc[%d] = 0x%x\n" % (j, crc[j])) + sys.stderr.write("0x%04X " % (crc[j])) + if (j + 1) % 7 == 0: + sys.stderr.write("\n ") j += 1 - return reduce(operator.add, [encode(i, 2) for i in crc]) + data[2*DELUGE_MAX_PAGES:] - -version = 0 + sys.stderr.write("\n") + return reduce(operator.add, [encode(i, 2) for i in crc]) + data for i in range(len(sys.argv)): - if sys.argv[i] == '-v': - version = int(sys.argv[i+1]) - elif sys.argv[i] == '-i': + if sys.argv[i] == '-i': img_num = int(sys.argv[i+1]) dom = parse(sys.argv[-1]) @@ -130,7 +113,7 @@ ident_list = [(n.localName, n.firstChild.nodeValue) for n in dom.getElementsByTagName('ident')[0].childNodes if n.localName != None] for (k, v) in ident_list: ident[k] = v -for p in ['unix_time', 'user_hash', 'uid_hash']: +for p in ['timestamp', 'userhash', 'uidhash']: ident[p] = int(ident[p][:-1], 16) error = "ERROR: getting the image from the XML file failed." @@ -178,8 +161,9 @@ for line in image.split(): start_addr = addr sys.stderr.write('Ihex read complete:\n') -sys.stderr.write(' Total bytes = %d\n' % reduce(operator.add, [len(l) for (_, l) in all])) -sys.stderr.write(' Sections = %d\n' % len(all)) +sys.stderr.write(' ' + '\n '.join(["%5d bytes starting at 0x%X" % (len(l), a) for (a, l) in all])) +sys.stderr.write('\n') +sys.stderr.write(' %d bytes in %d sections\n' % (reduce(operator.add, [len(l) for (_, l) in all]), len(all))) # Usually, there are two sections: one for the code and one for the # interrupt vector. @@ -189,10 +173,10 @@ for (addr, data) in all: all_data += encode(addr, 4) + \ encode(len(data), 4) + \ data -ident['size'] = len(all_data) -all_data = deluge_ident() + all_data -all_data = align([0] * 2 * DELUGE_MAX_PAGES + all_data) +padding = [0] * (DELUGE_BYTES_PER_PAGE - len(all_data) % DELUGE_BYTES_PER_PAGE) +if len(padding) < DELUGE_BYTES_PER_PAGE: + all_data += padding all_data = deluge_crc(all_data) -sys.stdout.write(int2byte(deluge_metadata(all_data, img_num)) + \ - int2byte(all_data)) +ident['size'] = DELUGE_IDENT_SIZE + len(all_data) +sys.stdout.write(int2byte(deluge_ident(all_data)) + int2byte(all_data)) diff --git a/tools/tinyos/misc/tos-deluge b/tools/tinyos/misc/tos-deluge index 5c593b97..88e6dccb 100755 --- a/tools/tinyos/misc/tos-deluge +++ b/tools/tinyos/misc/tos-deluge @@ -1,81 +1,60 @@ #!/usr/bin/env python -# Copyright (c) 2007 Johns Hopkins University. -# All rights reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose, without fee, and without written -# agreement is hereby granted, provided that the above copyright -# notice, the (updated) modification history and the author appear in -# all copies of this source code. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, -# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. - -# @author Chieh-Jan Mike Liang -# @author Razvan Musaloiu-E. - -############################################################################### -# Deluge Python Toolchain -# -# A command line utility to interact with nodes via a direct serial connection. -# For the usage menu, please run this tool without any arguments. For example, -# "./tos-deluge" -############################################################################### - -import sys, os, stat, struct, subprocess, time +import sys, stat, struct, subprocess, time import tinyos from datetime import datetime import os.path -# Script-specific parameters -HEX_OUTPUT_LINE_SIZE = 16 # Path to the python script that builds Deluge image from XML -PATH_PY_BUILD_IMAGE = os.path.join(os.path.dirname(sys.argv[0]), 'tos-build-deluge-image') +PATH_PY_BUILD_IMAGE = './tos-build-deluge-image' # TinyOS serial communication parameters -SERIAL_AMGROUP = 0 -SERIAL_AMID = 0xAB +FM_AMID = 0xAB +DM_AMID = 0xAC SERIAL_DATA_LENGTH = 28 - 1 - 1 - 2 - 2 - -# Serial message types -MSG_ERASE = 0 -MSG_WRITE = 1 -MSG_READ = 2 -MSG_REPROG = 5 -MSG_DISS = 6 -MSG_REPROG_BS = 7 -MSG_SYNC = 8 -MSG_IDENT = 9 +BAUDRATES = {'micaz': 57600, + 'telosb': 115200} + +# Commands for FlashManager +FM_CMD_ERASE = 0 +FM_CMD_WRITE = 1 +FM_CMD_READ = 2 +FM_CMD_CRC = 3 +FM_CMD_ADDR = 4 +FM_CMD_SYNC = 5 +FM_CMD_IDENT = 6 + +# Commands for DelugeManager +DM_CMD_STOP = 1 +DM_CMD_LOCAL_STOP = 2 +DM_CMD_ONLY_DISSEMINATE = 3 +DM_CMD_DISSEMINATE_AND_REPROGRAM = 4 +DM_CMD_REPROGRAM = 5 +DM_CMD_BOOT = 6 ERROR_SUCCESS = 0 # T2-compatible ERROR_FAIL = 1 # T2-compatible -# Deluge-specific parameters -DELUGE_PLATFORMS = ["telosb", "micaz"] # Currently supported platforms -DELUGE_MAX_PAGES = 128 -DELUGE_METADATA_OFFSET = 0 # Location offset in the image -DELUGE_METADATA_SIZE = 16 -DELUGE_IDENT_OFFSET = 16 + (2 * DELUGE_MAX_PAGES) -DELUGE_IDENT_SIZE = 16 + 16 + 16 + 16 + 4 + 4 + 4 + 4 # Metadata size in binary - # image +# Deluge parameters +DELUGE_MAX_PAGES = 128 +DELUGE_IDENT_OFFSET = 0 +DELUGE_IDENT_SIZE = 128 + +class FMReqPacket(tinyos.GenericPacket): + 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 SerialReqPacket(tinyos.GenericPacket): +class DMReqPacket(tinyos.GenericPacket): def __init__(self, packet = None): tinyos.GenericPacket.__init__(self, - [('msg_type', 'int', 1), - ('img_num', 'int', 1), - ('offset', 'int', 2), - ('len', 'int', 2), - ('data', 'blob', None)], + [('cmd', 'int', 1), + ('imgNum', 'int', 1)], packet) class SerialReplyPacket(tinyos.GenericPacket): @@ -85,18 +64,31 @@ class SerialReplyPacket(tinyos.GenericPacket): ('data', 'blob', None)], packet) -# Displays an integer representation of byte stream to hex representation -def print_hex(start_addr, byte_stream): - num_iterations = int( (len(byte_stream) - 1) / HEX_OUTPUT_LINE_SIZE ) + 1 - - for i in range(num_iterations): - line = "%07x" % start_addr + " " # Prints memory address - for j in range(HEX_OUTPUT_LINE_SIZE): - if (i * HEX_OUTPUT_LINE_SIZE + j) < len(byte_stream): - line += "%02x" % byte_stream[i * HEX_OUTPUT_LINE_SIZE + j] + " " - print line - - start_addr += HEX_OUTPUT_LINE_SIZE +class Ident(tinyos.GenericPacket): + 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): + def __init__(self, packet = None): + tinyos.GenericPacket.__init__(self, + [('appname', 'string', 16), + ('timestamp','int', 4), + ('uidhash', 'int', 4), + ('nodeid', 'int', 2)], + packet) + # Computes 16-bit CRC def crc16(data): @@ -112,68 +104,45 @@ def crc16(data): return crc -# Converts a byte-stream array to int representation -def toInt(byte_stream): - r = long(0) - for i in byte_stream[::-1]: - r = (r << 8) + i - - return r - -# Converts a byte-stream array to string representation -def toString(byte_stream): - r = "" - for i in range(len(byte_stream)): - if byte_stream[i] == 0: - r += " " +def handleResponse(success, msg): + if success == True: + packet = s.sniff_am() + while packet and packet.type == 100: + print "".join([chr(i) for i in p.data]) + packet = s.sniff_am() + reply = SerialReplyPacket(packet.data) + if reply.error == ERROR_SUCCESS: + print reply + return True else: - r += struct.pack("B", byte_stream[i]) - - return r + print msg, reply + return False + + print "ERROR: Unable to send the command" + return False -# Converts a byte-stream array to image status string representation -def toStatusStr(num_space, binary_stream): - r = "%sProg Name: %s\n" % (" " * num_space, - toString(binary_stream[16:32])) - r += "%sCompiled On: %s\n" % (" " * num_space, - datetime.fromtimestamp(toInt(binary_stream[84:88])).strftime('%a %h %d %T %Y')) - r += "%sPlatform: %s\n" % (" " * num_space, - toString(binary_stream[64:80])) - r += "%sUser ID: %s\n" % (" " * num_space, - toString(binary_stream[32:48])) - r += "%sHost Name: %s\n" % (" " * num_space, - toString(binary_stream[48:64])) - r += "%sUser Hash: %s\n" % (" " * num_space, - hex(toInt(binary_stream[88:92]))) - r += "%sNum Pages: %d/%d" % (" " * num_space, - toInt(binary_stream[7:8]), - toInt(binary_stream[10:11])) - - r += "\n\n" - r += "%sSize: %d\n" % (" " * num_space, - toInt(binary_stream[12:14])) - r += "%sUID: %d\n" % (" " * num_space, - toInt(binary_stream[0:4])) - r += "%sVersion: %d" % (" " * num_space, - toInt(binary_stream[4:6])) - - return r +def ident(): + sreqpkt = FMReqPacket((FM_CMD_IDENT, 0, 0, 0, [])) + if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)): + packet = s.sniff_am() + reply = SerialReplyPacket(packet.data) + if reply.error == ERROR_SUCCESS: + return ShortIdent(reply.data) + return 0 -# Reads a portion from the image in the external flash -def op_read(s, img_num, offset, length): +def read(imgNum, offset, length): r = [] - # Gets the metadata (first 16 bytes of the image) - sreqpkt = SerialReqPacket((MSG_READ, img_num, offset, length, [])) + sreqpkt = FMReqPacket((FM_CMD_READ, imgNum, offset, length, [])) while True: - if sreqpkt['len'] > SERIAL_DATA_LENGTH: - sreqpkt['len'] = SERIAL_DATA_LENGTH + if sreqpkt.length > SERIAL_DATA_LENGTH: + sreqpkt.length = SERIAL_DATA_LENGTH - if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()): - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - r.extend(sreplypkt.data) + if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)): + packet = s.sniff_am() + reply = SerialReplyPacket(packet.data) + if reply.error == ERROR_SUCCESS: + r.extend(reply.data) else: r = None break @@ -181,104 +150,28 @@ def op_read(s, img_num, offset, length): r = None break - sreqpkt['offset'] = sreqpkt['offset'] + sreqpkt['len'] - if sreqpkt['offset'] >= (offset + length): + sreqpkt.offset += sreqpkt.length + if sreqpkt.offset >= (offset + length): break - sreqpkt['len'] = (offset + length) - sreqpkt['offset'] - - return r - -def op_ident(s): - sreqpkt = SerialReqPacket((MSG_IDENT, 0, 0, 0, [])) - if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()): - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return toInt(sreplypkt.data) - return 0 - -# Checks for valid CRC and image timestamp -def verifyMetaData(r): - if r != None: - if crc16(r[6:8]) == toInt(r[8:10]) and r[84:88] != [0xFF, 0xFF, 0xFF, 0xFF]: - return True - else: - print "WARNING: Invalid image format detected" - - return False + sreqpkt.length = (offset + length) - sreqpkt.offset -# Returns the metadata (first 16 bytes of the image) plus the "ident" -# (DELUGE_IDENT_SIZE bytes after CRC) -def getMetaData(s, img_num): - # Gets the metadata (first 16 bytes of the image) - r = op_read(s, img_num, DELUGE_METADATA_OFFSET, DELUGE_METADATA_SIZE) - - # Gets the "ident" portion of the image - if r != None: - temp = op_read(s, img_num, DELUGE_IDENT_OFFSET, DELUGE_IDENT_SIZE) - if temp != None: - r.extend(temp) - return r - - print "ERROR: Unable to retrieve image information over serial" - return None - -# Prints status of the image in the external flash -def op_ping(s, img_num): - uid = op_ident(s) - metadata = getMetaData(s, img_num) - if not metadata == None: - if verifyMetaData(metadata) == True: - print "Connected to Deluge node." - # Prints out image status - print "--------------------------------------------------" - print "Currently Executing:" - print " UID: %d" % (uid) - print "Stored image %d" % img_num - print toStatusStr(2, metadata) - print "--------------------------------------------------" - return True - - return False + return r -# Erases an image volume -def op_erase(s, img_num): - sreqpkt = SerialReqPacket((MSG_ERASE, img_num, 0, 0, [])) - success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) - if success == True: - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return True - else: - print "ERROR: Unable to erase the flash volume" - return False - - print "ERROR: Unable to send the command" - return False +def erase(imgNum): + sreqpkt = FMReqPacket((FM_CMD_ERASE, imgNum, 0, 0, [])) + success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)) + return handleResponse(success, "ERROR: Unable to erase the flash volume") -def op_sync(s, img_num): - sreqpkt = SerialReqPacket((MSG_SYNC, img_num, 0, 0, [])) - success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) - if success == True: - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return True - else: - print "ERROR: Unable to sync the flash volume" - return False - - print "ERROR: Unable to send the command" - return False +def sync(imgNum): + sreqpkt = FMReqPacket((FM_CMD_SYNC, imgNum, 0, 0, [])) + success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)) + return handleResponse(success, "ERROR: Unable to sync the flash volume") -# Writes to an image volume -def op_write(s, img_num, binary_stream): - sreqpkt = SerialReqPacket((MSG_WRITE, img_num, 0, 0, [])) - local_crc = 0 # Running CRC - length = len(binary_stream) +def write(imgNum, data): + sreqpkt = FMReqPacket((FM_CMD_WRITE, imgNum, 0, 0, [])) + length = len(data) total_length = length # For progress bar - next_tick = 100 # For progress bar + next_tick = 100 # For progress bar start_time = time.time() print "[0% 25% 50% 75% 100%]\r[", @@ -292,40 +185,70 @@ def op_write(s, img_num, binary_stream): # Calculates the payload size for the current packet if length >= SERIAL_DATA_LENGTH: - sreqpkt.len = SERIAL_DATA_LENGTH + sreqpkt.length = SERIAL_DATA_LENGTH else: - sreqpkt.len = length - sreqpkt.data = [] - - # Reads in the file we want to transmit - for i in range(sreqpkt.len): - sreqpkt.data.append(struct.unpack("B", binary_stream[sreqpkt.offset + i])[0]) + sreqpkt.length = length + sreqpkt.data = data[sreqpkt.offset:sreqpkt.offset+sreqpkt.length] # Sends over serial to the mote - if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) == False: + if not s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)): print print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset return False # Waiting for confirmation - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error != ERROR_SUCCESS: + packet = s.sniff_am() + reply = SerialReplyPacket(packet.data) + if reply.error != ERROR_SUCCESS: print print "ERROR: Unable to write to the flash volume (file offset: %d)" % sreqpkt.offset return False - local_crc = s.crc16(local_crc, sreqpkt.data) # Computes running CRC - length -= sreqpkt.len - sreqpkt.offset += sreqpkt.len + length -= sreqpkt.length + sreqpkt.offset += sreqpkt.length print '\r' + ' ' * 52, elasped_time = time.time() - start_time print "\r%s bytes in %.2f seconds (%.4f bytes/s)" % (total_length, elasped_time, int(total_length) / (elasped_time)) return True + +# Checks for valid CRC and timestamp +def verifyIdent(i): + if i != None: + if crc16(i.payload()[0:10]) == i.crc and i.timestamp != 0xFFFFFFFF: + return True + else: + print "No valid image was detected." + return False + +def getIdent(imgNum): + r = read(imgNum, DELUGE_IDENT_OFFSET, DELUGE_IDENT_SIZE) + if r: + return Ident(r) + print "ERROR: Unable to retrieve the ident." + return None + +def formatIdent(i): + r = " Prog Name: %s\n" % (i.appname) + r += " UID: 0x%08X\n" % (i.uidhash) + r += " Compiled On: %s\n" % (datetime.fromtimestamp(i.timestamp).strftime('%a %h %d %T %Y')) + r += " Platform: %s\n" % (i.platform) + r += " User ID: %s\n" % (i.username) + r += " Host Name: %s\n" % (i.hostname) + r += " User Hash: 0x%08X\n" % (i.userhash) + r += " Size: %d\n" % (i.size) + r += " Num Pages: %d" % (i.pages) + return r + +def formatShortIdent(i): + r = " Prog Name: %s\n" % (i.appname) + r += " UID: 0x%08X\n" % (i.uidhash) + r += " Compiled On: %s\n" % (datetime.fromtimestamp(i.timestamp).strftime('%a %h %d %T %Y')) + r += " Node ID: %d\n" % (i.nodeid) + return r # Injects an image (specified by tos_image_xml) to an image volume -def op_inject(s, img_num, tos_image_xml): +def inject(imgNum, tos_image_xml): # Checks for valid file path try: os.stat(tos_image_xml) # Checks whether tos_image_xml is a valid file @@ -339,171 +262,203 @@ def op_inject(s, img_num, tos_image_xml): return False # Gets status information of stored image - version = 0 - metadata = getMetaData(s, img_num) - if not metadata == None: + i = getIdent(imgNum) + if ident: print "Connected to Deluge nodes." - if verifyMetaData(metadata) == True: + if verifyIdent(i): print "--------------------------------------------------" - print "Stored image %d" % img_num - print toStatusStr(2, metadata) - version = toInt(metadata[4:6]) + 1 # Increments the version + print "Stored image %d" % imgNum + print formatIdent(i) else: return False - + # Creates binary image from the TOS image XML print "--------------------------------------------------" - p = subprocess.Popen([PATH_PY_BUILD_IMAGE, "-v", str(version), "-i", str(img_num), tos_image_xml], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + 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(), print "--------------------------------------------------" # Writes the new binary image - image = p.stdout.read() - if len(image) > 0 and op_erase(s, img_num): - if op_write(s, img_num, image): - if op_sync(s, img_num): + image = [struct.unpack("B", c)[0] for c in p.stdout.read()] + if len(image) > 0 and erase(imgNum): + if write(imgNum, image): + if sync(imgNum): + print "--------------------------------------------------" + print "Replace image with:" + print formatIdent(getIdent(imgNum)) print "--------------------------------------------------" - metadata = getMetaData(s, img_num) - if not metadata == None: - if verifyMetaData(metadata) == True: - print "Replace image with:" - print toStatusStr(2, metadata) - print "--------------------------------------------------" - return True return False -# Requests the base station to reprogram itself -def op_reprog_bs(s, img_num): - metadata = getMetaData(s, img_num) - if not metadata == None: - if verifyMetaData(metadata) == True: - sreqpkt = SerialReqPacket((MSG_REPROG_BS, img_num, 0, 0, [])) - success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) - if success == True: - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return True - else: - print "ERROR: Unable to reprogram the base station" - - print "ERROR: Unable to send the command" - +def ping(imgNum): + uid = ident() + # Prints out image status + print "--------------------------------------------------" + print "Currently Executing:" + print formatShortIdent(ident()) + i = getIdent(imgNum) + if verifyIdent(i): + print "Stored image %d" % imgNum + print formatIdent(i) + print "--------------------------------------------------" + return True + + print "--------------------------------------------------" return False -# Requests the network to reprogram with the specified image number -def op_reprog(s, img_num): - sreqpkt = SerialReqPacket((MSG_REPROG, img_num, 0, 0, [])) - success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) - if success == True: - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return True - else: - print "ERROR: Unable to reprogram the network" - return False - - print "ERROR: Unable to send the command" +def boot(): + sreqpkt = DMReqPacket((DM_CMD_BOOT, 0)) + success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID)) + return handleResponse(success, "ERROR: Unable to boot the mote") -# Requests the mote to disseminate an image -def op_diss(s, img_num): - metadata = getMetaData(s, img_num) - if not metadata == None: - if verifyMetaData(metadata) == True: - sreqpkt = SerialReqPacket((MSG_DISS, img_num, 0, 0, [])) - success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) - if success == True: - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error == ERROR_SUCCESS: - return True - else: - print "ERROR: Unable to start the command dissemination" - - print "ERROR: Unable to send the command" - - return False +def reprogram(imgNum): + sreqpkt = DMReqPacket((DM_CMD_REPROGRAM, imgNum)) + success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID)) + return handleResponse(success, "ERROR: Unable to reprogram the mote") -# Resets image versioning information -def op_reset(s, img_num): - sreqpkt = SerialReqPacket((MSG_WRITE, img_num, 4, 2, [0, 0])) - if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) == False: - print "ERROR: Unable to send the command" - return False - - # Waiting for confirmation - packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID) - sreplypkt = SerialReplyPacket(packet[1]) - if sreplypkt.error != ERROR_SUCCESS: - print "ERROR: Unable to write new versioning information" - return False - else: - if op_sync(s, img_num) == False: - return False - - return True +def disseminate(imgNum): + sreqpkt = DMReqPacket((DM_CMD_ONLY_DISSEMINATE, imgNum)) + success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=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)) + 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)) + 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)) + return handleResponse(success, "ERROR: Unable to initiate the local stop") def print_usage(): print "Usage: %s <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0] - print " \n Either the platform name or the baud rate value" - print " -------------------" - print " | micaz | 57600 |" - print " ---------+---------" - print " | telosb | 115200 |" - print " -------------------" - print "" - print " -p --ping\n Provide status of the image in the external flash" - print " -i --inject\n Inject a compiled TinyOS application" - print " [options]: tos_image.xml file path" - print " -r --reprogram\n Reprogram the network" - print " -b --reprogram_bs\n Reprogram only the directly-connected mote" - print " -d --dissemination\n Disseminate the image in the external flash to the network" - print " -e --erase\n Erase an image in the external flash" - print " -s --reset\n Reset the versioning information for a given image" - -# ======== MAIN ======== # -num_req_arg = 5 # Minimum number of required arguments for this script -if len(sys.argv) >= num_req_arg: + print " Either the platform name (micaz or telosv) or a baudrate value" + print " -p --ping Provide status of the image in the external flash" + print " -i --inject Inject a compiled TinyOS application" + print " [options]: tos_image.xml file path" + print " -e --erase Erase an image in the external flash" + print " -b --boot Force a reboot of the mote" + print " -r --reprogram Reprogram the mote" + print " -d --disseminate Disseminate the image in the external flash to the network" + print " -dr --disseminate-and-reprogram" + print " -s --stop Stop the dissemination " + print " -ls --local-stop Stop the dissemination only on the local mote" + +# print " -b --reprogram_bs\n Reprogram only the directly-connected mote" +# print " -s --reset\n Reset the versioning information for a given image" + +def checkImgNum(): + global imgNum # Checks for valid image number format try: - sys.argv[4] = int(sys.argv[4]) + imgNum = int(sys.argv[4]) except: print "ERROR: Image number is not valid" - os._exit(-1) - + sys.exit(-1) + return imgNum + +# ======== MAIN ======== # +if len(sys.argv) >= 4: + + if sys.argv[2] in BAUDRATES: + baudrate = BAUDRATES[sys.argv[2]] + else: + try: + baudrate = int(sys.argv[2]) + except: + print "ERROR: Wrong baudrate" + sys.exit(-1) + # Initializes serial port communication try: - s = tinyos.Serial(sys.argv[1], sys.argv[2]) - s.set_debug(False) + s = tinyos.Serial(sys.argv[1], baudrate, flush=False) except: print "ERROR: Unable to initialize serial port connection to", sys.argv[1] - os._exit(-1) - + sys.exit(-1) + if sys.argv[3] in ["-p", "--ping"]: + checkImgNum() print "Pinging node ..." - op_ping(s, sys.argv[4]) - elif sys.argv[3] in ["-i", "--inject"] and len(sys.argv) == (num_req_arg + 1): + ping(imgNum) + elif sys.argv[3] in ["-i", "--inject"] and len(sys.argv) == 6: + checkImgNum() print "Pinging node ..." - op_inject(s, sys.argv[4], sys.argv[5]) + inject(imgNum, sys.argv[5]) + elif sys.argv[3] in ["-e", "--erase"]: + checkImgNum() + if erase(imgNum): + print "Image number %d erased" % imgNum + elif sys.argv[3] in ["-b", "--boot"]: + if boot(): + print "Command sent" elif sys.argv[3] in ["-r", "--reprogram"]: - if op_reprog(s, sys.argv[4]): + checkImgNum() + if reprogram(imgNum): print "Command sent" - elif sys.argv[3] in ["-b", "--reprogram_bs"]: - if op_reprog_bs(s, sys.argv[4]): + elif sys.argv[3] in ["-d", "--disseminate"]: + checkImgNum() + if disseminate(imgNum): print "Command sent" - elif sys.argv[3] in ["-d", "--dissemination"]: - if op_diss(s, sys.argv[4]): + elif sys.argv[3] in ["-dr", "--disseminate-and-reboot"]: + checkImgNum() + if disseminateAndReboot(imgNum): print "Command sent" - elif sys.argv[3] in ["-e", "--erase"]: - if op_erase(s, sys.argv[4]): - print "Image number %d erased" % sys.argv[4] - elif sys.argv[3] in ["-s", "--reset"]: - if op_reset(s, sys.argv[4]): - print "Successfully reset image versioning information" + elif sys.argv[3] in ["-s", "--stop"]: + if stop(): + print "Command sent" + elif sys.argv[3] in ["-ls", "--local-stop"]: + if localstop(): + print "Command sent" + + +# elif sys.argv[3] in ["-b", "--reprogram_bs"]: +# if op_reprog_bs(imgNum): +# print "Command sent" +# elif sys.argv[3] in ["-s", "--reset"]: +# if op_reset(imgNum): +# print "Successfully reset image versioning information" else: print_usage() else: print_usage() + +sys.exit() + +# Testing ------------------------------------------------------------ + +s = tinyos.Serial('/dev/ttyUSB0', 115200, flush=False) +# print "ident: 0x%x" % ident() +# r = read(0, 0, 10) +# print "read:", len(r), r + +# erase(0) +# write(0, [i % 256 for i in range(20*1024)]) +# r = read(0, 0, 10) +# print "read:", len(r), r + +# inject(0, 'build/telosb/tos_image.xml') +ping(0) + +# print formatDescription(getMetadata(0), getIdent(0)) +# print getMetadata(0) +# print getIdent(0) + +# print verifyDescription(getMetadata(0), getIdent(0)) + +# print formatShortIdent(ident()) + +# def encode(val, dim): +# output = [] +# for i in range(dim): +# output.append(val & 0xFF) +# val = val >> 8 +# return output diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockReaderC.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockReaderC.nc new file mode 100644 index 00000000..ad0a4e18 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockReaderC.nc @@ -0,0 +1,51 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "BlockStorageManager.h" +#include "Storage.h" + +generic configuration BlockReaderC(volume_id_t id) +{ + provides { + interface BlockRead; + interface Resource; + } +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_BSTORAGEM_CLIENT) + }; + + components new VolumeIdC(id); + components BlockStorageManagerC; + components new BlockStorageLockClientC(); + + BlockRead = BlockStorageManagerC.BlockRead[CLIENT_ID]; + Resource = BlockStorageLockClientC; + BlockStorageManagerC.VolumeId[CLIENT_ID] -> VolumeIdC; +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockC.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockC.nc new file mode 100644 index 00000000..fe0fef84 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration BlockStorageLockC +{ + provides { + interface Resource[uint8_t client]; + interface ArbiterInfo; + } +} + +implementation +{ + components new SimpleFcfsArbiterC(UQ_BSTORAGEL_CLIENT) as Arbiter; + Resource = Arbiter; + ArbiterInfo = Arbiter; +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockClientC.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockClientC.nc new file mode 100644 index 00000000..2e2598f8 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageLockClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration BlockStorageLockClientC() +{ + provides interface Resource; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_BSTORAGEL_CLIENT) + }; + + components BlockStorageLockC; + Resource = BlockStorageLockC.Resource[CLIENT_ID]; +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManager.h b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManager.h new file mode 100644 index 00000000..2ac9188f --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManager.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#ifndef BLOCK_STORAGE_MANAGER_H +#define BLOCK_STORAGE_MANAGER_H + +#define UQ_BSTORAGEM_CLIENT "BlockStorageManager.client" +#define UQ_BSTORAGEL_CLIENT "BlockStorageLock.client" + +#endif diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerC.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerC.nc new file mode 100644 index 00000000..49c4093d --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerC.nc @@ -0,0 +1,76 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "BlockStorageManager.h" + +configuration BlockStorageManagerC +{ + provides { + interface BlockRead[uint8_t client]; + interface BlockWrite[uint8_t client]; + interface StorageMap[uint8_t volume_id]; + } + uses interface VolumeId[uint8_t client]; +} + +implementation +{ + enum { + NUM_CLIENTS = uniqueCount(UQ_BSTORAGEM_CLIENT) + }; + + components new BlockStorageManagerP(NUM_CLIENTS); + + BlockRead = BlockStorageManagerP; + BlockWrite = BlockStorageManagerP; + VolumeId = BlockStorageManagerP; + StorageMap = BlockStorageManagerP; + + components new BlockStorageC(VOLUME_GOLDENIMAGE) as BlockStorageC_Golden; + components new BlockStorageC(VOLUME_DELUGE1) as BlockStorageC_1; + components new BlockStorageC(VOLUME_DELUGE2) as BlockStorageC_2; + components new BlockStorageC(VOLUME_DELUGE3) as BlockStorageC_3; + + BlockStorageManagerP.SubBlockRead[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; + BlockStorageManagerP.SubBlockRead[VOLUME_DELUGE1] -> BlockStorageC_1; + BlockStorageManagerP.SubBlockRead[VOLUME_DELUGE2] -> BlockStorageC_2; + BlockStorageManagerP.SubBlockRead[VOLUME_DELUGE3] -> BlockStorageC_3; + + BlockStorageManagerP.SubBlockWrite[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; + BlockStorageManagerP.SubBlockWrite[VOLUME_DELUGE1] -> BlockStorageC_1; + BlockStorageManagerP.SubBlockWrite[VOLUME_DELUGE2] -> BlockStorageC_2; + BlockStorageManagerP.SubBlockWrite[VOLUME_DELUGE3] -> BlockStorageC_3; + +#if defined(PLATFORM_TELOSB) + BlockStorageManagerP.SubStorageMap[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; + BlockStorageManagerP.SubStorageMap[VOLUME_DELUGE1] -> BlockStorageC_1; + BlockStorageManagerP.SubStorageMap[VOLUME_DELUGE2] -> BlockStorageC_2; + BlockStorageManagerP.SubStorageMap[VOLUME_DELUGE3] -> BlockStorageC_3; +#elif defined(PLATFORM_MICAZ) + components StorageMapperAt45dbC; + BlockStorageManagerP.At45dbVolume = At45dbStorageManagerC; +#endif +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerP.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerP.nc new file mode 100644 index 00000000..7a7cefb7 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockStorageManagerP.nc @@ -0,0 +1,212 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic module BlockStorageManagerP(uint8_t clients) +{ + provides { + interface BlockRead[uint8_t client]; + interface BlockWrite[uint8_t client]; + interface StorageMap[uint8_t volume_id]; + } + uses { + interface BlockRead as SubBlockRead[volume_id_t volume_id]; + interface BlockWrite as SubBlockWrite[volume_id_t volume_id]; + interface VolumeId[uint8_t client]; +#if defined(PLATFORM_TELOSB) + interface StorageMap as SubStorageMap[volume_id_t volume_id]; +#elif defined(PLATFORM_MICAZ) + interface At45dbVolume[volume_id_t volume_id]; +#endif + } +} + +implementation +{ + enum { + S_READY, + S_BUSY + }; + + uint8_t state = S_READY; + uint8_t current_client; + + /* BlockRead **************************/ + command error_t BlockRead.read[uint8_t client](storage_addr_t addr, void* buf, storage_len_t len) + { + error_t error; + if (state != S_READY) { + return EBUSY; + } + error = call SubBlockRead.read[call VolumeId.get[client]()](addr, buf, len); + if (error == SUCCESS) + { + state = S_BUSY; + current_client = client; + return SUCCESS; + } + return error; + } + + command error_t BlockRead.computeCrc[uint8_t client](storage_addr_t addr, storage_len_t len, uint16_t crc) + { + error_t error; + if (state != S_READY) { + return EBUSY; + } + error = call SubBlockRead.computeCrc[call VolumeId.get[client]()](addr, len, crc); + if (error == SUCCESS) + { + state = S_BUSY; + current_client = client; + return SUCCESS; + } + return error; + } + + command storage_len_t BlockRead.getSize[uint8_t client]() + { + return call SubBlockRead.getSize[client](); + } + + event void SubBlockRead.readDone[volume_id_t volume_id](storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + state = S_READY; + signal BlockRead.readDone[current_client](addr, buf, len, error); + } + + event void SubBlockRead.computeCrcDone[volume_id_t volume_id](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) + { + state = S_READY; + signal BlockRead.computeCrcDone[current_client](addr, len, crc, error); + } + + default command error_t SubBlockRead.read[uint8_t client](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t SubBlockRead.computeCrc[uint8_t client](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + default event void BlockRead.readDone[volume_id_t volume_id](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} + default event void BlockRead.computeCrcDone[volume_id_t volume_id](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {} + + + /* BlockWrite **************************/ + command error_t BlockWrite.write[uint8_t client](storage_addr_t addr, void* buf, storage_len_t len) + { + error_t error; + if (state != S_READY) { + return EBUSY; + } + error = call SubBlockWrite.write[call VolumeId.get[client]()](addr, buf, len); + if (error == SUCCESS) + { + state = S_BUSY; + current_client = client; + return SUCCESS; + } + return error; + } + + command error_t BlockWrite.erase[uint8_t client]() + { + error_t error; + if (state != S_READY) { + return EBUSY; + } + error = call SubBlockWrite.erase[call VolumeId.get[client]()](); + if (error == SUCCESS) + { + state = S_BUSY; + current_client = client; + return SUCCESS; + } + return error; + } + + command error_t BlockWrite.sync[uint8_t client]() + { + error_t error; + if (state != S_READY) { + return EBUSY; + } + error = call SubBlockWrite.sync[call VolumeId.get[client]()](); + if (error == SUCCESS) + { + state = S_BUSY; + return SUCCESS; + } + return error; + } + + event void SubBlockWrite.writeDone[volume_id_t volume_id](storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + state = S_READY; + signal BlockWrite.writeDone[current_client](addr, buf, len, error); + } + + event void SubBlockWrite.eraseDone[volume_id_t volume_id](error_t error) + { + state = S_READY; + signal BlockWrite.eraseDone[current_client](error); + } + + event void SubBlockWrite.syncDone[volume_id_t volume_id](error_t error) + { + state = S_READY; + signal BlockWrite.syncDone[current_client](error); + } + + command storage_addr_t StorageMap.getPhysicalAddress[uint8_t volume_id](storage_addr_t addr) + { + storage_addr_t p_addr = 0xFFFFFFFF; +#if defined(PLATFORM_TELOSB) + p_addr = call SubStorageMap.getPhysicalAddress[volume_id](addr); +#elif defined(PLATFORM_MICAZ) + at45page_t page = call At45dbVolume.remap[img_num]((addr >> AT45_PAGE_SIZE_LOG2)); + at45pageoffset_t offset = addr & ((1 << AT45_PAGE_SIZE_LOG2) - 1); + p_addr = page; + p_addr = p_addr << AT45_PAGE_SIZE_LOG2; + p_addr += offset; +#endif + return p_addr; + } + +#if defined(PLATFORM_TELOSB) + default command storage_addr_t SubStorageMap.getPhysicalAddress[uint8_t volume_id](storage_addr_t addr) + { + return 0xffffffff; + } +#endif + + default command error_t SubBlockWrite.write[uint8_t client](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t SubBlockWrite.erase[uint8_t client]() { return FAIL; } + default command error_t SubBlockWrite.sync[uint8_t client]() { return FAIL; } + default event void BlockWrite.writeDone[volume_id_t volume_id](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} + default event void BlockWrite.eraseDone[volume_id_t volume_id](error_t error) {} + default event void BlockWrite.syncDone[volume_id_t volume_id](error_t error) {} + + + default command volume_id_t VolumeId.get[uint8_t client]() + { + return 0xFF; // This is an invalid volume at least for STM25P. + } +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/BlockWriterC.nc b/tos/lib/net/Deluge/BlockStorageManager/BlockWriterC.nc new file mode 100644 index 00000000..e7a615f8 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/BlockWriterC.nc @@ -0,0 +1,51 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "BlockStorageManager.h" +#include "Storage.h" + +generic configuration BlockWriterC(volume_id_t id) +{ + provides { + interface BlockWrite; + interface Resource; + } +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_BSTORAGEM_CLIENT) + }; + + components new VolumeIdC(id); + components BlockStorageManagerC; + components new BlockStorageLockClientC(); + + BlockWrite = BlockStorageManagerC.BlockWrite[CLIENT_ID]; + Resource = BlockStorageLockClientC; + BlockStorageManagerC.VolumeId[CLIENT_ID] -> VolumeIdC; +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/VolumeId.nc b/tos/lib/net/Deluge/BlockStorageManager/VolumeId.nc new file mode 100644 index 00000000..e8282bc6 --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/VolumeId.nc @@ -0,0 +1,30 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +interface VolumeId +{ + command volume_id_t get(); +} diff --git a/tos/lib/net/Deluge/BlockStorageManager/VolumeIdC.nc b/tos/lib/net/Deluge/BlockStorageManager/VolumeIdC.nc new file mode 100644 index 00000000..6d13eedc --- /dev/null +++ b/tos/lib/net/Deluge/BlockStorageManager/VolumeIdC.nc @@ -0,0 +1,38 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic module VolumeIdC(volume_id_t id) +{ + provides interface VolumeId; +} + +implementation +{ + command volume_id_t VolumeId.get() + { + return id; + } +} diff --git a/tos/lib/net/Deluge/Deluge.h b/tos/lib/net/Deluge/Deluge.h index b938e4ae..6ef74f58 100644 --- a/tos/lib/net/Deluge/Deluge.h +++ b/tos/lib/net/Deluge/Deluge.h @@ -27,30 +27,49 @@ #ifndef __DELUGE_H__ #define __DELUGE_H__ -#include "DelugeMetadata.h" - -#define DISSMSG_DISS 0 -#define DISSMSG_REPROG 1 +typedef nx_struct DelugeIdent { + nx_uint32_t uidhash; // unique id of the image + nx_uint32_t size; // size of the whole image (ident + CRCs + binary) + nx_uint8_t numPgs; // number of pages of complete image + nx_uint8_t reserved; + nx_uint16_t crc; // crc over the above 4 fields + nx_uint8_t appname[16]; + nx_uint8_t username[16]; + nx_uint8_t hostname[16]; + nx_uint8_t platform[16]; + nx_uint32_t timestamp; + nx_uint32_t userhash; +} DelugeIdent; enum { DELUGE_INVALID_UID = 0xffffffff, DELUGE_NUM_VOLUMES = 4, }; -typedef nx_struct DelugeDissemination { - nx_uint8_t msg_type; - nx_uint32_t uid; // unique id of image - nx_uint16_t vNum; // version num of image +enum { + DELUGE_CMD_STOP = 1, + DELUGE_CMD_LOCAL_STOP = 2, + DELUGE_CMD_ONLY_DISSEMINATE = 3, + DELUGE_CMD_DISSEMINATE_AND_REPROGRAM = 4, + DELUGE_CMD_REPROGRAM = 5, // Reprogram the local mote + DELUGE_CMD_REBOOT = 6, // Reboot the local mode +}; + +#define UQ_DELUGE_METADATA "DelugeMetadata.client" +#define UQ_DELUGE_VOLUME_MANAGER "DelugeVolumeManager.client" + +typedef nx_struct DelugeCmd { + nx_uint8_t type; + nx_uint32_t uidhash; // unique id of image nx_uint8_t imgNum; // image number nx_uint16_t size; // size of the image -} DelugeDissemination; - -typedef struct DelugeNodeDesc { - imgvnum_t vNum; - uint32_t uid; - imgnum_t imgNum; - uint8_t reserved; - uint16_t crc; -} DelugeNodeDesc; +} DelugeCmd; + +typedef struct BootArgs { + uint16_t address; + uint32_t imageAddr; + uint8_t gestureCount; + bool noReprogram; +} BootArgs; #endif diff --git a/tos/lib/net/Deluge/DelugeC.nc b/tos/lib/net/Deluge/DelugeC.nc index 21a5320f..20532b56 100644 --- a/tos/lib/net/Deluge/DelugeC.nc +++ b/tos/lib/net/Deluge/DelugeC.nc @@ -27,62 +27,63 @@ #include "Deluge.h" #include "StorageVolumes.h" -configuration DelugeC -{ +configuration DelugeC { uses interface Leds; } implementation { - components DelugeStorageC; - -#ifdef DELUGE_BASESTATION - components SerialStarterC; - components new FlashVolumeManagerC(0xAB); + components ObjectTransferC; - DelugeP.DissNotify -> FlashVolumeManagerC.DissNotify; - DelugeP.ReprogNotify -> FlashVolumeManagerC.ReprogNotify; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; - FlashVolumeManagerC.BlockRead[VOLUME_GOLDENIMAGE] -> DelugeStorageC.BlockRead[VOLUME_GOLDENIMAGE]; - FlashVolumeManagerC.BlockWrite[VOLUME_GOLDENIMAGE] -> DelugeStorageC.BlockWrite[VOLUME_GOLDENIMAGE]; - FlashVolumeManagerC.DelugeStorage[VOLUME_GOLDENIMAGE] -> DelugeStorageC.DelugeStorage[VOLUME_GOLDENIMAGE]; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; - FlashVolumeManagerC.BlockRead[VOLUME_DELUGE1] -> DelugeStorageC.BlockRead[VOLUME_DELUGE1]; - FlashVolumeManagerC.BlockWrite[VOLUME_DELUGE1] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE1]; - FlashVolumeManagerC.DelugeStorage[VOLUME_DELUGE1] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE1]; + ObjectTransferC.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + ObjectTransferC.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + ObjectTransferC.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; - FlashVolumeManagerC.BlockRead[VOLUME_DELUGE2] -> DelugeStorageC.BlockRead[VOLUME_DELUGE2]; - FlashVolumeManagerC.BlockWrite[VOLUME_DELUGE2] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE2]; - FlashVolumeManagerC.DelugeStorage[VOLUME_DELUGE2] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE2]; + ObjectTransferC.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + ObjectTransferC.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + ObjectTransferC.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; - FlashVolumeManagerC.BlockRead[VOLUME_DELUGE3] -> DelugeStorageC.BlockRead[VOLUME_DELUGE3]; - FlashVolumeManagerC.BlockWrite[VOLUME_DELUGE3] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE3]; - FlashVolumeManagerC.DelugeStorage[VOLUME_DELUGE3] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE3]; -#endif - - components ObjectTransferC; - ObjectTransferC.BlockRead[VOLUME_DELUGE1] -> DelugeStorageC.BlockRead[VOLUME_DELUGE1]; - ObjectTransferC.BlockWrite[VOLUME_DELUGE1] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE1]; - ObjectTransferC.BlockRead[VOLUME_DELUGE2] -> DelugeStorageC.BlockRead[VOLUME_DELUGE2]; - ObjectTransferC.BlockWrite[VOLUME_DELUGE2] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE2]; - ObjectTransferC.BlockRead[VOLUME_DELUGE3] -> DelugeStorageC.BlockRead[VOLUME_DELUGE3]; - ObjectTransferC.BlockWrite[VOLUME_DELUGE3] -> DelugeStorageC.BlockWrite[VOLUME_DELUGE3]; ObjectTransferC.Leds = Leds; - components new DisseminatorC(DelugeDissemination, 0xDE00), DisseminationC; + components new DisseminatorC(DelugeCmd, 0xDE00); + components DisseminationC; components ActiveMessageC; components NetProgC, DelugeP; components new TimerMilliC() as Timer; + components BlockStorageManagerC; + components DelugeMetadataC; + components new DelugeMetadataClientC(); + components new DelugeVolumeManagerClientC(); + components new BlockStorageLockClientC(); + components MainC; + + DelugeP.Boot -> MainC; DelugeP.Leds = Leds; DelugeP.DisseminationValue -> DisseminatorC; - DelugeP.DisseminationUpdate -> DisseminatorC; - DelugeP.StdControlDissemination -> DisseminationC; + DelugeP.DisseminationStdControl -> DisseminationC; DelugeP.ObjectTransfer -> ObjectTransferC; DelugeP.NetProg -> NetProgC; - DelugeP.StorageReadyNotify -> DelugeStorageC; - DelugeP.DelugeMetadata -> DelugeStorageC; DelugeP.RadioSplitControl -> ActiveMessageC; - - components InternalFlashC as IFlash; - DelugeP.IFlash -> IFlash; + DelugeP.StorageMap -> BlockStorageManagerC; + DelugeP.DelugeMetadata -> DelugeMetadataClientC; + DelugeP.storageReady <- DelugeMetadataC; + DelugeP.DelugeVolumeManager -> DelugeVolumeManagerClientC; + DelugeP.Resource -> BlockStorageLockClientC; + +#ifdef DELUGE_BASESTATION + components SerialStarterC; + components new FlashVolumeManagerC(0xAB); + components new DelugeManagerC(0xAC); + + DelugeManagerC.DisseminationUpdate -> DisseminatorC; +#endif + } diff --git a/tos/lib/net/Deluge/DelugeManagerC.nc b/tos/lib/net/Deluge/DelugeManagerC.nc new file mode 100644 index 00000000..dcfb159c --- /dev/null +++ b/tos/lib/net/Deluge/DelugeManagerC.nc @@ -0,0 +1,63 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +#include "StorageVolumes.h" + +generic configuration DelugeManagerC(am_id_t AMId) +{ + uses interface DisseminationUpdate; +} + +implementation +{ + components new SerialAMSenderC(AMId); + components new SerialAMReceiverC(AMId); + components new TimerMilliC() as Timer; + components NoLedsC, LedsC; + components new DelugeManagerP(); + components NetProgC; + components BlockStorageManagerC; + components ObjectTransferC; + components new DelugeMetadataClientC(); + components new DelugeVolumeManagerClientC(); + components new BlockStorageLockClientC(); + + DelugeManagerP.DelayTimer -> Timer; + DelugeManagerP.SerialAMSender -> SerialAMSenderC; + DelugeManagerP.SerialAMReceiver -> SerialAMReceiverC; + DelugeManagerP.Leds -> LedsC; + DelugeManagerP.DisseminationUpdate = DisseminationUpdate; + DelugeManagerP.NetProg -> NetProgC; + DelugeManagerP.ObjectTransfer -> ObjectTransferC; + + DelugeManagerP.StorageMap -> BlockStorageManagerC; + DelugeManagerP.DelugeMetadata -> DelugeMetadataClientC; + DelugeManagerP.DelugeVolumeManager -> DelugeVolumeManagerClientC; + DelugeManagerP.Resource -> BlockStorageLockClientC; + + components DelugeP; + DelugeManagerP.stop -> DelugeP; +} diff --git a/tos/lib/net/Deluge/DelugeManagerP.nc b/tos/lib/net/Deluge/DelugeManagerP.nc new file mode 100644 index 00000000..d7146af9 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeManagerP.nc @@ -0,0 +1,136 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic module DelugeManagerP() +{ + uses { + interface DisseminationUpdate; + interface AMSend as SerialAMSender; + interface Receive as SerialAMReceiver; + interface Timer as DelayTimer; + interface NetProg; + interface Leds; + interface StorageMap[uint8_t volumeId]; + interface DelugeMetadata; + interface ObjectTransfer; + interface DelugeVolumeManager; + interface Resource; + command void stop(); + } +} + +implementation +{ + typedef nx_struct SerialReqPacket { + nx_uint8_t cmd; + nx_uint8_t imgNum; + } SerialReqPacket; + + typedef nx_struct SerialReplyPacket { + nx_uint8_t error; + } SerialReplyPacket; + + message_t serialMsg; + DelugeCmd delugeCmd; + + void sendReply(error_t error) + { + uint8_t len = sizeof(SerialReplyPacket); + SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, len); + if (reply == NULL) { + return; + } + reply->error = error; + call SerialAMSender.send(AM_BROADCAST_ADDR, &serialMsg, len); + } + + event message_t* SerialAMReceiver.receive(message_t* msg, void* payload, uint8_t len) + { + SerialReqPacket *request = (SerialReqPacket *)payload; + memset(&delugeCmd, 0, sizeof(DelugeCmd)); + + call stop(); + delugeCmd.type = request->cmd; + + switch (request->cmd) { + case DELUGE_CMD_STOP: + call DisseminationUpdate.change(&delugeCmd); + case DELUGE_CMD_LOCAL_STOP: + sendReply(SUCCESS); + call Resource.release(); + break; + case DELUGE_CMD_ONLY_DISSEMINATE: + case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM: + if (call Resource.immediateRequest() == SUCCESS) { + call DelugeMetadata.read(request->imgNum); + } else { + sendReply(FAIL); + } + break; + case DELUGE_CMD_REPROGRAM: + case DELUGE_CMD_REBOOT: + call DelayTimer.startOneShot(1024); + sendReply(SUCCESS); + break; + } + return msg; + } + + event void DelayTimer.fired() + { + switch (delugeCmd.type) { + case DELUGE_CMD_REPROGRAM: + call NetProg.programImageAndReboot(call StorageMap.getPhysicalAddress[delugeCmd.imgNum](0)); + break; + case DELUGE_CMD_REBOOT: + call NetProg.reboot(); + break; + } + } + + event void DelugeMetadata.readDone(uint8_t imgNum, DelugeIdent* ident, error_t error) + { + delugeCmd.imgNum = imgNum; + sendReply(error); + if (error != SUCCESS) { + return; + } + switch (delugeCmd.type) { + case DELUGE_CMD_ONLY_DISSEMINATE: + case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM: + delugeCmd.uidhash = ident->uidhash; + delugeCmd.size = ident->size; + call DisseminationUpdate.change(&delugeCmd); + call ObjectTransfer.publish(delugeCmd.uidhash, delugeCmd.size, delugeCmd.imgNum); + break; + } + } + + event void Resource.granted() {} + event void ObjectTransfer.receiveDone(error_t error) {} + event void SerialAMSender.sendDone(message_t* msg, error_t error) {} + event void DelugeVolumeManager.eraseDone(uint8_t imgNum) {} +} diff --git a/tos/lib/net/Deluge/DelugeMetadata.h b/tos/lib/net/Deluge/DelugeMetadata.h deleted file mode 100644 index 1c17f59c..00000000 --- a/tos/lib/net/Deluge/DelugeMetadata.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * "Copyright (c) 2000-2004 The Regents of the University of California. - * 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 following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - */ - -/** - * @author Jonathan Hui - */ - -#ifndef __DELUGE_METADATA_H__ -#define __DELUGE_METADATA_H__ - -#define DELUGE_METADATA_SIZE 16 - -typedef int16_t imgvnum_t; -typedef uint8_t imgnum_t; -typedef uint8_t pgnum_t; - -typedef struct DelugeImgDesc { - uint32_t uid; // unique id of image - imgvnum_t vNum; // version num of image - imgnum_t imgNum; // image number - pgnum_t numPgs; // num pages of complete image - uint16_t crc; // crc for vNum and numPgs - uint8_t numPgsComplete; // numPgsComplete in image - uint8_t reserved; - uint16_t size; // size of the whole image (metadata + CRCs + ident + binary) -} DelugeImgDesc; - -#endif diff --git a/tos/lib/net/Deluge/DelugeMetadata.nc b/tos/lib/net/Deluge/DelugeMetadata.nc index d6004449..3664bb2d 100644 --- a/tos/lib/net/Deluge/DelugeMetadata.nc +++ b/tos/lib/net/Deluge/DelugeMetadata.nc @@ -1,33 +1,14 @@ -/* - * "Copyright (c) 2000-2004 The Regents of the University of California. - * 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 following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - * - * Copyright (c) 2007 Johns Hopkins University. - * All rights reserved. - */ - /** - * @author Jonathan Hui - * @author Chieh-Jan Mike Liang - * @author Razvan Musaloiu-E. + * An interface for obtaining the identification data of an + * image. The pointer returned by readDone will be destroyed by the + * next read. + * + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang */ -interface DelugeMetadata { - command DelugeImgDesc* getImgDesc(imgnum_t imgNum); +interface DelugeMetadata +{ + command error_t read(uint8_t imgNum); + event void readDone(uint8_t imgNum, DelugeIdent* ident, error_t error); } diff --git a/tos/lib/net/Deluge/DelugeMetadataC.nc b/tos/lib/net/Deluge/DelugeMetadataC.nc new file mode 100644 index 00000000..91047e44 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeMetadataC.nc @@ -0,0 +1,61 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration DelugeMetadataC +{ + provides interface DelugeMetadata[uint8_t client]; + uses event void storageReady(); +} + +implementation +{ + components MainC; + components DelugeMetadataP; + + DelugeMetadata = DelugeMetadataP; + storageReady = DelugeMetadataP; + DelugeMetadataP.Boot -> MainC; + + components new BlockReaderC(VOLUME_GOLDENIMAGE) as BlockReaderGoldenImage; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; + + DelugeMetadataP.BlockRead[VOLUME_GOLDENIMAGE] -> BlockReaderGoldenImage; + DelugeMetadataP.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + DelugeMetadataP.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + DelugeMetadataP.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; + + components new BlockWriterC(VOLUME_GOLDENIMAGE) as BlockWriterGoldenImage; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; + + DelugeMetadataP.BlockWrite[VOLUME_GOLDENIMAGE] -> BlockWriterGoldenImage; + DelugeMetadataP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + DelugeMetadataP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + DelugeMetadataP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; +} diff --git a/tos/lib/net/Deluge/DelugeMetadataClientC.nc b/tos/lib/net/Deluge/DelugeMetadataClientC.nc new file mode 100644 index 00000000..f2a07564 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeMetadataClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration DelugeMetadataClientC() +{ + provides interface DelugeMetadata; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_DELUGE_METADATA) + }; + + components DelugeMetadataC; + DelugeMetadata = DelugeMetadataC.DelugeMetadata[CLIENT_ID]; +} diff --git a/tos/lib/net/Deluge/DelugeMetadataP.nc b/tos/lib/net/Deluge/DelugeMetadataP.nc new file mode 100644 index 00000000..6c2fa375 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeMetadataP.nc @@ -0,0 +1,171 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +module DelugeMetadataP +{ + provides interface DelugeMetadata[uint8_t client]; + uses { + interface Boot; + interface BlockRead[uint8_t volumeId]; + interface BlockWrite[uint8_t volumeId]; + interface StorageMap[uint8_t volumeId]; + event void storageReady(); + } +} + +implementation +{ + enum { + S_READ_IDENT, + S_READ_CRC, + S_CRC, + S_READY, + S_BUSY + }; + + DelugeIdent ident; + uint8_t state; + uint8_t currentImage; + uint8_t currentPage; + nx_uint16_t currentCrc; + uint8_t currentClient; + + void nextImage() + { + if (currentImage < DELUGE_NUM_VOLUMES) { + state = S_READ_IDENT; + call BlockRead.read[currentImage](0, &ident, sizeof(ident)); + } else { + signal storageReady(); + state = S_READY; + } + } + + uint32_t calcCrcAddr() + { + return DELUGE_IDENT_SIZE + currentPage * sizeof(uint16_t); + } + + uint32_t calcPageAddr() + { + return DELUGE_IDENT_SIZE + DELUGE_CRC_BLOCK_SIZE + currentPage * DELUGE_BYTES_PER_PAGE; + } + + event void Boot.booted() + { + // We are going to iterate over all the images and verify their + // integrity. For each image we first read the ident to find the + // number of pages and then iterate over all of them, compute the + // CRC and check it against the corresponding value from the CRCs + // block. + state = S_READ_IDENT; + currentImage = 0; + nextImage(); + } + + command error_t DelugeMetadata.read[uint8_t client](uint8_t imgNum) + { + error_t error; + if (state != S_READY) { + return FAIL; + } + currentClient = client; + error = call BlockRead.read[imgNum](0, &ident, sizeof(ident)); + state = error == SUCCESS ? S_BUSY : state; + return error; + } + + event void BlockRead.readDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) + { + switch (state) { + case S_BUSY: + state = S_READY; + signal DelugeMetadata.readDone[currentClient](imgNum, buf, error); + break; + case S_READ_IDENT: + if (error == SUCCESS) { + if (ident.uidhash != DELUGE_INVALID_UID) { + currentPage = 0; + state = S_READ_CRC; + call BlockRead.read[currentImage](calcCrcAddr(), ¤tCrc, sizeof(currentCrc)); + } else { + currentImage++; + nextImage(); + } + } + break; + case S_READ_CRC: + state = S_CRC; + call BlockRead.computeCrc[currentImage](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0); + break; + } + } + + event void BlockRead.computeCrcDone[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) + { + switch (state) { + case S_CRC: + if (crc != currentCrc) { +// printf("%04x %04x\n", crc, currentCrc); + // invalidate the image by erasing it + call BlockWrite.erase[currentImage](); + } else { + currentPage++; + if (currentPage < ident.numPgs) { + state = S_READ_CRC; + call BlockRead.read[currentImage](calcCrcAddr(), ¤tCrc, sizeof(currentCrc)); + } else { + currentImage++; + nextImage(); + } + } + break; + } + } + + default command error_t BlockRead.read[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.computeCrc[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + + event void BlockWrite.writeDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} + event void BlockWrite.eraseDone[uint8_t imgNum](error_t error) + { + switch (state) { + case S_READY: + signal BlockWrite.eraseDone[imgNum](error); + break; + case S_CRC: + currentImage++; + nextImage(); + break; + } + } + + event void BlockWrite.syncDone[uint8_t imgNum](error_t error) {} + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + + default event void DelugeMetadata.readDone[uint8_t client](uint8_t imgNum, DelugeIdent* i, error_t error) {} + default event void storageReady() {} +} diff --git a/tos/lib/net/Deluge/DelugeP.nc b/tos/lib/net/Deluge/DelugeP.nc index 8a4d14a9..f2df208f 100644 --- a/tos/lib/net/Deluge/DelugeP.nc +++ b/tos/lib/net/Deluge/DelugeP.nc @@ -20,142 +20,168 @@ */ /** - * @author Chieh-Jan Mike Liang * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang */ module DelugeP { uses { + interface Boot; interface Leds; - interface Notify as StorageReadyNotify; - interface DisseminationUpdate; - interface DisseminationValue; - interface StdControl as StdControlDissemination; - interface DelugeMetadata; + interface DisseminationValue; + interface StdControl as DisseminationStdControl; interface ObjectTransfer; - interface NetProg; - interface InternalFlash as IFlash; interface SplitControl as RadioSplitControl; - -#ifdef DELUGE_BASESTATION - interface Notify as DissNotify; - interface Notify as ReprogNotify; -#endif + interface NetProg; + interface StorageMap[uint8_t volumeId]; + interface DelugeMetadata; + interface DelugeVolumeManager; + interface Resource; + } + provides { + event void storageReady(); + command void stop(); } } implementation { - uint32_t recv_uid = 0xffffffff; - uint16_t recv_size = 0xffff; - uint8_t recv_imgNum = 0xff; - - /** - * Starts the radio - */ - event void StorageReadyNotify.notify(uint8_t val) + enum { + S_IDLE, + S_PUB, + S_RECV + }; + + DelugeCmd lastCmd; + uint8_t state = S_IDLE; + + event void storageReady() { call RadioSplitControl.start(); } - -#ifdef DELUGE_BASESTATION - /** - * Starts disseminating image information - */ - event void DissNotify.notify(uint8_t new_img_num) + + event void Boot.booted() + { + lastCmd.uidhash = DELUGE_INVALID_UID; + } + + event void RadioSplitControl.startDone(error_t error) + { + if (error == SUCCESS) { + call DisseminationStdControl.start(); + } + } + + command void stop() { - DelugeImgDesc* imgDesc = call DelugeMetadata.getImgDesc(new_img_num); - if (imgDesc->uid != DELUGE_INVALID_UID) { - DelugeDissemination delugeDis; - - call ObjectTransfer.stop(); - - delugeDis.uid = imgDesc->uid; - delugeDis.vNum = imgDesc->vNum; - delugeDis.imgNum = new_img_num; - delugeDis.size = imgDesc->size; - delugeDis.msg_type = DISSMSG_DISS; - - call DisseminationUpdate.change(&delugeDis); // Disseminates command - call ObjectTransfer.publish(delugeDis.uid, - delugeDis.size, - delugeDis.imgNum); // Prepares to publish image data + call Resource.release(); + if (state == S_RECV) { +// printf("erase %d\n", lastCmd.imgNum); + call DelugeVolumeManager.erase(lastCmd.imgNum); } + call ObjectTransfer.stop(); + state = S_IDLE; + } + + task void taskRequest() + { + signal Resource.granted(); } - event void ReprogNotify.notify(uint8_t new_img_num) + void request() { - DelugeDissemination delugeDis; - - delugeDis.uid = 0; - delugeDis.vNum = 0; - delugeDis.imgNum = new_img_num; - delugeDis.size = 0; - delugeDis.msg_type = DISSMSG_REPROG; - - call DisseminationUpdate.change(&delugeDis); // Disseminates command + if (call Resource.isOwner()) { + post taskRequest(); + } else { + call Resource.request(); + } } -#endif - /** - * Receives a disseminated message. If the message contains information about a - * newer image, then we should grab this image from the network - */ event void DisseminationValue.changed() { - const DelugeDissemination *delugeDis = call DisseminationValue.get(); - DelugeImgDesc *imgDesc = call DelugeMetadata.getImgDesc(delugeDis->imgNum); - - switch (delugeDis->msg_type) { - case DISSMSG_DISS: - if (imgDesc->uid == delugeDis->uid && imgDesc->uid != DELUGE_INVALID_UID) { - if (imgDesc->vNum < delugeDis->vNum) { - recv_uid = delugeDis->uid; - recv_size = delugeDis->size; - recv_imgNum = delugeDis->imgNum; - call ObjectTransfer.receive(delugeDis->uid, delugeDis->size, delugeDis->imgNum); - } - } else { - recv_uid = delugeDis->uid; - recv_size = delugeDis->size; - recv_imgNum = delugeDis->imgNum; - call ObjectTransfer.receive(delugeDis->uid, delugeDis->size, delugeDis->imgNum); - } - - break; - case DISSMSG_REPROG: - if (imgDesc->uid != DELUGE_INVALID_UID) { - DelugeNodeDesc nodeDesc; - call IFlash.read((uint8_t*)IFLASH_NODE_DESC_ADDR, - &nodeDesc, - sizeof(DelugeNodeDesc)); // Reads which image was just reprogrammed - if (nodeDesc.uid != imgDesc->uid || nodeDesc.vNum != imgDesc->vNum) { - call NetProg.programImgAndReboot(delugeDis->imgNum); - } - } - - break; + const DelugeCmd *cmd = call DisseminationValue.get(); +// printf("cmd: %d uidhash: 0x%lx imgNum: %d size: %u\n", cmd->type, cmd->uidhash, cmd->imgNum, cmd->size); + switch (cmd->type) { + case DELUGE_CMD_STOP: + call stop(); + break; + case DELUGE_CMD_ONLY_DISSEMINATE: + case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM: + if (state == S_RECV) { + if (cmd->uidhash == lastCmd.uidhash) { + if (cmd->imgNum == lastCmd.imgNum) { + // Same uidhash, same imgNum, only cmd should be + // different. That will be properly updated by the last + // statement from this function. + break; + } + } + call stop(); + } + if (cmd->uidhash != IDENT_UIDHASH) { + call DelugeMetadata.read(cmd->imgNum); + } else { + state = S_PUB; + request(); + } + break; } + lastCmd = *cmd; +// printf("lastCmd: %d uidhash: 0x%lx\n", lastCmd.type, lastCmd.uidhash); } event void ObjectTransfer.receiveDone(error_t error) { call Leds.set(LEDS_LED1 | LEDS_LED2); - call ObjectTransfer.publish(recv_uid, recv_size, recv_imgNum); + state = S_IDLE; + + if (error == SUCCESS) { + switch (lastCmd.type) { + case DELUGE_CMD_ONLY_DISSEMINATE: + state = S_PUB; + request(); + break; + case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM: + call NetProg.programImageAndReboot(call StorageMap.getPhysicalAddress[lastCmd.imgNum](0)); + break; + } + } else { + call DelugeVolumeManager.erase(lastCmd.imgNum); + } } - /** - * Prepares to publish the image that was just reprogrammed - */ - event void RadioSplitControl.startDone(error_t error) + event void DelugeMetadata.readDone(uint8_t imgNum, DelugeIdent* ident, error_t error) { - if (error == SUCCESS) { - call StdControlDissemination.start(); +// printf("readDone 0x%lx imgNum: %d size: %u\n", lastCmd.uidhash, lastCmd.imgNum, lastCmd.size); + if (ident->uidhash == lastCmd.uidhash) { + if (lastCmd.type == DELUGE_CMD_DISSEMINATE_AND_REPROGRAM) { + call NetProg.programImageAndReboot(call StorageMap.getPhysicalAddress[imgNum](0)); + } else { + // We already have the image so we'll go ahead and start publishing. + state = S_PUB; + request(); + } + } else { + state = S_RECV; + request(); } } - + + event void Resource.granted() + { + switch (state) { + case S_PUB: +// printf("start pub 0x%lx imgNum: %d size: %u\n", lastCmd.uidhash, lastCmd.imgNum, lastCmd.size); + call ObjectTransfer.publish(lastCmd.uidhash, lastCmd.size, lastCmd.imgNum); + break; + case S_RECV: + call ObjectTransfer.receive(lastCmd.uidhash, lastCmd.size, lastCmd.imgNum); + break; + } + } + + event void DelugeVolumeManager.eraseDone(uint8_t imgNum) {} event void RadioSplitControl.stopDone(error_t error) {} - default async void command Leds.set(uint8_t val) {} } diff --git a/tos/lib/net/Deluge/DelugePageTransfer.h b/tos/lib/net/Deluge/DelugePageTransfer.h index b5eb166b..e640de4d 100644 --- a/tos/lib/net/Deluge/DelugePageTransfer.h +++ b/tos/lib/net/Deluge/DelugePageTransfer.h @@ -70,9 +70,10 @@ enum { DELUGE_REBOOT_DELAY = 4, DELUGE_FAILED_SEND_DELAY = 16, DELUGE_MIN_DELAY = 16, - DELUGE_DATA_OFFSET = 128, +// DELUGE_DATA_OFFSET = 128, DELUGE_IDENT_SIZE = 128, DELUGE_INVALID_ADDR = (0x7fffffffL), + DELUGE_MIN_ADV_PERIOD_LOG2 = 9, DELUGE_MAX_REQ_DELAY = (0x1L << (DELUGE_MIN_ADV_PERIOD_LOG2 - 1)), DELUGE_NACK_TIMEOUT = (DELUGE_MAX_REQ_DELAY >> 0x1), DELUGE_MAX_IMAGE_SIZE = (128L * 1024L), @@ -83,6 +84,7 @@ enum { DELUGE_INVALID_OBJID = 0xff, DELUGE_INVALID_PKTNUM = 0xff, DELUGE_INVALID_PGNUM = 0xff, + DELUGE_QSIZE = 2 }; typedef struct DelugeAdvTimer { diff --git a/tos/lib/net/Deluge/DelugePageTransfer.nc b/tos/lib/net/Deluge/DelugePageTransfer.nc index b2929beb..b195bdda 100644 --- a/tos/lib/net/Deluge/DelugePageTransfer.nc +++ b/tos/lib/net/Deluge/DelugePageTransfer.nc @@ -37,6 +37,5 @@ interface DelugePageTransfer { event void suppressMsgs(object_id_t new_objid); event void receivedPage(object_id_t new_objid, page_num_t new_pgNum); command void setImgNum(uint8_t new_img_num); - command error_t stop(); } diff --git a/tos/lib/net/Deluge/DelugePageTransferC.nc b/tos/lib/net/Deluge/DelugePageTransferC.nc index c7380ba6..cd0efe33 100644 --- a/tos/lib/net/Deluge/DelugePageTransferC.nc +++ b/tos/lib/net/Deluge/DelugePageTransferC.nc @@ -46,12 +46,8 @@ implementation components DelugePageTransferP; DelugePageTransfer = DelugePageTransferP; - BlockRead[VOLUME_DELUGE1] = DelugePageTransferP.BlockRead[VOLUME_DELUGE1]; - BlockWrite[VOLUME_DELUGE1] = DelugePageTransferP.BlockWrite[VOLUME_DELUGE1]; - BlockRead[VOLUME_DELUGE2] = DelugePageTransferP.BlockRead[VOLUME_DELUGE2]; - BlockWrite[VOLUME_DELUGE2] = DelugePageTransferP.BlockWrite[VOLUME_DELUGE2]; - BlockRead[VOLUME_DELUGE3] = DelugePageTransferP.BlockRead[VOLUME_DELUGE3]; - BlockWrite[VOLUME_DELUGE3] = DelugePageTransferP.BlockWrite[VOLUME_DELUGE3]; + BlockRead = DelugePageTransferP.BlockRead; + BlockWrite = DelugePageTransferP.BlockWrite; ReceiveDataMsg = DelugePageTransferP.ReceiveDataMsg; ReceiveReqMsg = DelugePageTransferP.ReceiveReqMsg; diff --git a/tos/lib/net/Deluge/DelugePageTransferP.nc b/tos/lib/net/Deluge/DelugePageTransferP.nc index 57e6757b..5d9e1a8e 100644 --- a/tos/lib/net/Deluge/DelugePageTransferP.nc +++ b/tos/lib/net/Deluge/DelugePageTransferP.nc @@ -148,7 +148,6 @@ implementation { return (storage_addr_t)pgNum * (storage_addr_t)DELUGET2_BYTES_PER_PAGE + (uint16_t)pktNum * (uint16_t)DELUGET2_PKT_PAYLOAD_SIZE; - //+ DELUGE_METADATA_SIZE; } void setupDataMsg() @@ -175,7 +174,6 @@ implementation if (call BitVecUtils.indexOf(&nextPkt, pDataMsg->pktNum, pktsToSend, DELUGET2_PKTS_PER_PAGE) != SUCCESS) { // no more packets to send - //dbg(DBG_USR1, "DELUGE: SEND_DONE\n"); changeState(S_IDLE); } else { pDataMsg->pktNum = nextPkt; @@ -321,9 +319,6 @@ implementation page_num_t pgNum; int i; - //dbg(DBG_USR1, "DELUGE: Received REQ_MSG(dest=%d,vNum=%d,imgNum=%d,pgNum=%d,pkts=%x)\n", - // rxReqMsg->dest, rxReqMsg->vNum, rxReqMsg->imgNum, rxReqMsg->pgNum, rxReqMsg->requestedPkts[0]); - if (state == S_DISABLED) { return msg; } @@ -386,9 +381,6 @@ if (error == SUCCESS) { return msg; } - //dbg(DBG_USR1, "DELUGE: Received DATA_MSG(vNum=%d,imgNum=%d,pgNum=%d,pktNum=%d)\n", - // rxDataMsg->vNum, rxDataMsg->imgNum, rxDataMsg->pgNum, rxDataMsg->pktNum); - // check if need to suppress req or data messages suppressMsgs(rxDataMsg->objid, rxDataMsg->pgNum); @@ -401,14 +393,10 @@ if (error == SUCCESS) { // For collecting stats if (rxDataMsg->pktNum == 0) { //call StatsCollector.startRecvPageTransTime(0); - dbg("Deluge", "%.3f 115 116 116 117 115 1 %d\n", ((float)((sim_time() * 1000) / sim_ticks_per_sec())) / 1000, CC2420_DEF_CHANNEL); } call Leds.led1Toggle(); //call Leds.set(rxDataMsg->pktNum); - //dbg(DBG_USR1, "DELUGE: SAVING(pgNum=%d,pktNum=%d)\n", - // rxDataMsg->pgNum, rxDataMsg->pktNum); - // copy data memcpy(&rxQueue[head^size], rxDataMsg, sizeof(DelugeDataMsg)); if (++size == 1) { @@ -475,8 +463,8 @@ call Leds.led1Toggle(); if (call BitVecUtils.indexOf(&tmp, 0, pktsToReceive, DELUGET2_PKTS_PER_PAGE) != SUCCESS) { // For collecting stats //call StatsCollector.endRecvPageTransTime(publisher_addr); -dbg("Deluge", "%.3f 115 116 116 117 115 2 %d\n", ((float)((sim_time() * 1000) / sim_ticks_per_sec())) / 1000, publisher_addr); +call Leds.led1Off(); signal DelugePageTransfer.receivedPage(workingObjid, workingPgNum); changeState(S_IDLE); size = 0; @@ -496,4 +484,5 @@ dbg("Deluge", "%.3f 115 116 116 117 115 2 %d\n", ((float)((sim_time() * 1000) / default command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } default command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } default async command void Leds.led1Toggle() {} + default async command void Leds.led1Off() {} } diff --git a/tos/lib/net/Deluge/DelugeStorage.nc b/tos/lib/net/Deluge/DelugeStorage.nc deleted file mode 100644 index 15f1ed01..00000000 --- a/tos/lib/net/Deluge/DelugeStorage.nc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2005-2006 Arch Rock Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - Neither the name of the Arch Rock Corporation nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 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 - * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * 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 - */ - -/** - * An abstraction to map volume addresses to physical addresses. - * - * @author Jonathan Hui - * @version $Revision$ $Date$ - */ - -/** - * The same as StorageMap interface for STM25P. - * - * @author Chieh-Jan Mike Liang - * @author Razvan Musaloiu-E. - */ - -interface DelugeStorage { - - /** - * Get the physical address of a volume address. - * - * @param addr the volume addres. - * @return the physical address. - */ - command storage_addr_t getPhysicalAddress(storage_addr_t addr); -} diff --git a/tos/lib/net/Deluge/DelugeStorageC.nc b/tos/lib/net/Deluge/DelugeStorageC.nc deleted file mode 100644 index 214f4a86..00000000 --- a/tos/lib/net/Deluge/DelugeStorageC.nc +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2007 Johns Hopkins University. -* All rights reserved. -* -* Permission to use, copy, modify, and distribute this software and its -* documentation for any purpose, without fee, and without written -* agreement is hereby granted, provided that the above copyright -* notice, the (updated) modification history and the author appear in -* all copies of this source code. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS -* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, -* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -* THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @author Chieh-Jan Mike Liang - * @author Razvan Musaloiu-E. - */ - -#include "StorageVolumes.h" - -configuration DelugeStorageC -{ - provides { - interface BlockRead[uint8_t img_num]; - interface BlockWrite[uint8_t img_num]; - interface DelugeStorage[uint8_t img_num]; - interface DelugeMetadata; - - interface Notify as ReadyNotify; - } -} - -implementation -{ - components DelugeStorageP; - - BlockRead[VOLUME_GOLDENIMAGE] = DelugeStorageP.BlockRead[VOLUME_GOLDENIMAGE]; - BlockWrite[VOLUME_GOLDENIMAGE] = DelugeStorageP.BlockWrite[VOLUME_GOLDENIMAGE]; - BlockRead[VOLUME_DELUGE1] = DelugeStorageP.BlockRead[VOLUME_DELUGE1]; - BlockWrite[VOLUME_DELUGE1] = DelugeStorageP.BlockWrite[VOLUME_DELUGE1]; - BlockRead[VOLUME_DELUGE2] = DelugeStorageP.BlockRead[VOLUME_DELUGE2]; - BlockWrite[VOLUME_DELUGE2] = DelugeStorageP.BlockWrite[VOLUME_DELUGE2]; - BlockRead[VOLUME_DELUGE3] = DelugeStorageP.BlockRead[VOLUME_DELUGE3]; - BlockWrite[VOLUME_DELUGE3] = DelugeStorageP.BlockWrite[VOLUME_DELUGE3]; - DelugeMetadata = DelugeStorageP.DelugeMetadata; - - components new BlockStorageC(VOLUME_GOLDENIMAGE) as BlockStorageC_Golden; - DelugeStorageP.SubBlockRead[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; - DelugeStorageP.SubBlockWrite[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; - - components new BlockStorageC(VOLUME_DELUGE1) as BlockStorageC_1; - DelugeStorageP.SubBlockRead[VOLUME_DELUGE1] -> BlockStorageC_1; - DelugeStorageP.SubBlockWrite[VOLUME_DELUGE1] -> BlockStorageC_1; - - components new BlockStorageC(VOLUME_DELUGE2) as BlockStorageC_2; - DelugeStorageP.SubBlockRead[VOLUME_DELUGE2] -> BlockStorageC_2; - DelugeStorageP.SubBlockWrite[VOLUME_DELUGE2] -> BlockStorageC_2; - - components new BlockStorageC(VOLUME_DELUGE3) as BlockStorageC_3; - DelugeStorageP.SubBlockRead[VOLUME_DELUGE3] -> BlockStorageC_3; - DelugeStorageP.SubBlockWrite[VOLUME_DELUGE3] -> BlockStorageC_3; - -#if defined(PLATFORM_TELOSB) - DelugeStorageP.StorageMap[VOLUME_GOLDENIMAGE] -> BlockStorageC_Golden; - DelugeStorageP.StorageMap[VOLUME_DELUGE1] -> BlockStorageC_1; - DelugeStorageP.StorageMap[VOLUME_DELUGE2] -> BlockStorageC_2; - DelugeStorageP.StorageMap[VOLUME_DELUGE3] -> BlockStorageC_3; -#elif defined(PLATFORM_MICAZ) - components At45dbStorageManagerC; - DelugeStorageP.At45dbVolume[VOLUME_GOLDENIMAGE] -> At45dbStorageManagerC.At45dbVolume[VOLUME_GOLDENIMAGE]; - DelugeStorageP.At45dbVolume[VOLUME_DELUGE1] -> At45dbStorageManagerC.At45dbVolume[VOLUME_DELUGE1]; - DelugeStorageP.At45dbVolume[VOLUME_DELUGE2] -> At45dbStorageManagerC.At45dbVolume[VOLUME_DELUGE2]; - DelugeStorageP.At45dbVolume[VOLUME_DELUGE3] -> At45dbStorageManagerC.At45dbVolume[VOLUME_DELUGE3]; -#else - #error "Target platform is not currently supported by Deluge T2" -#endif - - DelugeStorage[VOLUME_GOLDENIMAGE] = DelugeStorageP.DelugeStorage[VOLUME_GOLDENIMAGE]; - DelugeStorage[VOLUME_DELUGE1] = DelugeStorageP.DelugeStorage[VOLUME_DELUGE1]; - DelugeStorage[VOLUME_DELUGE2] = DelugeStorageP.DelugeStorage[VOLUME_DELUGE2]; - DelugeStorage[VOLUME_DELUGE3] = DelugeStorageP.DelugeStorage[VOLUME_DELUGE3]; - - components LedsC, MainC; - DelugeStorageP.Leds -> LedsC; - DelugeStorageP.Boot -> MainC; - - ReadyNotify = DelugeStorageP.ReadyNotify; -} diff --git a/tos/lib/net/Deluge/DelugeStorageP.nc b/tos/lib/net/Deluge/DelugeStorageP.nc deleted file mode 100644 index 563ecd12..00000000 --- a/tos/lib/net/Deluge/DelugeStorageP.nc +++ /dev/null @@ -1,285 +0,0 @@ -/* Copyright (c) 2007 Johns Hopkins University. -* All rights reserved. -* -* Permission to use, copy, modify, and distribute this software and its -* documentation for any purpose, without fee, and without written -* agreement is hereby granted, provided that the above copyright -* notice, the (updated) modification history and the author appear in -* all copies of this source code. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS -* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, -* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -* THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @author Chieh-Jan Mike Liang - * @author Razvan Musaloiu-E. - */ - -#include "Deluge.h" -#include "DelugePageTransfer.h" - -module DelugeStorageP -{ - uses { - interface BlockRead as SubBlockRead[uint8_t img_num]; - interface BlockWrite as SubBlockWrite[uint8_t img_num]; - interface Boot; - interface Leds; -#if defined(PLATFORM_TELOSB) - interface StorageMap[uint8_t img_num]; -#elif defined(PLATFORM_MICAZ) - interface At45dbVolume[volume_id_t img_num]; -#endif - } - provides { - interface BlockRead[uint8_t img_num]; - interface BlockWrite[uint8_t img_num]; - interface DelugeStorage[uint8_t img_num]; - interface DelugeMetadata; - - interface Notify as ReadyNotify; - } -} - -implementation -{ - enum { - S_READ_META, - S_READ_CRC, - S_CRC, - S_READY, - }; - - uint8_t state; - uint8_t current_image; - uint8_t current_page; - uint16_t current_crc; - DelugeImgDesc imgDesc[DELUGE_NUM_VOLUMES]; - - void nextImage() - { - if (current_image < DELUGE_NUM_VOLUMES) { - state = S_READ_META; - call SubBlockRead.read[current_image](0, &(imgDesc[current_image]), sizeof(DelugeImgDesc)); - } else { - signal ReadyNotify.notify(SUCCESS); - state = S_READY; - } - } - - uint32_t calcCrcAddr() - { - return DELUGE_METADATA_SIZE + current_page * sizeof(uint16_t); - } - - uint32_t calcPageAddr() - { - return DELUGE_METADATA_SIZE + current_page * DELUGE_BYTES_PER_PAGE; - } - - event void Boot.booted() - { - uint32_t i; - for (i = 0; i < DELUGE_NUM_VOLUMES; i++) { - imgDesc[i].uid = DELUGE_INVALID_UID; - imgDesc[i].vNum = 0; - imgDesc[i].imgNum = 0; - imgDesc[i].numPgs = 0; - imgDesc[i].crc = 0; - imgDesc[i].numPgsComplete = 0; - imgDesc[i].reserved = 0; - imgDesc[i].size = 0; - } - - // We are going to iterate over all the images and verify their - // integrity. For each image we first read the metadata to find - // the number of pages and then iterate over all of them, compute - // the CRC and check it against the corresponding value from the CRCs - // block. - state = S_READ_META; - current_image = 0; - nextImage(); - } - - command DelugeImgDesc* DelugeMetadata.getImgDesc(imgnum_t imgNum) - { - return &(imgDesc[imgNum]); - } - - // SubBlockRead commands - command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) - { - return call SubBlockRead.read[img_num](addr, buf, len); - } - - command error_t BlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc) - { - return call SubBlockRead.computeCrc[img_num](addr, len, crc); - } - - command storage_len_t BlockRead.getSize[uint8_t img_num]() - { - return call SubBlockRead.getSize[img_num](); - } - - // BlockRead events - event void SubBlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) - { - switch (state) { - case S_READY: - signal BlockRead.readDone[img_num](addr, buf, len, error); - break; - case S_READ_META: - if (error == SUCCESS) { - if (imgDesc[current_image].uid != DELUGE_INVALID_UID) { - current_page = 0; - state = S_READ_CRC; - call SubBlockRead.read[current_image](calcCrcAddr(), ¤t_crc, sizeof(current_crc)); - } else { - current_image++; - nextImage(); - } - } - break; - case S_READ_CRC: - state = S_CRC; - if (current_page == 0) { - call SubBlockRead.computeCrc[current_image](calcPageAddr() + DELUGE_CRC_BLOCK_SIZE, - DELUGE_BYTES_PER_PAGE - DELUGE_CRC_BLOCK_SIZE, 0); - } else { - call SubBlockRead.computeCrc[current_image](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0); - } - break; - } - } - - event void SubBlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) - { - switch (state) { - case S_READY: - signal BlockRead.computeCrcDone[img_num](addr, len, crc, error); - break; - case S_CRC: - if (crc != current_crc) { - // invalidate the image by erasing it - call SubBlockWrite.erase[current_image](); - } else { - current_page++; - if (current_page < imgDesc[current_image].numPgs) { - state = S_READ_CRC; - call SubBlockRead.read[current_image](calcCrcAddr(), ¤t_crc, sizeof(current_crc)); - } else { - current_image++; - nextImage(); - } - } - break; - } - } - - // SubBlockWrite commands - command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) - { - return call SubBlockWrite.write[img_num](addr, buf, len); - } - - command error_t BlockWrite.erase[uint8_t img_num]() - { - return call SubBlockWrite.erase[img_num](); - } - - command error_t BlockWrite.sync[uint8_t img_num]() - { - return call SubBlockWrite.sync[img_num](); - } - - // BlockWrite events - event void SubBlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) - { - if (error == SUCCESS) { - if (addr < sizeof(DelugeImgDesc)) { - memcpy((char*)&(imgDesc[img_num]) + addr, buf, sizeof(DelugeImgDesc) - addr); - } - } - - signal BlockWrite.writeDone[img_num](addr, buf, len, error); - } - - event void SubBlockWrite.eraseDone[uint8_t img_num](error_t error) - { - if (error == SUCCESS) { - // Successful erase triggers resetting the cached image description - imgDesc[img_num].uid = DELUGE_INVALID_UID; - imgDesc[img_num].vNum = 0; - imgDesc[img_num].imgNum = 0; - imgDesc[img_num].numPgs = 0; - imgDesc[img_num].crc = 0; - imgDesc[img_num].numPgsComplete = 0; - imgDesc[img_num].reserved = 0; - imgDesc[img_num].size = 0; - } - - switch (state) { - case S_READY: - signal BlockWrite.eraseDone[img_num](error); - break; - case S_CRC: - current_image++; - nextImage(); - break; - } - } - - event void SubBlockWrite.syncDone[uint8_t img_num](error_t error) - { - signal BlockWrite.syncDone[img_num](error); - } - - command storage_addr_t DelugeStorage.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) - { - storage_addr_t p_addr = 0xFFFFFFFF; - - #if defined(PLATFORM_TELOSB) - p_addr = call StorageMap.getPhysicalAddress[img_num](addr); - #elif defined(PLATFORM_MICAZ) - at45page_t page = call At45dbVolume.remap[img_num]((addr >> AT45_PAGE_SIZE_LOG2)); - at45pageoffset_t offset = addr & ((1 << AT45_PAGE_SIZE_LOG2) - 1); - p_addr = page; - p_addr = p_addr << AT45_PAGE_SIZE_LOG2; - p_addr += offset; - #endif - - return p_addr; - } - - default event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} - default event void BlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {} - default event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} - default event void BlockWrite.eraseDone[uint8_t img_num](error_t error) {} - default event void BlockWrite.syncDone[uint8_t img_num](error_t error) {} - - default command error_t SubBlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } - default command error_t SubBlockWrite.erase[uint8_t img_num]() { return FAIL; } - default command error_t SubBlockWrite.sync[uint8_t img_num]() { return FAIL; } - default command error_t SubBlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } - default command error_t SubBlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } - default command storage_len_t SubBlockRead.getSize[uint8_t img_num]() { return 0; } - - command error_t ReadyNotify.enable() { return SUCCESS; } - command error_t ReadyNotify.disable() { return SUCCESS; } - -#if defined(PLATFORM_TELOSB) - default command storage_addr_t StorageMap.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) { return 0xFFFFFFFF; } -#elif defined(PLATFORM_MICAZ) - default command at45page_t At45dbVolume.remap[volume_id_t volid](at45page_t volumePage) { return 0xFFFF; }; -#endif -} diff --git a/tos/lib/net/Deluge/DelugeVolumeManager.nc b/tos/lib/net/Deluge/DelugeVolumeManager.nc new file mode 100644 index 00000000..4f9f7970 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeVolumeManager.nc @@ -0,0 +1,31 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +interface DelugeVolumeManager +{ + command error_t erase(uint8_t imgNum); + event void eraseDone(uint8_t imgNum); +} diff --git a/tos/lib/net/Deluge/DelugeVolumeManagerC.nc b/tos/lib/net/Deluge/DelugeVolumeManagerC.nc new file mode 100644 index 00000000..832ec06c --- /dev/null +++ b/tos/lib/net/Deluge/DelugeVolumeManagerC.nc @@ -0,0 +1,49 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +configuration DelugeVolumeManagerC +{ + provides interface DelugeVolumeManager[uint8_t client]; +} + +implementation +{ + components DelugeVolumeManagerP; + + DelugeVolumeManager = DelugeVolumeManagerP; + + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; + + DelugeVolumeManagerP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + DelugeVolumeManagerP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + DelugeVolumeManagerP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; + + DelugeVolumeManagerP.Resource[VOLUME_DELUGE1] -> BlockWriterDeluge1; + DelugeVolumeManagerP.Resource[VOLUME_DELUGE2] -> BlockWriterDeluge2; + DelugeVolumeManagerP.Resource[VOLUME_DELUGE3] -> BlockWriterDeluge3; +} diff --git a/tos/lib/net/Deluge/DelugeVolumeManagerClientC.nc b/tos/lib/net/Deluge/DelugeVolumeManagerClientC.nc new file mode 100644 index 00000000..31807b56 --- /dev/null +++ b/tos/lib/net/Deluge/DelugeVolumeManagerClientC.nc @@ -0,0 +1,40 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +generic configuration DelugeVolumeManagerClientC() +{ + provides interface DelugeVolumeManager; +} + +implementation +{ + enum { + CLIENT_ID = unique(UQ_DELUGE_VOLUME_MANAGER) + }; + + components DelugeVolumeManagerC; + DelugeVolumeManager = DelugeVolumeManagerC.DelugeVolumeManager[CLIENT_ID]; +} diff --git a/tos/lib/net/Deluge/DelugeVolumeManagerP.nc b/tos/lib/net/Deluge/DelugeVolumeManagerP.nc new file mode 100644 index 00000000..87f1c5fe --- /dev/null +++ b/tos/lib/net/Deluge/DelugeVolumeManagerP.nc @@ -0,0 +1,71 @@ +/* Copyright (c) 2007 Johns Hopkins University. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose, without fee, and without written +* agreement is hereby granted, provided that the above copyright +* notice, the (updated) modification history and the author appear in +* all copies of this source code. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, +* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang + */ + +module DelugeVolumeManagerP +{ + provides interface DelugeVolumeManager[uint8_t client]; + uses { + interface BlockWrite[uint8_t volumeId]; + interface Resource[uint8_t volumeId]; + } +} + +implementation +{ + uint8_t currentClient; + bool busy = FALSE; + + command error_t DelugeVolumeManager.erase[uint8_t client](uint8_t imgNum) + { + if (busy) + return FAIL; + busy = call Resource.request[imgNum]() == SUCCESS; + if (busy) { + currentClient = client; + return SUCCESS; + } + return FAIL; + } + + event void Resource.granted[uint8_t imgNum]() + { + call BlockWrite.erase[imgNum](); + } + + event void BlockWrite.eraseDone[uint8_t imgNum](error_t error) + { + busy = FALSE; + call Resource.release[imgNum](); + signal DelugeVolumeManager.eraseDone[currentClient](error); + } + + event void BlockWrite.writeDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {} + event void BlockWrite.syncDone[uint8_t imgNum](error_t error) {} + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + default event void DelugeVolumeManager.eraseDone[uint8_t client](uint8_t imgNum) {} + default async command error_t Resource.request[uint8_t imgNum]() { return FAIL; } + default async command error_t Resource.release[uint8_t imgNum]() { return FAIL; } +} diff --git a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManager.h b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManager.h deleted file mode 100644 index 9af71b10..00000000 --- a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManager.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2007 Johns Hopkins University. -* All rights reserved. -* -* Permission to use, copy, modify, and distribute this software and its -* documentation for any purpose, without fee, and without written -* agreement is hereby granted, provided that the above copyright -* notice, the (updated) modification history and the author appear in -* all copies of this source code. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS -* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, -* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -* THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - * @author Chieh-Jan Mike Liang - * @author Razvan Musaloiu-E. - */ - -#ifndef FLASHVOLUMEMANAGER_H -#define FLASHVOLUMEMANAGER_H - -#define SERIALMSG_ERASE 0 -#define SERIALMSG_WRITE 1 -#define SERIALMSG_READ 2 -#define SERIALMSG_CRC 3 -#define SERIALMSG_ADDR 4 -#define SERIALMSG_REPROG 5 -#define SERIALMSG_DISS 6 -#define SERIALMSG_REPROG_BS 7 -#define SERIALMSG_SYNC 8 -#define SERIALMSG_IDENT 9 - -typedef nx_struct SerialReqPacket { - nx_uint8_t msg_type; - nx_uint8_t img_num; - nx_uint16_t offset; - nx_uint16_t len; - nx_uint8_t data[0]; -} SerialReqPacket; - -#define SERIALMSG_SUCCESS 0 -#define SERIALMSG_FAIL 1 - -typedef nx_struct SerialReplyPacket { - nx_uint8_t error; - nx_uint8_t data[0]; -} SerialReplyPacket; - -#endif diff --git a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerC.nc b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerC.nc index 7ef0c385..19b769d3 100644 --- a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerC.nc +++ b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerC.nc @@ -27,51 +27,46 @@ #include "AM.h" #include "StorageVolumes.h" -generic configuration FlashVolumeManagerC(am_id_t AMId) -{ -#ifdef DELUGE - provides interface Notify as DissNotify; - provides interface Notify as ReprogNotify; -#endif - uses { - interface BlockRead[uint8_t img_num]; - interface BlockWrite[uint8_t img_num]; -#ifdef DELUGE - interface DelugeStorage[uint8_t img_num]; -#endif - } -} +generic configuration FlashVolumeManagerC(am_id_t AMId) {} implementation { - components new SerialAMSenderC(AMId), - new SerialAMReceiverC(AMId), - new FlashVolumeManagerP(), - NoLedsC, LedsC; + components new SerialAMSenderC(AMId); + components new SerialAMReceiverC(AMId); + components new FlashVolumeManagerP(); + components new TimerMilliC() as TimeoutTimer; + components NoLedsC, LedsC; + components BlockStorageLockC; + + components new BlockReaderC(VOLUME_GOLDENIMAGE) as BlockReaderGoldenImage; + components new BlockReaderC(VOLUME_DELUGE1) as BlockReaderDeluge1; + components new BlockReaderC(VOLUME_DELUGE2) as BlockReaderDeluge2; + components new BlockReaderC(VOLUME_DELUGE3) as BlockReaderDeluge3; + + components new BlockWriterC(VOLUME_GOLDENIMAGE) as BlockWriterGoldenImage; + components new BlockWriterC(VOLUME_DELUGE1) as BlockWriterDeluge1; + components new BlockWriterC(VOLUME_DELUGE2) as BlockWriterDeluge2; + components new BlockWriterC(VOLUME_DELUGE3) as BlockWriterDeluge3; - FlashVolumeManagerP.BlockRead[VOLUME_GOLDENIMAGE] = BlockRead[VOLUME_GOLDENIMAGE]; - FlashVolumeManagerP.BlockWrite[VOLUME_GOLDENIMAGE] = BlockWrite[VOLUME_GOLDENIMAGE]; - FlashVolumeManagerP.BlockRead[VOLUME_DELUGE1] = BlockRead[VOLUME_DELUGE1]; - FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE1] = BlockWrite[VOLUME_DELUGE1]; - FlashVolumeManagerP.BlockRead[VOLUME_DELUGE2] = BlockRead[VOLUME_DELUGE2]; - FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE2] = BlockWrite[VOLUME_DELUGE2]; - FlashVolumeManagerP.BlockRead[VOLUME_DELUGE3] = BlockRead[VOLUME_DELUGE3]; - FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE3] = BlockWrite[VOLUME_DELUGE3]; + FlashVolumeManagerP.BlockRead[VOLUME_GOLDENIMAGE] -> BlockReaderGoldenImage; + FlashVolumeManagerP.BlockRead[VOLUME_DELUGE1] -> BlockReaderDeluge1; + FlashVolumeManagerP.BlockRead[VOLUME_DELUGE2] -> BlockReaderDeluge2; + FlashVolumeManagerP.BlockRead[VOLUME_DELUGE3] -> BlockReaderDeluge3; + + FlashVolumeManagerP.BlockWrite[VOLUME_GOLDENIMAGE] -> BlockWriterGoldenImage; + FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE1] -> BlockWriterDeluge1; + FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE2] -> BlockWriterDeluge2; + FlashVolumeManagerP.BlockWrite[VOLUME_DELUGE3] -> BlockWriterDeluge3; + + FlashVolumeManagerP.Resource[VOLUME_GOLDENIMAGE] -> BlockWriterGoldenImage; + FlashVolumeManagerP.Resource[VOLUME_DELUGE1] -> BlockWriterDeluge1; + FlashVolumeManagerP.Resource[VOLUME_DELUGE2] -> BlockWriterDeluge2; + FlashVolumeManagerP.Resource[VOLUME_DELUGE3] -> BlockWriterDeluge3; + + FlashVolumeManagerP.ArbiterInfo -> BlockStorageLockC; + FlashVolumeManagerP.TimeoutTimer -> TimeoutTimer; FlashVolumeManagerP.SerialAMSender -> SerialAMSenderC; FlashVolumeManagerP.SerialAMReceiver -> SerialAMReceiverC; - FlashVolumeManagerP.Leds -> NoLedsC; - -#ifdef DELUGE - components NetProgC, new TimerMilliC(); - - FlashVolumeManagerP.NetProg -> NetProgC; - FlashVolumeManagerP.Timer -> TimerMilliC; - FlashVolumeManagerP.DelugeStorage[VOLUME_GOLDENIMAGE] = DelugeStorage[VOLUME_GOLDENIMAGE]; - FlashVolumeManagerP.DelugeStorage[VOLUME_DELUGE1] = DelugeStorage[VOLUME_DELUGE1]; - FlashVolumeManagerP.DelugeStorage[VOLUME_DELUGE2] = DelugeStorage[VOLUME_DELUGE2]; - FlashVolumeManagerP.DelugeStorage[VOLUME_DELUGE3] = DelugeStorage[VOLUME_DELUGE3]; - DissNotify = FlashVolumeManagerP.DissNotify; - ReprogNotify = FlashVolumeManagerP.ReprogNotify; -#endif + FlashVolumeManagerP.Leds -> LedsC; } diff --git a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc index c728b11f..138c6b02 100644 --- a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc +++ b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc @@ -24,33 +24,46 @@ * @author Razvan Musaloiu-E. */ -#include "FlashVolumeManager.h" - generic module FlashVolumeManagerP() { -#ifdef DELUGE - provides { - interface Notify as DissNotify; - interface Notify as ReprogNotify; - } -#endif uses { - interface BlockRead[uint8_t img_num]; - interface BlockWrite[uint8_t img_num]; -#ifdef DELUGE - interface DelugeStorage[uint8_t img_num]; - interface NetProg; - interface Timer as Timer; -#endif + interface BlockRead[uint8_t imgNum]; + interface BlockWrite[uint8_t imgNum]; + interface Resource[uint8_t imgNum]; + interface ArbiterInfo; interface AMSend as SerialAMSender; interface Receive as SerialAMReceiver; + interface Timer as TimeoutTimer; interface Leds; } } implementation { - // States for keeping track of split-phase events + typedef nx_struct SerialReqPacket { + nx_uint8_t cmd; + nx_uint8_t imgNum; + nx_uint16_t offset; + nx_uint16_t len; + nx_uint8_t data[0]; + } SerialReqPacket; + + typedef nx_struct SerialReplyPacket { + nx_uint8_t error; + nx_uint8_t data[0]; + } SerialReplyPacket; + + + enum { + CMD_ERASE = 0, + CMD_WRITE = 1, + CMD_READ = 2, + CMD_CRC = 3, + CMD_ADDR = 4, + CMD_SYNC = 5, + CMD_IDENT = 6 + }; + enum { S_IDLE, S_ERASE, @@ -62,45 +75,47 @@ implementation }; message_t serialMsg; - uint8_t buffer[TOSH_DATA_LENGTH]; // Temporary buffer for "write" operation - uint8_t img_num_reboot = 0xFF; // Image number to reprogram + uint8_t buffer[TOSH_DATA_LENGTH]; // Temporary buffer for "write" operation + uint8_t currentImgNum = 0xFF; // Image number to reprogram uint8_t state = S_IDLE; // Manager state for multiplexing "done" events + + nx_struct ShortIdent { + nx_uint8_t name[16]; + //nx_uint8_t username[16]; + //nx_uint8_t hostname[16]; + nx_uint32_t timestamp; + nx_uint32_t uidhash; + nx_uint16_t nodeid; + }; - /** - * Replies to the PC request with operation results - */ void sendReply(error_t error, storage_len_t len) { - SerialReplyPacket *srpkt = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); - if (srpkt == NULL) { + SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); + if (reply == NULL) { return; } - if (error == SUCCESS) { - srpkt->error = SERIALMSG_SUCCESS; - } else { - srpkt->error = SERIALMSG_FAIL; - } + reply->error = error; call SerialAMSender.send(AM_BROADCAST_ADDR, &serialMsg, len); } - event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, + event void BlockRead.readDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) { if (state == S_READ) { - SerialReplyPacket *serialMsg_payload = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); - if (serialMsg_payload == NULL) { + SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); + if (reply == NULL) { return; } - if (buf == serialMsg_payload->data) { + if (buf == reply->data) { state = S_IDLE; sendReply(error, len + sizeof(SerialReplyPacket)); } } } - event void BlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, + event void BlockRead.computeCrcDone[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) @@ -120,7 +135,7 @@ implementation } } - event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, + event void BlockWrite.writeDone[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len, error_t error) @@ -131,14 +146,14 @@ implementation } } - event void BlockWrite.eraseDone[uint8_t img_num](error_t error) + event void BlockWrite.eraseDone[uint8_t imgNum](error_t error) { if (state == S_ERASE) { - call BlockWrite.sync[img_num](); + call BlockWrite.sync[imgNum](); } } - event void BlockWrite.syncDone[uint8_t img_num](error_t error) + event void BlockWrite.syncDone[uint8_t imgNum](error_t error) { if (state == S_ERASE || state == S_SYNC) { state = S_IDLE; @@ -146,91 +161,93 @@ implementation } } - event void SerialAMSender.sendDone(message_t* msg, error_t error) {} - + event message_t* SerialAMReceiver.receive(message_t* msg, void* payload, uint8_t len) { error_t error = SUCCESS; - SerialReqPacket *srpkt = (SerialReqPacket *)payload; - SerialReplyPacket *serialMsg_payload = - (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); - uint8_t img_num = 0xFF; + SerialReqPacket *request = (SerialReqPacket *)payload; + SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket)); + nx_struct ShortIdent *shortIdent; + uint8_t imgNum = 0xFF; + + if (reply == NULL) { + return msg; + } - if (serialMsg_payload == NULL) { + if (state != S_IDLE) { return msg; } + // Converts the image number that the user wants to the real image number - switch (srpkt->img_num) { + switch (request->imgNum) { case 0: - img_num = VOLUME_GOLDENIMAGE; + imgNum = VOLUME_GOLDENIMAGE; break; case 1: - img_num = VOLUME_DELUGE1; + imgNum = VOLUME_DELUGE1; break; case 2: - img_num = VOLUME_DELUGE2; + imgNum = VOLUME_DELUGE2; break; case 3: - img_num = VOLUME_DELUGE3; + imgNum = VOLUME_DELUGE3; break; } - if (img_num != 0xFF) { - switch (srpkt->msg_type) { - case SERIALMSG_ERASE: // === Erases a volume === + if (imgNum != 0xFF) { + error = SUCCESS; + // We ask for a reservation only for erase and write. + switch (request->cmd) { + case CMD_ERASE: + case CMD_WRITE: + if (!call Resource.isOwner[imgNum]()) { + error = call Resource.immediateRequest[imgNum](); + } + } + if (error == SUCCESS) { + call Leds.led1On(); + call TimeoutTimer.startOneShot(2*1024); + currentImgNum = imgNum; + switch (request->cmd) { + case CMD_ERASE: // === Erases a volume === state = S_ERASE; - error = call BlockWrite.erase[img_num](); + error = call BlockWrite.erase[imgNum](); break; - case SERIALMSG_WRITE: // === Writes to a volume === + case CMD_WRITE: // === Writes to a volume === state = S_WRITE; - memcpy(buffer, srpkt->data, srpkt->len); - error = call BlockWrite.write[img_num](srpkt->offset, - buffer, - srpkt->len); + memcpy(buffer, request->data, request->len); + error = call BlockWrite.write[imgNum](request->offset, + buffer, + request->len); break; - case SERIALMSG_READ: // === Reads a portion of a volume === + case CMD_READ: // === Reads a portion of a volume === state = S_READ; - error = call BlockRead.read[img_num](srpkt->offset, - serialMsg_payload->data, - srpkt->len); + error = call BlockRead.read[imgNum](request->offset, + reply->data, + request->len); break; - case SERIALMSG_CRC: // === Computes CRC over a portion of a volume === + case CMD_CRC: // === Computes CRC over a portion of a volume === state = S_CRC; - error = call BlockRead.computeCrc[img_num](srpkt->offset, - srpkt->len, 0); + error = call BlockRead.computeCrc[imgNum](request->offset, + request->len, 0); break; - case SERIALMSG_SYNC: // === Sync the flash === + case CMD_SYNC: // === Sync the flash === state = S_SYNC; - error = call BlockWrite.sync[img_num](); + error = call BlockWrite.sync[imgNum](); break; - #ifdef DELUGE - case SERIALMSG_ADDR: // === Gets the physical starting address of a volume === - *(nx_uint32_t*)(&serialMsg_payload->data) = - (uint32_t)call DelugeStorage.getPhysicalAddress[img_num](0); - sendReply(SUCCESS, sizeof(SerialReplyPacket) + 4); - break; - case SERIALMSG_REPROG_BS: // === Reprograms only the base station === - state = S_REPROG; - sendReply(SUCCESS, sizeof(SerialReplyPacket)); - img_num_reboot = img_num; - call Timer.startOneShot(1024); - break; - case SERIALMSG_DISS: // === Starts disseminating a volume === - signal DissNotify.notify(img_num); // Notifies Deluge to start disseminate - sendReply(SUCCESS, sizeof(SerialReplyPacket)); - break; - case SERIALMSG_REPROG: // === Reprograms the network (except the base station) === - signal ReprogNotify.notify(img_num); - sendReply(SUCCESS, sizeof(SerialReplyPacket)); - break; - case SERIALMSG_IDENT: - // This is not send using nx_uint32 in order to maintain - // consistency with data from the Deluge image. - *(uint32_t*)(&serialMsg_payload->data) = IDENT_UID_HASH; - sendReply(SUCCESS, sizeof(SerialReplyPacket) + 4); + case CMD_IDENT: + shortIdent = (nx_struct ShortIdent*)&reply->data; + memset(shortIdent, 0, sizeof(nx_struct ShortIdent)); + memcpy(shortIdent->name, IDENT_APPNAME, sizeof(IDENT_APPNAME)); + //memcpy(shortIdent->username, IDENT_USER_ID, sizeof(IDENT_USER_ID)); + //memcpy(shortIdent->hostname, IDENT_HOSTNAME, sizeof(IDENT_HOSTNAME)); + shortIdent->timestamp = IDENT_TIMESTAMP; + shortIdent->uidhash = IDENT_UIDHASH; + shortIdent->nodeid = TOS_NODE_ID; + sendReply(SUCCESS, sizeof(SerialReplyPacket) + sizeof(nx_struct ShortIdent)); break; - #endif - } + } + } } else { error = FAIL; } @@ -244,24 +261,28 @@ implementation return msg; } -#ifdef DELUGE - event void Timer.fired() + event void TimeoutTimer.fired() { - // Reboots and reprograms - call NetProg.programImgAndReboot(img_num_reboot); + // Release the resource. + if (state == S_IDLE && call Resource.isOwner[currentImgNum]()) { + call Leds.led1Off(); + call Resource.release[currentImgNum](); + } + if (state == S_IDLE && !call ArbiterInfo.inUse()) { + call Leds.led1Off(); + } } - - command error_t DissNotify.enable() { return SUCCESS; } - command error_t DissNotify.disable() { return SUCCESS; } - command error_t ReprogNotify.enable() { return SUCCESS; } - command error_t ReprogNotify.disable() { return SUCCESS; } - - default command storage_addr_t DelugeStorage.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) { return 0; } -#endif - default command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } - default command error_t BlockWrite.erase[uint8_t img_num]() { return FAIL; } - default command error_t BlockWrite.sync[uint8_t img_num]() { return FAIL; } - default command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } - default command error_t BlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + event void SerialAMSender.sendDone(message_t* msg, error_t error) {} + event void Resource.granted[uint8_t imgNum]() {} + + default command error_t BlockWrite.write[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockWrite.erase[uint8_t imgNum]() { return FAIL; } + default command error_t BlockWrite.sync[uint8_t imgNum]() { return FAIL; } + default command error_t BlockRead.read[uint8_t imgNum](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; } + default command error_t BlockRead.computeCrc[uint8_t imgNum](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; } + + default async command error_t Resource.immediateRequest[uint8_t imgNum]() { return FAIL; } + default async command error_t Resource.release[uint8_t imgNum]() { return FAIL; } + default async command bool Resource.isOwner[uint8_t imgNum]() { return FAIL; } } diff --git a/tos/lib/net/Deluge/ObjectTransferC.nc b/tos/lib/net/Deluge/ObjectTransferC.nc index 03ace370..8e77dc63 100644 --- a/tos/lib/net/Deluge/ObjectTransferC.nc +++ b/tos/lib/net/Deluge/ObjectTransferC.nc @@ -40,17 +40,12 @@ configuration ObjectTransferC implementation { components ObjectTransferP, DelugePageTransferC; + components CrcP; ObjectTransfer = ObjectTransferP; - BlockRead[VOLUME_DELUGE1] = DelugePageTransferC.BlockRead[VOLUME_DELUGE1]; - BlockWrite[VOLUME_DELUGE1] = DelugePageTransferC.BlockWrite[VOLUME_DELUGE1]; - BlockRead[VOLUME_DELUGE2] = DelugePageTransferC.BlockRead[VOLUME_DELUGE2]; - BlockWrite[VOLUME_DELUGE2] = DelugePageTransferC.BlockWrite[VOLUME_DELUGE2]; - BlockRead[VOLUME_DELUGE3] = DelugePageTransferC.BlockRead[VOLUME_DELUGE3]; - BlockWrite[VOLUME_DELUGE3] = DelugePageTransferC.BlockWrite[VOLUME_DELUGE3]; + DelugePageTransferC.BlockRead = BlockRead; + DelugePageTransferC.BlockWrite = BlockWrite; ObjectTransferP.DelugePageTransfer -> DelugePageTransferC.DelugePageTransfer; - - components CrcP; ObjectTransferP.Crc -> CrcP.Crc; components new AMSenderC(AM_DELUGEADVMSG) as SendAdvMsg, @@ -69,9 +64,7 @@ implementation DelugePageTransferC.AMPacket -> SendDataMsg; DelugePageTransferC.Leds = Leds; - ObjectTransferP.BlockWrite[VOLUME_DELUGE1] = BlockWrite[VOLUME_DELUGE1]; - ObjectTransferP.BlockWrite[VOLUME_DELUGE2] = BlockWrite[VOLUME_DELUGE2]; - ObjectTransferP.BlockWrite[VOLUME_DELUGE3] = BlockWrite[VOLUME_DELUGE3]; + ObjectTransferP.BlockWrite = BlockWrite; components RandomC, new TimerMilliC() as Timer; ObjectTransferP.Random -> RandomC; diff --git a/tos/lib/net/Deluge/ObjectTransferP.nc b/tos/lib/net/Deluge/ObjectTransferP.nc index 88878217..d3ef9f3a 100644 --- a/tos/lib/net/Deluge/ObjectTransferP.nc +++ b/tos/lib/net/Deluge/ObjectTransferP.nc @@ -63,7 +63,6 @@ implementation }; DelugeAdvTimer advTimers; - //DelugeNodeDesc nodeDesc; uint8_t state = S_STOPPED; object_id_t cont_receive_new_objid; @@ -117,11 +116,6 @@ implementation } } -// bool isNodeDescValid(DelugeNodeDesc* tmpNodeDesc) -// { -// return (tmpNodeDesc->crc == crc16(tmpNodeDesc, 4 + sizeof(object_id_t) + 1)); -// } - bool isObjDescValid(DelugeObjDesc* tmpObjDesc) { return (tmpObjDesc->crc == call Crc.crc16(tmpObjDesc, sizeof(object_id_t) + sizeof(page_num_t)) @@ -137,23 +131,11 @@ implementation if (isBusy_pMsgBuf == FALSE) { pMsg->sourceAddr = TOS_NODE_ID; pMsg->version = DELUGE_VERSION; - //pMsg->type = (imagesLoaded) ? DELUGE_ADV_NORMAL : DELUGE_ADV_ERROR; pMsg->type = DELUGE_ADV_NORMAL; - - // make sure node desc is valid -// if (!isNodeDescValid(&nodeDesc)) { -// memset(&nodeDesc, 0xff, sizeof(nodeDesc)); -// } -// memcpy(&pMsg->nodeDesc, &nodeDesc, sizeof(DelugeNodeDesc)); - - // make sure obj desc is valid -// if (!isObjDescValid(&curObjDesc)) { -// //curObjDesc.objid = objid; -// } + memcpy(&(pMsg->objDesc), &curObjDesc, sizeof(DelugeObjDesc)); if (call SendAdvMsg.send(addr, &pMsgBuf, sizeof(DelugeAdvMsg)) == SUCCESS) { - //dbg(DBG_USR1, "DELUGE: Sent ADV_MSG(imgNum=%d)\n", imgDesc->imgNum); //call StatsCollector.msg_bcastReq(); isBusy_pMsgBuf = TRUE; } @@ -243,6 +225,7 @@ implementation event void DelugePageTransfer.receivedPage(object_id_t new_objid, page_num_t new_pgNum) { +// printf("R: %08lx %d\n", new_objid, new_pgNum); if (new_objid == curObjDesc.objid && new_pgNum == curObjDesc.numPgsComplete) { curObjDesc.numPgsComplete++; curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t)); @@ -287,9 +270,7 @@ implementation return msg; } - if (rxAdvMsg->version != DELUGE_VERSION - //|| !isNodeDescValid(&rxAdvMsg->nodeDesc) - || state != S_STARTED) { + if (rxAdvMsg->version != DELUGE_VERSION || state != S_STARTED) { return msg; } diff --git a/tos/lib/net/Deluge/extra/NetProg.h b/tos/lib/net/Deluge/extra/NetProg.h index b8624c05..fd07e403 100644 --- a/tos/lib/net/Deluge/extra/NetProg.h +++ b/tos/lib/net/Deluge/extra/NetProg.h @@ -38,11 +38,11 @@ #endif static const uint32_t DELUGE_IMAGE_UID = IDENT_UID_HASH; - +/* typedef struct NetProg_TOSInfo { uint16_t addr; uint8_t groupId; uint16_t crc; } NetProg_TOSInfo; - +*/ #endif diff --git a/tos/lib/net/Deluge/extra/NetProg.nc b/tos/lib/net/Deluge/extra/NetProg.nc index 5762caef..a2164599 100644 --- a/tos/lib/net/Deluge/extra/NetProg.nc +++ b/tos/lib/net/Deluge/extra/NetProg.nc @@ -42,16 +42,14 @@ interface NetProg command error_t reboot(); /** - * Reboot into the image specified by imgNum. This - * assumes that an image has been downloaded into slot imgNum - * using Deluge. + * Reboot into the image specified by imageAddr. This + * assumes that an image is present into the external flash + * at the imageAddr address. * - * @param imgNum Number of image to boot in to. + * @param imageAddr Address in external flash * @return FAIL if the reboot command fails to - * complete due to an invalid imgNum or incomplete - * image, - * does not return, otherwise. + * complete, does not return, otherwise. */ - command error_t programImgAndReboot(uint8_t imgNum); + command error_t programImageAndReboot(uint32_t imageAddr); } diff --git a/tos/lib/net/Deluge/extra/NetProgC.nc b/tos/lib/net/Deluge/extra/NetProgC.nc index aeef0279..8a4c6c12 100644 --- a/tos/lib/net/Deluge/extra/NetProgC.nc +++ b/tos/lib/net/Deluge/extra/NetProgC.nc @@ -40,17 +40,11 @@ configuration NetProgC { implementation { - components MainC, InternalFlashC as IFlash, CrcP, - DelugeStorageC, NetProgM; + components MainC, InternalFlashC as IFlash, CrcP, NetProgM; NetProg = NetProgM; MainC.SoftwareInit -> NetProgM.Init; - NetProgM.DelugeStorage[VOLUME_GOLDENIMAGE] -> DelugeStorageC.DelugeStorage[VOLUME_GOLDENIMAGE]; - NetProgM.DelugeStorage[VOLUME_DELUGE1] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE1]; - NetProgM.DelugeStorage[VOLUME_DELUGE2] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE2]; - NetProgM.DelugeStorage[VOLUME_DELUGE3] -> DelugeStorageC.DelugeStorage[VOLUME_DELUGE3]; - NetProgM.DelugeMetadata -> DelugeStorageC; NetProgM.IFlash -> IFlash; NetProgM.Crc -> CrcP; diff --git a/tos/lib/net/Deluge/extra/NetProgM.nc b/tos/lib/net/Deluge/extra/NetProgM.nc index 413abc00..ad39d254 100644 --- a/tos/lib/net/Deluge/extra/NetProgM.nc +++ b/tos/lib/net/Deluge/extra/NetProgM.nc @@ -25,8 +25,8 @@ /** * @author Jonathan Hui - * @author Chieh-Jan Mike Liang * @author Razvan Musaloiu-E. + * @author Chieh-Jan Mike Liang */ #include "AM.h" @@ -37,10 +37,8 @@ module NetProgM { interface Init; } uses { - interface DelugeStorage[uint8_t img_num]; interface InternalFlash as IFlash; interface Crc; - interface DelugeMetadata; interface Leds; interface CC2420Config; async command void setAmAddress(am_addr_t a); @@ -49,82 +47,52 @@ module NetProgM { implementation { - uint16_t computeTosInfoCrc(NetProg_TOSInfo* tosInfo) - { - return call Crc.crc16(tosInfo, sizeof(NetProg_TOSInfo)-2); - } - - void writeTOSinfo() - { - NetProg_TOSInfo tosInfo; - uint16_t crc; - call IFlash.read((uint8_t*)IFLASH_TOS_INFO_ADDR, &tosInfo, sizeof(tosInfo)); - tosInfo.addr = TOS_NODE_ID; - tosInfo.groupId = TOS_AM_GROUP; - crc = computeTosInfoCrc(&tosInfo); - // don't write if data is already correct - if (tosInfo.crc == crc) - return; - tosInfo.crc = crc; - call IFlash.write((uint8_t*)IFLASH_TOS_INFO_ADDR, &tosInfo, sizeof(tosInfo)); - } - command error_t Init.init() { + BootArgs bootArgs; + call IFlash.read((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs)); - NetProg_TOSInfo tosInfo; - - call IFlash.read((uint8_t*)IFLASH_TOS_INFO_ADDR, &tosInfo, sizeof(tosInfo)); - - if (tosInfo.crc == computeTosInfoCrc(&tosInfo)) { - // TOS_AM_GROUP is not a variable in T2 - // TOS_AM_GROUP = tosInfo.groupId; - - // Updates local node ID - atomic { - TOS_NODE_ID = tosInfo.addr; - call setAmAddress(tosInfo.addr); - } - call CC2420Config.setShortAddr(tosInfo.addr); - call CC2420Config.sync(); - } - else { - writeTOSinfo(); + // Update the local node ID + if (bootArgs.address != 0xFFFF) { + TOS_NODE_ID = bootArgs.address; + call setAmAddress(bootArgs.address); } + call CC2420Config.setShortAddr(bootArgs.address); + call CC2420Config.sync(); return SUCCESS; } command error_t NetProg.reboot() { + BootArgs bootArgs; + atomic { - writeTOSinfo(); + call IFlash.read((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs)); + + if (bootArgs.address != TOS_NODE_ID) { + bootArgs.address = TOS_NODE_ID; + call IFlash.write((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs)); + } netprog_reboot(); } + return FAIL; } - command error_t NetProg.programImgAndReboot(uint8_t img_num) + command error_t NetProg.programImageAndReboot(uint32_t imgAddr) { - tosboot_args_t args; - DelugeNodeDesc nodeDesc; - DelugeImgDesc *imgDesc; - + BootArgs bootArgs; + atomic { - writeTOSinfo(); - - args.imageAddr = call DelugeStorage.getPhysicalAddress[img_num](0); - args.gestureCount = 0xff; - args.noReprogram = FALSE; - call IFlash.write((uint8_t*)TOSBOOT_ARGS_ADDR, &args, sizeof(args)); - - // Write info about what img to disseminate after reboot - imgDesc = call DelugeMetadata.getImgDesc(img_num); - nodeDesc.uid = imgDesc->uid; - nodeDesc.imgNum = img_num; - nodeDesc.vNum = imgDesc->vNum; - call IFlash.write((uint8_t*)IFLASH_NODE_DESC_ADDR, &nodeDesc, sizeof(nodeDesc)); + call IFlash.read((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs)); + bootArgs.imageAddr = imgAddr; + bootArgs.gestureCount = 0xff; + bootArgs.noReprogram = FALSE; + + call IFlash.write((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs)); + // reboot netprog_reboot(); } @@ -135,6 +103,4 @@ implementation { event void CC2420Config.syncDone(error_t error) {} - default command storage_addr_t DelugeStorage.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) { return 0xFFFFFFFF; } - } diff --git a/tos/lib/net/Deluge/extra/mica2/NetProg_platform.h b/tos/lib/net/Deluge/extra/mica2/NetProg_platform.h index 165cdef7..3f225ecd 100644 --- a/tos/lib/net/Deluge/extra/mica2/NetProg_platform.h +++ b/tos/lib/net/Deluge/extra/mica2/NetProg_platform.h @@ -31,11 +31,6 @@ #ifndef __NETPROG_PLATFORM_H__ #define __NETPROG_PLATFORM_H__ -enum { - IFLASH_TOS_INFO_ADDR = 0xfe0, // 6 bytes - IFLASH_NODE_DESC_ADDR = 0xfe6, // 10 bytes -}; - void netprog_reboot() { wdt_enable(1); while(1); diff --git a/tos/lib/net/Deluge/extra/micaz/TOSBoot_platform.h b/tos/lib/net/Deluge/extra/micaz/TOSBoot_platform.h index 736bb2e8..e2392a0c 100644 --- a/tos/lib/net/Deluge/extra/micaz/TOSBoot_platform.h +++ b/tos/lib/net/Deluge/extra/micaz/TOSBoot_platform.h @@ -29,19 +29,10 @@ #define __TOSBOOT_PLATFORM_H__ enum { - // address of TOSBoot args in internal flash - TOSBOOT_ARGS_ADDR = 0xff0, - // number of resets to force golden image - TOSBOOT_GESTURE_MAX_COUNT = 3, - // address of the golden image in external flash - TOSBOOT_GOLDEN_IMG_ADDR = 0x0L, - // size of each internal program flash page - TOSBOOT_INT_PAGE_SIZE = SPM_PAGESIZE, -}; - -enum { - DELUGE_MIN_ADV_PERIOD_LOG2 = 9, - DELUGE_QSIZE = 2, + TOSBOOT_ARGS_ADDR = 0xff0, // address of TOSBoot args in internal flash + TOSBOOT_GESTURE_MAX_COUNT = 3, // number of resets to force golden image + TOSBOOT_GOLDEN_IMG_ADDR = 0x0L, // address of the golden image in external flash + TOSBOOT_INT_PAGE_SIZE = SPM_PAGESIZE, // size of each internal program flash page }; #endif diff --git a/tos/lib/net/Deluge/extra/telos/NetProg_platform.h b/tos/lib/net/Deluge/extra/telos/NetProg_platform.h index 365831a8..52d4acb7 100644 --- a/tos/lib/net/Deluge/extra/telos/NetProg_platform.h +++ b/tos/lib/net/Deluge/extra/telos/NetProg_platform.h @@ -31,11 +31,6 @@ #ifndef __NETPROG_PLATFORM_H__ #define __NETPROG_PLATFORM_H__ -enum { - IFLASH_TOS_INFO_ADDR = 0x60, // 6 bytes - IFLASH_NODE_DESC_ADDR = 0x66, // 10 bytes -}; - void netprog_reboot() { WDTCTL = WDT_ARST_1_9; while(1); diff --git a/tos/lib/net/Deluge/extra/telosb/TOSBoot_platform.h b/tos/lib/net/Deluge/extra/telosb/TOSBoot_platform.h index afc7693a..d1fe5fac 100644 --- a/tos/lib/net/Deluge/extra/telosb/TOSBoot_platform.h +++ b/tos/lib/net/Deluge/extra/telosb/TOSBoot_platform.h @@ -29,19 +29,10 @@ #define __TOSBOOT_PLATFORM_H__ enum { - // address of TOSBoot args in internal flash - TOSBOOT_ARGS_ADDR = 0x70, - // number of resets to force golden image - TOSBOOT_GESTURE_MAX_COUNT = 3, - // address of the golden image in external flash - TOSBOOT_GOLDEN_IMG_ADDR = 0xf0000L, - // size of each internal program flash page - TOSBOOT_INT_PAGE_SIZE = 512L, -}; - -enum { - DELUGE_MIN_ADV_PERIOD_LOG2 = 9, - DELUGE_QSIZE = 1, + TOSBOOT_ARGS_ADDR = 0x70, // address of TOSBoot args in internal flash + TOSBOOT_GESTURE_MAX_COUNT = 3, // number of resets to force golden image + TOSBOOT_GOLDEN_IMG_ADDR = 0xf0000L, // address of the golden image in external flash + TOSBOOT_INT_PAGE_SIZE = 512L, // size of each internal program flash page }; #endif diff --git a/tos/lib/tosboot/Deluge.h b/tos/lib/tosboot/Deluge.h deleted file mode 100644 index b6aa2873..00000000 --- a/tos/lib/tosboot/Deluge.h +++ /dev/null @@ -1,142 +0,0 @@ -// $Id$ - -/* tab:2 - * - * - * "Copyright (c) 2000-2005 The Regents of the University of California. - * 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 following - * two paragraphs and the author appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." - * - */ - -/** - * @author Jonathan Hui - */ - -#ifndef __DELUGE_H__ -#define __DELUGE_H__ - -#include "DelugeMetadata.h" -#include "TOSBoot.h" - -#ifndef DELUGE_NUM_IMAGES -#define DELUGE_NUM_IMAGES 3 -#endif - -enum { - DELUGE_VERSION = 2, - DELUGE_MAX_ADV_PERIOD_LOG2 = 22, - DELUGE_NUM_NEWDATA_ADVS_REQUIRED = 2, - DELUGE_NUM_MIN_ADV_PERIODS = 2, - DELUGE_MAX_NUM_REQ_TRIES = 1, - DELUGE_REBOOT_DELAY = 4, - DELUGE_FAILED_SEND_DELAY = 16, - DELUGE_MIN_DELAY = 16, - DELUGE_PKTS_PER_PAGE = 48, - DELUGE_PKT_PAYLOAD_SIZE = 23, - DELUGE_DATA_OFFSET = 128, - DELUGE_IDENT_SIZE = 128, - DELUGE_INVALID_ADDR = (0x7fffffffL), - DELUGE_MAX_REQ_DELAY = (0x1L << (DELUGE_MIN_ADV_PERIOD_LOG2-1)), - DELUGE_NACK_TIMEOUT = (DELUGE_MAX_REQ_DELAY >> 0x1), - DELUGE_BYTES_PER_PAGE = (DELUGE_PKTS_PER_PAGE*DELUGE_PKT_PAYLOAD_SIZE), - DELUGE_PKT_BITVEC_SIZE = (((DELUGE_PKTS_PER_PAGE-1) / 8) + 1), - DELUGE_MAX_IMAGE_SIZE = (128L*1024L), - DELUGE_MAX_PAGES = 128, - DELUGE_CRC_SIZE = sizeof(uint16_t), - DELUGE_CRC_BLOCK_SIZE = DELUGE_MAX_PAGES*DELUGE_CRC_SIZE, - DELUGE_GOLDEN_IMAGE_NUM = 0x0, - DELUGE_INVALID_VNUM = -1, - DELUGE_INVALID_IMGNUM = 0xff, - DELUGE_INVALID_PKTNUM = 0xff, - DELUGE_INVALID_PGNUM = 0xff, -}; - -#include "Storage.h" - -struct deluge_image_t { - imgnum_t imageNum; - volume_id_t volumeId; -}; - -typedef struct DelugeAdvTimer { - uint32_t timer : 32; - uint8_t periodLog2 : 8; - bool overheard : 1; - uint8_t newAdvs : 7; -} DelugeAdvTimer; - -typedef struct DelugeNodeDesc { - imgvnum_t vNum; - uint32_t uid; - imgnum_t imgNum; - uint8_t reserved; - uint16_t crc; -} DelugeNodeDesc; - -enum { - DELUGE_VOLUME_ID_0 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 2 - DELUGE_VOLUME_ID_1 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 3 - DELUGE_VOLUME_ID_2 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 4 - DELUGE_VOLUME_ID_3 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 5 - DELUGE_VOLUME_ID_4 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 6 - DELUGE_VOLUME_ID_5 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 7 - DELUGE_VOLUME_ID_6 = unique("StorageManager"), -#if DELUGE_NUM_IMAGES >= 8 - DELUGE_VOLUME_ID_7 = unique("StorageManager"), -#endif -#endif -#endif -#endif -#endif -#endif -#endif -}; - -static const struct deluge_image_t DELUGE_IMAGES[DELUGE_NUM_IMAGES] = { - { DELUGE_VOLUME_ID_0, 0xDF }, -#if DELUGE_NUM_IMAGES >= 2 - { DELUGE_VOLUME_ID_1, 0xD0 }, -#if DELUGE_NUM_IMAGES >= 3 - { DELUGE_VOLUME_ID_2, 0xD1 }, -#if DELUGE_NUM_IMAGES >= 4 - { DELUGE_VOLUME_ID_3, 0xD2 }, -#if DELUGE_NUM_IMAGES >= 5 - { DELUGE_VOLUME_ID_4, 0xD3 }, -#if DELUGE_NUM_IMAGES >= 6 - { DELUGE_VOLUME_ID_5, 0xD4 }, -#if DELUGE_NUM_IMAGES >= 7 - { DELUGE_VOLUME_ID_6, 0xD5 }, -#if DELUGE_NUM_IMAGES >= 8 - { DELUGE_VOLUME_ID_7, 0xD6 }, -#endif -#endif -#endif -#endif -#endif -#endif -#endif -}; - -#endif diff --git a/tos/lib/tosboot/TOSBoot.h b/tos/lib/tosboot/TOSBoot.h index ab5524b5..e3a124df 100644 --- a/tos/lib/tosboot/TOSBoot.h +++ b/tos/lib/tosboot/TOSBoot.h @@ -30,10 +30,4 @@ #include "TOSBoot_platform.h" -typedef struct tosboot_args_t { - uint32_t imageAddr; - uint8_t gestureCount; - bool noReprogram; -} tosboot_args_t; - #endif diff --git a/tos/lib/tosboot/TOSBoot.nc b/tos/lib/tosboot/TOSBoot.nc index d08429b7..4666a17c 100644 --- a/tos/lib/tosboot/TOSBoot.nc +++ b/tos/lib/tosboot/TOSBoot.nc @@ -29,6 +29,7 @@ */ includes Deluge; +includes DelugePageTransfer; includes TOSBoot; configuration TOSBoot { diff --git a/tos/lib/tosboot/TOSBootM.nc b/tos/lib/tosboot/TOSBootM.nc index 2f9d242e..fe6eec83 100644 --- a/tos/lib/tosboot/TOSBootM.nc +++ b/tos/lib/tosboot/TOSBootM.nc @@ -70,55 +70,66 @@ implementation { in_flash_addr_t extFlashReadAddr() { in_flash_addr_t result = 0; - uint8_t i; - for ( i = 0; i < 4; i++ ) + int8_t i; + for ( i = 3; i >= 0; i-- ) result |= ((in_flash_addr_t)call ExtFlash.readByte() & 0xff) << (i*8); return result; } - bool verifyImage(ex_flash_addr_t startAddr) { + bool verifyBlock(ex_flash_addr_t crcAddr, ex_flash_addr_t startAddr, uint16_t len) + { + uint16_t crcTarget, crcTmp; + + // read crc + call ExtFlash.startRead(crcAddr); + crcTarget = (uint16_t)(call ExtFlash.readByte() & 0xff) << 8; + crcTarget |= (uint16_t)(call ExtFlash.readByte() & 0xff); + call ExtFlash.stopRead(); - uint16_t crcTarget = 0, crcTmp = 0; - uint16_t addr, len; - pgnum_t numPgs; + // compute crc + call ExtFlash.startRead(startAddr); + for ( crcTmp = 0; len; len-- ) + crcTmp = crcByte(crcTmp, call ExtFlash.readByte()); + call ExtFlash.stopRead(); + + return crcTarget == crcTmp; + } + + bool verifyImage(ex_flash_addr_t startAddr) { + uint16_t addr; + uint8_t numPgs; uint8_t i; + if (!verifyBlock(startAddr + offsetof(DelugeIdent,crc), + startAddr, offsetof(DelugeIdent,crc))) + return FALSE; + // read size of image - call ExtFlash.startRead(startAddr + offsetof(DelugeImgDesc,numPgs)); + call ExtFlash.startRead(startAddr + offsetof(DelugeIdent,numPgs)); numPgs = call ExtFlash.readByte(); call ExtFlash.stopRead(); if (numPgs == 0 || numPgs == 0xff) return FALSE; - startAddr += DELUGE_METADATA_SIZE; - + startAddr += DELUGE_IDENT_SIZE; addr = DELUGE_CRC_BLOCK_SIZE; - len = DELUGE_BYTES_PER_PAGE-DELUGE_CRC_BLOCK_SIZE; - - for ( i = 0; i < numPgs && crcTarget == crcTmp; i++ ) { - - // read crc - call ExtFlash.startRead(startAddr + i*sizeof(uint16_t)); - crcTarget = (uint16_t)(call ExtFlash.readByte() & 0xff); - crcTarget |= (uint16_t)(call ExtFlash.readByte() & 0xff) << 8; - call ExtFlash.stopRead(); - - // compute crc - call ExtFlash.startRead(startAddr + addr); - for ( crcTmp = 0; len; len-- ) - crcTmp = crcByte(crcTmp, call ExtFlash.readByte()); - call ExtFlash.stopRead(); - addr = (uint16_t)(i+1)*DELUGE_BYTES_PER_PAGE; - len = DELUGE_BYTES_PER_PAGE; + for ( i = 0; i < numPgs; i++ ) { + if (!verifyBlock(startAddr + i*sizeof(uint16_t), + startAddr + addr, DELUGE_BYTES_PER_PAGE)) { + if (i == 0) + while (1) + call Leds.flash(1); + return FALSE; + } + addr += DELUGE_BYTES_PER_PAGE; } - return (i == numPgs) && (crcTarget == crcTmp); + return TRUE; } error_t programImage(ex_flash_addr_t startAddr) { - uint8_t buf[TOSBOOT_INT_PAGE_SIZE]; uint16_t pageAddr, newPageAddr; in_flash_addr_t intAddr; @@ -128,7 +139,7 @@ implementation { if (!verifyImage(startAddr)) return R_INVALID_IMAGE_ERROR; - curAddr = startAddr + DELUGE_METADATA_SIZE + DELUGE_CRC_BLOCK_SIZE + DELUGE_IDENT_SIZE; + curAddr = startAddr + DELUGE_IDENT_SIZE + DELUGE_CRC_BLOCK_SIZE; call ExtFlash.startRead(curAddr); @@ -147,7 +158,7 @@ implementation { return R_INVALID_IMAGE_ERROR; } - call ExtFlash.stopRead(); // MIKE_LIANG + call ExtFlash.stopRead(); while ( secLength ) { @@ -159,7 +170,7 @@ implementation { // check if secLength is all ones if ( secLength == 0xffffffff ) { - call ExtFlash.stopRead(); // MIKE_LIANG + call ExtFlash.stopRead(); return FAIL; } @@ -179,7 +190,6 @@ implementation { call Leds.set(pageAddr); - // write out page if (call ProgFlash.write(pageAddr*TOSBOOT_INT_PAGE_SIZE, buf, TOSBOOT_INT_PAGE_SIZE) == FAIL) { @@ -198,7 +208,7 @@ implementation { void startupSequence() { - tosboot_args_t args; + BootArgs args; // check voltage and make sure flash can be programmed // if not, just run the app, can't check for gestures