COMPONENT=BlinkAppC
TINYOS_NP=BNP
-CFLAGS += -DDELUGE_BASESTATION
+#CFLAGS += -DDELUGE_BASESTATION
+#CFLAGS += -DDELUGE_LIGHT_BASESTATION
include $(MAKERULES)
TOS_DELUGE=../../../../tools/tinyos/misc/tos-deluge
fi
-if [ $# -ne 2 ]; then
- echo "Usage: $0 <port> <platform>"
+if [[ $# -ne 2 && $# -ne 3 ]]; then
+ echo "Usage: $0 <port> [<comm_port>] <platform>"
echo " <port> /dev/ttyUSB0"
- echo " <platform> micaz or telosb"
+ echo " <comm_port> /dev/ttyUSB1"
+ echo " <platform> micaz, telosb or iris"
exit 2
fi
-PORT=$1
+PPORT=$1
+CPORT=$1
PLATFORM=$2
-if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' ]; then
+if [ $# -eq 3 ]; then
+ CPORT=$2
+ PLATFORM=$3
+fi
+
+if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' -a ${PLATFORM} != 'iris' ]; then
echo "\"${PLATFORM}\" is not a supported platform"
exit 2
fi
echo ============================ Compile and load Blink ============================
if [ $PLATFORM == 'micaz' ]
then
- CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PORT}
+ CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PPORT}
elif [ $PLATFORM == 'telosb' ]
then
- CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install bsl,${PORT}
+ CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install bsl,${PPORT}
+elif [ $PLATFORM == 'iris' ]
+then
+ CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} install mib510,${PPORT}
fi
+
echo ' +-------------------------------------------------------+'
echo ' | |'
echo ' | At this point the first led (red) should be blinking. |'
CFLAGS=-DBLINK_REVERSE\ -DDELUGE_BASESTATION make ${PLATFORM}
echo =============================== Upload the image ===============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
+${TOS_DELUGE} ${CPORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
echo ' +----------------------------------------------------------------+'
echo ' | |'
read
echo =========================== Reboot the base station ============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -r 1
+${TOS_DELUGE} ${CPORT} ${PLATFORM} -r 1
if [ $# -ne 2 ]; then
echo "Usage: $0 <platform> <number of motes>"
- echo " <platform> micaz or telosb"
+ echo " <platform> micaz, telosb or iris"
echo " <number of motes> how many motes will be used in the test"
exit 2
fi
PLATFORM=$1
NO_MOTES=$2
-if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' ]; then
+if [ ${PLATFORM} != 'micaz' -a ${PLATFORM} != 'telosb' -a ${PLATFORM} != 'iris' ]; then
echo "\"${PLAFTORM}\" is not a supported platform"
exit 2
fi
echo ================================ Compile Blink =================================
make clean
-CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM}
ID=0
function burn_one() {
ID=`expr $ID + 1`
- echo -n ">>> Please plug mote $ID and type the port to continue: "
+ echo -n ">>> Please plug mote $ID and type the programming port to continue: "
read PORT
if [ ${PLATFORM} == 'micaz' ]
then
- CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} reinstall,$ID mib510,${PORT}
+ CFLAGS=$1 make ${PLATFORM} install,$ID mib510,${PORT}
elif [ ${PLATFORM} == 'telosb' ]
then
- CFLAGS=-DDELUGE_BASESTATION make ${PLATFORM} reinstall,$ID bsl,${PORT}
+ CFLAGS=$1 make ${PLATFORM} install,$ID bsl,${PORT}
+ elif [ ${PLATFORM} == 'iris' ]
+ then
+ CFLAGS=$1 make ${PLATFORM} install,$ID mib510,${PORT}
fi
-
}
-while [[ ${NO_MOTES} > 0 ]]
+while [[ ${NO_MOTES} > 1 ]]
do
- burn_one
+ burn_one -DDELUGE_LIGHT_BASESTATION
NO_MOTES=`expr ${NO_MOTES} - 1`
done
+echo ">>> Note: this last mote will be the basestation! <<<"
+burn_one -DDELUGE_BASESTATION
+echo -n ">>> Please plug mote $ID and type the communication port to continue: "
+read PORT
+BASESTATION_PORT=$PORT
echo ' +------------------------------------------------------------------------+'
echo ' | |'
read
echo ============================= Compile a new Blink ==============================
-CFLAGS=-DBLINK_REVERSE\ -DDELUGE_BASESTATION make ${PLATFORM}
+CFLAGS=-DBLINK_REVERSE\ -DDELUGE_LIGHT_BASESTATION make ${PLATFORM}
echo ========= Upload the new image to the external flash of the last mote ==========
-${TOS_DELUGE} ${PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
+${TOS_DELUGE} ${BASESTATION_PORT} ${PLATFORM} -i 1 build/${PLATFORM}/tos_image.xml
echo ' +-----------------------------------------------------+'
echo ' | |'
echo ' | Press ENTER to continue... |'
echo ' | |'
echo ' +-----------------------------------------------------+'
-
read
echo ============================= Start dissemination ==============================
-${TOS_DELUGE} ${PORT} ${PLATFORM} -dr 1
+${TOS_DELUGE} ${BASESTATION_PORT} ${PLATFORM} -dr 1
echo ' +------------------------------------------------------------+'
echo ' | |'
bin_PROGRAMS = tos-serial-debug
pythondir = $(bindir)
-python_DATA = tinyos.py
+python_DATA = tos.py
+++ /dev/null
-"""A library that implements the T2 serial communication.
-
-This library has two parts: one that deals with sending and receiving
-packets using the serial format from T2 (TEP113) and a second one that
-tries to simplifies the work with arbitrary packets.
-
-"""
-
-import sys, struct, time, serial, socket, operator
-from Queue import Queue
-
-__version__ = "$Id$"
-
-__all__ = ['Serial', 'GenericPacket', 'RawPacket',
- 'AckFrame', 'DataFrame', 'NoAckDataFrame',
- 'ActiveMessage']
-
-_seqno = 1
-
-def list2hex(v):
- return " ".join(["%02x" % p for p in v])
-
-class Serial:
- """
- A Serial object offers a way to send and data using a HDLC-like
- formating.
- """
-
- HDLC_FLAG_BYTE = 0x7e
- HDLC_CTLESC_BYTE = 0x7d
-
- TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
- TOS_SERIAL_CC1000_ID = 1
- TOS_SERIAL_802_15_4_ID = 2
- TOS_SERIAL_UNKNOWN_ID = 255
-
- SERIAL_PROTO_ACK = 67
- SERIAL_PROTO_PACKET_ACK = 68
- SERIAL_PROTO_PACKET_NOACK = 69
- SERIAL_PROTO_PACKET_UNKNOWN = 255
-
- _debug = False # Debug mode
-
- def __init__(self, port, baudrate, flush=True):
- self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
- self._queue = Queue()
- self._ts = None
- self._seqno = 0
-
- self._s.flushInput()
- start = time.time();
- if flush:
- print "Flushing the serial port",
- while time.time() - start < 1:
- p = self.sniff()
- sys.stdout.write(".")
- if not self._debug:
- sys.stdout.write("\n")
-
- def _format_packet(self, payload):
- f = NoAckDataFrame(payload)
- if f.protocol == self.SERIAL_PROTO_ACK:
- rpacket = AckFrame(payload)
- return "Ack seqno: %d" % (rpacket.seqno)
- else:
- rpacket = ActiveMessage(f.data)
- return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
- (rpacket.destination, rpacket.source,
- rpacket.length, rpacket.group, rpacket.type,
- list2hex(rpacket.data))
-
- def crc16(self, base_crc, frame_data):
- crc = base_crc
- for b in frame_data:
- crc = crc ^ (b << 8)
- for i in range(0, 8):
- if crc & 0x8000 == 0x8000:
- crc = (crc << 1) ^ 0x1021
- else:
- crc = crc << 1
- crc = crc & 0xffff
- return crc
-
- def _encode(self, val, dim):
- output = []
- for i in range(dim):
- output.append(val & 0xFF)
- val = val >> 8
- return output
-
- def _decode(self, v):
- r = long(0)
- for i in v[::-1]:
- r = (r << 8) + i
- return r
-
- def _get_byte(self):
- try:
- r = struct.unpack("B", self._s.read())[0]
- return r
- except struct.error:
- # Serial port read timeout
- raise socket.timeout
-
- def _put_bytes(self, data):
- #print "DEBUG: _put_bytes:", data
- for b in data:
- self._s.write(struct.pack('B', b))
-
- def _unescape(self, packet):
- r = []
- esc = False
- for b in packet:
- if esc:
- r.append(b ^ 0x20)
- esc = False
- elif b == self.HDLC_CTLESC_BYTE:
- esc = True
- else:
- r.append(b)
- return r
-
- def _escape(self, packet):
- r = []
- for b in packet:
- if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
- r.append(self.HDLC_CTLESC_BYTE)
- r.append(b ^ 0x20)
- else:
- r.append(b)
- return r
-
- # Returns the next incoming serial packet
- def sniff(self, skip_queue = False):
- """Wait for a packet and return it as a RawPacket."""
-
- if (not skip_queue and not self._queue.empty()):
- print "DEBUG: sniff_packet: return a packet from the queue(%d)." % self._queue.qsize()
- return self._queue.get()
- try:
- d = self._get_byte()
- ts = time.time()
- while d != self.HDLC_FLAG_BYTE:
- d = self._get_byte()
- ts = time.time()
- packet = [d]
- d = self._get_byte()
- if d == self.HDLC_FLAG_BYTE:
- d = self._get_byte()
- ts = time.time()
- else:
- packet.append(d)
- while d != self.HDLC_FLAG_BYTE:
- d = self._get_byte()
- packet.append(d)
- if self._debug == True:
- print "sniff: unescaped", packet
- packet = self._unescape(packet)
-
- crc = self.crc16(0, packet[1:-3])
- packet_crc = self._decode(packet[-3:-1])
-
- if self._debug:
- if crc != packet_crc:
- print "Warning: wrong CRC! %s" % packet
- if self._ts == None:
- self._ts = ts
- else:
- print "%.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
- self._ts = ts
- return RawPacket(ts, packet[1:-3], crc == packet_crc)
- except socket.timeout:
- return None
-
- def sniff_am(self, skip_queue = False, timeout=0):
- """Wait for a packet and return it as a ActiveMessage."""
-
- start = time.time();
- p = None
- done = False
- while not done:
- while p == None:
- if timeout == 0 or time.time() - start < timeout:
- p = self.sniff(skip_queue)
- else:
- return None
- if p.crc:
- done = True
- return ActiveMessage(NoAckDataFrame(p.data).data)
-
-
- # Sends data with the specified AM group ID and AM ID. To have a "reliable"
- # transfer, num_tries defines how many times to retry before giving up
- def write(self, payload, num_tries=3):
- """
- Write a packet. If the payload argument is a list, it is
- assumed to be exactly the payload. Otherwise the payload is
- assume to be a GenericPacket and the real payload is obtain
- by calling the .payload().
- """
-
- global _seqno
- if type(payload) != type([]):
- # Assume this will be derived from GenericPacket
- payload = payload.payload()
- _seqno = (_seqno + 1) % 100
- packet = DataFrame();
- packet.protocol = self.SERIAL_PROTO_PACKET_ACK
- packet.seqno = _seqno
- packet.dispatch = 0
- packet.data = payload
- packet = packet.payload()
- crc = self.crc16(0, packet)
- packet.append(crc & 0xff)
- packet.append((crc >> 8) & 0xff)
- packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
-
- for i in range(num_tries):
- self._put_bytes(packet)
- if self._debug == True:
- print "Send:", packet
-
- # Waits for ACK
- for j in range(3):
- p = self.sniff(skip_queue = True)
- if p != None:
- ack = AckFrame(p.data)
- if ack.protocol == self.SERIAL_PROTO_ACK:
- if ack.seqno != _seqno:
- print ">" * 40, "Wrong ACK!", ack.seqno, _seqno, "<" * 40
- return True
- else:
- if self._debug == True:
- print "write_packet: put a packet in the queue(%d)." % (self._queue.qsize())
- self._queue.put(p)
-
- return False
-
- def debug(self, debug):
- self._debug = debug
-
-
-
-class GenericPacket:
- """ GenericPacket """
-
- def _decode(self, v):
- r = long(0)
- for i in v:
- r = (r << 8) + i
- return r
-
- def _encode(self, val, dim):
- output = []
- for i in range(dim):
- output.append(int(val & 0xFF))
- val = val >> 8
- output.reverse()
- return output
-
- def __init__(self, desc, packet = None):
- offset = 0
- boffset = 0
- sum = 0
- for i in range(len(desc)-1, -1, -1):
- (n, t, s) = desc[i]
- if s == None:
- if sum > 0:
- desc[i] = (n, t, -sum)
- break
- sum += s
- self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
- self.__dict__['_names'] = [n for (n, t, s) in desc]
- self.__dict__['_values'] = []
- if type(packet) == type([]):
- for (t, s) in self._schema:
- if t == 'int':
- self._values.append(self._decode(packet[offset:offset + s]))
- offset += s
- elif t == 'bint':
- doffset = 8 - (boffset + s)
- self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
- boffset += s
- if boffset == 8:
- offset += 1
- boffset = 0
- elif t == 'string':
- self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
- offset += s
- elif t == 'blob':
- if s:
- if s > 0:
- self._values.append(packet[offset:offset + s])
- offset += s
- else:
- self._values.append(packet[offset:s])
- offset = len(packet) + s
- else:
- self._values.append(packet[offset:])
- elif type(packet) == type(()):
- for i in packet:
- self._values.append(i)
- else:
- for v in self._schema:
- self._values.append(None)
-
- def __repr__(self):
- return self._values.__repr__()
-
- def __str__(self):
- r = ""
- for i in range(len(self._names)):
- r += "%s: %s " % (self._names[i], self._values[i])
- for i in range(len(self._names), len(self._values)):
- r += "%s" % self._values[i]
- return r
-# return self._values.__str__()
-
- # Implement the map behavior
- def __getitem__(self, key):
- return self.__getattr__(key)
-
- def __setitem__(self, key, value):
- self.__setattr__(key, value)
-
- def __len__(self):
- return len(self._values)
-
- def keys(self):
- return self._names
-
- def values(self):
- return self._names
-
- # Implement the struct behavior
- def __getattr__(self, name):
- #print "DEBUG: __getattr__", name
- if type(name) == type(0):
- return self._names[name]
- else:
- return self._values[self._names.index(name)]
-
- def __setattr__(self, name, value):
- if type(name) == type(0):
- self._values[name] = value
- else:
- self._values[self._names.index(name)] = value
-
- def __ne__(self, other):
- if other.__class__ == self.__class__:
- return self._values != other._values
- else:
- return True
-
- def __eq__(self, other):
- if other.__class__ == self.__class__:
- return self._values == other._values
- else:
- return False
-
- def __nonzero__(self):
- return True;
-
- # Custom
- def names(self):
- return self._names
-
- def sizes(self):
- return self._schema
-
- def payload(self):
- r = []
- boffset = 0
- for i in range(len(self._schema)):
- (t, s) = self._schema[i]
- if t == 'int':
- r += self._encode(self._values[i], s)
- boffset = 0
- elif t == 'bint':
- doffset = 8 - (boffset + s)
- if boffset == 0:
- r += [self._values[i] << doffset]
- else:
- r[-1] |= self._values[i] << doffset
- boffset += s
- if boffset == 8:
- boffset = 0
- elif self._values[i] != []:
- r += self._values[i]
- for i in self._values[len(self._schema):]:
- r += i
- return r
-
-
-class RawPacket(GenericPacket):
- def __init__(self, ts = None, data = None, crc = None):
- GenericPacket.__init__(self,
- [('ts' , 'int', 4),
- ('crc', 'int', 1),
- ('data', 'blob', None)],
- None)
- self.ts = ts;
- self.data = data
- self.crc = crc
-
-
-class AckFrame(GenericPacket):
- def __init__(self, payload = None):
- GenericPacket.__init__(self,
- [('protocol', 'int', 1),
- ('seqno', 'int', 1)],
- payload)
-
-class DataFrame(GenericPacket):
- def __init__(self, payload = None):
- if payload != None and type(payload) != type([]):
- # Assume is a GenericPacket
- payload = payload.payload()
- GenericPacket.__init__(self,
- [('protocol', 'int', 1),
- ('seqno', 'int', 1),
- ('dispatch', 'int', 1),
- ('data', 'blob', None)],
- payload)
-
-class NoAckDataFrame(GenericPacket):
- def __init__(self, payload = None):
- if payload != None and type(payload) != type([]):
- # Assume is a GenericPacket
- payload = payload.payload()
- GenericPacket.__init__(self,
- [('protocol', 'int', 1),
- ('dispatch', 'int', 1),
- ('data', 'blob', None)],
- payload)
-
-class ActiveMessage(GenericPacket):
- def __init__(self, gpacket = None, am_id = 0x00, dest = 0xFFFF):
- if type(gpacket) == type([]):
- payload = gpacket
- else:
- # Assume this will be derived from GenericPacket
- payload = None
- GenericPacket.__init__(self,
- [('destination', 'int', 2),
- ('source', 'int', 2),
- ('length', 'int', 1),
- ('group', 'int', 1),
- ('type', 'int', 1),
- ('data', 'blob', None)],
- payload)
- if payload == None:
- self.destination = dest
- self.source = 0x0000
- self.group = 0x00
- self.type = am_id
- self.data = gpacket.payload()
- self.length = len(self.data)
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
-# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
import sys, struct, operator
from xml.dom.minidom import parse
all.append((start_addr, section))
if rectype == 0x03:
# This last record updates the first 4 bytes which
- # holds some some low level configuration. They are
- # the same all the time so I guess that's why they are
+ # holds some low level configuration. They are the
+ # same all the time so I guess that's why they are
# skipped.
break
section = []
all_data += encode(addr, 4) + \
encode(len(data), 4) + \
data
+all_data += encode(0, 4) + encode(0, 4) # Add the marker for the end of an image
padding = [0] * (DELUGE_BYTES_PER_PAGE - len(all_data) % DELUGE_BYTES_PER_PAGE)
if len(padding) < DELUGE_BYTES_PER_PAGE:
all_data += padding
# @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
import sys, stat, struct, subprocess, time
-import tinyos
+import tos
from datetime import datetime
import os.path
DM_AMID = 0xAC
SERIAL_DATA_LENGTH = 28 - 1 - 1 - 2 - 2
BAUDRATES = {'micaz': 57600,
- 'telosb': 115200}
+ 'telosb': 115200,
+ 'iris': 57600}
# Commands for FlashManager
FM_CMD_ERASE = 0
DELUGE_IDENT_OFFSET = 0
DELUGE_IDENT_SIZE = 128
-class FMReqPacket(tinyos.GenericPacket):
+class FMReqPacket(tos.Packet):
def __init__(self, packet = None):
- tinyos.GenericPacket.__init__(self,
- [('cmd', 'int', 1),
- ('imgNum', 'int', 1),
- ('offset', 'int', 2),
- ('length', 'int', 2),
- ('data', 'blob', None)],
- packet)
-
-class DMReqPacket(tinyos.GenericPacket):
+ tos.Packet.__init__(self,
+ [('cmd', 'int', 1),
+ ('imgNum', 'int', 1),
+ ('offset', 'int', 2),
+ ('length', 'int', 2),
+ ('data', 'blob', None)],
+ packet)
+
+class DMReqPacket(tos.Packet):
def __init__(self, packet = None):
- tinyos.GenericPacket.__init__(self,
- [('cmd', 'int', 1),
- ('imgNum', 'int', 1)],
- packet)
+ tos.Packet.__init__(self,
+ [('cmd', 'int', 1),
+ ('imgNum', 'int', 1)],
+ packet)
-class SerialReplyPacket(tinyos.GenericPacket):
+class SerialReplyPacket(tos.Packet):
def __init__(self, packet = None):
- tinyos.GenericPacket.__init__(self,
- [('error', 'int', 1),
- ('data', 'blob', None)],
- packet)
+ tos.Packet.__init__(self,
+ [('error', 'int', 1),
+ ('data', 'blob', None)],
+ packet)
-class Ident(tinyos.GenericPacket):
+class Ident(tos.Packet):
def __init__(self, packet = None):
- tinyos.GenericPacket.__init__(self,
- [('uidhash', 'int', 4),
- ('size', 'int', 4),
- ('pages', 'int', 1),
- ('reserved', 'int', 1),
- ('crc', 'int', 2),
- ('appname', 'string', 16),
- ('username', 'string', 16),
- ('hostname', 'string', 16),
- ('platform', 'string', 16),
- ('timestamp','int', 4),
- ('userhash', 'int', 4)],
- packet)
-
-class ShortIdent(tinyos.GenericPacket):
+ tos.Packet.__init__(self,
+ [('uidhash', 'int', 4),
+ ('size', 'int', 4),
+ ('pages', 'int', 1),
+ ('reserved', 'int', 1),
+ ('crc', 'int', 2),
+ ('appname', 'string', 16),
+ ('username', 'string', 16),
+ ('hostname', 'string', 16),
+ ('platform', 'string', 16),
+ ('timestamp','int', 4),
+ ('userhash', 'int', 4)],
+ packet)
+
+class ShortIdent(tos.Packet):
def __init__(self, packet = None):
- tinyos.GenericPacket.__init__(self,
- [('appname', 'string', 16),
- ('timestamp','int', 4),
- ('uidhash', 'int', 4),
- ('nodeid', 'int', 2)],
- packet)
+ tos.Packet.__init__(self,
+ [('appname', 'string', 16),
+ ('timestamp','int', 4),
+ ('uidhash', 'int', 4),
+ ('nodeid', 'int', 2)],
+ packet)
# Computes 16-bit CRC
def handleResponse(success, msg):
if success == True:
- packet = s.sniff_am()
+ packet = am.read(timeout=1)
while packet and packet.type == 100:
print "".join([chr(i) for i in packet.data])
- packet = s.sniff_am()
+ packet = am.read()
+ if not packet:
+ print "No response"
+ return False
reply = SerialReplyPacket(packet.data)
if reply.error == ERROR_SUCCESS:
- print reply
return True
else:
print msg, reply
def ident():
sreqpkt = FMReqPacket((FM_CMD_IDENT, 0, 0, 0, []))
- if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
- packet = s.sniff_am()
+ if am.write(sreqpkt, FM_AMID):
+ packet = am.read()
reply = SerialReplyPacket(packet.data)
if reply.error == ERROR_SUCCESS:
return ShortIdent(reply.data)
if sreqpkt.length > SERIAL_DATA_LENGTH:
sreqpkt.length = SERIAL_DATA_LENGTH
- if s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
- packet = s.sniff_am()
+ if am.write(sreqpkt, FM_AMID):
+ packet = am.read()
reply = SerialReplyPacket(packet.data)
if reply.error == ERROR_SUCCESS:
r.extend(reply.data)
def erase(imgNum):
sreqpkt = FMReqPacket((FM_CMD_ERASE, imgNum, 0, 0, []))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID))
+ success = am.write(sreqpkt, FM_AMID)
return handleResponse(success, "ERROR: Unable to erase the flash volume")
def sync(imgNum):
sreqpkt = FMReqPacket((FM_CMD_SYNC, imgNum, 0, 0, []))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID))
+ success = am.write(sreqpkt, FM_AMID)
return handleResponse(success, "ERROR: Unable to sync the flash volume")
def write(imgNum, data):
sreqpkt.data = data[sreqpkt.offset:sreqpkt.offset+sreqpkt.length]
# Sends over serial to the mote
- if not s.write(tinyos.ActiveMessage(sreqpkt, am_id=FM_AMID)):
+ if not am.write(sreqpkt, FM_AMID):
print
print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset
return False
# Waiting for confirmation
- packet = s.sniff_am()
+ packet = am.read()
reply = SerialReplyPacket(packet.data)
if reply.error != ERROR_SUCCESS:
print
cmd = [PATH_PY_BUILD_IMAGE, "-i", str(imgNum), tos_image_xml]
print "Create image:", ' '.join(cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- print p.stderr.read(),
+ (out, err) = p.communicate(None)
+ print err,
print "--------------------------------------------------"
# Writes the new binary image
- image = [struct.unpack("B", c)[0] for c in p.stdout.read()]
+ image = [struct.unpack("B", c)[0] for c in out]
if len(image) > 0 and erase(imgNum):
if write(imgNum, image):
if sync(imgNum):
def boot():
sreqpkt = DMReqPacket((DM_CMD_BOOT, 0))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to boot the mote")
def reprogram(imgNum):
sreqpkt = DMReqPacket((DM_CMD_REPROGRAM, imgNum))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to reprogram the mote")
def disseminate(imgNum):
sreqpkt = DMReqPacket((DM_CMD_ONLY_DISSEMINATE, imgNum))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to disseminate")
def disseminateAndReboot(imgNum):
sreqpkt = DMReqPacket((DM_CMD_DISSEMINATE_AND_REPROGRAM, imgNum))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to disseminate-and-reboot")
def stop():
sreqpkt = DMReqPacket((DM_CMD_STOP, 0))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to initiate the stop")
def localstop():
sreqpkt = DMReqPacket((DM_CMD_LOCAL_STOP, 0))
- success = s.write(tinyos.ActiveMessage(sreqpkt, am_id=DM_AMID))
+ success = am.write(sreqpkt, DM_AMID)
return handleResponse(success, "ERROR: Unable to initiate the local stop")
def print_usage():
# Initializes serial port communication
try:
- s = tinyos.Serial(sys.argv[1], baudrate, flush=False)
+ s = tos.Serial(sys.argv[1], baudrate, flush=True, debug=False)
+ am = tos.AM(s)
except:
print "ERROR: Unable to initialize serial port connection to", sys.argv[1]
sys.exit(-1)
--- /dev/null
+# Copyright (c) 2008 Johns Hopkins University.
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose, without fee, and without written
+# agreement is hereby granted, provided that the above copyright
+# notice, the (updated) modification history and the author appear in
+# all copies of this source code.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+
+"""A library that implements the T2 serial communication.
+
+This library has two parts: one that deals with sending and receiving
+packets using the serial format from T2 (TEP113) and a second one that
+tries to simplifies the work with arbitrary packets.
+
+"""
+
+import sys, struct, time, serial, socket, operator, thread
+from Queue import Queue
+from threading import Lock, Condition
+
+__version__ = "$Id$"
+
+__all__ = ['Serial', 'AM',
+ 'Packet', 'RawPacket',
+ 'AckFrame', 'DataFrame', 'NoAckDataFrame',
+ 'ActiveMessage']
+
+def list2hex(v):
+ return " ".join(["%02x" % p for p in v])
+
+class Serial:
+ """
+ A Serial object offers a way to send and data using a HDLC-like
+ formating.
+ """
+
+ HDLC_FLAG_BYTE = 0x7e
+ HDLC_CTLESC_BYTE = 0x7d
+
+ TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
+ TOS_SERIAL_CC1000_ID = 1
+ TOS_SERIAL_802_15_4_ID = 2
+ TOS_SERIAL_UNKNOWN_ID = 255
+
+ SERIAL_PROTO_ACK = 67
+ SERIAL_PROTO_PACKET_ACK = 68
+ SERIAL_PROTO_PACKET_NOACK = 69
+ SERIAL_PROTO_PACKET_UNKNOWN = 255
+
+ def __init__(self, port, baudrate, flush=False, debug=False, qsize=10):
+ self._debug = debug
+ self._in_queue = Queue(qsize)
+ self._out_lock = Lock()
+ self._out_ack = Condition()
+ self._seqno = 0
+ self._ack = None
+ self._write_counter = 0
+ self._write_counter_failures = 0
+ self._read_counter = 0
+ self._ts = None
+
+ self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
+ self._s.flushInput()
+ start = time.time();
+ if flush:
+ print >>sys.stdout, "Flushing the serial port",
+ while time.time() - start < 1:
+ p = self._read()
+ sys.stdout.write(".")
+ if not self._debug:
+ sys.stdout.write("\n")
+ self._s.close()
+ self._s = serial.Serial(port, baudrate, rtscts=0, timeout=None)
+
+ thread.start_new_thread(self.run, ())
+
+ def run(self):
+
+ while True:
+ p = self._read()
+ self._read_counter += 1
+ if self._debug:
+ print "Serial:run: got a packet(%d): %s" % (self._read_counter, p)
+ ack = AckFrame(p.data)
+ if ack.protocol == self.SERIAL_PROTO_ACK:
+ if not self._ack:
+ self._ack = ack
+ if self._debug:
+ print "Serial:run: got an ack:", ack
+ self._ack = ack
+ # Wake up the writer
+ self._out_ack.acquire()
+ self._out_ack.notify()
+ self._out_ack.release()
+ else:
+ ampkt = ActiveMessage(NoAckDataFrame(p.data).data)
+ if ampkt.type == 100:
+ for t in "".join([chr(i) for i in ampkt.data]).strip('\n\0').split('\n'):
+ print "PRINTF:", t.strip('\n')
+ else:
+ if self._in_queue.full():
+ print "Warning: Buffer overflow"
+ self._in_queue.get()
+ self._in_queue.put(p, block=False)
+
+
+ # Returns the next incoming serial packet
+ def _read(self):
+ """Wait for a packet and return it as a RawPacket."""
+
+ try:
+ d = self._get_byte()
+ ts = time.time()
+ while d != self.HDLC_FLAG_BYTE:
+ d = self._get_byte()
+ ts = time.time()
+ packet = [d]
+ d = self._get_byte()
+ if d == self.HDLC_FLAG_BYTE:
+ d = self._get_byte()
+ ts = time.time()
+ else:
+ packet.append(d)
+ while d != self.HDLC_FLAG_BYTE:
+ d = self._get_byte()
+ packet.append(d)
+ if self._debug == True:
+ print "Serial:_read: unescaped", packet
+ packet = self._unescape(packet)
+
+ crc = self._crc16(0, packet[1:-3])
+ packet_crc = self._decode(packet[-3:-1])
+
+ if crc != packet_crc:
+ print "Warning: wrong CRC! %x != %x %s" % (crc, packet_crc, ["%2x" % i for i in packet])
+ if self._debug:
+ if self._ts == None:
+ self._ts = ts
+ else:
+ print "Serial:_read: %.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
+ self._ts = ts
+ return RawPacket(ts, packet[1:-3], crc == packet_crc)
+ except socket.timeout:
+ return None
+
+
+ def read(self, timeout=0):
+ start = time.time();
+ done = False
+ while not done:
+ p = None
+ while p == None:
+ if timeout == 0 or time.time() - start < timeout:
+ p = self._in_queue.get()
+ else:
+ return None
+ if p.crc:
+ done = True
+ else:
+ p = None
+ # In the current TinyOS the packets from the mote are always NoAckDataFrame
+ return NoAckDataFrame(p.data)
+
+ def write(self, payload):
+ """
+ Write a packet. If the payload argument is a list, it is
+ assumed to be exactly the payload. Otherwise the payload is
+ assume to be a Packet and the real payload is obtain by
+ calling the .payload().
+ """
+
+ if type(payload) != type([]):
+ # Assume this will be derived from Packet
+ payload = payload.payload()
+ self._out_lock.acquire()
+ self._seqno = (self._seqno + 1) % 100
+ packet = DataFrame();
+ packet.protocol = self.SERIAL_PROTO_PACKET_ACK
+ packet.seqno = self._seqno
+ packet.dispatch = 0
+ packet.data = payload
+ packet = packet.payload()
+ crc = self._crc16(0, packet)
+ packet.append(crc & 0xff)
+ packet.append((crc >> 8) & 0xff)
+ packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
+
+ while True:
+ self._put_bytes(packet)
+ self._write_counter += 1
+ if self._debug == True:
+ print "Send(%d/%d): %s" % (self._write_counter, self._write_counter_failures, packet)
+ print "Wait for ack %d ..." % (self._seqno)
+ self._out_ack.acquire()
+ self._out_ack.wait(0.2)
+ if self._debug:
+ print "Wait for ack %d done. Latest ack:" % (self._seqno), self._ack
+ self._out_ack.release()
+ if self._ack and self._ack.seqno == self._seqno:
+ if self._debug:
+ print "The packet was acked."
+ self._out_lock.release()
+ if self._debug:
+ print "Returning from Serial.write..."
+ return True
+ else:
+ self._write_counter_failures += 1
+ if self._debug:
+ print "The packet was not acked. Try again."
+ # break # make only one sending attempt
+ self._out_lock.release()
+ return False
+
+
+ def _format_packet(self, payload):
+ f = NoAckDataFrame(payload)
+ if f.protocol == self.SERIAL_PROTO_ACK:
+ rpacket = AckFrame(payload)
+ return "Ack seqno: %d" % (rpacket.seqno)
+ else:
+ rpacket = ActiveMessage(f.data)
+ return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
+ (rpacket.destination, rpacket.source,
+ rpacket.length, rpacket.group, rpacket.type,
+ list2hex(rpacket.data))
+
+ def _crc16(self, base_crc, frame_data):
+ crc = base_crc
+ for b in frame_data:
+ crc = crc ^ (b << 8)
+ for i in range(0, 8):
+ if crc & 0x8000 == 0x8000:
+ crc = (crc << 1) ^ 0x1021
+ else:
+ crc = crc << 1
+ crc = crc & 0xffff
+ return crc
+
+ def _encode(self, val, dim):
+ output = []
+ for i in range(dim):
+ output.append(val & 0xFF)
+ val = val >> 8
+ return output
+
+ def _decode(self, v):
+ r = long(0)
+ for i in v[::-1]:
+ r = (r << 8) + i
+ return r
+
+ def _get_byte(self):
+ try:
+ r = struct.unpack("B", self._s.read())[0]
+ return r
+ except struct.error:
+ # Serial port read timeout
+ raise socket.timeout
+
+ def _put_bytes(self, data):
+ #print "DEBUG: _put_bytes:", data
+ for b in data:
+ self._s.write(struct.pack('B', b))
+
+ def _unescape(self, packet):
+ r = []
+ esc = False
+ for b in packet:
+ if esc:
+ r.append(b ^ 0x20)
+ esc = False
+ elif b == self.HDLC_CTLESC_BYTE:
+ esc = True
+ else:
+ r.append(b)
+ return r
+
+ def _escape(self, packet):
+ r = []
+ for b in packet:
+ if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
+ r.append(self.HDLC_CTLESC_BYTE)
+ r.append(b ^ 0x20)
+ else:
+ r.append(b)
+ return r
+
+ def debug(self, debug):
+ self._debug = debug
+
+
+class SFClient:
+ def __init__(self, host, port, qsize=10):
+ self._in_queue = Queue(qsize)
+ self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._s.connect((host, port))
+ data = self._s.recv(2)
+ if data != 'U ':
+ print "Wrong handshake"
+ self._s.send("U ")
+ print "Connected"
+ thread.start_new_thread(self.run, ())
+
+ def run(self):
+ while True:
+ length = ord(self._s.recv(1))
+ data = self._s.recv(length)
+ data = [ord(c) for c in data][1:]
+ #print "Recv %d bytes" % (length), ActiveMessage(data)
+ if self._in_queue.full():
+ print "Warning: Buffer overflow"
+ self._in_queue.get()
+ p = RawPacket()
+ p.crc = 1
+ p.data = data
+ self._in_queue.put(p, block=False)
+
+ def read(self, timeout=0):
+ return self._in_queue.get()
+
+ def write(self, payload):
+ print "SFClient: write:", payload
+ if type(payload) != type([]):
+ # Assume this will be derived from Packet
+ payload = payload.payload()
+ payload = [0] + payload
+ self._s.send(chr(len(payload)))
+ self._s.send(''.join([chr(c) for c in payload]))
+ return True
+
+class AM:
+ def __init__(self, s):
+ self._s = s
+
+ def read(self, timeout=0):
+ return ActiveMessage(self._s.read().data)
+
+ def write(self, packet, amid):
+ return self._s.write(ActiveMessage(packet, amid=amid))
+
+
+class Packet:
+ """
+ The Packet class offers a handy way to build pack and unpack
+ binary data based on a given pattern.
+ """
+
+ def _decode(self, v):
+ r = long(0)
+ for i in v:
+ r = (r << 8) + i
+ return r
+
+ def _encode(self, val, dim):
+ output = []
+ for i in range(dim):
+ output.append(int(val & 0xFF))
+ val = val >> 8
+ output.reverse()
+ return output
+
+ def __init__(self, desc, packet = None):
+ offset = 0
+ boffset = 0
+ sum = 0
+ for i in range(len(desc)-1, -1, -1):
+ (n, t, s) = desc[i]
+ if s == None:
+ if sum > 0:
+ desc[i] = (n, t, -sum)
+ break
+ sum += s
+ self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
+ self.__dict__['_names'] = [n for (n, t, s) in desc]
+ self.__dict__['_values'] = []
+ if type(packet) == type([]):
+ for (t, s) in self._schema:
+ if t == 'int':
+ self._values.append(self._decode(packet[offset:offset + s]))
+ offset += s
+ elif t == 'bint':
+ doffset = 8 - (boffset + s)
+ self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
+ boffset += s
+ if boffset == 8:
+ offset += 1
+ boffset = 0
+ elif t == 'string':
+ self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
+ offset += s
+ elif t == 'blob':
+ if s:
+ if s > 0:
+ self._values.append(packet[offset:offset + s])
+ offset += s
+ else:
+ self._values.append(packet[offset:s])
+ offset = len(packet) + s
+ else:
+ self._values.append(packet[offset:])
+ elif type(packet) == type(()):
+ for i in packet:
+ self._values.append(i)
+ else:
+ for v in self._schema:
+ self._values.append(None)
+
+ def __repr__(self):
+ return self._values.__repr__()
+
+ def __str__(self):
+ r = ""
+ for i in range(len(self._names)):
+ r += "%s: %s " % (self._names[i], self._values[i])
+ for i in range(len(self._names), len(self._values)):
+ r += "%s" % self._values[i]
+ return r
+# return self._values.__str__()
+
+ # Implement the map behavior
+ def __getitem__(self, key):
+ return self.__getattr__(key)
+
+ def __setitem__(self, key, value):
+ self.__setattr__(key, value)
+
+ def __len__(self):
+ return len(self._values)
+
+ def keys(self):
+ return self._names
+
+ def values(self):
+ return self._names
+
+ # Implement the struct behavior
+ def __getattr__(self, name):
+ #print "DEBUG: __getattr__", name
+ if type(name) == type(0):
+ return self._names[name]
+ else:
+ return self._values[self._names.index(name)]
+
+ def __setattr__(self, name, value):
+ if type(name) == type(0):
+ self._values[name] = value
+ else:
+ self._values[self._names.index(name)] = value
+
+ def __ne__(self, other):
+ if other.__class__ == self.__class__:
+ return self._values != other._values
+ else:
+ return True
+
+ def __eq__(self, other):
+ if other.__class__ == self.__class__:
+ return self._values == other._values
+ else:
+ return False
+
+ def __nonzero__(self):
+ return True;
+
+ # Custom
+ def names(self):
+ return self._names
+
+ def sizes(self):
+ return self._schema
+
+ def payload(self):
+ r = []
+ boffset = 0
+ for i in range(len(self._schema)):
+ (t, s) = self._schema[i]
+ if t == 'int':
+ r += self._encode(self._values[i], s)
+ boffset = 0
+ elif t == 'bint':
+ doffset = 8 - (boffset + s)
+ if boffset == 0:
+ r += [self._values[i] << doffset]
+ else:
+ r[-1] |= self._values[i] << doffset
+ boffset += s
+ if boffset == 8:
+ boffset = 0
+ elif self._values[i] != []:
+ r += self._values[i]
+ for i in self._values[len(self._schema):]:
+ r += i
+ return r
+
+
+class RawPacket(Packet):
+ def __init__(self, ts = None, data = None, crc = None):
+ Packet.__init__(self,
+ [('ts' , 'int', 4),
+ ('crc', 'int', 1),
+ ('data', 'blob', None)],
+ None)
+ self.ts = ts;
+ self.data = data
+ self.crc = crc
+
+class AckFrame(Packet):
+ def __init__(self, payload = None):
+ Packet.__init__(self,
+ [('protocol', 'int', 1),
+ ('seqno', 'int', 1)],
+ payload)
+
+class DataFrame(Packet):
+ def __init__(self, payload = None):
+ if payload != None and type(payload) != type([]):
+ # Assume is a Packet
+ payload = payload.payload()
+ Packet.__init__(self,
+ [('protocol', 'int', 1),
+ ('seqno', 'int', 1),
+ ('dispatch', 'int', 1),
+ ('data', 'blob', None)],
+ payload)
+
+class NoAckDataFrame(Packet):
+ def __init__(self, payload = None):
+ if payload != None and type(payload) != type([]):
+ # Assume is a Packet
+ payload = payload.payload()
+ Packet.__init__(self,
+ [('protocol', 'int', 1),
+ ('dispatch', 'int', 1),
+ ('data', 'blob', None)],
+ payload)
+
+class ActiveMessage(Packet):
+ def __init__(self, gpacket = None, amid = 0x00, dest = 0xFFFF):
+ if type(gpacket) == type([]):
+ payload = gpacket
+ else:
+ # Assume this will be derived from Packet
+ payload = None
+ Packet.__init__(self,
+ [('destination', 'int', 2),
+ ('source', 'int', 2),
+ ('length', 'int', 1),
+ ('group', 'int', 1),
+ ('type', 'int', 1),
+ ('data', 'blob', None)],
+ payload)
+ if payload == None:
+ self.destination = dest
+ self.source = 0x0000
+ self.group = 0x00
+ self.type = amid
+ self.data = []
+ if gpacket:
+ self.data = gpacket.payload()
+ self.length = len(self.data)
+
enum {
DELUGE_INVALID_UID = 0xffffffff,
DELUGE_NUM_VOLUMES = 4,
+ DELUGE_KEY = 0xDE00,
+ DELUGE_AM_FLASH_VOL_MANAGER = 0xAB,
+ DELUGE_AM_DELUGE_MANAGER = 0xAC,
};
enum {
ObjectTransferC.Leds = Leds;
- components new DisseminatorC(DelugeCmd, 0xDE00);
+ components new DisseminatorC(DelugeCmd, DELUGE_KEY);
components DisseminationC;
components ActiveMessageC;
components NetProgC, DelugeP;
DelugeP.Boot -> MainC;
DelugeP.Leds = Leds;
+#ifndef DELUGE_BASESTATION
DelugeP.DisseminationValue -> DisseminatorC;
+#endif
DelugeP.DisseminationStdControl -> DisseminationC;
DelugeP.ObjectTransfer -> ObjectTransferC;
DelugeP.NetProg -> NetProgC;
DelugeP.DelugeVolumeManager -> DelugeVolumeManagerClientC;
DelugeP.Resource -> BlockStorageLockClientC;
-#ifdef DELUGE_BASESTATION
+#if defined(DELUGE_BASESTATION) || defined(DELUGE_LIGHT_BASESTATION)
components SerialStarterC;
- components new FlashVolumeManagerC(0xAB);
- components new DelugeManagerC(0xAC);
+ components new FlashVolumeManagerC(DELUGE_AM_FLASH_VOL_MANAGER);
+#endif
+
+#ifdef DELUGE_BASESTATION
+ components new DelugeManagerC(DELUGE_AM_DELUGE_MANAGER);
DelugeManagerC.DisseminationUpdate -> DisseminatorC;
#endif
* @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
*/
+#include "imgNum2volumeId.h"
+
generic module DelugeManagerP()
{
uses {
message_t serialMsg;
DelugeCmd delugeCmd;
- uint8_t imgNum2volumeId[] = {
- VOLUME_GOLDENIMAGE,
- VOLUME_DELUGE1,
- VOLUME_DELUGE2,
- VOLUME_DELUGE3
- };
void sendReply(error_t error)
{
{
SerialReqPacket *request = (SerialReqPacket *)payload;
memset(&delugeCmd, 0, sizeof(DelugeCmd));
-
call stop();
delugeCmd.type = request->cmd;
+ // Converts the image number that the user wants to the real image number
+ request->imgNum = imgNum2volumeId(request->imgNum);
switch (request->cmd) {
case DELUGE_CMD_STOP:
break;
case DELUGE_CMD_ONLY_DISSEMINATE:
case DELUGE_CMD_DISSEMINATE_AND_REPROGRAM:
- if (request->imgNum < DELUGE_NUM_VOLUMES &&
+ if (request->imgNum != NON_DELUGE_VOLUME &&
(call Resource.isOwner() ||
call Resource.immediateRequest() == SUCCESS)) {
- call DelugeMetadata.read(imgNum2volumeId[request->imgNum]);
+ call DelugeMetadata.read(request->imgNum);
} else {
sendReply(FAIL);
}
break;
case DELUGE_CMD_REPROGRAM:
- if (!(request->imgNum < DELUGE_NUM_VOLUMES)) {
+ case DELUGE_CMD_REBOOT:
+ if (request->imgNum == NON_DELUGE_VOLUME) {
sendReply(FAIL);
break;
}
- case DELUGE_CMD_REBOOT:
- delugeCmd.imgNum = imgNum2volumeId[request->imgNum];
+ delugeCmd.imgNum = request->imgNum;
call DelayTimer.startOneShot(1024);
sendReply(SUCCESS);
break;
* @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
*/
+#include "imgNum2volumeId.h"
+
module DelugeMetadataP
{
provides interface DelugeMetadata[uint8_t client];
DelugeIdent ident;
uint8_t state;
- uint8_t currentImage;
+ uint8_t currentVolume;
+ uint8_t currentImageIdx;
uint8_t currentPage;
nx_uint16_t currentCrc;
uint8_t currentClient;
void nextImage()
{
- if (currentImage < DELUGE_NUM_VOLUMES) {
+ if (currentImageIdx < DELUGE_NUM_VOLUMES) {
state = S_READ_IDENT;
- call BlockRead.read[currentImage](0, &ident, sizeof(ident));
+ call BlockRead.read[currentVolume](0, &ident, sizeof(ident));
} else {
signal storageReady();
state = S_READY;
// CRC and check it against the corresponding value from the CRCs
// block.
state = S_READ_IDENT;
- currentImage = 0;
+ currentImageIdx = 0;
+ currentVolume = _imgNum2volumeId[currentImageIdx];
nextImage();
}
if (ident.uidhash != DELUGE_INVALID_UID) {
currentPage = 0;
state = S_READ_CRC;
- call BlockRead.read[currentImage](calcCrcAddr(), ¤tCrc, sizeof(currentCrc));
+ call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, sizeof(currentCrc));
} else {
- currentImage++;
+ currentImageIdx++;
nextImage();
}
}
break;
case S_READ_CRC:
state = S_CRC;
- call BlockRead.computeCrc[currentImage](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0);
+ call BlockRead.computeCrc[currentVolume](calcPageAddr(), DELUGE_BYTES_PER_PAGE, 0);
break;
}
}
if (crc != currentCrc) {
// printf("%04x %04x\n", crc, currentCrc);
// invalidate the image by erasing it
- call BlockWrite.erase[currentImage]();
+ call BlockWrite.erase[currentVolume]();
} else {
currentPage++;
if (currentPage < ident.numPgs) {
state = S_READ_CRC;
- call BlockRead.read[currentImage](calcCrcAddr(), ¤tCrc, sizeof(currentCrc));
+ call BlockRead.read[currentVolume](calcCrcAddr(), ¤tCrc, sizeof(currentCrc));
} else {
- currentImage++;
+ currentImageIdx++;
+ currentVolume = _imgNum2volumeId[currentImageIdx];
nextImage();
}
}
signal BlockWrite.eraseDone[imgNum](error);
break;
case S_CRC:
- currentImage++;
+ currentImageIdx++;
+ currentVolume = _imgNum2volumeId[currentImageIdx];
nextImage();
break;
}
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
*/
+#include "imgNum2volumeId.h"
+
generic module FlashVolumeManagerP()
{
uses {
nx_uint16_t nodeid;
};
- uint8_t imgNum2volumeId[] = {
- VOLUME_GOLDENIMAGE,
- VOLUME_DELUGE1,
- VOLUME_DELUGE2,
- VOLUME_DELUGE3
- };
-
void sendReply(error_t error, storage_len_t len)
{
SerialReplyPacket *reply = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket));
}
// Converts the image number that the user wants to the real image number
- imgNum = request->imgNum < DELUGE_NUM_VOLUMES ? imgNum2volumeId[request->imgNum] : 0xFF;
+ imgNum = imgNum2volumeId(request->imgNum);
- if (imgNum != 0xFF) {
+ if (imgNum != NON_DELUGE_VOLUME) {
error = SUCCESS;
// We ask for a reservation only for erase and write.
switch (request->cmd) {
{
// Release the resource.
if (state == S_IDLE && call Resource.isOwner()) {
- call Leds.led1Off();
call Resource.release();
}
- if (state == S_IDLE && !call ArbiterInfo.inUse()) {
+ if (state == S_IDLE) {
call Leds.led1Off();
}
}
--- /dev/null
+interface ReprogramGuard
+{
+ command error_t okToProgram();
+ event void okToProgramDone(bool ok);
+}
implementation {
- components MainC, InternalFlashC as IFlash, CrcP, NetProgM;
+ components MainC, InternalFlashC as IFlash, CrcP;
+ components NetProgM, ReprogramGuardC;
NetProg = NetProgM;
MainC.SoftwareInit -> NetProgM.Init;
NetProgM.IFlash -> IFlash;
NetProgM.Crc -> CrcP;
-
+ NetProgM.ReprogramGuard -> ReprogramGuardC;
+
components LedsC;
NetProgM.Leds -> LedsC;
interface Leds;
interface CC2420Config;
async command void setAmAddress(am_addr_t a);
+ interface ReprogramGuard;
}
}
implementation {
+ uint32_t reprogramImgAddr;
+
command error_t Init.init()
{
BootArgs bootArgs;
}
command error_t NetProg.programImageAndReboot(uint32_t imgAddr)
+ {
+ reprogramImgAddr = imgAddr;
+ return call ReprogramGuard.okToProgram();
+ }
+
+ event void ReprogramGuard.okToProgramDone(bool ok)
{
BootArgs bootArgs;
+ if (!ok) {
+ // The voltage is too low. Nothing to do.
+ return;
+ }
+
atomic {
call IFlash.read((uint8_t*)TOSBOOT_ARGS_ADDR, &bootArgs, sizeof(bootArgs));
- bootArgs.imageAddr = imgAddr;
+ bootArgs.imageAddr = reprogramImgAddr;
bootArgs.gestureCount = 0xff;
bootArgs.noReprogram = FALSE;
bootArgs.address = TOS_NODE_ID;
// reboot
netprog_reboot();
}
-
- // couldn't reboot
- return FAIL;
}
event void CC2420Config.syncDone(error_t error) {}
-
}
--- /dev/null
+configuration ReprogramGuardC
+{
+ provides interface ReprogramGuard;
+}
+
+implementation
+{
+ components ReprogramGuardP;
+ components new VoltageC();
+
+ ReprogramGuard = ReprogramGuardP;
+ ReprogramGuardP.Voltage -> VoltageC;
+}
--- /dev/null
+module ReprogramGuardP
+{
+ provides interface ReprogramGuard;
+ uses interface Read<uint16_t> as Voltage;
+}
+
+implementation
+{
+ enum {
+ VTHRESH = 0x1CF, // 2.7V
+ };
+
+ command error_t ReprogramGuard.okToProgram()
+ {
+ return call Voltage.read();
+ }
+
+ event void Voltage.readDone(error_t result, uint16_t val)
+ {
+ signal ReprogramGuard.okToProgramDone(result == SUCCESS && val < VTHRESH);
+ }
+
+}
--- /dev/null
+configuration ReprogramGuardC
+{
+ provides interface ReprogramGuard;
+}
+
+implementation
+{
+ components ReprogramGuardP;
+ components new VoltageC();
+
+ ReprogramGuard = ReprogramGuardP;
+ ReprogramGuardP.Voltage -> VoltageC;
+}
--- /dev/null
+module ReprogramGuardP
+{
+ provides interface ReprogramGuard;
+ uses interface Read<uint16_t> as Voltage;
+}
+
+implementation
+{
+ enum {
+ VTHRESH = 0xE66, // 2.7V
+ };
+
+ command error_t ReprogramGuard.okToProgram()
+ {
+ return call Voltage.read();
+ }
+
+ event void Voltage.readDone(error_t result, uint16_t val)
+ {
+ signal ReprogramGuard.okToProgramDone(result == SUCCESS && val > VTHRESH);
+ }
+
+}
--- /dev/null
+#ifndef __IMGNUM2VOLUMEID_H__
+#define __IMGNUM2VOLUMEID_H__
+
+uint8_t _imgNum2volumeId[] = {
+ VOLUME_GOLDENIMAGE,
+ VOLUME_DELUGE1,
+ VOLUME_DELUGE2,
+ VOLUME_DELUGE3
+};
+
+enum {
+ NON_DELUGE_VOLUME = 0xFF
+};
+
+uint8_t imgNum2volumeId(uint8_t imgNum)
+{
+ return imgNum < DELUGE_NUM_VOLUMES ? _imgNum2volumeId[imgNum] : NON_DELUGE_VOLUME;
+}
+
+#endif
typedef uint32_t in_flash_addr_t;
typedef uint32_t ex_flash_addr_t;
-void wait( uint16_t t ) {
- for ( ; t; t-- );
+static inline void wait( uint16_t dt ) {
+ /* In most cases (constant arg), the test is elided at compile-time */
+ if (dt)
+ /* loop takes 8 cycles. this is 1uS if running on an internal 8MHz
+ clock, and 1.09uS if running on the external crystal. */
+ asm volatile (
+ "1: sbiw %0,1\n"
+ " adiw %0,1\n"
+ " sbiw %0,1\n"
+ " brne 1b" : "+w" (dt));
}
// LED assignments