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
-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 <cliang4@cs.jhu.edu>
-# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
-
-###############################################################################
-# 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
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:
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:
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:
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))
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<<s) - 1))
+ boffset += s
+ if boffset == 8:
+ offset += 1
+ boffset = 0
+ elif t == 'string':
+ self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
offset += s
elif t == 'blob':
if s:
- self._values.append(packet[offset:offset + s])
- offset += s
+ if s > 0:
+ self._values.append(packet[offset:offset + s])
+ offset += s
+ else:
+ self._values.append(packet[offset:s])
+ offset = len(packet) + s
else:
- self._values.append(packet[offset:-3])
+ self._values.append(packet[offset:])
elif type(packet) == type(()):
for i in packet:
self._values.append(i)
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):
# Implement the struct behavior
def __getattr__(self, name):
+ #print "DEBUG: __getattr__", name
if type(name) == type(0):
return self._names[name]
else:
else:
self._values[self._names.index(name)] = value
+ def __ne__(self, other):
+ if other.__class__ == self.__class__:
+ return self._values != other._values
+ else:
+ return True
+
+ def __eq__(self, other):
+ if other.__class__ == self.__class__:
+ return self._values == other._values
+ else:
+ return False
+
+ def __nonzero__(self):
+ return True;
+
# Custom
def names(self):
return self._names
def 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)
+
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):
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])
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
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])
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."
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.
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))
#!/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 <cliang4@cs.jhu.edu>
-# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
-
-###############################################################################
-# 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):
('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):
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
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[",
# 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
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 <device_port> <baud_rate> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
- print " <baud_rate>\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 " <baud_rate> 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
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+configuration BlockStorageLockC
+{
+ provides {
+ interface Resource[uint8_t client];
+ interface ArbiterInfo;
+ }
+}
+
+implementation
+{
+ components new SimpleFcfsArbiterC(UQ_BSTORAGEL_CLIENT) as Arbiter;
+ Resource = Arbiter;
+ ArbiterInfo = Arbiter;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+generic configuration BlockStorageLockClientC()
+{
+ provides interface Resource;
+}
+
+implementation
+{
+ enum {
+ CLIENT_ID = unique(UQ_BSTORAGEL_CLIENT)
+ };
+
+ components BlockStorageLockC;
+ Resource = BlockStorageLockC.Resource[CLIENT_ID];
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#ifndef BLOCK_STORAGE_MANAGER_H
+#define BLOCK_STORAGE_MANAGER_H
+
+#define UQ_BSTORAGEM_CLIENT "BlockStorageManager.client"
+#define UQ_BSTORAGEL_CLIENT "BlockStorageLock.client"
+
+#endif
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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.
+ }
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#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;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+interface VolumeId
+{
+ command volume_id_t get();
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+generic module VolumeIdC(volume_id_t id)
+{
+ provides interface VolumeId;
+}
+
+implementation
+{
+ command volume_id_t VolumeId.get()
+ {
+ return id;
+ }
+}
#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
#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
+
}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#include "StorageVolumes.h"
+
+generic configuration DelugeManagerC(am_id_t AMId)
+{
+ uses interface DisseminationUpdate<DelugeCmd>;
+}
+
+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;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+generic module DelugeManagerP()
+{
+ uses {
+ interface DisseminationUpdate<DelugeCmd>;
+ interface AMSend as SerialAMSender;
+ interface Receive as SerialAMReceiver;
+ interface Timer<TMilli> 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) {}
+}
+++ /dev/null
-/*
- * "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 <jwhui@cs.berkeley.edu>
- */
-
-#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
-/*
- * "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 <jwhui@cs.berkeley.edu>
- * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
- * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * 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. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
*/
-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);
}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+generic configuration DelugeMetadataClientC()
+{
+ provides interface DelugeMetadata;
+}
+
+implementation
+{
+ enum {
+ CLIENT_ID = unique(UQ_DELUGE_METADATA)
+ };
+
+ components DelugeMetadataC;
+ DelugeMetadata = DelugeMetadataC.DelugeMetadata[CLIENT_ID];
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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() {}
+}
*/
/**
- * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
*/
module DelugeP
{
uses {
+ interface Boot;
interface Leds;
- interface Notify<uint8_t> as StorageReadyNotify;
- interface DisseminationUpdate<DelugeDissemination>;
- interface DisseminationValue<DelugeDissemination>;
- interface StdControl as StdControlDissemination;
- interface DelugeMetadata;
+ interface DisseminationValue<DelugeCmd>;
+ interface StdControl as DisseminationStdControl;
interface ObjectTransfer;
- interface NetProg;
- interface InternalFlash as IFlash;
interface SplitControl as RadioSplitControl;
-
-#ifdef DELUGE_BASESTATION
- interface Notify<uint8_t> as DissNotify;
- interface Notify<uint8_t> 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) {}
}
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),
DELUGE_INVALID_OBJID = 0xff,
DELUGE_INVALID_PKTNUM = 0xff,
DELUGE_INVALID_PGNUM = 0xff,
+ DELUGE_QSIZE = 2
};
typedef struct DelugeAdvTimer {
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();
}
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;
{
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()
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;
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;
}
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);
// 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) {
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;
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() {}
}
+++ /dev/null
-/*\r
- * Copyright (c) 2005-2006 Arch Rock Corporation\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * - Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * - Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the\r
- * distribution.\r
- * - Neither the name of the Arch Rock Corporation nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
- * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
- * OF THE POSSIBILITY OF SUCH DAMAGE\r
- */\r
-\r
-/**\r
- * An abstraction to map volume addresses to physical addresses.\r
- *\r
- * @author Jonathan Hui <jhui@archrock.com>\r
- * @version $Revision$ $Date$\r
- */\r
-\r
-/**\r
- * The same as StorageMap interface for STM25P.\r
- *\r
- * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>\r
- * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>\r
- */\r
-\r
-interface DelugeStorage {\r
-\r
- /**\r
- * Get the physical address of a volume address.\r
- *\r
- * @param addr the volume addres.\r
- * @return the physical address.\r
- */\r
- command storage_addr_t getPhysicalAddress(storage_addr_t addr);\r
-}\r
+++ /dev/null
-/* 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 <cliang4@cs.jhu.edu>
- * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
- */
-
-#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<uint8_t> 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;
-}
+++ /dev/null
-/* 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 <cliang4@cs.jhu.edu>
- * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
- */
-
-#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<uint8_t> 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
-}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+interface DelugeVolumeManager
+{
+ command error_t erase(uint8_t imgNum);
+ event void eraseDone(uint8_t imgNum);
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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;
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+generic configuration DelugeVolumeManagerClientC()
+{
+ provides interface DelugeVolumeManager;
+}
+
+implementation
+{
+ enum {
+ CLIENT_ID = unique(UQ_DELUGE_VOLUME_MANAGER)
+ };
+
+ components DelugeVolumeManagerC;
+ DelugeVolumeManager = DelugeVolumeManagerC.DelugeVolumeManager[CLIENT_ID];
+}
--- /dev/null
+/* Copyright (c) 2007 Johns Hopkins University.
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written
+* agreement is hereby granted, provided that the above copyright
+* notice, the (updated) modification history and the author appear in
+* all copies of this source code.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+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; }
+}
+++ /dev/null
-/* 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 <cliang4@cs.jhu.edu>
- * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
- */
-
-#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
#include "AM.h"
#include "StorageVolumes.h"
-generic configuration FlashVolumeManagerC(am_id_t AMId)
-{
-#ifdef DELUGE
- provides interface Notify<uint8_t> as DissNotify;
- provides interface Notify<uint8_t> 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;
}
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
*/
-#include "FlashVolumeManager.h"
-
generic module FlashVolumeManagerP()
{
-#ifdef DELUGE
- provides {
- interface Notify<uint8_t> as DissNotify;
- interface Notify<uint8_t> 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<TMilli> 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<TMilli> 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,
};
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)
}
}
- 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)
}
}
- 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;
}
}
- 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;
}
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; }
}
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,
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;
};
DelugeAdvTimer advTimers;
- //DelugeNodeDesc nodeDesc;
uint8_t state = S_STOPPED;
object_id_t cont_receive_new_objid;
}
}
-// 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))
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;
}
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));
return msg;
}
- if (rxAdvMsg->version != DELUGE_VERSION
- //|| !isNodeDescValid(&rxAdvMsg->nodeDesc)
- || state != S_STARTED) {
+ if (rxAdvMsg->version != DELUGE_VERSION || state != S_STARTED) {
return msg;
}
#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
command error_t reboot();
/**
- * Reboot into the image specified by <code>imgNum</code>. This
- * assumes that an image has been downloaded into slot <code>imgNum</code>
- * using Deluge.
+ * Reboot into the image specified by <code>imageAddr</code>. This
+ * assumes that an image is present into the external flash
+ * at the <code>imageAddr</code> address.
*
- * @param imgNum Number of image to boot in to.
+ * @param imageAddr Address in external flash
* @return <code>FAIL</code> 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);
}
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;
/**
* @author Jonathan Hui <jwhui@cs.berkeley.edu>
- * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
*/
#include "AM.h"
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);
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();
}
event void CC2420Config.syncDone(error_t error) {}
- default command storage_addr_t DelugeStorage.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) { return 0xFFFFFFFF; }
-
}
#ifndef __NETPROG_PLATFORM_H__\r
#define __NETPROG_PLATFORM_H__\r
\r
-enum {\r
- IFLASH_TOS_INFO_ADDR = 0xfe0, // 6 bytes\r
- IFLASH_NODE_DESC_ADDR = 0xfe6, // 10 bytes\r
-};\r
-\r
void netprog_reboot() {\r
wdt_enable(1);\r
while(1);\r
#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
#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);
#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
+++ /dev/null
-// $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 <jwhui@cs.berkeley.edu>
- */
-
-#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
#include "TOSBoot_platform.h"
-typedef struct tosboot_args_t {
- uint32_t imageAddr;
- uint8_t gestureCount;
- bool noReprogram;
-} tosboot_args_t;
-
#endif
*/
includes Deluge;
+includes DelugePageTransfer;
includes TOSBoot;
configuration TOSBoot {
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;
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);
return R_INVALID_IMAGE_ERROR;
}
- call ExtFlash.stopRead(); // MIKE_LIANG
+ call ExtFlash.stopRead();
while ( secLength ) {
// check if secLength is all ones
if ( secLength == 0xffffffff ) {
- call ExtFlash.stopRead(); // MIKE_LIANG
+ call ExtFlash.stopRead();
return FAIL;
}
call Leds.set(pageAddr);
-
// write out page
if (call ProgFlash.write(pageAddr*TOSBOOT_INT_PAGE_SIZE, buf,
TOSBOOT_INT_PAGE_SIZE) == FAIL) {
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