From: smckown Date: Tue, 2 Sep 2008 15:02:26 +0000 (+0000) Subject: Incorporate new modular tos-bsl. X-Git-Tag: patchset/2.1.1-4.4~22 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=5312c1ac9464a4c368f38efeb9f46dc474066d09 Incorporate new modular tos-bsl. --- diff --git a/support/make/msp/bsl.extra b/support/make/msp/bsl.extra index 4be2e8a2..f8ad9e13 100644 --- a/support/make/msp/bsl.extra +++ b/support/make/msp/bsl.extra @@ -17,7 +17,7 @@ PROGRAM = bsl MSP_BSL ?= msp430-bsl # BSL is the comm port, can be specified as "bsl,2" when making BSL ?= auto -MSP_BSL_FLAGS ?= --telos +MSP_BSL_FLAGS ?= --device=telosa ifeq ($(BSL),auto) BSLTEST = $(shell motelist -c | perl -e '<> =~ /^[^,]+,(\S+?(\d+)[^,]*)/; print $$1;' ) diff --git a/support/make/telosb.target b/support/make/telosb.target index 697edf07..ed333efe 100644 --- a/support/make/telosb.target +++ b/support/make/telosb.target @@ -10,7 +10,7 @@ PFLAGS += -mdisable-hwmul OPTFLAGS += -O MSP_BSL ?= tos-bsl -MSP_BSL_FLAGS = --telosb +MSP_BSL_FLAGS = --device=telosb VOLUME_FILE = volumes-stm25p.xml VOLUME_ALLOCATOR ?= tos-storage-stm25p diff --git a/tools/platforms/msp430/pybsl/TODO b/tools/platforms/msp430/pybsl/TODO new file mode 100644 index 00000000..818703b2 --- /dev/null +++ b/tools/platforms/msp430/pybsl/TODO @@ -0,0 +1,10 @@ +- The python code in tos-bsl.in runs on Linux or in Cygwin but the latter + requires installation of the cp210x_rt python shim module, which is not + yet built or installed by the makefile. + +- The Cygwin/Windows code is currently not built, but untarred from a tarball. + This code is apparently from V1.5 of tos-bsl, prior to support for the + modular architecture and cp2103 additions in V1.6. This code should be + rebuilt. + +- The Binary windows version should be built from source. diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntime.lib b/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntime.lib new file mode 100644 index 00000000..e5d4b93a Binary files /dev/null and b/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntime.lib differ diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntimeDLL.h b/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntimeDLL.h new file mode 100644 index 00000000..f6fa9a7c --- /dev/null +++ b/tools/platforms/msp430/pybsl/cp210x_rt/CP210xRuntimeDLL.h @@ -0,0 +1,56 @@ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the CP210xRUNTIMEDLL_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// CP210xRUNTIMEDLL_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifdef CP210xRUNTIMEDLL_EXPORTS +#define CP210xRUNTIMEDLL_API __declspec(dllexport) +#else +#define CP210xRUNTIMEDLL_API __declspec(dllimport) +#endif + +#define CP210x_MAX_SETUP_LENGTH 65536 + +#ifndef _CP210x_STANDARD_DEF_ +#define _CP210x_STANDARD_DEF_ +// GetDeviceVersion() return codes +#define CP210x_CP2101_VERSION 0x01 +#define CP210x_CP2102_VERSION 0x02 +#define CP210x_CP2103_VERSION 0x03 + +// Return codes +#define CP210x_SUCCESS 0x00 +#define CP210x_DEVICE_NOT_FOUND 0xFF +#define CP210x_INVALID_HANDLE 0x01 +#define CP210x_INVALID_PARAMETER 0x02 +#define CP210x_DEVICE_IO_FAILED 0x03 +#define CP210x_FUNCTION_NOT_SUPPORTED 0x04 +#define CP210x_GLOBAL_DATA_ERROR 0x05 +#define CP210x_COMMAND_FAILED 0x08 +#define CP210x_INVALID_ACCESS_TYPE 0x09 + +// Type definitions +typedef int CP210x_STATUS; +#endif /*_CP210x_STANDARD_DEF_*/ + +// Mask and Latch value bit definitions +#define CP210x_GPIO_0 0x01 +#define CP210x_GPIO_1 0x02 +#define CP210x_GPIO_2 0x04 +#define CP210x_GPIO_3 0x08 + +CP210xRUNTIMEDLL_API CP210x_STATUS WINAPI +CP210xRT_ReadLatch( HANDLE cyHandle, + LPBYTE lpbLatch); + +CP210xRUNTIMEDLL_API CP210x_STATUS WINAPI +CP210xRT_WriteLatch( HANDLE cyHandle, + BYTE bMask, + BYTE bLatch); + + +CP210xRUNTIMEDLL_API CP210x_STATUS WINAPI +CP210xRT_GetPartNumber( HANDLE cyHandle, + LPBYTE lpbPartNum); diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/cp210xrtmodule.c b/tools/platforms/msp430/pybsl/cp210x_rt/cp210xrtmodule.c new file mode 100644 index 00000000..860c03d3 --- /dev/null +++ b/tools/platforms/msp430/pybsl/cp210x_rt/cp210xrtmodule.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2010, Titanium Mirror, Inc. + * All rights reserved. + * Based upon work Copyright (c) 2006-2007 by Sporian Microsystems, Inc. + * + * 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 Technische Universität Berlin 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 THE COPYRIGHT + * OWNER OR 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 R. Steve McKown + */ + +#include +#include +#include +#include +#include "CP210xRuntimeDLL.h" + +typedef CP210xRUNTIMEDLL_API CP210x_STATUS WINAPI (*fn_t)(HANDLE, BYTE, BYTE); + +void* dll; +fn_t writeLatch; +PyObject* exception; + + +static PyObject* cp210xrt_writeLatch(PyObject* self, PyObject* args) +{ + int fd; + BYTE bMask; + BYTE bData; + HANDLE hDevice; + CP210x_STATUS ret; + + if (!PyArg_ParseTuple(args, "iBB", &fd, &bMask, &bData)) + return NULL; + if (!writeLatch) { + PyErr_SetString(exception, "No access to CP210xRuntime.dll"); + return NULL; + } + + hDevice = (HANDLE)get_osfhandle(fd); + if (hDevice == INVALID_HANDLE_VALUE) + { + PyErr_SetString(exception, "No access to device"); + return NULL; + } + + /* If we don't call writeLatch, then we don't core dump when we return to + * the python caller. If we do call writeLatch, the latches are set, but + * when we return return into python, perhaps the stack has been corrupted + * somehow. We get a stackdump from cygwin. + * + * Note: when we opened the handle here, via CreateFile(), then closed it + * before returning, we had no problems. + */ + ret = writeLatch(hDevice, bMask, bData); + if (ret != CP210x_SUCCESS) { + PyErr_SetString(exception, "IO Error with device"); + return NULL; + } + +#if 1 + Py_INCREF(Py_None); + return Py_None; +#else + return Py_BuildValue("i", ret); +#endif +} + + +static PyMethodDef cp210xrtMethods[] = { + { "writeLatch", cp210xrt_writeLatch, METH_VARARGS, "Set GPIO bits" }, + { NULL, NULL, 0, NULL } +}; + + +PyMODINIT_FUNC initcp210xrt(void) +{ + PyObject* m = Py_InitModule("cp210xrt", cp210xrtMethods); + exception = PyErr_NewException("cp210xrt.error", NULL, NULL); + Py_INCREF(exception); + PyModule_AddObject(m, "error", exception); + + if (!dll) { + dll = dlopen("CP210xRuntime.dll", RTLD_NOW); + if (dll) { + dlerror(); + writeLatch = (fn_t)dlsym(dll, "CP210xRT_WriteLatch"); + if (dlerror()) + writeLatch = NULL; + } + } +} + diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.cygwin-1.5.12-i686.tar.gz b/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.cygwin-1.5.12-i686.tar.gz new file mode 100644 index 00000000..7c2aa956 Binary files /dev/null and b/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.cygwin-1.5.12-i686.tar.gz differ diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.tar.gz b/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.tar.gz new file mode 100644 index 00000000..1f21b920 Binary files /dev/null and b/tools/platforms/msp430/pybsl/cp210x_rt/dist/cp210xrt-0.1.tar.gz differ diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/setup.py b/tools/platforms/msp430/pybsl/cp210x_rt/setup.py new file mode 100644 index 00000000..859bc2c5 --- /dev/null +++ b/tools/platforms/msp430/pybsl/cp210x_rt/setup.py @@ -0,0 +1,10 @@ +#!/usr/bin/python + +from distutils.core import setup, Extension + +module1 = Extension('cp210xrt', sources = ['cp210xrtmodule.c']) + +setup(name = 'cp210xrt', version = '0.1', + description = 'Interface to cp210x runtime dll', + ext_modules = [module1]) + diff --git a/tools/platforms/msp430/pybsl/cp210x_rt/test/reset.py b/tools/platforms/msp430/pybsl/cp210x_rt/test/reset.py new file mode 100644 index 00000000..3a58b1f9 --- /dev/null +++ b/tools/platforms/msp430/pybsl/cp210x_rt/test/reset.py @@ -0,0 +1,21 @@ +#!/usr/bin/python + +import sys, os, time, serial, cp210xrt; + +sys.stderr.write("os.name is %s\n" % os.name); +sys.stderr.write("sys.platform is %s\n" % sys.platform); + +serialport = serial.Serial(9, 9600, parity = serial.PARITY_EVEN, + timeout = 1000) +sys.stderr.write("using serial port %r\n" % serialport.portstr) +sys.stderr.write("serial port fd is %d\n" % serialport.fd) +#sys.stderr.write("serial port HANDLE is %d\n" % _get_osfhandle(serialport.fd)) + + +sys.stderr.write("clear bit...\n") +cp210xrt.writeLatch(serialport.fd, 0x04, 0x0) +sys.stderr.write("clear bit done\n") +time.sleep(0.250) +sys.stderr.write("set bit...\n") +cp210xrt.writeLatch(serialport.fd, 0x04, 0x04) + diff --git a/tools/platforms/msp430/pybsl/tos-bsl.in b/tools/platforms/msp430/pybsl/tos-bsl.in index ee0d4152..4cd94d86 100644 --- a/tools/platforms/msp430/pybsl/tos-bsl.in +++ b/tools/platforms/msp430/pybsl/tos-bsl.in @@ -6,11 +6,117 @@ # # fixes from Colin Domoney # -# based on the application note slas96b.pdf from Texas Instruments, Inc., +# based on the application note slaa96b.pdf from Texas Instruments, Inc., # Volker Rzehak # additional infos from slaa089a.pdf +# +# Modularization by R. Steve McKown, . +# Based upon work Copyright (c) 2006-2007 by Sporian Microsystems, Inc. +# +# +# Set and clear of digital signals +# ================================ +# +# All functions that can set or clear a digital pin or signal state do so +# relative to the assertion state of its signal. That is, setXXX(1) asserts +# signal XXX and setXXX(0) unasserts signal XXX. Asserting a signal means its +# logic value is set to that value that asserts, or activates, its condition. +# Signals may be either active high or active low, as shown in the chart below. +# +# signal -- asserted -- - unasserted - +# active --- value --- --- value --- +# state logic voltage logic voltage +# ---------------------------------------- +# high 1 Vcc 0 GND +# low 0 GND 1 VCC +# +# It is the responsibility of the setXXX functions to properly convert the +# set request into the proper output value. This provides a consistency for +# applications using the set functions, since they no longer care the manner +# in which an asserted or unasserted signal are actually represented in the +# transmission medium. +# +# +# Important information about RS-232C signals +# =========================================== +# +# RS-232C signals are active low. Confusingly, however, RS-232C physical +# drivers effectively invert the value, such that a high value, or MARK, is +# delivered over the wire as a negative voltage while a low value, or SPACE, is +# delivered as a positive voltage. By looking at an RS-232C signal on an +# oscilloscope, one might conclude that the RS-232C signals are active high for +# this reason. Here is how RS-232 breaks down: +# +# signal logical RS-232C RS-232C TTL RS-232 +# state value value name output voltage output voltage +# --------------------------------------------------------------- +# asserted 0/low SPACE +3v...+15v GND (0V) +# unasserted 1/high MARK -3v...-15v VCC +# +# Note that some RS-232 signals, notably TxD (transmit data) and RxD (receive +# data), can be idle. An idle signal is always unasserted. +# +# Using this guidance, an asserted DTR signal is logic low, is 0V in TTL RS-232 +# and +3V..15V in RS-232C. +# +# PC serial ports often break the spec and treat 0v as a logic 1/MARK instead +# of an invalid value. +# +# +# Important MSP430 signals +# ======================== +# +# The BSL protocol is entered by manipulating the RST and TCK pins on MSP430 +# uC's with dedicated JTAG pins, and by manipulating RST and TEST pins on +# MSP430 uC's with shared JTAG pins. The assertion state of TEST and TCK +# are the same, so we use the term TTCK to imply either or both of them +# simultaneously. +# +# RST and TCK are active low signals. TEST is active high. +# +# An MSP430 is reset by simplying asserting RST for a short period then +# unasserting it. +# +# The BSL mode is entered by performing this sequence of events, subject to +# timing constraints documented by TI: +# Assert RST +# Assert TTCK +# Unssert TTCK +# Assert TTCK +# Unssert RST +# Unssert TTCK +# +# +# The TI slaa096d Document +# ======================== +# +# The TI slaa096d document defines a circuit that can be used to program MSP430 +# parts using the BSL protocol. Other platforms, such as Telos, EyesIFx and +# Tinynode to name a few, also incorporate support for BSL using circuitry +# that can vary significantly from the TI schematic. +# +# The code presented in the TI document does not use a consistent methodology +# to indicate what is happening when a setXXX(n) function is called. In some +# cases, 'n' represents the assertion state, where 1=asserted and 0=unasserted. +# In other cases, 'n' represents the inverse of the assertion state. In yet +# other cases, 'n' represents the logic value of the signal on a given pin, or +# the inverse of the logic value. +# +# To improve readability and allow for modular, pluggable BSL handling, this +# code explicitly defines all setXXX(n) functions where 'n' represents the +# assertion state of the signal. In other words, when n==1 the signal is +# asserted and when n==0 the signal is unasserted. One can trivially determine +# the logic state of any signal pin by applying the current assertion state to +# the signal's active state (see the charts above). +# +# Device support +# ============== +# +# To add support for a new MSP430-based device, create a new class deriving +# from bsl_standard or one of its specializations. +# -import sys, time, string, cStringIO, struct +import sys, fcntl, time, string, cStringIO, struct sys.path.append("@tinyoslibdir@") import serial @@ -183,17 +289,20 @@ q #cpu types for "change baudrate" #use strings as ID so that they can be used in outputs too F1x = "F1x family" +F2x = "F2x family" F4x = "F4x family" #known device list deviceids = { 0xf149: F1x, + 0xf169: F1x, 0xf16c: F1x, #for telosb 0xf112: F1x, 0xf413: F4x, 0xf123: F1x, 0xf449: F4x, 0x1232: F1x, + 0xf26f: F2x, } class BSLException(Exception): @@ -266,14 +375,6 @@ class LowLevel: else: self.prolongFactor = aProlongFactor - #flags for inverted use of control pins - #used for some hardware - self.invertRST = 0 - self.invertTEST = 0 - self.swapRSTTEST = 0 - self.telosLatch = 0 - self.telosI2C = 0 - self.protocolMode = self.MODE_BSL self.BSLMemAccessWarning = 0 #Default: no warning. self.slowmode = 0 @@ -298,8 +399,7 @@ class LowLevel: timeout = self.timeout ) if DEBUG: sys.stderr.write("using serial port %r\n" % self.serialport.portstr) - self.SetRSTpin() #enable power - self.SetTESTpin() #enable power + self.bslInit() #enable power self.serialport.flushInput() self.serialport.flushOutput() @@ -310,8 +410,7 @@ class LowLevel: used in other programs. Returns zero if the function is successful.""" if DEBUG > 1: sys.stderr.write("* comDone()") - self.SetRSTpin(1) #disable power - self.SetTESTpin(0) #disable power + self.bslDone() #disable power self.serialport.close() def comRxHeader(self): @@ -437,141 +536,6 @@ class LowLevel: raise BSLException("Unknown header 0x%02x\nAre you downloading to RAM into an old device that requires the patch? Try option -U" % rxHeader) - def SetDTR(self, level, invert): - """Controls DTR pin (0: GND; 1: VCC; unless inverted flag is set)""" - if invert: - self.serialport.setDTR(not level) - else: - self.serialport.setDTR(level) - if self.slowmode: - time.sleep(0.040) - - def SetRTS(self, level, invert): - """Controls RTS pin (0: GND; 1: VCC; unless inverted flag is set)""" - if invert: - self.serialport.setRTS(not level) - else: - self.serialport.setRTS(level) - if self.slowmode: - time.sleep(0.040) - - def SetRSTpin(self, level=1): - """Controls RST/NMI pin (0: GND; 1: VCC; unless inverted flag is set)""" - if self.swapRSTTEST: - self.SetRTS(level, self.invertRST) - else: - self.SetDTR(level, self.invertRST) - - def SetTESTpin(self, level=1): - """Controls TEST pin (inverted on board: 0: VCC; 1: GND; unless inverted flag is set)""" - if self.swapRSTTEST: - self.SetDTR(level, self.invertTEST) - else: - self.SetRTS(level, self.invertTEST) - - def telosSetSCL(self, level): - self.serialport.setRTS(not level) - - def telosSetSDA(self, level): - self.serialport.setDTR(not level) - - def telosI2CStart(self): - self.telosSetSDA(1) - self.telosSetSCL(1) - self.telosSetSDA(0) - - def telosI2CStop(self): - self.telosSetSDA(0) - self.telosSetSCL(1) - self.telosSetSDA(1) - - def telosI2CWriteBit(self, bit): - self.telosSetSCL(0) - self.telosSetSDA(bit) - time.sleep(2e-6) - self.telosSetSCL(1) - time.sleep(1e-6) - self.telosSetSCL(0) - - def telosI2CWriteByte(self, byte): - self.telosI2CWriteBit( byte & 0x80 ); - self.telosI2CWriteBit( byte & 0x40 ); - self.telosI2CWriteBit( byte & 0x20 ); - self.telosI2CWriteBit( byte & 0x10 ); - self.telosI2CWriteBit( byte & 0x08 ); - self.telosI2CWriteBit( byte & 0x04 ); - self.telosI2CWriteBit( byte & 0x02 ); - self.telosI2CWriteBit( byte & 0x01 ); - self.telosI2CWriteBit( 0 ); # "acknowledge" - - def telosI2CWriteCmd(self, addr, cmdbyte): - self.telosI2CStart() - self.telosI2CWriteByte( 0x90 | (addr << 1) ) - self.telosI2CWriteByte( cmdbyte ) - self.telosI2CStop() - - def telosBReset(self,invokeBSL=0): - - # "BSL entry sequence at dedicated JTAG pins" - # rst !s0: 0 0 0 0 1 1 - # tck !s1: 1 0 1 0 0 1 - # s0|s1: 1 3 1 3 2 0 - - # "BSL entry sequence at shared JTAG pins" - # rst !s0: 0 0 0 0 1 1 - # tck !s1: 0 1 0 1 1 0 - # s0|s1: 3 1 3 1 0 2 - - if invokeBSL: - self.telosI2CWriteCmd(0,1) - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,1) - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,2) - self.telosI2CWriteCmd(0,0) - else: - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,2) - self.telosI2CWriteCmd(0,0) - time.sleep(0.250) #give MSP430's oscillator time to stabilize - self.serialport.flushInput() #clear buffers - - def bslReset(self, invokeBSL=0): - """Applies BSL entry sequence on RST/NMI and TEST/VPP pins - Parameters: - invokeBSL = 1: complete sequence - invokeBSL = 0: only RST/NMI pin accessed - - RST is inverted twice on boot loader hardware - TEST is inverted (only once) - Need positive voltage on DTR, RTS for power-supply of hardware""" - if self.telosI2C: - self.telosBReset(invokeBSL) - return - - if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL) - self.SetRSTpin(1) #power suply - self.SetTESTpin(1) #power suply - time.sleep(0.250) #charge capacitor on boot loader hardware - - if self.telosLatch: - self.SetTESTpin(0) - self.SetRSTpin(0) - self.SetTESTpin(1) - - self.SetRSTpin(0) #RST pin: GND - if invokeBSL: - self.SetTESTpin(1) #TEST pin: GND - self.SetTESTpin(0) #TEST pin: Vcc - self.SetTESTpin(1) #TEST pin: GND - self.SetTESTpin(0) #TEST pin: Vcc - self.SetRSTpin (1) #RST pin: Vcc - self.SetTESTpin(1) #TEST pin: GND - else: - self.SetRSTpin(1) #RST pin: Vcc - time.sleep(0.250) #give MSP430's oscillator time to stabilize - - self.serialport.flushInput() #clear buffers def bslSync(self,wait=0): """Transmits Synchronization character and expects to receive Acknowledge character @@ -765,6 +729,8 @@ class Memory: self.loadTIText(open(filename, "rb")) elif filename[-4:].lower() in ('.a43', '.hex'): self.loadIHex(open(filename, "rb")) + elif filename[-5:].lower() in ('.ihex'): + self.loadIHex(open(filename, "rb")) else: self.loadELF(open(filename, "rb")) @@ -874,7 +840,7 @@ class BootStrapLoader(LowLevel): continue def programBlk(self, addr, blkout, action): - """programm a memory block""" + """program a memory block""" if DEBUG > 1: sys.stderr.write("* programBlk()\n") #Check, if specified range is erased @@ -894,7 +860,7 @@ class BootStrapLoader(LowLevel): #list of tuples or lists: #segements = [ (addr1, [d0,d1,d2,...]), (addr2, [e0,e1,e2,...])] def programData(self, segments, action): - """programm or verify data""" + """program or verify data""" if DEBUG > 1: sys.stderr.write("* programData()\n") for seg in segments: currentAddr = seg.startaddress @@ -964,6 +930,19 @@ class BootStrapLoader(LowLevel): #Transmit password to get access to protected BSL functions. self.txPasswd() + def actionMainErase(self): + """Erase the main flash memory only""" + sys.stderr.write("Main Erase...\n") + sys.stderr.flush() + self.bslReset(1) #Invoke the boot loader. + self.txPasswd(self.passwd) #transmit password + for i in range(self.meraseCycles): + if i == 1: sys.stderr.write("Additional Main Erase Cycles...\n") + self.bslTxRx(self.BSL_ERASE, #Command: Segment Erase + 0xfffe, #Any address within flash memory. + 0xa504) #Required setting for main erase! + self.passwd = None #Password gets erased + def actionStartBSL(self, usepatch=1, adjsp=1, replacementBSL=None, forceBSL=0, mayuseBSL=0, speed=None, bslreset=1): """start BSL, download patch if desired and needed, adjust SP if desired""" sys.stderr.write("Invoking BSL...\n") @@ -1020,11 +999,16 @@ class BootStrapLoader(LowLevel): sys.stderr.write("Using built in BSL replacement for F4x devices\n") sys.stderr.flush() replacementBSL.loadTIText(cStringIO.StringIO(F4X_BSL)) #parse embedded BSL - else: + elif self.cpu == F1x: if DEBUG: sys.stderr.write("Using built in BSL replacement for F1x devices\n") sys.stderr.flush() replacementBSL.loadTIText(cStringIO.StringIO(F1X_BSL)) #parse embedded BSL + else: + if DEBUG: + sys.stderr.write("NO built in BSL replacement for F2x devices\n") + sys.stderr.flush() + #replacementBSL.loadTIText(cStringIO.StringIO(F1X_BSL)) #parse embedded BSL #now download the new BSL, if allowed and needed (version lower than the #the replacement) or forced @@ -1121,7 +1105,7 @@ class BootStrapLoader(LowLevel): raise BSLException, "verify without data not possible" def actionReset(self): - """perform a reset, start user programm""" + """perform a reset, start user program""" sys.stderr.write("Reset device ...\n") sys.stderr.flush() self.bslReset(0) #only reset @@ -1140,6 +1124,11 @@ class BootStrapLoader(LowLevel): 19200:[0x86e0, 0x0001], 38400:[0x87e0, 0x0002], }, + F2x: { + 9600:[0x8580, 0x0000], + 19200:[0x8b00, 0x0001], + 38400:[0x8c80, 0x0002], + }, F4x: { 9600:[0x9800, 0x0000], 19200:[0xb000, 0x0001], @@ -1175,6 +1164,342 @@ class BootStrapLoader(LowLevel): print "Device Type: 0x%04x\nBSL version: 0x%04x\n" % (family_type, bsl_version) +class bsl_standard(BootStrapLoader): + """ + This class supports the TI RS-232C programmer presented in slaa096d. + The programmer and the MSP430 being programmed are powered from power + scavenged off the DTR and RTS lines. Therefore, it is important that + DTR and RTS are asserted for some period before programming to charge + the programmer's power capacitor. Recall that an asserted RS-232 + signal generates a voltage between +3v and +15v. + + Per the documentation the signals' assertion states map as follows: + rs232.DTR -> (invert) -> msp430.RST + rs232.RTS -> (invert) -> msp430.TTCK + msp430.TTCK -> msp430.TCK + msp430.TTCK -> (invert) -> msp430.TEST + """ + def __init__(self, *args, **kargs): + BootStrapLoader.__init__(self, *args, **kargs) + + def mayuseBSL(self): + return 1 + + def speed(self): + return None + + def setRST(self, assertme): + """ + Calling setRST(1) asserts the RST signal at the msp430. Since RST + is active low, asserted=GND and unasserted=Vcc. + + Do not override this method + """ + self.lsetRST(assertme) + if (self.slowmode): + time.sleep(0.040) + + def setTTCK(self, assertme): + """ + Calling setTTCK(1) asserts TTCK. TTCK is a pseudo-signal that + acts as TCK and/or TEST. TCK is active high and TEST is active low. + + Do not override this method + """ + self.lsetTTCK(assertme) + if (self.slowmode): + time.sleep(0.040) + + def lsetRST(self, assertme): + """ rs232.DTR -> (invert) -> msp430.RST """ + self.serialport.setDTR(not assertme) + + def lsetTTCK(self, assertme): + """ rs232.RTS -> (invert) -> msp430.TTCK """ + self.serialport.setRTS(not assertme) + + def bslInit(self): + """ Initial state: RST and TTCK are unasserted """ + self.setRST(0) + self.setTTCK(0) + + def bslPrepare(self): + """ + bslInit unaserted RST and TTCK, which asserted DTR and RTS. Wait + a while to allow the programmer power cap to charge from the V+ + supplied by DTR and RTS. + """ + time.sleep(0.250) + + def bslDone(self): + """ Unasserting RST and TTCK also cuts power to the programmer """ + self.setRST(0) + self.setTTCK(0) + + def bslReset(self, invokeBSL=0): + if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL) + self.bslInit() + self.bslPrepare() + self.setRST(1) + if invokeBSL: + self.setTTCK(1) + self.setTTCK(0) + self.setTTCK(1) + self.setRST(0) + self.setTTCK(0) + else: + self.setRST(0) + time.sleep(0.250) # Allow MSP430 oscillator time to stabilize + self.serialport.flushInput() + + +class bsl_telosa(bsl_standard): + """ + The telosa hardware allows for programming its MSP430 via a USB port + through a USB/serial chip. The mapping of serial to uC signals differ + from the standard TI bsl hardware supported in bsl_standard. DTR from + the USB/serial chip is tied directly to TCK and RST is configured + through inverters and a type D flip-flop to help prevent spurious uC + resets. + + The signals' assertion states map as follows: + usbserial.RTS -> msp430.RST + usbserial.DTR -> msp430.TCK + + When performing a bslReset(), RST must first be asserted by clearing + the onboard flip-flop: + assert usbserial.DTR + assert usbserial.RTS + unassert usbserial.DTR + """ + def __init__(self, *args, **kargs): + bsl_standard.__init__(self, *args, **kargs) + + def lsetRST(self, assertme): + """ rs232.RTS -> msp430.RST """ + self.serialport.setRTS(assertme); + + def lsetTTCK(self, assertme): + """ rs232.DTR -> msp430.TTCK """ + self.serialport.setDTR(assertme); + + def bslPrepare(self): + """ Run the standard bslPrepare, then set the telosa flip-flop """ + bsl_standard.bslPrepare(self) + self.serialport.setDTR(1) + self.serialport.setRTS(1) + self.serialport.setDTR(0) + + +class bsl_telosb(bsl_standard): + """ + The telosb allows programming of its MSP430 via a USB port through a + USB/serial chip. It incorporates an I2C switch, whose SDA and SCL + inputs driven by the serial DTR and RTS signals. Switch outputs are + tied to the uC RST and TCK pins. + + The signals' assertion states map as follows: + usbserial.RTS -> (invert) -> I2C.SCL + usbserial.DTR -> (invert) -> I2C.SDA + """ + def __init__(self, *args, **kargs): + bsl_standard.__init__(self, *args, **kargs) + + def mayuseBSL(self): + return 0 + + def speed(self): + return 38400 + + def setSCL(self, level): + self.serialport.setRTS(not level) + + def setSDA(self, level): + self.serialport.setDTR(not level) + + def i2cStart(self): + self.setSDA(1) + self.setSCL(1) + self.setSDA(0) + + def i2cStop(self): + self.setSDA(0) + self.setSCL(1) + self.setSDA(1) + + def i2cWriteBit(self, bit): + self.setSCL(0) + self.setSDA(bit) + time.sleep(2e-6) + self.setSCL(1) + time.sleep(1e-6) + self.setSCL(0) + + def i2cWriteByte(self, byte): + self.i2cWriteBit( byte & 0x80 ); + self.i2cWriteBit( byte & 0x40 ); + self.i2cWriteBit( byte & 0x20 ); + self.i2cWriteBit( byte & 0x10 ); + self.i2cWriteBit( byte & 0x08 ); + self.i2cWriteBit( byte & 0x04 ); + self.i2cWriteBit( byte & 0x02 ); + self.i2cWriteBit( byte & 0x01 ); + self.i2cWriteBit( 0 ); # "acknowledge" + + def i2cWriteCmd(self, addr, cmdbyte): + self.i2cStart() + self.i2cWriteByte( 0x90 | (addr << 1) ) + self.i2cWriteByte( cmdbyte ) + self.i2cStop() + + def bslInit(self): + """ Not needed for telosb """ + + def bslDone(self): + """ Not needed for telosb """ + + def bslReset(self,invokeBSL=0): + # "BSL entry sequence at dedicated JTAG pins" + # rst !s0: 0 0 0 0 1 1 + # tck !s1: 1 0 1 0 0 1 + # s0|s1: 1 3 1 3 2 0 + + # "BSL entry sequence at shared JTAG pins" + # rst !s0: 0 0 0 0 1 1 + # tck !s1: 0 1 0 1 1 0 + # s0|s1: 3 1 3 1 0 2 + + if invokeBSL: + self.i2cWriteCmd(0,1) + self.i2cWriteCmd(0,3) + self.i2cWriteCmd(0,1) + self.i2cWriteCmd(0,3) + self.i2cWriteCmd(0,2) + self.i2cWriteCmd(0,0) + else: + self.i2cWriteCmd(0,3) + self.i2cWriteCmd(0,2) + self.i2cWriteCmd(0,0) + time.sleep(0.250) #give MSP430's oscillator time to stabilize + self.serialport.flushInput() #clear buffers + + +class bsl_cp2103(bsl_standard): + """ + Some boards allow programming of their MSP430 via an onboard cp2103 + USB/serial chip configured such that two of its gpio pins are tied + directly to the RST and TCK pins of the uC. In this configuration the + RST and TCK signals are pulled up and the cp2103's gpio pins are + configured as open drain outputs. The gpio pins are active low and + are unasserted on power-up. + + The signals' assertion states map as follows: + usbserial.GPIO_3 -> msp430.RST + usbserial.GPIO_2 -> msp430.TCK + """ + def __init__(self, *args, **kargs): + bsl_standard.__init__(self, *args, **kargs) + self.cp2103 = None + + def mayuseBSL(self): + return 0 + + def speed(self): + return 38400 + + def lsetRST(self, assertme): + """ usbserial.GPIO_3 -> msp430.RST """ + self.cp2103.setGpio3(assertme); + + def lsetTTCK(self, assertme): + """ usbserial.GPIO_2 -> msp430.TTCK """ + self.cp2103.setGpio2(assertme); + + def bslInit(self): + if not self.cp2103: + # We can't define cp2103 until the first call to bslInit, since + # self.serialport is not instantiated until then. + self.cp2103 = cp2103_factory(self.serialport) + bsl_standard.bslInit(self) + + +GPIOBIC = 0x89f2 +GPIOBIS = 0x89f3 +GPIO_2 = 0x04 +GPIO_3 = 0x08 + +class cp2103_posix: + """ + Implements cp2103 gpio access for posix systems using ioctl() calls. + Requires a cp210x driver providing gpio control. + """ + def __init__(self, serialport): + sys.stderr.write("cp2103_posix\n") + self.fd = serialport.fd + + def setGpio2(self, assertme): + """ set not assertme to the gpio pin """ + if not self.fd: raise "connection not open" + if assertme: + fcntl.ioctl(self.fd, GPIOBIC, GPIO_2) + else: + fcntl.ioctl(self.fd, GPIOBIS, GPIO_2) + time.sleep(0.010) # no sleep = too fast + + def setGpio3(self, assertme): + """ set not assertme to the gpio pin """ + if not self.fd: raise "connection not open" + if assertme: + fcntl.ioctl(self.fd, GPIOBIC, GPIO_3) + else: + fcntl.ioctl(self.fd, GPIOBIS, GPIO_3) + time.sleep(0.010) # no sleep = too fast + + +class cp2103_cygwin: + """ + Implements cp2103 gpio access for windows cygwin systems via the + cp210x VCP and the CP210xRuntime.dll. + """ + def __init__(self, serialport): + import cp210xrt + sys.stderr.write("cp2103_cygwin\n") + self.fd = serialport.fd + + def setGpio2(self, assertme): + """ set not assertme to the gpio pin """ + import cp210xrt + if assertme: + cp210xrt.writeLatch(self.fd, GPIO_2, 0) + else: + cp210xrt.writeLatch(self.fd, GPIO_2, GPIO_2) + + def setGpio3(self, assertme): + """ set not assertme to the gpio pin """ + import cp210xrt + if assertme: + cp210xrt.writeLatch(self.fd, GPIO_3, 0) + else: + cp210xrt.writeLatch(self.fd, GPIO_3, GPIO_3) + + +def cp2103_factory(serialport): + import os; + if os.name == 'posix': + if sys.platform == 'cygwin': + return cp2103_cygwin(serialport) + else: + return cp2103_posix(serialport) + else: + raise "No cp2103 support is available for your platform." + + +def getClass(classname, modulename="__main__"): + """ Used by main() to select the appropriate bsl class based on device """ + return getattr(__import__(modulename, globals(), locals(), [classname]), + classname) + + def usage(): """print some help message""" sys.stderr.write(""" @@ -1221,22 +1546,20 @@ General options: Possible values are 9600, 19200, 38400 (default 9600) -1, --f1x Specify CPU family, in case autodetect fails + -2, --f2x Specify CPU family, in case autodetect fails -4, --f4x Specify CPU family, in case autodetect fails - --F1x and --f2x are only needed when the "change + --f1x, --f2x and --f4x are only needed when the "change baudrate" feature is used and the autodetect feature fails. If the device ID that is uploaded is known, it has precedence to the command line option. - --invert-reset Invert signal on RST pin (used for some BSL hardware) - --invert-test Invert signal on TEST/TCK pin (used for some BSL - hardware) - --swap-reset-test Swap the RST and TEST pins (used for some BSL hardware) - --telos-latch Special twiddle in BSL reset for Telos hardware - --telos-i2c DTR/RTS map via an I2C switch to TCK/RST in Telos Rev.B - --telos Implies options --invert-reset, --invert-test, - --swap-reset-test, and --telos-latch - --telosb Implies options --swap-reset-test, --telos-i2c, - --no-BSL-download, and --speed=38400 - --tmote Identical operation to --telosb + --device=device Required device. Supported devices are: + standard - Standard BSL programmer per TI specs + telosa - Telos revA and compatible boards + telosb - Telos revB and compatible boards + cp2103 - Boards using cp2103 gpio for BSL support + cp2103_old - The old cp2103 gpio format + Most settings for a device are defined within the + device specific bsl_{device} class. --no-BSL-download Do not download replacement BSL (disable automatic) --force-BSL-download Download replacement BSL even if not needed (the one in the device would have the required features) @@ -1245,6 +1568,7 @@ General options: Program Flow Specifiers: -e, --masserase Mass Erase (clear all flash memory) + -M, --mainerase Erase main flash memory only (requires --password) -E, --erasecheck Erase Check by file -p, --program Program file -v, --verify Verify by file @@ -1263,11 +1587,11 @@ Data retreiving: to redirect the output into a file. Do before exit: - -g, --go=address Start programm execution at specified address. + -g, --go=address Start program execution at specified address. This implies option --wait. -r, --reset Reset connected MSP430. Starts application. This is a normal device reset and will start - the programm that is specified in the reset + the program that is specified in the reset vector. (see also -g) -w, --wait Wait for before closing serial port. @@ -1320,7 +1644,7 @@ def main(): reset = 0 wait = 0 #wait at the end goaddr = None - bsl = BootStrapLoader() + bsl = None # now defined dynamically BootStrapLoader() toinit = [] todo = [] startaddr = None @@ -1335,21 +1659,35 @@ def main(): try: opts, args = getopt.getopt(sys.argv[1:], - "hc:P:wf:m:eEpvrg:UDudsxbITNB:S:V14", + "hc:P:wf:m:eMEpvrg:UDu:ds:xbITNB:S:V124", ["help", "comport=", "password=", "wait", "framesize=", - "erasecycles=", "masserase", "erasecheck", "program", + "erasecycles=", "masserase", "mainerase", "erasecheck", "program", "verify", "reset", "go=", "unpatched", "debug", "upload=", "download=", "size=", "hex", "bin", "intelhex", "titext", "notimeout", "bsl=", "speed=", - "bslversion", "f1x", "f4x", "invert-reset", "invert-test", - "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb", - "tmote","no-BSL-download", "force-BSL-download", "slow"] + "bslversion", "f1x", "f2x", "f4x", "no-BSL-download", + "force-BSL-download", "slow", "device=" ] ) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) + # Get the --device setting first. If none, then use bsl_standard + for o, a in opts: + if o in ("--device", ): + # TBD: dynamically instantiate the correct bootloader class + bsl = getClass("bsl_%s" % a)() + if not bsl: + bsl = getClass("bsl_standard")() + if not callable(bsl.preparePatch): + raise BSLException("Invalid device %s\n" % a) + sys.stderr.write("Using device class %s\n" % bsl.__class__.__name__) + if callable(bsl.mayuseBSL): + mayuseBSL = bsl.mayuseBSL() + if callable(bsl.speed): + speed = bsl.speed() + for o, a in opts: if o in ("-h", "--help"): usage() @@ -1394,9 +1732,11 @@ def main(): bsl.meraseCycles = meraseCycles elif o in ("-e", "--masserase"): toinit.append(bsl.actionMassErase) #Erase Flash + elif o in ("-M", "--mainerase"): + toinit.append(bsl.actionMainErase) #Erase main Flash elif o in ("-E", "--erasecheck"): toinit.append(bsl.actionEraseCheck) #Erase Check (by file) - elif o in ("-p", "--programm"): + elif o in ("-p", "--program"): todo.append(bsl.actionProgram) #Program file elif o in ("-v", "--verify"): todo.append(bsl.actionVerify) #Verify file @@ -1456,34 +1796,14 @@ def main(): sys.stderr.write("speed must be decimal number\n") sys.exit(2) elif o in ("-1", "--f1x"): + # TBD: the cpu spec would best be defined in the device, eh? bsl.cpu = F1x + elif o in ("-2", "--f2x"): + # TBD: the cpu spec would best be defined in the device, eh? + bsl.cpu = F2x elif o in ("-4", "--f4x"): + # TBD: the cpu spec would best be defined in the device, eh? bsl.cpu = F4x - elif o in ("--invert-reset", ): - bsl.invertRST = 1 - elif o in ("--invert-test", ): - bsl.invertTEST = 1 - elif o in ("--swap-reset-test", ): - bsl.swapRSTTEST = 1 - elif o in ("--telos-latch", ): - bsl.telosLatch = 1 - elif o in ("--telos-i2c", ): - bsl.telosI2C = 1 - elif o in ("--telos", ): - bsl.invertRST = 1 - bsl.invertTEST = 1 - bsl.swapRSTTEST = 1 - bsl.telosLatch = 1 - elif o in ("--telosb", ): - bsl.swapRSTTEST = 1 - bsl.telosI2C = 1 - mayuseBSL = 0 - speed = 38400 - elif o in ("--tmote", ): - bsl.swapRSTTEST = 1 - bsl.telosI2C = 1 - mayuseBSL = 0 - speed = 38400 elif o in ("--no-BSL-download", ): mayuseBSL = 0 elif o in ("--force-BSL-download", ): @@ -1585,7 +1905,7 @@ def main(): if reset: #reset device first if desired bsl.actionReset() - if goaddr is not None: #start user programm at specified address + if goaddr is not None: #start user program at specified address bsl.actionRun(goaddr) #load PC and execute #upload datablock and output diff --git a/tools/platforms/msp430/pybsl/tos-bsl.txt b/tools/platforms/msp430/pybsl/tos-bsl.txt index 8f7c5fa4..121687b0 100644 --- a/tools/platforms/msp430/pybsl/tos-bsl.txt +++ b/tools/platforms/msp430/pybsl/tos-bsl.txt @@ -13,10 +13,16 @@ It is released under a free software license, see tos-bsl-license.txt for more details. (C) 2001-2003 Chris Liechti +(C) 2007-2010 Sporian Microsystems, Inc. and + Titanium Mirror, Inc. Features -------- +- new modular design supports multiple BSL interfacing techniques, + currently including standard serial as defined by TI, methods used by the + telosa and telosb platforms employing an FTDI usb/serial chip, and a new + open technique using the cp2103 usb/serial chip. - understands TI-Text and Intel-hex - download to Flash and/or RAM, erase, verify - reset and wait for keypress (to run a device directly from the port @@ -67,10 +73,11 @@ First the MSP430 BSL hardware is needed. An example schematics can be found in the application note "slaa96b" from TI (see references). Then this programm can be used to communicate between the PC and the MSP430 device. -The program can be started by typing "python bsl.py" in a console. Often -it works also with just "bsl.py" or "./bsl.py". +The program can be started by typing "python tos-bsl" in a console. Often +it works also with just "tos-bsl" or "./tos-bsl". -USAGE: bsl.py [options] [file] +USAGE: %s [options] [file] +Version: %s If "-" is specified as file the data is read from the stdinput. A file ending with ".txt" is considered to be in TIText format, @@ -112,19 +119,29 @@ General options: Possible values are 9600, 19200, 38400 (default 9600) -1, --f1x Specify CPU family, in case autodetect fails + -2, --f2x Specify CPU family, in case autodetect fails -4, --f4x Specify CPU family, in case autodetect fails - --F1x and --f2x are only needed when the "change + --f1x, --f2x and --f4x are only needed when the "change baudrate" feature is used and the autodetect feature fails. If the device ID that is uploaded is known, it has precedence to the command line option. - --invert-reset Invert signal on RST pin (used for some BSL hardware) - --invert-test Invert signal on TEST/TCK pin (used for some BSL - hardware) + --device=device Required device. Supported devices are: + standard - Standard BSL programmer per TI specs + telosa - Telos revA and compatible boards + telosb - Telos revB and compatible boards + cp2103 - Boards using cp2103 gpio for BSL support + cp2103_old - The old cp2103 gpio format + Most settings for a device are defined within the + device specific bsl_{device} class. + --no-BSL-download Do not download replacement BSL (disable automatic) + --force-BSL-download Download replacement BSL even if not needed (the one + in the device would have the required features) --slow Add delays when operating the conrol pins. Useful if the pins/circuit has high capacitance. Program Flow Specifiers: -e, --masserase Mass Erase (clear all flash memory) + -M, --mainerase Erase main flash memory only (requires --password) -E, --erasecheck Erase Check by file -p, --program Program file -v, --verify Verify by file @@ -143,11 +160,11 @@ Data retreiving: to redirect the output into a file. Do before exit: - -g, --go=address Start programm execution at specified address. + -g, --go=address Start program execution at specified address. This implies option --wait. -r, --reset Reset connected MSP430. Starts application. This is a normal device reset and will start - the programm that is specified in the reset + the program that is specified in the reset vector. (see also -g) -w, --wait Wait for before closing serial port. @@ -257,6 +274,11 @@ History ELF file support replacement BSLs are now internal + V1.6 + modular design uses --device option to select a communications method + support for motes using a cp2103 usb/serial chip + + References ---------- - Python: http://www.python.org