CVS: python/mspgcc .cvsignore,NONE,1.1 HIL.py,NONE,1.1 __init__.py,NONE,1.1 bsl.py,NONE,1.1 clock.py,NONE,1.1 elf.py,NONE,1.1 hilspi.py,NONE,1.1 jtag.py,NONE,1.1 memory.py,NONE,1.1 util.py,NONE,1.1

Chris Liechti <[email protected]>
Newsgroups gmane.comp.hardware.texas-instruments.msp430.gcc.cvs
Message-ID <[email protected]>
Update of /cvsroot/mspgcc/python/mspgcc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24301/python/mspgcc

Added Files:
	.cvsignore HIL.py __init__.py bsl.py clock.py elf.py hilspi.py 
	jtag.py memory.py util.py 
Log Message:
rename msp430 package to mspgcc (resolves naming/import conflicts with msp430.dll)

--- NEW FILE: .cvsignore ---
*.pyc
--- NEW FILE: HIL.py ---
# Python bindings to the functions in the MSP430 JTAG HIL
# (Hardware Interface Library)
# 
# (C) 2004 Chris Liechti <[email protected]>
# this is distributed under a free software license, see license.txt
# 
# http://mspgcc.sf.net
# 
# Requires Python 2+, ctypes and HIL.dll/libHIL.so
# 
# $Id: HIL.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import ctypes

HIL = ctypes.windll.HIL

Initialize          = HIL.HIL_Initialize
Initialize.argtypes = [ctypes.c_char_p]
Initialize.restype  = ctypes.c_int
Open                = HIL.HIL_Open
Open.argtypes       = []
Open.restype        = ctypes.c_int
Connect             = HIL.HIL_Connect
Connect.argtypes    = []
Connect.restype     = ctypes.c_int
Release             = HIL.HIL_Release
Release.argtypes    = []
Release.restype     = ctypes.c_int
Close               = HIL.HIL_Close
Close.argtypes      = [ctypes.c_long]
Close.restype       = ctypes.c_int
JTAG_IR             = HIL.HIL_JTAG_IR
JTAG_IR.argtypes    = [ctypes.c_long]
JTAG_IR.restype     = ctypes.c_long
TEST_VPP            = HIL.HIL_TEST_VPP
TEST_VPP.argtypes   = [ctypes.c_long]
TEST_VPP.restype    = ctypes.c_long
JTAG_DR             = HIL.HIL_JTAG_DR
JTAG_DR.argtypes    = [ctypes.c_long, ctypes.c_long]
JTAG_DR.restype     = ctypes.c_long
VCC                 = HIL.HIL_VCC
VCC.argtypes        = [ctypes.c_long]
VCC.restype         = ctypes.c_int
TST                 = HIL.HIL_TST
TST.argtypes        = [ctypes.c_long]
TST.restype         = ctypes.c_int
TCK                 = HIL.HIL_TCK
TCK.argtypes        = [ctypes.c_long]
TCK.restype         = ctypes.c_int
TMS                 = HIL.HIL_TMS
TMS.argtypes        = [ctypes.c_long]
TMS.restype         = ctypes.c_int
TDI                 = HIL.HIL_TDI
TDI.argtypes        = [ctypes.c_long]
TDI.restype         = ctypes.c_int
TCLK                = HIL.HIL_TCLK
TCLK.argtypes       = [ctypes.c_long]
TCLK.restype        = ctypes.c_int
RST                 = HIL.HIL_RST
RST.argtypes        = [ctypes.c_long]
RST.restype         = ctypes.c_int
VPP                 = HIL.HIL_VPP
VPP.argtypes        = [ctypes.c_long]
VPP.restype         = ctypes.c_int
DelayMSec           = HIL.HIL_DelayMSec
DelayMSec.argtypes  = [ctypes.c_ulong]
DelayMSec.restype   = ctypes.c_int
StartTimer          = HIL.HIL_StartTimer
StartTimer.argtypes = []
StartTimer.restype  = ctypes.c_int
ReadTimer           = HIL.HIL_ReadTimer
ReadTimer.argtypes  = []
ReadTimer.restype   = ctypes.c_ulong
StopTimer           = HIL.HIL_StopTimer
StopTimer.argtypes  = []
StopTimer.restype   = ctypes.c_int
ReadTDO             = HIL.HIL_ReadTDO
ReadTDO.argtypes    = []
ReadTDO.restype     = ctypes.c_long

if __name__ == '__main__':
    Initialize('1')
    Connect()
    VCC(3000)
    
    #~ HIL_TST(1)
    #~ HIL_DelayMSec(1000)
    #~ HIL_TST(0)
    
    #~ HIL_TCK(1)
    #~ HIL_TDI(1)
    
    #~ for i in range(3):
        #~ HIL_DelayMSec(100)
        #~ HIL_TMS(1)
        #~ HIL_DelayMSec(100)
        #~ HIL_TMS(0)

    JTAG_DR(0x1234, 16)
    
    Release()
    Close(1)

--- NEW FILE: __init__.py ---
# $Id: __init__.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $
--- NEW FILE: bsl.py ---
# (C) 2001-2004 Chris Liechti <[email protected]>
# this is distributed under a free software license, see license.txt
#
# fixes from Colin Domoney
#
# based on the application note slas96b.pdf from Texas Instruments, Inc.,
# Volker Rzehak
# additional infos from slaa089a.pdf
# $Id: bsl.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import sys, time, string, cStringIO, struct
import serial
from memory import Memory

DEBUG = 0

#copy of the patch file provided by TI
#this part is (C) by Texas Instruments
PATCH = """@0220
[...983 lines suppressed...]
            a,l = baudconfigs[baudrate]
        except KeyError:
            raise ValueError, "baudrate not valid. valid values are %r" % baudconfigs.keys()
        
        sys.stderr.write("Changing baudrate to %d ...\n" % baudrate)
        if baudrate > 38400:
            sys.stderr.write("Note: The selected baudrate is not TI standard! They will not work with TI's BSLs.\n")
        sys.stderr.flush()
        self.bslTxRx(self.BSL_CHANGEBAUD,   #Command: change baudrate
                    a, l)                   #args are coded in adr and len
        time.sleep(0.010)                   #recomended delay
        self.serialport.setBaudrate(baudrate)

    def actionReadBSLVersion(self):
        """Informational output of BSL version number.
        (newer MSP430-BSLs only)"""
        ans = self.bslTxRx(self.BSL_TXVERSION, 0) #Command: receive version info
        #the following values are in big endian style!!!
        family_type, bsl_version = struct.unpack(">H8xH4x", ans[:-2]) #cut away checksum and extract data
        print "Device Type: 0x%04x\nBSL version: 0x%04x\n" % (family_type, bsl_version)

--- NEW FILE: clock.py ---
# Utility functions for the DCO clock in MSP430 devices.
#
# Functions to measure the DCO clock and functions to do a software FLL to
# callibrate the clock to a gived frequency.
#
# $Id: clock.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import cStringIO
import sys
import memory, jtag

debug = False
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#see mspgcc cvs/jtag/funclets/counter.S
COUNTER_FUNCLET = """\
@0200
00 02 0a 02 2a 02 60 07 00 00 32 c2 d2 40 f9 ff
57 00 d2 40 f4 ff 58 00 d2 40 ec ff 56 00 0e 43
0f 43 1e 53 0f 63 fd 3f 03 43 ff 3f
q
"""


def getDCOFreq(dcoctl, bcsctl1, bcsctl2=0):
    """measure DCO frequency on a F1xx or F2xx device.
    
       return: frequency in Hz"""
    funclet = memory.Memory()
    funclet.loadTIText(cStringIO.StringIO(COUNTER_FUNCLET))
    
    funclet[0].data = funclet[0].data[:6] \
                    + chr(dcoctl) + chr(bcsctl1) + chr(bcsctl2) \
                    + funclet[0].data[9:]
    runtime = jtag._parjtag.funclet(funclet[0].data, 100)
    count = jtag._parjtag.regread(14) | (jtag._parjtag.regread(15) << 16)
    
    return 1000*count*4/runtime

def setDCO(fmin, fmax, maxrsel=7, dcor=False):
    """Software FLL for F1xx and F2xx devices.
    
       return: (frequency, DCOCTL, BCSCTL1)"""
    if debug: sys.stderr.write("setDCO target: %dHz < frequency < %dHz\n" % (fmin, fmax))
    resolution = 128
    dco = 3<<5
    bcs1 = maxrsel
    fast = True
    upper = False
    lower = False
    
    for tries in range(50):
        if upper and lower and resolution > 1:
            resolution /= 2
            if resolution < 1: resolution = 1
            if debug: sys.stderr.write("switching to higher resolution (-> %d)\n" % (resolution,))
            upper = False
            lower = False
        frequency = getDCOFreq(dco, bcs1, dcor and 1 or 0)
        if frequency > fmax:
            if debug: sys.stderr.write("%luHz is too high, decreasing (was: BCSCTL1=0x%02x; DCOCTL=0x%02x)\n" % (frequency, bcs1, dco))
            upper = True
            dco -= resolution
            if dco <= 0:
                dco = 255
                bcs1 -= 1
                if bcs1 < 0:
                    if resolution > 1:
                        #try again with minimum settings but increased resolution
                        resolution /= 2
                        if resolution < 1: resolution = 1
                        bcs1 = 0
                        dco = 0
                    else:
                        raise IOError("Couldn't get DCO working with correct frequency. Device is not slower than %dHz." % (frequency,))
        elif frequency < fmin:
            if debug: sys.stderr.write("%luHz is too low, increasing (was: BCSCTL1=0x%02x; DCOCTL=0x%02x)\n" % (frequency, bcs1, dco))
            lower = True
            dco += resolution
            if dco > 255:
                dco = 0
                bcs1 += 1
                if bcs1 > maxrsel:
                    if resolution > 1:
                        #try again with maximum settings but increased resolution
                        resolution /= 2
                        if resolution < 1: resolution = 1
                        bcs1 = maxrsel
                        dco = 255
                    else:
                        raise IOError("Couldn't get DCO working with correct frequency. Device is not faster than %dHz." % (frequency,))
        else:
            if debug: sys.stderr.write("%luHz is OK (BCSCTL1=0x%02x; DCOCTL=0x%02x)\n" % (frequency, bcs1, dco))
            return frequency, dco, bcs1
    raise IOError("Couldn't get DCO working with correct frequency. Tolerance too tight? Last frequency was %dHz" % (frequency,))

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#see mspgcc cvs/jtag/funclets/counterplus.S
COUNTERPLUS_FUNCLET = """\
@0200
00 02 0c 02 3c 02 00 0e 80 80 00 00 32 c2 72 d0
40 00 d2 40 f4 ff 52 00 d2 40 ed ff 51 00 d2 40
e9 ff 53 00 d2 40 e4 ff 54 00 d2 40 da ff 50 00
0e 43 0f 43 1e 53 0f 63 fd 3f 03 43 ff 3f
q
"""

def getDCOPlusFreq(scfi0, scfi1, scfqctl, fll_ctl0, fll_ctl1):
    """measure DCO frequency on a F4xx device
    
       return: frequency in Hz"""
    funclet = memory.Memory()
    funclet.loadTIText(cStringIO.StringIO(COUNTERPLUS_FUNCLET))
    funclet[0].data = funclet[0].data[:6] \
                    + chr(scfi0) + chr(scfi1) \
                    + chr(scfqctl) + chr(fll_ctl0) \
                    + chr(fll_ctl1) + funclet[0].data[11:]
    #~ funclet..[0x205] = scfi0, scfi1, scfqctl, fll_ctl0, fll_ctl1
    runtime = jtag._parjtag.funclet(funclet[0].data, 100)
    count = jtag._parjtag.regread(14) | (jtag._parjtag.regread(15) << 16)
    return 1000*count*4/runtime

def setDCOPlus(fmin, fmax):
    """Software FLL for F4xx devices.
    
       return: (frequency, SCFI0, SCFI1, SCFQCTL, FLL_CTL0, FLL_CTL1)"""
    first = 0
    last = 27 << 5
    
    if debug: sys.stderr.write("setDCOPlus target: %dHz < frequency < %dHz\n" % (fmin, fmax))

    # Binary search through the available frequencies, selecting the highest
    # frequency whithin the acceptable range
    while first + 1 < last:
        mid = (last + first) / 2
        # Select DCO range from 0.23MHz to 11.2MHz. Specify frequency via Ndco.
        # Disable Modulation. Enable DCO+.
        frequency = getDCOPlusFreq(mid&3, mid>>2, 0x80, 0x80, 0)
        if frequency > fmax:
            if debug: sys.stderr.write("%luHz is too high, decreasing\n" % frequency)
            last = mid
        elif frequency < fmin:
            if debug: sys.stderr.write("%luHz is too low, increasing\n" % frequency)
            first = mid
        else:
            break

    frequency = getDCOPlusFreq(mid&3, mid>>2, 0x80, 0x80, 0)
    if debug: sys.stderr.write("%luHz\n" % frequency)
    if fmin <= frequency <= fmax:
        return frequency, mid&3, mid>>2, 0x80, 0x80, 0
    raise IOError("Couldn't get DCO working with correct frequency.")

--- NEW FILE: elf.py ---
#!/usr/bin/env python
# $Id: elf.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import struct

# ELF object file reader
# (C) 2003 [email protected]
# Python license

#            size  alignment
# Elf32_Addr    4  4  Unsigned program address
# Elf32_Half    2  2  Unsigned medium integer
# Elf32_Off     4  4  Unsigned file offset
# Elf32_Sword   4  4  Signed large integer
# Elf32_Word    4  4  Unsigned large integer
# unsignedchar  1  1  Unsigned small integer

#define EI_NIDENT 16
#~ typedef struct{
    #~ unsigned char e_ident[EI_NIDENT];
    #~ Elf32_Half e_type;
    #~ Elf32_Half e_machine;
    #~ Elf32_Word e_version;
    #~ Elf32_Addr e_entry;
    #~ Elf32_Off  e_phoff;
    #~ Elf32_Off  e_shoff;
    #~ Elf32_Word e_flags;
    #~ Elf32_Half e_ehsize;
    #~ Elf32_Half e_phentsize;
    #~ Elf32_Half e_phnum;
    #~ Elf32_Half e_shentsize;
    #~ Elf32_Half e_shnum;
    #~ Elf32_Half e_shstrndx;
#~ } Elf32_Ehdr;


#Section Header
#~ typedef struct {
    #~ Elf32_Word sh_name;
    #~ Elf32_Word sh_type;
    #~ Elf32_Word sh_flags;
    #~ Elf32_Addr sh_addr;
    #~ Elf32_Off  sh_offset;
    #~ Elf32_Word sh_size;
    #~ Elf32_Word sh_link;
    #~ Elf32_Word sh_info;
    #~ Elf32_Word sh_addralign;
    #~ Elf32_Word sh_entsize;
#~ } Elf32_Shdr; 

#~ typedef struct {
    #~ Elf32_Word p_type;
    #~ Elf32_Off  p_offset;
    #~ Elf32_Addr p_vaddr;
    #~ Elf32_Addr p_paddr;
    #~ Elf32_Word p_filesz;
    #~ Elf32_Word p_memsz;
    #~ Elf32_Word p_flags;
    #~ Elf32_Word p_align;
#~ } Elf32_Phdr;


class ELFException(Exception): pass

class ELFSection:
    """read and store a section"""
    Elf32_Shdr = "<IIIIIIIIII"          #header format
    
    #section types
    SHT_NULL        = 0
    SHT_PROGBITS    = 1
    SHT_SYMTAB      = 2
    SHT_STRTAB      = 3
    SHT_RELA        = 4
    SHT_HASH        = 5
    SHT_DYNAMIC     = 6
    SHT_NOTE        = 7
    SHT_NOBITS      = 8
    SHT_REL         = 9
    SHT_SHLIB       = 10
    SHT_DYNSYM      = 11
    SHT_LOPROC      = 0x70000000L
    SHT_HIPROC      = 0x7fffffffL
    SHT_LOUSER      = 0x80000000L
    SHT_HIUSER      = 0xffffffffL
    #section attribute flags
    SHF_WRITE       = 0x1
    SHF_ALLOC       = 0x2
    SHF_EXECINSTR   = 0x4
    SHF_MASKPROC    = 0xf0000000L

    def __init__(self):
        """creat a new empty section object"""
        (self.sh_name, self.sh_type, self.sh_flags, self.sh_addr,
         self.sh_offset, self.sh_size, self.sh_link, self.sh_info,
         self.sh_addralign, self.sh_entsize) = [0]*10
        self.name = None
        self.data = None
        self.lma =  None

    def fromString(self, s):
        """get section header from string"""
        (self.sh_name, self.sh_type, self.sh_flags, self.sh_addr,
         self.sh_offset, self.sh_size, self.sh_link, self.sh_info,
         self.sh_addralign, self.sh_entsize) = struct.unpack(self.Elf32_Shdr, s)
         
    def __str__(self):
        """pretty print for debug..."""
        return "%s(%s, sh_type=%s, sh_flags=%s, "\
               "sh_addr=0x%04x, sh_offset=0x%04x, sh_size=%s, sh_link=%s, "\
               "sh_info=%s, sh_addralign=%s, sh_entsize=%s, lma=0x%04x)" % (
            self.__class__.__name__,
            self.name is not None and "%r" % self.name or "sh_name=%s" % self.sh_name,
            self.sh_type, self.sh_flags, self.sh_addr,
            self.sh_offset, self.sh_size, self.sh_link, self.sh_info,
            self.sh_addralign, self.sh_entsize, self.lma)

class ELFProgramHeader:
    """Store and parse a program header"""
    Elf32_Phdr = "<IIIIIIII"            #header format
    
    #segmet types
    PT_NULL         = 0
    PT_LOAD         = 1
    PT_DYNAMIC      = 2
    PT_INTERP       = 3
    PT_NOTE         = 4
    PT_SHLIB        = 5
    PT_PHDR         = 6
    PT_LOPROC       = 0x70000000L
    PT_HIPROC       = 0x7fffffffL
    
    #segment flags
    PF_R            = 0x4       #segment is readable
    PF_W            = 0x2       #segment is writable
    PF_X            = 0x1       #segment is executable
     
    def __init__(self):
        """create a new, empty segment/program header"""
        (self.p_type, self.p_offset, self.p_vaddr, self.p_paddr,
            self.p_filesz, self.p_memsz, self.p_flags, self.p_align) = [0]*8
        self.data = None

    def fromString(self, s):
        """parse header info from string"""
        (self.p_type, self.p_offset, self.p_vaddr, self.p_paddr,
            self.p_filesz, self.p_memsz, self.p_flags,
            self.p_align) = struct.unpack(self.Elf32_Phdr, s)

    def __str__(self):
        """pretty print for debug..."""
        return "%s(p_type=%s, p_offset=0x%04x, p_vaddr=0x%04x, p_paddr=0x%04x, "\
            "p_filesz=%s, p_memsz=%s, p_flags=%s, "\
            "p_align=%s)" % (
            self.__class__.__name__,
            self.p_type, self.p_offset, self.p_vaddr, self.p_paddr,
            self.p_filesz, self.p_memsz, self.p_flags,
            self.p_align)

class ELFObject:
    """Object to read and handle an LEF object file"""
    #header information
    Elf32_Ehdr = "<16sHHIIIIIHHHHHH"
    
    #offsets within e_ident
    EI_MAG0         = 0     #File identification
    EI_MAG1         = 1     #File identification
    EI_MAG2         = 2     #File identification
    EI_MAG3         = 3     #File identification
    EI_CLASS        = 4     #File class
    EI_DATA         = 5     #Data encoding
    EI_VERSION      = 6     #File version
    EI_PAD          = 7     #Start of padding bytes
    EI_NIDENT       = 16    #Size of e_ident[]
    #elf file type flags
    ET_NONE         = 0     #No file type
    ET_REL          = 1     #Relocatable file
    ET_EXEC         = 2     #Executable file
    ET_DYN          = 3     #Shared object file
    ET_CORE         = 4     #Core file
    ET_LOPROC       = 0xff00 #Processor-specific
    ET_HIPROC       = 0xffff #Processor-specific
    #ELF format
    ELFCLASSNONE    = 0     #Invalid class
    ELFCLASS32      = 1     #32-bit objects
    ELFCLASS64      = 2     #64-bit objects
    #encoding
    ELFDATANONE     = 0     #Invalid data encoding
    ELFDATA2LSB     = 1     #See below
    ELFDATA2MSB     = 2     #See below

    def __init__(self):
        """create a new elf object"""
        (self.e_ident, self.e_type, self.e_machine, self.e_version,
        self.e_entry, self.e_phoff, self.e_shoff,
        self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum,
        self.e_shentsize, self.e_shnum, self.e_shstrndx) = [0]*14

    def fromFile(self, fileobj):
        """read all relevant data from fileobj.
        the file must be seekable"""
        #get file header
        (self.e_ident, self.e_type, self.e_machine, self.e_version,
        self.e_entry, self.e_phoff, self.e_shoff,
        self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum,
        self.e_shentsize, self.e_shnum, self.e_shstrndx) = struct.unpack(
            self.Elf32_Ehdr, fileobj.read(struct.calcsize(self.Elf32_Ehdr)))
        #verify if its a known format and realy an ELF file
        if self.e_ident[0:4]             != '\x7fELF' and\
           self.e_ident[self.EI_CLASS]   != self.ELFCLASS32 and\
           self.e_ident[self.EI_DATA]    != self.ELFDATA2LSB and\
           self.e_ident[self.EI_VERSION] != 1:
                raise ELFException("Not a valid ELF file")

        #load programm headers
        self.programmheaders = []
        if self.e_phnum:
            #load program headers
            fileobj.seek(self.e_phoff)
            for sectionnum in range(self.e_phnum):
                shdr = (fileobj.read(self.e_phentsize) + '\0'* struct.calcsize(ELFProgramHeader.Elf32_Phdr))[0:struct.calcsize(ELFProgramHeader.Elf32_Phdr)]
                psection = ELFProgramHeader()
                psection.fromString(shdr)
                if psection.p_offset:   #skip if section has invalid offset in file
                    self.programmheaders.append(psection)
            #~ #get the segment data from the file for each prg header
            #~ for phdr in self.programmheaders:
                #~ fileobj.seek(phdr.p_offset)
                #~ phdr.data = fileobj.read(phdr.p_filesz)
                #~ #pad if needed
                #~ if phdr.p_filesz < phdr.p_memsz:
                    #~ phdr.data = phdr.data + '\0' * (phdr.p_memsz-phdr.p_filesz)

        #load sections
        self.sections = []
        fileobj.seek(self.e_shoff)
        for sectionnum in range(self.e_shnum):
            shdr = (fileobj.read(self.e_shentsize) + '\0'* struct.calcsize(ELFSection.Elf32_Shdr))[0:struct.calcsize(ELFSection.Elf32_Shdr)]
            elfsection = ELFSection()
            elfsection.fromString(shdr)
            self.sections.append(elfsection)
        
        #load data for all sections
        for section in self.sections:
            fileobj.seek(section.sh_offset)
            data = fileobj.read(section.sh_size)
            section.data = data
            if section.sh_type == ELFSection.SHT_STRTAB:
                section.values = data.split('\0')
            section.lma = self.getLMA(section)
        
        #get section names
        for section in self.sections:
            start = self.sections[self.e_shstrndx].data[section.sh_name:]
            section.name = start.split('\0')[0]
        
    def getSection(self, name):
        """get section by name"""
        for section in self.sections:
            if section.name == '.text':
                return section
    
    def getProgrammableSections(self):
        """get all program headers that are marked as executable and
        have suitable attributes to be code"""
        res = []
        for p in self.programmheaders:
            #~ print p
            #~ if section.sh_flags & self.SHF_ALLOC and section.name not in ('.data', '.data1', '.bss'):
            #~ if p.p_type == ELFProgramHeader.PT_LOAD:# and p.p_paddr == p.p_vaddr and p.p_flags & ELFProgramHeader.PF_X:
            if p.p_type == ELFProgramHeader.PT_LOAD:
                res.append(p)
        return res

    def getLMA(self, section):
        #magic load memory address calculation ;-)
        for p in self.programmheaders:
            if (p.p_paddr != 0 and \
                p.p_type == ELFProgramHeader.PT_LOAD and \
                p.p_vaddr != p.p_paddr and \
                p.p_vaddr <= section.sh_addr and \
                (p.p_vaddr + p.p_memsz >= section.sh_addr + section.sh_size) \
                    and (not (section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS) \
                    or  (p.p_offset <= section.sh_offset \
                    and (p.p_offset + p.p_filesz >= section.sh_offset + section.sh_size)))):
                return section.sh_addr + p.p_paddr - p.p_vaddr
        return section.sh_addr

    def getSections(self):
        """get sections relevant for the application"""
        res = []
        for section in self.sections:
            if section.sh_flags & ELFSection.SHF_ALLOC and section.sh_type != ELFSection.SHT_NOBITS:
                res.append(section)
        return res

    def __str__(self):
        """pretty print for debug..."""
        return "%s(self.e_type=%r, self.e_machine=%r, self.e_version=%r, sections=%r)" % (
            self.__class__.__name__, 
            self.e_type, self.e_machine, self.e_version,
            [section.name for section in self.sections])


if __name__ == '__main__':
    print "This is only a module test!"
    elf = ELFObject()
    elf.fromFile(open("test.elf"))
    if elf.e_type != ELFObject.ET_EXEC:
        raise Exception("No executable")
    print elf

    #~ print repr(elf.getSection('.text').data)
    #~ print [(s.name, hex(s.sh_addr)) for s in elf.getSections()]
    print "-"*20
    for p in elf.sections: print p
    print "-"*20
    for p in elf.getSections(): print p
    print "-"*20
    for p in elf.getProgrammableSections(): print p

--- NEW FILE: hilspi.py ---
# Using the MSP430 JTAG parallel port board as SPI interface.
#
# (C) 2004 Chris Liechti <[email protected]>
# this is distributed under a free software license, see license.txt
# 
# http://mspgcc.sf.net
# 
# Requires Python 2+, ctypes and HIL.dll/libHIL.so
# 
# $Id: hilspi.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import HIL
#~ import psyco
#~ psyco.full()

def init(port='1'):
    """open the parallel port and prepare for SPI mode"""
    HIL.Initialize(port)
    HIL.Connect()
    HIL.VCC(3000)
    HIL.TST(0)
    HIL.TCK(1)
    HIL.TDI(1)
    HIL.TMS(1)

def close():
    """close the parallel port"""
    HIL.Release()
    HIL.Close(1)

def _delay():
    """can be implemented if the SPI data rate has to be lowered"""
    #~ HIL.DelayMSec(1)
    #~ for i in range(10): HIL.DelayMSec(0)
    #~ HIL.DelayMSec(0)
    pass

def shift(data):
    """shift an binary string from/to the slave, returning the
       answer string of the same length
    """
    answer = []
    for character in data:
        shiftout = ord(character)
        indata = 0
        for i in range(8):
            HIL.TCK(0)
            HIL.TDI(shiftout & 0x80)
            shiftout <<= 1
            _delay()
            HIL.TCK(1)
            _delay()
            indata = (indata << 1) | HIL.ReadTDO()
        answer.append(chr(indata))
    return ''.join(answer)

def sync():
    """read untlil something else as a 0xff arrives.
    """
    while shift('\xff') != '\xff':
        pass

def getNullTeminated(maxlen=80):
    """read a null terminated string over SPI."""
    answer = []
    while maxlen:
        c = shift('\xff')
        if c == '\0': break
        answer.append(c)
        maxlen -= 1
    return ''.join(answer)


#test application
if __name__ == '__main__':
    import time
    init()
    #reset target
    HIL.RST(0)
    HIL.DelayMSec(10)
    HIL.RST(1)
    HIL.DelayMSec(10)
    
    #simple speed test
    bytes = 0
    t1 = time.time()
    for i in range(200):
        #~ print '%r' % getNullTeminated()
        bytes += len(getNullTeminated()) + 1
    dt = time.time() - t1
    print "%d bytes in %.2f seconds -> %.2f bytes/second" % (bytes, dt, bytes/dt)

--- NEW FILE: jtag.py ---
# Parallel JTAG programmer for the MSP430 embedded proccessor.
#
# (C) 2002-2004 Chris Liechti <[email protected]>
# this is distributed under a free software license, see license.txt
#
# http://mspgcc.sf.net
#
# Requires Python 2+ and the binary extension _parjtag or ctypes
# and MSP430mspgcc.dll/libMSP430mspgcc.so and HIL.dll/libHIL.so
#
# $Id: jtag.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import sys

#erase modes
ERASE_SEGMENT = 0       #Erase a segment.
ERASE_MAIN    = 1       #Erase all MAIN memory.
ERASE_ALL     = 2       #Erase all MAIN and INFORMATION memory.

#Configurations of the MSP430 driver
VERIFICATION_MODE = 0   #Verify data downloaded to FLASH memories.
RAMSIZE_OPTION    = 1   #Change RAM used to download and program flash blocks
DEBUG_OPTION      = 2   #Set debug level. Enables debug outputs.
FLASH_CALLBACK    = 3   #Set a callback for progress report during flash write void f(WORD count, WORD total)

#reset methods
PUC_RESET = 1 << 0      #Power up clear (i.e., a "soft") reset.
RST_RESET = 1 << 1      #RST/NMI (i.e., "hard") reset.
VCC_RESET = 1 << 2      #Cycle Vcc (i.e., a "power on") reset.
ALL_RESETS = PUC_RESET + RST_RESET + VCC_RESET


DEBUG = 0

#for module tests, enable debug outputs from the beginning on
if __name__ == '__main__':
    DEBUG = 1

#ctypes backend variations:
CTYPES_PARJTAG = "parjtag/mspgcc"
CTYPES_MSPGCC = "ctypes/mspgcc"
CTYPES_TI = "ctypes/TI or 3rd party"

#exceptions
class JTAGException(Exception): pass

backend = None
backend_info = None
def init_backend(force=None):
    global backend
    global backend_info
    global _parjtag
    
    #1st try the ctypes implementation, if that's not available try to use the C extension
    try:
        import ctypes
    except ImportError:
        if force is not None and force != CTYPES_MSPGCC:
            raise JTAGException("Desired backend is not available: %s" % force)
        try:
            import _parjtag
        except ImportError:
            raise ImportError(
                "Can not find neither _parjtag nor ctypes. No JTAG backend available.\n"
                "\n"
                "The ctypes backend is prefered. Make sure that the ctypes python\n"
                "extension is available on this system.\n"
                "\n"
                "Alternatively, the older _parjtag backend is a python extension that\n"
                "can be built from sources from http://mspgcc.sf.net\n"
            )
        else:
            backend = CTYPES_PARJTAG
    else:
        import os
        #create a wrapper class with ctypes, that has the same API as _parjtag
        def locate_library(libname, paths=sys.path, loader=ctypes.windll):
            for path in paths:
                if path.lower().endswith('.zip'):
                    path = os.path.dirname(path)
                library = os.path.join(path, libname)
                if DEBUG > 4: sys.stderr.write('trying %r...\n' % library)
                if os.path.exists(library):
                    if DEBUG > 4: sys.stderr.write('using %r\n' % library)
                    return loader.LoadLibrary(library), library
            else:
                raise IOError('%s not found' % libname)
        
        #an absolute path to the library can be given.
        #LIBMSPGCC_PATH is used to pass its location
        search_path = sys.path[:]   #copy sys.path list
        #if environment variable is set, insert this path first
        try:
            search_path.insert(0, os.environ['LIBMSPGCC_PATH'])
        except KeyError:
            if DEBUG > 4: sys.stderr.write('LIBMSPGCC_PATH is not set\n')
        #as fallback, append PATH
        try:
            search_path.extend(os.environ['PATH'].split(os.pathsep))
        except KeyError:
            pass
        
        #~ print search_path
        STATUS_OK    = 0
        STATUS_ERROR = -1
        TRUE         = 1
        FALSE        = 0
        WRITE        = 0
        READ         = 1
        if sys.platform == 'win32':
            #the library is found on the PATH, respectively in the executables directory
            
            if force == CTYPES_MSPGCC:
                MSP430mspgcc, backend_info = locate_library('MSP430mspgcc.dll', search_path)
                backend = CTYPES_MSPGCC
            elif force == CTYPES_TI:
                #~ MSP430mspgcc = ctypes.windll.MSP430
                MSP430mspgcc, backend_info = locate_library('MSP430.dll', search_path)
                backend = CTYPES_TI
            else:
                #autodetect
                try:
                    #try to use the TI or third party library
                    MSP430mspgcc, backend_info = locate_library('MSP430.dll', search_path)
                    backend = CTYPES_TI
                except IOError:
                    #when that fails, use the mspgcc implementation
                    MSP430mspgcc, backend_info = locate_library('MSP430mspgcc.dll', search_path)
                    backend = CTYPES_MSPGCC
        else:
            #now try to locate library
            try:
                MSP430mspgcc, backend_info = locate_library('libMSP430mspgcc.so', search_path, ctypes.cdll)
            except IOError, e:
                raise IOError('The environment variable "LIBMSPGCC_PATH" must point to the folder that contains "libMSP430mspgcc.so": %s' % e)
            backend = CTYPES_MSPGCC
        
        MSP430_Initialize               = MSP430mspgcc.MSP430_Initialize
        MSP430_Initialize.argtypes      = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_long)]
        MSP430_Initialize.restype       = ctypes.c_int
        if backend == CTYPES_MSPGCC:
            MSP430_Open                 = MSP430mspgcc.MSP430_Open
            MSP430_Open.argtypes        = []
            MSP430_Open.restype         = ctypes.c_int
        else:
            MSP430_Identify             = MSP430mspgcc.MSP430_Identify
            MSP430_Identify.argtypes    = [ctypes.POINTER(ctypes.c_char*56), ctypes.c_long, ctypes.c_long]
            MSP430_Identify.restype     = ctypes.c_int
            #TI's USB-FET lib does not have this function, they have an MSP430_Identify instead
            def MSP430_Open():
                buffer = (ctypes.c_char*56)()
                status = MSP430_Identify(ctypes.byref(buffer), 56, 0)
                if status != STATUS_OK:
                    return STATUS_ERROR
                if DEBUG:
                    sys.stderr.write('MSP430_Identify: Device type: %r\n' % str(buffer[4:36]).replace('\0',''))
                #~ status = MSP430_Reset(ALL_RESETS, FALSE, FALSE)
                return status

        MSP430_Close                    = MSP430mspgcc.MSP430_Close
        MSP430_Close.argtypes           = [ctypes.c_long]
        MSP430_Close.restype            = ctypes.c_int
        MSP430_Configure                = MSP430mspgcc.MSP430_Configure
        MSP430_Configure.argtypes       = [ctypes.c_long, ctypes.c_long]
        MSP430_Configure.restype        = ctypes.c_int
        MSP430_VCC                      = MSP430mspgcc.MSP430_VCC
        MSP430_VCC.argtypes             = [ctypes.c_long]
        MSP430_VCC.restype              = ctypes.c_int
        MSP430_Reset                    = MSP430mspgcc.MSP430_Reset
        MSP430_Reset.argtypes           = [ctypes.c_long, ctypes.c_long, ctypes.c_long]
        MSP430_Reset.restype            = ctypes.c_int
        MSP430_Erase                    = MSP430mspgcc.MSP430_Erase
        MSP430_Erase.argtypes           = [ctypes.c_long, ctypes.c_long, ctypes.c_long]
        MSP430_Erase.restype            = ctypes.c_int
        MSP430_Memory                   = MSP430mspgcc.MSP430_Memory
        MSP430_Memory.argtypes          = [ctypes.c_long, ctypes.POINTER(ctypes.c_char), ctypes.c_long, ctypes.c_long]
        MSP430_Memory.restype           = ctypes.c_int
        MSP430_VerifyMem                = MSP430mspgcc.MSP430_VerifyMem
        MSP430_VerifyMem.argtypes       = [ctypes.c_long, ctypes.c_long, ctypes.c_char_p]
        MSP430_VerifyMem.restype        = ctypes.c_int
        MSP430_EraseCheck               = MSP430mspgcc.MSP430_EraseCheck
        MSP430_EraseCheck.argtypes      = ctypes.c_long, ctypes.c_long
        MSP430_EraseCheck.restype       = ctypes.c_int
        if backend == CTYPES_MSPGCC:
            MSP430_ReadRegister             = MSP430mspgcc.MSP430_ReadRegister
            MSP430_ReadRegister.argtypes    = [ctypes.c_long, ctypes.POINTER(ctypes.c_long)]
            MSP430_ReadRegister.restype     = ctypes.c_int
            MSP430_WriteRegister            = MSP430mspgcc.MSP430_WriteRegister
            MSP430_WriteRegister.argtypes   = [ctypes.c_long, ctypes.c_long]
            MSP430_WriteRegister.restype    = ctypes.c_int
        else:
            #TI's USB-FET lib does not have this function
            if DEBUG:
                sys.stderr.write('MSP430_*Register not found in library. Not supported.\n')
        if backend == CTYPES_MSPGCC:
            #~ MSP430_Funclet                  = MSP430mspgcc.MSP430_Funclet
            #~ MSP430_Funclet.argtypes         = [ctypes.c_char_p, ctypes.c_long, ctypes.c_int, ctypes.c_int]
            #~ MSP430_Funclet.restype          = ctypes.c_int
            MSP430_FuncletWait              = MSP430mspgcc.MSP430_FuncletWait
            MSP430_FuncletWait.argtypes     = [ctypes.c_char_p, ctypes.c_long, ctypes.c_int, ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong)]
            MSP430_FuncletWait.restype      = ctypes.c_int
            MSP430_isHalted                 = MSP430mspgcc.MSP430_isHalted
            MSP430_isHalted.argtypes        = []
            MSP430_isHalted.restype         = ctypes.c_int
        else:
            #TI's USB-FET lib does not have this function
            if DEBUG:
                sys.stderr.write('MSP430_Funclet and isHalted not found in library. Not supported.\n')
        MSP430_Error_Number             = MSP430mspgcc.MSP430_Error_Number
        MSP430_Error_Number.argtypes    = []
        MSP430_Error_Number.restype     = ctypes.c_long
        MSP430_Error_String             = MSP430mspgcc.MSP430_Error_String
        MSP430_Error_String.argtypes    = [ctypes.c_long]
        MSP430_Error_String.restype     = ctypes.c_char_p
        try:
            MSP430_Secure                   = MSP430mspgcc.MSP430_Secure
            MSP430_Secure.argtypes          = []
            MSP430_Secure.restype           = ctypes.c_int
        except AttributeError:
            #mspgcc lib does not have this function
            if DEBUG:
                sys.stderr.write('MSP430_Secure not found in library. Not supported.\n')
            def MSP430_Secure():
                raise NotImplementedError("this function is not supported with this MSP430 library")
        
        messagecallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_short, ctypes.c_short) #void f(WORD count, WORD total)

        class ParJTAG:
            """implementation of the _parjtag module in python with the help of ctypes"""
            
            def open(self, port = None):
                """Initilize library"""
                version = ctypes.c_long(0)
                if port is None:
                    if sys.platform == 'win32':
                        port = "1"
                    else:
                        port = "/dev/parport0"
                if backend == CTYPES_TI:
                    port = port.upper()
                status = MSP430_Initialize(port, ctypes.byref(version))
                if status != STATUS_OK:
                    raise IOError("Could not initialize the library (port: %s)" % port)
                if DEBUG:
                    sys.stderr.write('backend library version: %d\n' % (version.value,))
                
            def connect(self,):
                """Enable JTAG and connect to target. This stops it.
                This function must be called before using any other JTAG function,
                or the other functions will yield unpredictable data."""
                MSP430_VCC(3000)
                
                status = MSP430_Open()
                if status != STATUS_OK:
                    raise IOError("Can't open interface: %s" % MSP430_Error_String(MSP430_Error_Number()))
            
                status = MSP430_Configure(VERIFICATION_MODE, TRUE)
                if status != STATUS_OK:
                    raise IOError("Could not configure the library: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def release(self):
                """Release the target, disable JTAG lines.
                Subsequent access to the JTAG yields wrong data, until
                connect() is called again.
                The execution is started wherever the PC stays. Don't use this
                function after Flash operations or memverify. The PC was modified
                and points to an unpredicatble location. Use reset() before calling
                this function."""
                status = MSP430_Close(TRUE)
                if status != STATUS_OK:
                    raise IOError("Could not close the library: %s" % MSP430_Error_String(MSP430_Error_Number()))
            
            def reset(self, execute = 0, release = 0, resets = ALL_RESETS):
                """Reset the device, optionaly start execution and/or release JTAG."""
                status = MSP430_Reset(resets, execute, release)
                if status != STATUS_OK:
                    raise IOError("Could not reset target (no connection?): %s" % MSP430_Error_String(MSP430_Error_Number()))

            def memread(self, address, size):
                """Read 'size' bytes starting at the specified address.
                The return value is a string with the (binary) data.
                It is possible to read peripherals, RAM as well as Flash."""
                if size < 0: raise ValueError("Size must not be negative")
                buffer = (ctypes.c_char*size)();
                
                status = MSP430_Memory(address, buffer, size, READ)
                if status == STATUS_OK:
                    return ''.join([str(x) for x in buffer])
                else:
                    raise IOError("Could not read target memory: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def memwrite(self, address, buffer):
                """'mem' has to be a string, containing the data to write.
                It is possible to write peripherals, RAM as well as Flash.
                Flash must be erased before writing it with memerase()."""
                size = len(buffer)
                c_buffer = (ctypes.c_char*(size+2))();    #just to be sure + 2 (shouldn't be needed though)
                for i in range(size): c_buffer[i] = buffer[i]
                status = MSP430_Memory(address, c_buffer, size, WRITE)
                if status != STATUS_OK:
                    raise IOError("Could not write target memory: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def memverify(self, address, buffer):
                """'mem' has to be a string of even length.
                Verify device memory against the supplied data using PSA analysis."""
                size = len(buffer)
                if size & 1:
                    raise ValueError("Buffer must have an even length")
                status = MSP430_VerifyMem(address, size, buffer)
                return (status == STATUS_OK)

            def memerase(self, type=ERASE_ALL, address=0xfffe, length=2):
                """Erase the Flash.
                
                Valid modes are:
                    ERASE_SEGMENT = 0
                    ERASE_MAIN    = 1
                    ERASE_ALL     = 2
                    
                The default address and length is fine for mass and main erase.
                To erase a single segment ERASE_SEGMENT and an address within that
                segement must be specified. The length can be choosen larger than
                one segment to erase a consecutive block of segments.
                The erased segments are checked for erasure using PSA analysis."""
                status = MSP430_Erase(type, address, length)
                if status != STATUS_OK:
                    raise IOError("Could not erase the Flash: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def funclet(self, code, timeout=1000):
                """Download a 'funclet' contained in the string 'code' to the target
                and execute it. This function waits until the code stops on a "jmp $"
                or a timeout.
                Please refer to the 'funclet' documentation for the contents of the
                code string.
                return the runtime in seconds"""
                runtime = ctypes.c_ulong()
                size = len(code)
                if size & 1:
                    raise ValueError("data must be of even size")
                
                status = MSP430_FuncletWait(code, size, 1, timeout, ctypes.byref(runtime))
                if status != STATUS_OK:
                    raise IOError("Could not execute code: %s" % MSP430_Error_String(MSP430_Error_Number()))
                return runtime.value

            def configure(self, mode, value = 0):
                """Configure the MSP430 driver."""
                status = MSP430_Configure(mode, value)
                if status != STATUS_OK:
                    raise IOError("Could not change mode: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def regread(self, regnum):
                """returns register value"""
                value = ctypes.c_long()
                status = MSP430_ReadRegister(regnum, ctypes.byref(value))
                if status != STATUS_OK:
                    raise IOError("Could not read register: %s" % MSP430_Error_String(MSP430_Error_Number()))
                return value.value

            def regwrite(self, regnum, value):
                """write value to register"""
                status = MSP430_WriteRegister(regnum, value);
                if status != STATUS_OK:
                    raise IOError("Could not write register: %s" % MSP430_Error_String(MSP430_Error_Number()))

            def set_flash_callback(self, function):
                """The 'function' is called with (count, total) as arguments
                while the flash is written."""

                self._callback = messagecallback(function)
                #~ MSP430_Configure(FLASH_CALLBACK, ctypes.addressof(self._callback))
                #hack following, close your eyes ;-)...
                argtypes = MSP430_Configure.argtypes
                MSP430_Configure.argtypes = [ctypes.c_long, messagecallback]
                MSP430_Configure(FLASH_CALLBACK, self._callback)
                MSP430_Configure.argtypes = argtypes

            def isHalted(self):
                """Check if cpu is stuck on an address."""
                value = MSP430_isHalted()
                return value
                
            def secure(self):
                """burn JTAG security fuse.
                   Note: not reversibly. use with care.
                   Note: not supported by all JTAG adapters.
                """
                status = MSP430_Secure()
                if status != STATUS_OK:
                    raise IOError("Could not secure device: %s" % MSP430_Error_String(MSP430_Error_Number()))
        
        _parjtag = ParJTAG()
    
    # print the used backend
    if DEBUG:
        sys.stderr.write("JTAG backend: %s (%s)\n" % (backend, backend_info))


class JTAG:
    """wrap the _parjtag extension.
    The action* methods all do output messages on stderr and they take their
    settings and data from the object and not as parameters.
    """

    def __init__(self):
        self.showprogess = 0
        self.data = None
        self.verbose = 1
    
    # ---------- direct use API ---------------
    
    def open(self, lpt=None):
        """Initialize and open port."""
        if backend is None: init_backend()
        if lpt is None:
            _parjtag.open()
        else:
            _parjtag.open(lpt)

    def connect(self):
        """Connect to devcice."""
        _parjtag.connect()

    def close(self):
        """Release device from JTAG."""
        _parjtag.release()

    def setDebugLevel(self, level):
        """Set level of debugging messages."""
        global DEBUG
        DEBUG = level
        #this option is only available in the mspgcc library
        if backend == CTYPES_MSPGCC:
            _parjtag.configure(DEBUG_OPTION, level)

    def setRamsize(self, ramsize):
        """Set download chunk size."""
        if DEBUG > 1: sys.stderr.write("* setRamsize(%d)\n" % ramsize)
        #this option is only available in the mspgcc library
        if backend == CTYPES_MSPGCC:
            _parjtag.configure(RAMSIZE_OPTION, ramsize)
        else:
            if DEBUG > 1: sys.stderr.write("* setRamsize ignored for %s backend\n" % backend)

    def downloadData(self, startaddress, data):
        """Write data to given address."""
        _parjtag.memwrite(startaddress, data)
        
    def uploadData(self, startaddress, size):
        """Upload a datablock."""
        if DEBUG > 1: sys.stderr.write("* uploadData()\n")
        return _parjtag.memread(startaddress, size)

    def reset(self, execute=0, release=0):
        """Perform a reset and optionally release device."""
        if self.verbose:
            sys.stderr.write("Reset %sdevice...\n" % (release and 'and release ' or ''))
            sys.stderr.flush()
        _parjtag.reset(execute, release)

    def getCPURegister(self, regnum):
        """Read CPU register."""
        return _parjtag.regread(regnum)
        
    def setCPURegister(self, regnum, value):
        """Write CPU register."""
        _parjtag.regwrite(regnum, value)

    # ---------- action based API ---------------

    def actionMassErase(self):
        """Erase the flash memory completely (with mass erase command)."""
        if self.verbose:
            sys.stderr.write("Mass Erase...\n")
        _parjtag.memerase(ERASE_ALL)

    def actionMainErase(self):
        """Erase the MAIN flash memory, leave the INFO mem"""
        if self.verbose:
            sys.stderr.write("Erase Main Flash...\n")
            sys.stderr.flush()
        _parjtag.memerase(ERASE_MAIN, 0xfffe)

    def makeActionSegmentErase(self, address):
        """Selective segment erase, the returned object can be called
        to execute the action."""
        class SegmentEraser:
            def __init__(self, segaddr, verbose=0):
                self.address = segaddr
                self.verbose = verbose
            def __call__(self):
                if self.verbose:
                    sys.stderr.write("Erase Segment @ 0x%04x...\n" % self.address)
                    sys.stderr.flush()
                _parjtag.memerase(ERASE_SEGMENT, self.address)
            def __repr__(self):
                return "Erase Segment @ 0x%04x" % self.address
        return SegmentEraser(address, self.verbose)

    def actionEraseCheck(self):
        """Check the erasure of required flash cells. Erase check by file."""
        sys.stderr.write("Erase Check by file...\n")
        if self.data is not None:
            for seg in self.data:
                data = _parjtag.memread(seg.startaddress, len(seg.data))
                if data != '\xff'*len(seg.data): raise JTAGException("Erase check failed")
        else:
            raise JTAGException("Cannot do erase check against data with not knowing the actual data")

    def progess_update(self, count, total):
        """Textual progress output. Override in subclass to implement a
        different output."""
        sys.stderr.write("\r%d%%" % (100*count/total))
        sys.stderr.flush()

    def actionProgram(self):
        """Program data into flash memory."""
        if self.data is not None:
            if self.verbose:
                sys.stderr.write("Program...\n")
                sys.stderr.flush()
            if self.showprogess:
                _parjtag.set_flash_callback(self.progess_update)
            bytes = 0
            for seg in self.data:
                _parjtag.memwrite(seg.startaddress, seg.data)
                bytes += len(seg.data)
            if self.verbose:
                sys.stderr.write("%i bytes programmed.\n" % bytes)
                sys.stderr.flush()
        else:
            raise JTAGException("Programming without data is not possible")

    def actionVerify(self):
        """Verify programmed data."""
        if self.data is not None:
            sys.stderr.write("Verify...\n")
            sys.stderr.flush()
            for seg in self.data:
                data = _parjtag.memread(seg.startaddress, len(seg.data))
                if data != seg.data: raise JTAGException("Verify failed")
        else:
            raise JTAGException("Verify without data not possible")

    def actionRun(self, address):
        """Start program at specified address."""
        raise NotImplementedError
        #sys.stderr.write("Load PC with 0x%04x ...\n" % address)

    def actionFunclet(self, timeout=1):
        """Download and start funclet. Timeout in seconds."""
        if self.data is not None:
            if self.verbose:
                sys.stderr.write("Download and execute funclet...\n")
                sys.stderr.flush()
            if len(self.data) != 1:
                raise JTAGException("Funclets must have exactly one segment")
            runtime = _parjtag.funclet(self.data[0].data, int(timeout*1000)) / 1000.0
            if runtime >= timeout:
                sys.stderr.write("Funclet stopped on timeout\n")
                sys.stderr.flush()
            if self.verbose:
                sys.stderr.write("Funclet OK (%.2fs).\n" % (runtime,))
                sys.stderr.flush()
        else:
            raise JTAGException("No funclet available, set data")

    def actionSecure(self):
        """Secure device by burning the JTAG security fuse."""
        if self.verbose:
            sys.stderr.write("Blowing JTAG fuse...\n")
            sys.stderr.flush()
        _parjtag.secure()


# simple, stupid module test, debug is set above
if __name__ == '__main__':
    #~ init_backend(CTYPES_MSPGCC)
    #~ init_backend(CTYPES_TI)
    jtagobj = JTAG()
    print "Backend: %s" % (backend, )
    jtagobj.open()
    try:
        jtagobj.connect()
        jtagobj.reset()
    finally:
        jtagobj.close()

--- NEW FILE: memory.py ---
# $Id: memory.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $
import sys
import elf

DEBUG = 0

class FileFormatError(IOError):
    """file is not in the expected format"""


class Segment:
    """store a string with memory contents along with its startaddress"""
    def __init__(self, startaddress = 0, data=None):
        if data is None:
            self.data = ''
        else:
            self.data = data
        self.startaddress = startaddress

    def __getitem__(self, index):
        return self.data[index]

    def __len__(self):
        return len(self.data)

    def __repr__(self):
        return "Segment(startaddress = 0x%04x, data=%r)" % (self.startaddress, self.data)

class Memory:
    """represent memory contents. with functions to load files"""
    def __init__(self, filename=None):
        self.segments = []
        if filename:
            self.filename = filename
            self.loadFile(filename)

    def append(self, seg):
        self.segments.append(seg)

    def __getitem__(self, index):
        return self.segments[index]

    def __len__(self):
        return len(self.segments)

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    def loadIHex(self, file):
        """load data from a (opened) file in Intel-HEX format"""
        segmentdata = []
        currentAddr = 0
        startAddr   = 0
        lines = file.readlines()
        for l in lines:
            if not l.strip(): continue  #skip empty lines
            if l[0] != ':': raise FileFormatError("line not valid intel hex data: '%s...'" % l[0:10])
            l = l.strip()               #fix CR-LF issues...
            length  = int(l[1:3],16)
            address = int(l[3:7],16)
            type    = int(l[7:9],16)
            check   = int(l[-2:],16)
            if type == 0x00:
                if currentAddr != address:
                    if segmentdata:
                        self.segments.append( Segment(startAddr, ''.join(segmentdata)) )
                    startAddr = currentAddr = address
                    segmentdata = []
                for i in range(length):
                    segmentdata.append( chr(int(l[9+2*i:11+2*i],16)) )
                currentAddr = length + currentAddr
            elif type in (0x01, 0x02, 0x03, 0x04, 0x05):
                pass
            else:
                sys.stderr.write("Ignored unknown field (type 0x%02x) in ihex file.\n" % type)
        if segmentdata:
            self.segments.append( Segment(startAddr, ''.join(segmentdata)) )

    def loadTIText(self, file):
        """load data from a (opened) file in TI-Text format"""
        startAddr   = 0
        segmentdata = []
        #Convert data for MSP430, TXT-File is parsed line by line
        for line in file:       #Read one line
            if not line: break #EOF
            l = line.strip()
            if l[0] == 'q': break
            elif l[0] == '@':        #if @ => new address => send frame and set new addr.
                #create a new segment
                if segmentdata:
                    self.segments.append( Segment(startAddr, ''.join(segmentdata)) )
                startAddr = int(l[1:],16)
                segmentdata = []
            else:
                for i in l.split():
                    try:
                        segmentdata.append(chr(int(i,16)))
                    except ValueError, e:
                        raise FileFormatError('File is no valid TI-Text (%s)' % e)
        if segmentdata:
            self.segments.append( Segment(startAddr, ''.join(segmentdata)) )

    def loadELF(self, file):
        """load data from a (opened) file in ELF object format.
        File must be seekable"""
        obj = elf.ELFObject()
        obj.fromFile(file)
        if obj.e_type != elf.ELFObject.ET_EXEC:
            raise Exception("No executable")
        for section in obj.getSections():
            if DEBUG:
                sys.stderr.write("ELF section %s at 0x%04x %d bytes\n" % (section.name, section.lma, len(section.data)))
            if len(section.data):
                self.segments.append( Segment(section.lma, section.data) )
        
    def loadFile(self, filename):
        """fill memory with the contents of a file. file type is determined from extension"""
        #first check extension
        try:
            if filename[-4:].lower() == '.txt':
                self.loadTIText(open(filename, "rb"))
                return
            elif filename[-4:].lower() in ('.a43', '.hex'):
                self.loadIHex(open(filename, "rb"))
                return
        except FileFormatError:
            pass #do contents based detection below
        #then do a contents based detection
        try:
            self.loadELF(open(filename, "rb"))
        except elf.ELFException:
            try:
                self.loadIHex(open(filename, "rb"))
            except FileFormatError:
                try:
                    self.loadTIText(open(filename, "rb"))
                except FileFormatError:
                    raise FileFormatError('file could not be loaded (not ELF, Intel-Hex, or TI-Text)')

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    def saveIHex(self, filelike):
        """write a string containing intel hex to given file object"""
        noeof=0
        for seg in self.segments:
            address = seg.startaddress
            data    = seg.data
            start = 0
            while start<len(data):
                end = start + 16
                if end > len(data): end = len(data)
                filelike.write(self._ihexline(address, data[start:end]))
                start += 16
                address += 16
        filelike.write(self._ihexline(0, [], end=1))   #append no data but an end line
    
    def _ihexline(self, address, buffer, end=0):
        """internal use: generate a line with intel hex encoded data"""
        out = []
        if end:
            type = 1
        else:
            type = 0
        out.append( ':%02X%04X%02X' % (len(buffer),address&0xffff,type) )
        sum = len(buffer) + ((address>>8)&255) + (address&255) + (type&255)
        for b in [ord(x) for x in buffer]:
            out.append('%02X' % (b&255) )
            sum += b&255
        out.append('%02X\r\n' %( (-sum)&255))
        return ''.join(out)
    
    def saveTIText(self, filelike):
        """output TI-Text to given file object"""
        for segment in self.segments:
            filelike.write("@%04x\n" % segment.startaddress)
            for i in range(0, len(segment.data), 16):
                filelike.write("%s\n" % " ".join(["%02x" % ord(x) for x in segment.data[i:i+16]]))
        filelike.write("q\n")
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
    def getMemrange(self, fromadr, toadr):
        """get a range of bytes from the memory. unavailable values are filled with 0xff."""
        res = ''
        toadr = toadr + 1   #python indexes are excluding end, so include it
        while fromadr < toadr:
            for seg in self.segments:
                segend = seg.startaddress + len(seg.data)
                if seg.startaddress <= fromadr and fromadr < segend:
                    if toadr > segend:   #not all data in segment
                        catchlength = segend - fromadr
                    else:
                        catchlength = toadr - fromadr
                    res = res + seg.data[fromadr-seg.startaddress : fromadr-seg.startaddress+catchlength]
                    fromadr = fromadr + catchlength    #adjust start
                    if len(res) >= toadr-fromadr:
                        break   #return res
            else:   #undefined memory is filled with 0xff
                res = res + chr(255)
                fromadr = fromadr + 1 #adjust start
        return res

    def getMem(self, address, size):
        """get a range of bytes from the memory. a ValueError is raised if
           unavailable addresses are tried to read"""
        data = []
        for seg in self.segments:
            #~ print "0x%04x  " * 2 % (seg.startaddress, seg.startaddress + len(seg.data))
            if seg.startaddress <= address and seg.startaddress + len(seg.data) >= address:
                #segment contains data in the address range
                offset = address - seg.startaddress
                length = min(len(seg.data)-offset, size)
                data.append(seg.data[offset:offset+length])
                address += length
        value = ''.join(data)
        if len(value) != size:
            raise ValueError("could not collect the requested data")
        return value
    
    def setMem(self, address, contents):
        """write a range of bytes to the memory. a segment covering the address
           range to be written has to be existent. a ValueError is raised if not
           all data could be written (attention: a part of the data may have been
           written!)"""
        #~ print "%04x: %r" % (address, contents)
        for seg in self.segments:
            #~ print "0x%04x  " * 3 % (address, seg.startaddress, seg.startaddress + len(seg.data))
            if seg.startaddress <= address and seg.startaddress + len(seg.data) >= address:
                #segment contains data in the address range
                offset = address - seg.startaddress
                length = min(len(seg.data)-offset, len(contents))
                seg.data = seg.data[:offset] + contents[:length] + seg.data[offset+length:]
                contents = contents[length:]    #cut away what is used
                if not contents: return         #stop if done
                address += length
        raise ValueError("could not write all data")

--- NEW FILE: util.py ---
# $Id: util.py,v 1.1 2006/04/11 18:35:23 cliechti Exp $

import sys

#for the use with memread
def hexdump( (adr, memstr), output=sys.stdout ):
    """Print a hex dump of data collected with memread
    arg1: tuple with adress, memory
    return None"""
    count = 0
    ascii = ''
    for value in map(ord, memstr):
        if not count: output.write("%04x:  " % adr)
        output.write("%02x " % value)
        ascii += (32 <= value < 128) and chr(value) or '.'
        count += 1
        adr += 1
        if count == 16:
            count = 0
            output.write("   %s\n" % ascii)
            ascii = ''
    if count < 16: output.write("%s   %s\n" % ("   "*(16-count), ascii))

def makeihex((address, data), eof=1, output=sys.stdout):
    """work though the data and output lines in inzel hex format.
    and end tag is appended"""
    start = 0
    while start<len(data):
        end = start + 16
        if end > len(data): end = len(data)
        _ihexline(address, [ord(x) for x in data[start:end]], output=output)
        start += 16
        address += 16
    if eof:
        _ihexline(address, [], type=1, output=output)   #append no data but an end line

def _ihexline(address, buffer, type=0, output=sys.stdout):
    """encode one line, output with checksum"""
    output.write( ':%02X%04X%02X' % (len(buffer), address & 0xffff, type) )
    sum = len(buffer) + ((address >> 8) & 255) + (address & 255) + (type&255)
    for b in buffer:
        if b == None: b = 0         #substitute nonexistent values with zero
        output.write('%02X' % (b & 255))
        sum += b & 255
    output.write('%02X\n' %( (-sum) & 255))

#add some arguments to a function, but don't call it yet, instead return
#a wrapper object for later invocation
class curry:
    """create a callable with some arguments specified in advance"""
    def __init__(self, fun, *args, **kwargs):
        self.fun = fun
        self.pending = args[:]
        self.kwargs = kwargs.copy()

    def __call__(self, *args, **kwargs):
        if kwargs and self.kwargs:
            kw = self.kwargs.copy()
            kw.update(kwargs)
        else:
            kw = kwargs or self.kwargs
        return apply(self.fun, self.pending + args, kw)

    def __repr__(self):
        #first try if it a function
        try:
            return "curry(%s, %r, %r)" % (self.fun.func_name, self.pending, self.kwargs)
        except AttributeError:
            #fallback for callable classes
            return "curry(%s, %r, %r)" % (self.fun, self.pending, self.kwargs)

if __name__ == '__main__':
    hexdump((0x1000, '0123456789ABCDEF'*3))
    hexdump((0x1000, 'abcdefg'))



-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.