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