[Tinyos-2-commits] CVS: tinyos-2.x/apps/tosthreads/tinyld/SerialLoaderFlash FlashVolumeManager.h, NONE, 1.1 FlashVolumeManagerC.nc, NONE, 1.1 FlashVolumeManagerP.nc, NONE, 1.1 Makefile, NONE, 1.1 README, NONE, 1.1 SerialLoaderFlashAppC.nc, NONE, 1.1 serialloader.py, NONE, 1.1 tinyos.py, NONE, 1.1 volumes-stm25p.xml, NONE, 1.1

Chieh-Jan Mike Liang liang_mike at users.sourceforge.net
Wed Feb 4 20:12:57 PST 2009


Update of /cvsroot/tinyos/tinyos-2.x/apps/tosthreads/tinyld/SerialLoaderFlash
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29587/SerialLoaderFlash

Added Files:
	FlashVolumeManager.h FlashVolumeManagerC.nc 
	FlashVolumeManagerP.nc Makefile README 
	SerialLoaderFlashAppC.nc serialloader.py tinyos.py 
	volumes-stm25p.xml 
Log Message:
Add the external flash version of SerialLoader to demonstrate TinyLD


--- NEW FILE: FlashVolumeManager.h ---
/*
 * 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 at 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

--- NEW FILE: FlashVolumeManagerC.nc ---
/*
 * 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 at 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;
}

--- NEW FILE: FlashVolumeManagerP.nc ---
/*
 * 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 at 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) {} 
}

--- NEW FILE: Makefile ---
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)

--- NEW FILE: README ---
README for SerialLoaderFlash
Author/Contact: Chieh-Jan Mike Liang <cliang4 at 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

--- NEW FILE: SerialLoaderFlashAppC.nc ---
/*
 * 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 at cs.stanford.edu)
 * @author Chieh-Jan Mike Liang <cliang4 at 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;
}

--- NEW FILE: serialloader.py ---
#!/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 at 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"

--- NEW FILE: tinyos.py ---
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

--- NEW FILE: volumes-stm25p.xml ---
<volume_table>
  <volume name="MICROEXEIMAGE" size="262144" type="block"/>
</volume_table>



More information about the Tinyos-2-commits mailing list