--- /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 Chieh-Jan Mike Liang <cliang4@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_LEDS 5
+#define SERIALMSG_RUN 7
+
+typedef nx_struct SerialReqPacket {
+ nx_uint8_t msg_type;
+ nx_uint8_t pad;
+ 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 pad;
+ nx_uint8_t data[0];
+} SerialReplyPacket;
+
+#endif
--- /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 Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#include "AM.h"
+
+generic configuration FlashVolumeManagerC(am_id_t AMId)
+{
+ uses {
+ interface BlockRead;
+ interface BlockWrite;
+ interface DynamicLoader;
+ }
+}
+
+implementation
+{
+ components MainC,
+ SerialActiveMessageC,
+ new SerialAMSenderC(AMId),
+ new SerialAMReceiverC(AMId),
+ new FlashVolumeManagerP(),
+ NoLedsC, LedsC;
+
+ DynamicLoader = FlashVolumeManagerP;
+ BlockRead = FlashVolumeManagerP;
+ BlockWrite = FlashVolumeManagerP;
+
+ FlashVolumeManagerP.Boot -> MainC;
+ FlashVolumeManagerP.SerialSplitControl -> SerialActiveMessageC;
+
+ FlashVolumeManagerP.SerialAMSender -> SerialAMSenderC;
+ FlashVolumeManagerP.SerialAMReceiver -> SerialAMReceiverC;
+ FlashVolumeManagerP.Leds -> LedsC;
+}
--- /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 Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#include "FlashVolumeManager.h"
+#include "StorageVolumes.h"
+
+generic module FlashVolumeManagerP()
+{
+ uses {
+ interface Boot;
+ interface SplitControl as SerialSplitControl;
+ interface BlockRead;
+ interface BlockWrite;
+ interface AMSend as SerialAMSender;
+ interface Receive as SerialAMReceiver;
+ interface Leds;
+ interface DynamicLoader;
+ }
+}
+
+implementation
+{
+ message_t serialMsg;
+ storage_addr_t dumpAddr = 0;
+
+ event void Boot.booted() {
+ while (call SerialSplitControl.start() != SUCCESS);
+ }
+
+ event void SerialSplitControl.startDone(error_t error)
+ {
+ if (error != SUCCESS) {
+ while (call SerialSplitControl.start() != SUCCESS);
+ }
+ }
+
+ void sendReply(error_t error, storage_len_t len)
+ {
+ SerialReplyPacket *srpkt = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket));
+ if (error == SUCCESS) {
+ srpkt->error = SERIALMSG_SUCCESS;
+ } else {
+ srpkt->error = SERIALMSG_FAIL;
+ }
+ call SerialAMSender.send(AM_BROADCAST_ADDR, &serialMsg, len);
+ }
+
+ event void BlockRead.readDone(storage_addr_t addr, void* buf, storage_len_t len, error_t error) {
+ sendReply(error, len + sizeof(SerialReplyPacket));
+ }
+
+ event void BlockRead.computeCrcDone(storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error)
+ {
+ if (error == SUCCESS) {
+ SerialReplyPacket *srpkt = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket));
+ srpkt->data[1] = crc & 0xFF;
+ srpkt->data[0] = (crc >> 8) & 0xFF;
+ }
+ sendReply(error, 2 + sizeof(SerialReplyPacket));
+ }
+
+ event void BlockWrite.writeDone(storage_addr_t addr, void* buf, storage_len_t len, error_t error)
+ {
+ if (error != SUCCESS) {
+ call Leds.led1On();
+ }
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+
+ event void BlockWrite.eraseDone(error_t error) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+
+ event message_t* SerialAMReceiver.receive(message_t* msg, void* payload, uint8_t len)
+ {
+ uint16_t i;
+ error_t error = SUCCESS;
+ SerialReqPacket *srpkt = (SerialReqPacket *)payload;
+ SerialReplyPacket *serialMsg_payload = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg, sizeof(SerialReplyPacket));
+
+ switch (srpkt->msg_type) {
+ case SERIALMSG_ERASE :
+ error = call BlockWrite.erase();
+ if (error != SUCCESS) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+ break;
+ case SERIALMSG_WRITE :
+ call Leds.led2On();
+ error = call BlockWrite.write(srpkt->offset, srpkt->data, srpkt->len);
+ if (error != SUCCESS) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ call Leds.led0On();
+ }
+ break;
+ case SERIALMSG_READ :
+ error = call BlockRead.read(srpkt->offset, serialMsg_payload->data, srpkt->len);
+ if (error != SUCCESS) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+ break;
+ case SERIALMSG_CRC :
+ error = call BlockRead.computeCrc(srpkt->offset, srpkt->len, 0);
+ if (error != SUCCESS) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+ break;
+ case SERIALMSG_LEDS:
+ call Leds.set(7);
+ for (i = 0; i < 2000; i++) {}
+ call Leds.set(0);
+ break;
+ case SERIALMSG_RUN :
+ error = call DynamicLoader.loadFromFlash(VOLUME_MICROEXEIMAGE);
+ if (error != SUCCESS)
+ sendReply(error, sizeof(SerialReplyPacket));
+ break;
+ }
+
+ return msg;
+ }
+
+ event void DynamicLoader.loadFromFlashDone(uint8_t volumeId, tosthread_t id, error_t error) {
+ sendReply(error, sizeof(SerialReplyPacket));
+ }
+
+ event void DynamicLoader.loadFromMemoryDone(void *addr, tosthread_t id, error_t error) {}
+ event void BlockWrite.syncDone(error_t error) {}
+ event void SerialAMSender.sendDone(message_t* msg, error_t error) {}
+ event void SerialSplitControl.stopDone(error_t error) {}
+}
--- /dev/null
+COMPONENT=SerialLoaderFlashAppC
+
+GOALS += threads
+
+THREADS_DIR ?= $(TOSDIR)/lib/tosthreads
+CFLAGS += -I$(THREADS_DIR)/lib/tinyld
+CFLAGS += -I$(THREADS_DIR)/csystem
+CFLAGS += -I$(THREADS_DIR)/sensorboards/tmote_onboard
+CFLAGS += -I$(THREADS_DIR)/sensorboards/universal
+CFLAGS += -I$(THREADS_DIR)/lib/net/ctp
+CFLAGS += -I$(THREADS_DIR)/lib/net
+CFLAGS += -I$(TOSDIR)/lib/net
+CFLAGS += -I$(TOSDIR)/lib/net/ctp
+CFLAGS += -I$(TOSDIR)/lib/net/4bitle
+CFLAGS += -I$(THREADS_DIR)/lib/printf
+
+# Creates VolumeMapC.nc
+VOLUME_ALLOCATOR_FLAGS += -t
+
+CLEAN_EXTRA += *.pyc
+
+include $(MAKERULES)
--- /dev/null
+README for SerialLoaderFlash
+Author/Contact: Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+
+Description:
+
+SerialLoaderFlash is similar to SerialLoader in that it receives
+loadable programs from the serial port. However, SerialLoaderFlash
+stores them on the external flash. Then, when it receives the command to
+load the code, it makes the call to the dynamic loader.
+
+Here are the steps:
+1.) Load SerialLoader:
+ make telosb install bsl,<device_port>
+
+2.) Create the loadable code, Blink.tos:
+ tosthreads-gen-dynamic-app ../../capps/Blink/Blink.c
+
+3.) Erase the external flash:
+ ./serialloader.py <device_port> 0
+
+4.) Upload the binary:
+ ./serialloader.py <device_port> 1 Blink.tos
+
+5.) Run the binary:
+ ./serialloader.py <device_port> 7
--- /dev/null
+/*
+ * Copyright (c) 2008 Stanford University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Stanford University nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD
+ * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @author Kevin Klues (klueska@cs.stanford.edu)
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ */
+
+#include "StorageVolumes.h"
+
+configuration SerialLoaderFlashAppC {}
+
+implementation {
+ components DynamicLoaderC,
+ new FlashVolumeManagerC(0xAB),
+ new BlockStorageC(VOLUME_MICROEXEIMAGE) as ImageVolume;
+
+ FlashVolumeManagerC.BlockRead -> ImageVolume;
+ FlashVolumeManagerC.BlockWrite -> ImageVolume;
+ FlashVolumeManagerC.DynamicLoader -> DynamicLoaderC;
+}
--- /dev/null
+#!/usr/bin/env python
+
+# 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 Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+
+import sys, os, stat, struct
+import tinyos
+
+SERIALMSG_AMGROUP = 0
+SERIALMSG_AMID = 0xAB
+
+SERIALMSG_ERASE = 0
+SERIALMSG_WRITE = 1
+SERIALMSG_READ = 2
+SERIALMSG_CRC = 3
+SERIALMSG_LEDS = 5
+SERIALMSG_RUN = 7
+
+SERIALMSG_SUCCESS = 0
+SERIALMSG_FAIL = 1
+
+SERIALMSG_DATA_PAYLOAD_SIZE = 20
+DELUGE_VOLUME_SIZE = 262144
+
+HEX_OUTPUT_LINE_SIZE = 16
+
+class SerialReqPacket(tinyos.GenericPacket):
+ def __init__(self, packet = None):
+ tinyos.GenericPacket.__init__(self,
+ [('msg_type', 'int', 1),
+ ('pad', 'int', 1),
+ ('offset', 'int', 2),
+ ('len', 'int', 2),
+ ('data', 'blob', None)],
+ packet)
+
+class SerialReplyPacket(tinyos.GenericPacket):
+ def __init__(self, packet = None):
+ tinyos.GenericPacket.__init__(self,
+ [('error', 'int', 1),
+ ('pad', 'int', 1),
+ ('data', 'blob', None)],
+ packet)
+
+# Display an integer representation of byte stream to hex representation
+def print_hex(start_addr, byte_stream):
+ byte_stream = ["%02x" % one_byte for one_byte in byte_stream] # Converts to each byte to hex
+
+ num_iterations = int( (len(byte_stream) - 1) / HEX_OUTPUT_LINE_SIZE )
+ num_iterations += 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 += byte_stream[i * HEX_OUTPUT_LINE_SIZE + j] + " "
+ print line
+
+ start_addr += HEX_OUTPUT_LINE_SIZE
+
+def op_run(s, sreqpkt):
+ success = s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload())
+ if success == True:
+ packet = s.read_packet()
+ sreplypkt = SerialReplyPacket(packet[1])
+ return (sreplypkt.error == SERIALMSG_SUCCESS)
+
+def op_erase(s, sreqpkt):
+ success = s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload())
+ if success == True:
+ packet = s.read_packet()
+ sreplypkt = SerialReplyPacket(packet[1])
+ return (sreplypkt.error == SERIALMSG_SUCCESS)
+
+def op_print(s, sreqpkt, offset, length):
+ if (offset + length) <= DELUGE_VOLUME_SIZE:
+ while length > 0:
+ sreqpkt.offset = offset
+ # Calculates the payload size for the reply packet
+ if length >= HEX_OUTPUT_LINE_SIZE:
+ sreqpkt.len = HEX_OUTPUT_LINE_SIZE
+ else:
+ sreqpkt.len = length
+
+ success = s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload())
+ if success == True:
+ packet = s.read_packet()
+ sreplypkt = SerialReplyPacket(packet[1])
+ if sreplypkt.error != SERIALMSG_SUCCESS:
+ return False
+
+ print_hex(offset, sreplypkt.data)
+ length -= sreqpkt.len
+ offset += sreqpkt.len
+ else:
+ print "ERROR: Specified offset and length are too large for the flash volume"
+ return False
+
+ return True
+
+def op_write(s, sreqpkt, input_file, length):
+ local_crc = 0
+ input_file_size = length
+
+ sreqpkt.offset = 0
+ while length > 0:
+ # Calculates the payload size for the current packet
+ if length >= SERIALMSG_DATA_PAYLOAD_SIZE:
+ sreqpkt.len = SERIALMSG_DATA_PAYLOAD_SIZE
+ 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", input_file.read(1))[0])
+
+ # Sends over serial to the mote
+ if s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload()) == True:
+ # Waiting for confirmation
+ packet = s.read_packet()
+ sreplypkt = SerialReplyPacket(packet[1])
+ if sreplypkt.error != SERIALMSG_SUCCESS:
+ return False
+ local_crc = s.crc16(local_crc, sreqpkt.data) # Computes running CRC
+ else:
+ print "ERROR: Unable to write to flash"
+ return False
+
+ length -= sreqpkt.len
+ sreqpkt.offset += sreqpkt.len
+
+ # Check local and remote CRC
+ sreqpkt.msg_type = SERIALMSG_CRC
+ remote_crc = op_crc(s, sreqpkt, 0, input_file_size)
+ if remote_crc != None:
+ local_crc = [(local_crc >> 8) & 0xFF, local_crc & 0xFF]
+ print "Local CRC: " + ("%02x" % local_crc[0]) + " " + ("%02x" % local_crc[1])
+ print "Remote CRC: " + ("%02x" % remote_crc[0]) + " " + ("%02x" % remote_crc[1])
+ if remote_crc != local_crc:
+ print "ERROR: Remote CRC doesn't match local CRC"
+ return False
+ else:
+ print "ERROR: Unable to verify CRC"
+ return False
+
+ return True
+
+def op_crc(s, sreqpkt, offset, length):
+ sreqpkt.offset = offset
+ sreqpkt.len = length
+ success = s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload())
+ if success == True:
+ packet = s.read_packet()
+ sreplypkt = SerialReplyPacket(packet[1])
+ if sreplypkt.error == SERIALMSG_SUCCESS:
+ return sreplypkt.data
+ else:
+ return None
+
+def op_leds(s, sreqpkt):
+ success = s.write_packet(SERIALMSG_AMGROUP, SERIALMSG_AMID, sreqpkt.payload())
+
+# ======== MAIN ======== #
+if len(sys.argv) >= 3:
+ sys.argv[2] = int(sys.argv[2])
+
+ s = tinyos.Serial(sys.argv[1], 57600)
+ s.set_debug(False) # Disables debug msg
+ sreqpkt = SerialReqPacket((sys.argv[2], 0, 0, 0, [])) # msg_type, pad, offset, length, data
+
+ if sys.argv[2] == SERIALMSG_RUN:
+ if op_run(s, sreqpkt) == True:
+ print "Loaded image should be running now!"
+ else:
+ print "ERROR: Unable to run loaded image"
+ elif sys.argv[2] == SERIALMSG_ERASE:
+ if op_erase(s, sreqpkt) == True:
+ print "Flash volume has been erased"
+ else:
+ print "ERROR: Unable to erase flash volume"
+
+ elif sys.argv[2] == SERIALMSG_WRITE:
+ input_file = file(sys.argv[3], 'rb')
+ fileStats = os.stat(sys.argv[3])
+
+ if fileStats[stat.ST_SIZE] <= DELUGE_VOLUME_SIZE:
+ #sreqpkt = SerialReqPacket((SERIALMSG_LEDS, 0, 0, 0, []))
+ #op_leds(s, sreqpkt)
+ sreqpkt = SerialReqPacket((sys.argv[2], 0, 0, 0, []))
+ if op_write(s, sreqpkt, input_file, fileStats[stat.ST_SIZE]) == True:
+ print "File has been successfully transmitted (" + str(fileStats[stat.ST_SIZE]) + " bytes)"
+ else:
+ print "ERROR: Unable to transmit file"
+ sreqpkt = SerialReqPacket((SERIALMSG_LEDS, 0, 0, 0, []))
+ op_leds(s, sreqpkt)
+ else:
+ print "ERROR: File is larger than flash volume (" + DELUGE_VOLUME_SIZE + ")"
+
+ elif sys.argv[2] == SERIALMSG_READ:
+ data = op_print(s, sreqpkt, int(sys.argv[3]), int(sys.argv[4]))
+ if data != True:
+ print "ERROR: Unable to read the specified range"
+
+ elif sys.argv[2] == SERIALMSG_CRC:
+ remote_crc = op_crc(s, sreqpkt, int(sys.argv[3]), int(sys.argv[4]))
+ if remote_crc != None:
+ print_hex(0, remote_crc)
+ else:
+ print "ERROR: Unable to compute remote CRC"
--- /dev/null
+import struct, time, serial
+
+class Serial:
+ 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
+
+ __s = None; # An instance of serial.Serial object
+ __debug = True # Debug mode
+
+ def __init__(self, port, baudrate):
+ self.__s = serial.Serial(port, baudrate, rtscts=0)
+
+ def __format_packet(self, packet):
+ return " ".join(["%02x" % p for p in packet]) + " | " + \
+ " ".join(["%d" % p for p in packet])
+
+ 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):
+ r = struct.unpack("B", self.__s.read())[0]
+ return r
+
+ def __put_bytes(self, 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 read_packet(self):
+ 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)
+ un_packet = self.__unescape(packet)
+ crc = self.crc16(0, un_packet[1:-3])
+ packet_crc = self.__decode(un_packet[-3:-1])
+ if crc != packet_crc:
+ print "Warning: wrong CRC!"
+ if self.__debug == True:
+ print "Recv:", self.__format_packet(un_packet)
+ return (ts, un_packet)
+
+ def write_packet(self, am_group, am_id, data):
+ # 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]
+ if self.__debug == True:
+ print "Send:", self.__format_packet(packet)
+ self.__put_bytes(packet)
+
+ # Waiting for ACK
+ packet = self.read_packet()
+ if len(packet) > 1 and len(packet[1]) > 1:
+ return ((packet[1])[1] == self.SERIAL_PROTO_ACK)
+ return False
+
+ def set_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):
+ 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]))
+ offset += s
+ elif t == 'blob':
+ if s:
+ self._values.append(packet[offset:offset + s])
+ offset += s
+ else:
+ self._values.append(packet[offset:-3])
+ 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):
+ 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):
+ 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
+
+ # Custom
+ def names(self):
+ return self._names
+
+ def sizes(self):
+ return self._schema
+
+ def payload(self):
+ r = []
+ 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._values[i]
+ return r
--- /dev/null
+<volume_table>
+ <volume name="MICROEXEIMAGE" size="262144" type="block"/>
+</volume_table>