From a502f8b43dfae5ebbc7a3f2b3f72cd71152beef0 Mon Sep 17 00:00:00 2001 From: liang_mike Date: Thu, 5 Feb 2009 04:12:55 +0000 Subject: [PATCH] Add the external flash version of SerialLoader to demonstrate TinyLD --- .../SerialLoaderFlash/FlashVolumeManager.h | 55 +++++ .../SerialLoaderFlash/FlashVolumeManagerC.nc | 57 +++++ .../SerialLoaderFlash/FlashVolumeManagerP.nc | 154 ++++++++++++ .../tinyld/SerialLoaderFlash/Makefile | 22 ++ .../tinyld/SerialLoaderFlash/README | 25 ++ .../SerialLoaderFlashAppC.nc | 49 ++++ .../tinyld/SerialLoaderFlash/serialloader.py | 229 ++++++++++++++++++ .../tinyld/SerialLoaderFlash/tinyos.py | 223 +++++++++++++++++ .../SerialLoaderFlash/volumes-stm25p.xml | 3 + 9 files changed, 817 insertions(+) create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManager.h create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerC.nc create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerP.nc create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/Makefile create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/README create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/SerialLoaderFlashAppC.nc create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/serialloader.py create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/tinyos.py create mode 100755 apps/tosthreads/tinyld/SerialLoaderFlash/volumes-stm25p.xml diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManager.h b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManager.h new file mode 100755 index 00000000..8b2b5e3b --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManager.h @@ -0,0 +1,55 @@ +/* + * 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 + */ + +#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 diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerC.nc b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerC.nc new file mode 100755 index 00000000..88b8f007 --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerC.nc @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#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; +} diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerP.nc b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerP.nc new file mode 100755 index 00000000..a9984204 --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/FlashVolumeManagerP.nc @@ -0,0 +1,154 @@ +/* + * 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 + */ + +#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) {} +} diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/Makefile b/apps/tosthreads/tinyld/SerialLoaderFlash/Makefile new file mode 100755 index 00000000..83d3dbeb --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/Makefile @@ -0,0 +1,22 @@ +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) diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/README b/apps/tosthreads/tinyld/SerialLoaderFlash/README new file mode 100755 index 00000000..3a891a00 --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/README @@ -0,0 +1,25 @@ +README for SerialLoaderFlash +Author/Contact: Chieh-Jan Mike Liang + +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, + +2.) Create the loadable code, Blink.tos: + tosthreads-gen-dynamic-app ../../capps/Blink/Blink.c + +3.) Erase the external flash: + ./serialloader.py 0 + +4.) Upload the binary: + ./serialloader.py 1 Blink.tos + +5.) Run the binary: + ./serialloader.py 7 diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/SerialLoaderFlashAppC.nc b/apps/tosthreads/tinyld/SerialLoaderFlash/SerialLoaderFlashAppC.nc new file mode 100755 index 00000000..eef04aff --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/SerialLoaderFlashAppC.nc @@ -0,0 +1,49 @@ +/* + * 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 + */ + +#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; +} diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/serialloader.py b/apps/tosthreads/tinyld/SerialLoaderFlash/serialloader.py new file mode 100755 index 00000000..686bf95b --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/serialloader.py @@ -0,0 +1,229 @@ +#!/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 + +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" diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/tinyos.py b/apps/tosthreads/tinyld/SerialLoaderFlash/tinyos.py new file mode 100755 index 00000000..e922f58c --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/tinyos.py @@ -0,0 +1,223 @@ +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 diff --git a/apps/tosthreads/tinyld/SerialLoaderFlash/volumes-stm25p.xml b/apps/tosthreads/tinyld/SerialLoaderFlash/volumes-stm25p.xml new file mode 100755 index 00000000..801def91 --- /dev/null +++ b/apps/tosthreads/tinyld/SerialLoaderFlash/volumes-stm25p.xml @@ -0,0 +1,3 @@ + + + -- 2.39.2