Import of the contiki-2.x development code from the SICS internal CVS server
This commit is contained in:
parent
c2ae514a13
commit
05f6bb5feb
18
cpu/msp430/buildscripts/Makefile.unix
Normal file
18
cpu/msp430/buildscripts/Makefile.unix
Normal file
|
@ -0,0 +1,18 @@
|
|||
ifndef JTAG
|
||||
JTAG := $(CONTIKI_CPU)/buildscripts/jtag/pyjtag/jtag.py
|
||||
endif
|
||||
|
||||
ifndef JTAG_PORT
|
||||
JTAG_PORT = /dev/ppi0
|
||||
endif
|
||||
|
||||
%.u: %.$(TARGET)
|
||||
$(JTAG) -l $(JTAG_PORT) -e
|
||||
$(JTAG) -l $(JTAG_PORT) -D -D -S -R 2048 -p $^
|
||||
$(JTAG) -l $(JTAG_PORT) -D -r
|
||||
|
||||
r:
|
||||
$(JTAG) -l $(JTAG_PORT) -r
|
||||
|
||||
erase:
|
||||
$(JTAG) -l $(JTAG_PORT) -e
|
7
cpu/msp430/buildscripts/Makefile.win
Normal file
7
cpu/msp430/buildscripts/Makefile.win
Normal file
|
@ -0,0 +1,7 @@
|
|||
%.u: %.ihex
|
||||
msp430-jtag -eI $^
|
||||
|
||||
#CW=cw23
|
||||
|
||||
#%.u: %.ihex
|
||||
# $(CW) -d f430p $^
|
BIN
cpu/msp430/buildscripts/jtag/pyjtag/_parjtag.so
Executable file
BIN
cpu/msp430/buildscripts/jtag/pyjtag/_parjtag.so
Executable file
Binary file not shown.
318
cpu/msp430/buildscripts/jtag/pyjtag/elf.py
Normal file
318
cpu/msp430/buildscripts/jtag/pyjtag/elf.py
Normal file
|
@ -0,0 +1,318 @@
|
|||
#!/usr/bin/env python
|
||||
import struct
|
||||
|
||||
# ELF object file reader
|
||||
# (C) 2003 cliechti@gmx.net
|
||||
# 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 = 0xf0000000
|
||||
|
||||
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
|
49
cpu/msp430/buildscripts/jtag/pyjtag/gen-ihex.py
Normal file
49
cpu/msp430/buildscripts/jtag/pyjtag/gen-ihex.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python
|
||||
"""Test File generator.
|
||||
This tool generates a hex file, of given size, ending on address
|
||||
0xffff.
|
||||
|
||||
USAGE: hen-ihex.py size_in_kilobyte
|
||||
|
||||
The resulting Intel-hex file is output to stdout, use redirection
|
||||
to save the data to a file.
|
||||
"""
|
||||
|
||||
#return a string with data in intel hex format
|
||||
def makeihex(address, data):
|
||||
out = []
|
||||
start = 0
|
||||
while start<len(data):
|
||||
end = start + 16
|
||||
if end > len(data): end = len(data)
|
||||
out.append(_ihexline(address, [ord(x) for x in data[start:end]]))
|
||||
start += 16
|
||||
address += 16
|
||||
out.append(_ihexline(address, [], end=1)) #append no data but an end line
|
||||
return ''.join(out)
|
||||
|
||||
def _ihexline(address, buffer, end=0):
|
||||
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)
|
||||
for b in buffer:
|
||||
if b == None: b = 0 #substitute nonexistent values with zero
|
||||
out.append('%02X' % (b&255) )
|
||||
sum += b&255
|
||||
out.append('%02X\n' %( (-sum)&255))
|
||||
return ''.join(out)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import struct, sys
|
||||
if len(sys.argv) != 2:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
size = int(sys.argv[1]) #in kilo
|
||||
startadr = 0x10000 - 1024*size
|
||||
data = ''.join([struct.pack(">H", x) for x in range(startadr, startadr+ 1024*size, 2)])
|
||||
print makeihex(startadr, data)
|
108
cpu/msp430/buildscripts/jtag/pyjtag/install-pyjtag.nsi
Normal file
108
cpu/msp430/buildscripts/jtag/pyjtag/install-pyjtag.nsi
Normal file
|
@ -0,0 +1,108 @@
|
|||
Name "install-pyjtag"
|
||||
OutFile "install-pyjtag.exe"
|
||||
|
||||
!define SF_SELECTED 1
|
||||
!define SF_SUBSEC 2
|
||||
!define SF_SUBSECEND 4
|
||||
!define SF_BOLD 8
|
||||
!define SF_RO 16
|
||||
!define SF_EXPAND 32
|
||||
|
||||
!define SECTION_OFF 0xFFFFFFFE
|
||||
|
||||
LicenseText License
|
||||
LicenseData license.txt
|
||||
|
||||
SetOverwrite on
|
||||
SetDateSave on
|
||||
|
||||
; The default installation directory
|
||||
InstallDir $PROGRAMFILES\mspgcc
|
||||
; Registry key to check for directory (so if you install again, it will
|
||||
; overwrite the old one automatically)
|
||||
InstallDirRegKey HKLM SOFTWARE\mspgcc "rootdir"
|
||||
|
||||
; The text to prompt the user to enter a directory
|
||||
DirText "This will install the pyjtag executables. You can choose the same \
|
||||
directory as for the other mspgcc tools."
|
||||
|
||||
; The text to prompt the user to enter a directory
|
||||
ComponentText "Select which optional things you want installed."
|
||||
|
||||
Section "msp430-jtag (required)"
|
||||
SectionIn RO
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
File /r bin
|
||||
File /oname=license-pyjtag.txt license.txt
|
||||
File /oname=readme-pyjtag.txt readme.txt
|
||||
File /oname=bin\jtag.py jtag.py
|
||||
|
||||
; Write the installation path into the registry
|
||||
WriteRegStr HKLM SOFTWARE\mspgcc "rootdir" "$INSTDIR"
|
||||
; Write the uninstall keys for Windows
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\mspgcc-pyjtag" "DisplayName" "mspgcc pyjtag (remove only)"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\mspgcc-pyjtag" "UninstallString" '"$INSTDIR\uninstall-pyjtag.exe"'
|
||||
WriteUninstaller "uninstall-pyjtag.exe"
|
||||
SectionEnd
|
||||
|
||||
Section "giveio (needed on Win NT/2k/XP, but NOT on 9x/ME)"
|
||||
SetOutPath $INSTDIR\bin
|
||||
File ..\jtag\hardware_access\giveio\giveio.sys
|
||||
File ..\jtag\hardware_access\giveio\loaddrv.exe
|
||||
SetOutPath $INSTDIR
|
||||
nsExec::ExecToLog '$INSTDIR\bin\loaddrv.exe install giveio $INSTDIR\bin\giveio.sys'
|
||||
Pop $0 ;return value/error/timeout
|
||||
IntCmp $0 2 ext_here ;assume its alredy installed
|
||||
IntCmp $0 0 0 ext_err ext_err ;if not 0 -> error
|
||||
nsExec::ExecToLog '$INSTDIR\bin\loaddrv.exe start giveio'
|
||||
Pop $0 ;return value/error/timeout
|
||||
IntCmp $0 0 0 ext_err ext_err ;if not 0 -> error
|
||||
nsExec::ExecToLog '$INSTDIR\bin\loaddrv.exe starttype giveio auto'
|
||||
Pop $0 ;return value/error/timeout
|
||||
IntCmp $0 0 0 ext_err ext_err ;if not 0 -> error
|
||||
WriteRegStr HKLM SOFTWARE\mspgcc "giveio" "started"
|
||||
Goto ext_ok
|
||||
ext_err:
|
||||
DetailPrint "Error while installing and starting giveio"
|
||||
MessageBox MB_OK|MB_ICONSTOP "Error while installing and starting giveio"
|
||||
Goto ext_ok
|
||||
ext_here:
|
||||
DetailPrint "Installing giveio gave an error, assuming its already installed"
|
||||
ext_ok:
|
||||
SectionEnd
|
||||
|
||||
; special uninstall section.
|
||||
Section "Uninstall"
|
||||
; remove registry keys
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\mspgcc-pyjtag"
|
||||
DeleteRegKey HKLM SOFTWARE\NSIS_Example2
|
||||
; remove files
|
||||
Delete $INSTDIR\bin\msp430-jtag.exe
|
||||
Delete $INSTDIR\bin\_parjtag.pyd
|
||||
Delete $INSTDIR\bin\jtag.py
|
||||
Delete $INSTDIR\bin\HIL.dll
|
||||
Delete $INSTDIR\bin\MSP430mspgcc.dll
|
||||
;XXX python22.dll is left installed as it is used by pybsl and other tools
|
||||
Delete $INSTDIR\license-pyjtag.txt
|
||||
Delete $INSTDIR\readme-pyjtag.txt
|
||||
; giveio
|
||||
; if it was started by us, stop it
|
||||
ReadRegStr $0 HKLM SOFTWARE\mspgcc "giveio"
|
||||
StrCmp $0 '' no_giveio
|
||||
nsExec::ExecToLog '$INSTDIR\bin\loaddrv.exe stop giveio'
|
||||
Pop $0 ;return value/error/timeout
|
||||
IntCmp $0 0 0 giveio_err giveio_err ;if not 0 -> error
|
||||
nsExec::ExecToLog '$INSTDIR\bin\loaddrv.exe remove giveio'
|
||||
Pop $0 ;return value/error/timeout
|
||||
IntCmp $0 0 0 giveio_err giveio_err ;if not 0 -> error
|
||||
Goto no_giveio
|
||||
giveio_err:
|
||||
DetailPrint "Error while uninstalling giveio service"
|
||||
MessageBox MB_OK|MB_ICONSTOP "Error while uninstalling giveio service"
|
||||
no_giveio:
|
||||
Delete loaddrv.exe
|
||||
Delete giveio.sys
|
||||
; MUST REMOVE UNINSTALLER, too
|
||||
Delete $INSTDIR\uninstall-pyjtag.exe
|
||||
SectionEnd
|
604
cpu/msp430/buildscripts/jtag/pyjtag/jtag.py
Executable file
604
cpu/msp430/buildscripts/jtag/pyjtag/jtag.py
Executable file
|
@ -0,0 +1,604 @@
|
|||
#!/usr/bin/env python
|
||||
#Parallel JTAG programmer for the MSP430 embedded proccessor.
|
||||
#
|
||||
#(C) 2002 Chris Liechti <cliechti@gmx.net>
|
||||
#this is distributed under a free software license, see license.txt
|
||||
#
|
||||
#Requires Python 2+ and the binary extension _parjtag.
|
||||
|
||||
import sys
|
||||
import _parjtag
|
||||
|
||||
VERSION = "1.3"
|
||||
|
||||
DEBUG = 0 #disable debug messages by default
|
||||
|
||||
|
||||
#frame specific consts
|
||||
ERASE_MASS = 2
|
||||
ERASE_MAIN = 1
|
||||
ERASE_SGMT = 0
|
||||
|
||||
#states
|
||||
FREERUNNING = 0
|
||||
STOPPED = 1
|
||||
|
||||
#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.
|
||||
|
||||
#enumeration of output formats for uploads
|
||||
HEX = 0
|
||||
INTELHEX = 1
|
||||
BINARY = 2
|
||||
|
||||
#exceptions
|
||||
class JTAGException(Exception): pass
|
||||
|
||||
#for the use with memread
|
||||
def hexdump( (adr, memstr) ):
|
||||
"""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: print "%04x: " % adr,
|
||||
print "%02x" % value,
|
||||
ascii += (32 <= value < 128) and chr(value) or '.'
|
||||
count += 1
|
||||
adr += 1
|
||||
if count == 16:
|
||||
count = 0
|
||||
print " ", ascii
|
||||
ascii = ''
|
||||
if count < 16: print " "*(16-count), " ", ascii
|
||||
|
||||
def makeihex( (address, data) ):
|
||||
"""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]])
|
||||
start += 16
|
||||
address += 16
|
||||
_ihexline(address, [], type=1) #append no data but an end line
|
||||
|
||||
def _ihexline(address, buffer, type=0):
|
||||
"""encode one line, output with checksum"""
|
||||
sys.stdout.write( ':%02X%04X%02X' % (len(buffer), address & 0xffff, type) )
|
||||
sum = len(buffer) + ((address >> 8) & 255) + (address & 255)
|
||||
for b in buffer:
|
||||
if b == None: b = 0 #substitute nonexistent values with zero
|
||||
sys.stdout.write('%02X' % (b & 255))
|
||||
sum += b&255
|
||||
sys.stdout.write('%02X\n' %( (-sum) & 255))
|
||||
|
||||
|
||||
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 Exception("File Format Error\n")
|
||||
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 == 0x01:
|
||||
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"""
|
||||
next = 1
|
||||
currentAddr = 0
|
||||
startAddr = 0
|
||||
segmentdata = []
|
||||
#Convert data for MSP430, TXT-File is parsed line by line
|
||||
while next >= 1:
|
||||
#Read one line
|
||||
l = file.readline()
|
||||
if not l: break #EOF
|
||||
l = l.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 = currentAddr = int(l[1:],16)
|
||||
segmentdata = []
|
||||
else:
|
||||
for i in l.split():
|
||||
segmentdata.append(chr(int(i,16)))
|
||||
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"""
|
||||
import elf
|
||||
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"""
|
||||
#TODO: do a contents based detection
|
||||
if filename[-4:].lower() == '.txt':
|
||||
self.loadTIText(open(filename, "rb"))
|
||||
elif filename[-4:].lower() in ('.a43', '.hex'):
|
||||
self.loadIHex(open(filename, "rb"))
|
||||
else:
|
||||
self.loadELF(open(filename, "rb"))
|
||||
|
||||
def getMemrange(self, fromadr, toadr):
|
||||
"""get a range of bytes from the memory. unavailable values are filled with 0xff."""
|
||||
res = ''
|
||||
toadr = toadr + 1 #python indxes 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
|
||||
|
||||
class JTAG:
|
||||
"""wrap the _parjtag extension"""
|
||||
|
||||
def __init__(self):
|
||||
self.showprogess = 0
|
||||
|
||||
def connect(self, lpt=None):
|
||||
"""connect to specified or default port"""
|
||||
if lpt is None:
|
||||
_parjtag.connect()
|
||||
else:
|
||||
_parjtag.connect(lpt)
|
||||
|
||||
def close(self):
|
||||
"""release JTAG"""
|
||||
_parjtag.release()
|
||||
|
||||
def uploadData(self, startaddress, size):
|
||||
"""upload a datablock"""
|
||||
if DEBUG > 1: sys.stderr.write("* uploadData()\n")
|
||||
return _parjtag.memread(startaddress, size)
|
||||
|
||||
def actionMassErase(self):
|
||||
"""Erase the flash memory completely (with mass erase command)"""
|
||||
sys.stderr.write("Mass Erase...\n")
|
||||
_parjtag.memerase(ERASE_MASS)
|
||||
|
||||
def actionMainErase(self):
|
||||
"""Erase the MAIN flash memory, leave the INFO mem"""
|
||||
sys.stderr.write("Erase Main Flash...\n")
|
||||
_parjtag.memerase(ERASE_MAIN, 0xfffe)
|
||||
|
||||
def makeActionSegmentErase(self, address):
|
||||
"""Selective segment erase"""
|
||||
class SegmentEraser:
|
||||
def __init__(self, segaddr):
|
||||
self.address = segaddr
|
||||
def __call__(self):
|
||||
sys.stderr.write("Erase Segment @ 0x%04x...\n" % self.address)
|
||||
_parjtag.memerase(ERASE_SGMT, self.address)
|
||||
return SegmentEraser(address)
|
||||
|
||||
def actionEraseCheck(self):
|
||||
"""check the erasure of required flash cells."""
|
||||
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):
|
||||
sys.stderr.write("\r%d%%" % (100*count/total))
|
||||
|
||||
def actionProgram(self):
|
||||
"""program data into flash memory."""
|
||||
if self.data is not None:
|
||||
sys.stderr.write("Program ...\n")
|
||||
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.showprogess:
|
||||
sys.stderr.write("\r")
|
||||
sys.stderr.write("%i bytes programmed.\n" % bytes)
|
||||
else:
|
||||
raise JTAGException("programming without data not possible")
|
||||
|
||||
def actionVerify(self):
|
||||
"""Verify programmed data"""
|
||||
if self.data is not None:
|
||||
sys.stderr.write("Verify ...\n")
|
||||
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 actionReset(self):
|
||||
"""perform a reset"""
|
||||
sys.stderr.write("Reset device ...\n")
|
||||
_parjtag.reset(0, 0)
|
||||
|
||||
def actionRun(self, address):
|
||||
"""start program at specified address"""
|
||||
raise NotImplementedError
|
||||
#sys.stderr.write("Load PC with 0x%04x ...\n" % address)
|
||||
|
||||
def funclet(self):
|
||||
"""download and start funclet"""
|
||||
sys.stderr.write("Download and execute of funclet...\n")
|
||||
if len(self.data) > 1:
|
||||
raise JTAGException("don't know how to handle multiple segments in funclets")
|
||||
_parjtag.funclet(self.data[0].data)
|
||||
sys.stderr.write("Funclet OK.\n")
|
||||
|
||||
def usage():
|
||||
"""print some help message"""
|
||||
sys.stderr.write("""
|
||||
USAGE: %s [options] [file]
|
||||
Version: %s
|
||||
|
||||
If "-" is specified as file the data is read from the stdinput.
|
||||
A file ending with ".txt" is considered to be in TIText format all
|
||||
other filenames are considered IntelHex.
|
||||
|
||||
General options:
|
||||
-h, --help Show this help screen.
|
||||
-l, --lpt=name Specify an other parallel port.
|
||||
(defaults to LPT1 (/dev/parport0 on unix)
|
||||
-D, --debug Increase level of debug messages. This won't be
|
||||
very useful for the average user...
|
||||
-I, --intelhex Force fileformat to IntelHex
|
||||
-T, --titext Force fileformat to be TIText
|
||||
-f, --funclet The given file is a funclet (a small program to
|
||||
be run in RAM)
|
||||
-R, --ramsize Specify the amont of RAM to be used to program
|
||||
flash (default 256).
|
||||
|
||||
Program Flow Specifiers:
|
||||
|
||||
-e, --masserase Mass Erase (clear all flash memory)
|
||||
-m, --mainerase Erase main flash memory only
|
||||
--eraseinfo Erase info flash memory only (0x1000-0x10ff)
|
||||
--erase=address Selectively erase segment at the specified address
|
||||
-E, --erasecheck Erase Check by file
|
||||
-p, --program Program file
|
||||
-v, --verify Verify by file
|
||||
|
||||
The order of the above options matters! The table is ordered by normal
|
||||
execution order. For the options "Epv" a file must be specified.
|
||||
Program flow specifiers default to "p" if a file is given.
|
||||
Don't forget to specify "e" or "eE" when programming flash!
|
||||
"p" already verifies the programmed data, "v" adds an additional
|
||||
verification though uploading the written data for a 1:1 compare.
|
||||
No default action is taken if "p" and/or "v" is given, say specifying
|
||||
only "v" does a check by file of a programmed device.
|
||||
|
||||
Data retreiving:
|
||||
-u, --upload=addr Upload a datablock (see also: -s).
|
||||
-s, --size=num Size of the data block do upload. (Default is 2)
|
||||
-x, --hex Show a hexadecimal display of the uploaded data.
|
||||
(Default)
|
||||
-b, --bin Get binary uploaded data. This can be used
|
||||
to redirect the output into a file.
|
||||
-i, --ihex Uploaded data is output in Intel HEX format.
|
||||
This can be used to clone a device.
|
||||
|
||||
Do before exit:
|
||||
-g, --go=address Start programm execution at specified address.
|
||||
This implies option "w" (wait)
|
||||
-r, --reset Reset connected MSP430. Starts application.
|
||||
This is a normal device reset and will start
|
||||
the programm that is specified in the reset
|
||||
interrupt vector. (see also -g)
|
||||
-w, --wait Wait for <ENTER> before closing parallel port.
|
||||
""" % (sys.argv[0], VERSION))
|
||||
|
||||
def main():
|
||||
global DEBUG
|
||||
import getopt
|
||||
filetype = None
|
||||
filename = None
|
||||
reset = 0
|
||||
wait = 0
|
||||
goaddr = None
|
||||
jtag = JTAG()
|
||||
toinit = []
|
||||
todo = []
|
||||
startaddr = None
|
||||
size = 2
|
||||
outputformat= HEX
|
||||
lpt = None
|
||||
funclet = None
|
||||
ramsize = None
|
||||
|
||||
sys.stderr.write("MSP430 parallel JTAG programmer Version: %s\n" % VERSION)
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:],
|
||||
"hl:weEmpvrg:Du:d:s:xbiITfR:S",
|
||||
["help", "lpt=", "wait"
|
||||
"masserase", "erasecheck", "mainerase", "program",
|
||||
"erase=", "eraseinfo",
|
||||
"verify", "reset", "go=", "debug",
|
||||
"upload=", "download=", "size=", "hex", "bin", "ihex",
|
||||
"intelhex", "titext", "funclet", "ramsize=", "progress"]
|
||||
)
|
||||
except getopt.GetoptError:
|
||||
# print help information and exit:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
for o, a in opts:
|
||||
if o in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif o in ("-l", "--lpt"):
|
||||
lpt = a
|
||||
elif o in ("-w", "--wait"):
|
||||
wait = 1
|
||||
elif o in ("-e", "--masserase"):
|
||||
toinit.append(jtag.actionMassErase) #Erase Flash
|
||||
elif o in ("-E", "--erasecheck"):
|
||||
toinit.append(jtag.actionEraseCheck) #Erase Check (by file)
|
||||
elif o in ("-m", "--mainerase"):
|
||||
toinit.append(jtag.actionMainErase) #Erase main Flash
|
||||
elif o == "--erase":
|
||||
try:
|
||||
seg = int(a, 0)
|
||||
toinit.append(jtag.makeActionSegmentErase(seg))
|
||||
except ValueError:
|
||||
sys.stderr.write("segment address must be a valid number in dec, hex or octal\n")
|
||||
sys.exit(2)
|
||||
elif o == "--eraseinfo":
|
||||
toinit.append(jtag.makeActionSegmentErase(0x1000))
|
||||
toinit.append(jtag.makeActionSegmentErase(0x1080))
|
||||
elif o in ("-p", "--program"):
|
||||
todo.append(jtag.actionProgram) #Program file
|
||||
elif o in ("-v", "--verify"):
|
||||
todo.append(jtag.actionVerify) #Verify file
|
||||
elif o in ("-r", "--reset"):
|
||||
reset = 1
|
||||
elif o in ("-g", "--go"):
|
||||
try:
|
||||
goaddr = int(a, 0) #try to convert decimal
|
||||
except ValueError:
|
||||
sys.stderr.write("upload address must be a valid number in dec, hex or octal\n")
|
||||
sys.exit(2)
|
||||
elif o in ("-D", "--debug"):
|
||||
DEBUG = DEBUG + 1
|
||||
elif o in ("-u", "--upload"):
|
||||
try:
|
||||
startaddr = int(a, 0) #try to convert number of any base
|
||||
except ValueError:
|
||||
sys.stderr.write("upload address must be a valid number in dec, hex or octal\n")
|
||||
sys.exit(2)
|
||||
elif o in ("-s", "--size"):
|
||||
try:
|
||||
size = int(a, 0)
|
||||
except ValueError:
|
||||
sys.stderr.write("upload address must be a valid number in dec, hex or octal\n")
|
||||
sys.exit(2)
|
||||
#outut formats
|
||||
elif o in ("-x", "--hex"):
|
||||
outputformat = HEX
|
||||
elif o in ("-b", "--bin"):
|
||||
outputformat = BINARY
|
||||
elif o in ("-i", "--ihex"):
|
||||
outputformat = INTELHEX
|
||||
#input formats
|
||||
elif o in ("-I", "--intelhex"):
|
||||
filetype = 0
|
||||
elif o in ("-T", "--titext"):
|
||||
filetype = 1
|
||||
#others
|
||||
elif o in ("-f", "--funclet"):
|
||||
funclet = 1
|
||||
elif o in ("-R", "--ramsize"):
|
||||
try:
|
||||
ramsize = int(a, 0)
|
||||
except ValueError:
|
||||
sys.stderr.write("ramsize must be a valid number in dec, hex or octal\n")
|
||||
sys.exit(2)
|
||||
elif o in ("-S", "--progress"):
|
||||
jtag.showprogess = 1
|
||||
|
||||
if len(args) == 0:
|
||||
sys.stderr.write("Use -h for help\n")
|
||||
elif len(args) == 1: #a filename is given
|
||||
if not funclet:
|
||||
if not todo: #if there are no actions yet
|
||||
todo.extend([ #add some useful actions...
|
||||
jtag.actionProgram,
|
||||
])
|
||||
filename = args[0]
|
||||
else: #number of args is wrong
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
if DEBUG: #debug infos
|
||||
sys.stderr.write("debug level set to %d\n" % DEBUG)
|
||||
_parjtag.configure(DEBUG_OPTION, DEBUG)
|
||||
sys.stderr.write("python version: %s\n" % sys.version)
|
||||
|
||||
|
||||
#sanity check of options
|
||||
if goaddr and reset:
|
||||
sys.stderr.write("Warning: option --reset ignored as --go is specified!\n")
|
||||
reset = 0
|
||||
|
||||
if startaddr and reset:
|
||||
sys.stderr.write("Warning: option --reset ignored as --upload is specified!\n")
|
||||
reset = 0
|
||||
|
||||
#prepare data to download
|
||||
jtag.data = Memory() #prepare downloaded data
|
||||
if filetype is not None: #if the filetype is given...
|
||||
if filename is None:
|
||||
raise ValueError("no filename but filetype specified")
|
||||
if filename == '-': #get data from stdin
|
||||
file = sys.stdin
|
||||
else:
|
||||
file = open(filename,"rb") #or from a file
|
||||
if filetype == 0: #select load function
|
||||
jtag.data.loadIHex(file) #intel hex
|
||||
elif filetype == 1:
|
||||
jtag.data.loadTIText(file) #TI's format
|
||||
else:
|
||||
raise ValueError("illegal filetype specified")
|
||||
else: #no filetype given...
|
||||
if filename == '-': #for stdin:
|
||||
jtag.data.loadIHex(sys.stdin) #assume intel hex
|
||||
elif filename:
|
||||
jtag.data.loadFile(filename) #autodetect otherwise
|
||||
|
||||
if DEBUG > 5: sys.stderr.write("File: %r\n" % filename)
|
||||
|
||||
try:
|
||||
jtag.connect(lpt) #try to open port
|
||||
except IOError:
|
||||
raise #do not handle here
|
||||
else: #continue if open was successful
|
||||
if ramsize is not None:
|
||||
_parjtag.configure(RAMSIZE_OPTION, ramsize)
|
||||
#initialization list
|
||||
if toinit: #erase and erase check
|
||||
if DEBUG: sys.stderr.write("Preparing device ...\n")
|
||||
for f in toinit: f()
|
||||
|
||||
#work list
|
||||
if todo:
|
||||
if DEBUG > 0: #debug
|
||||
#show a nice list of sheduled actions
|
||||
sys.stderr.write("TODO list:\n")
|
||||
for f in todo:
|
||||
try:
|
||||
sys.stderr.write(" %s\n" % f.func_name)
|
||||
except AttributeError:
|
||||
sys.stderr.write(" %r\n" % f)
|
||||
for f in todo: f() #work through todo list
|
||||
|
||||
if reset: #reset device first if desired
|
||||
jtag.actionReset()
|
||||
|
||||
if funclet is not None: #download and start funclet
|
||||
jtag.funclet()
|
||||
|
||||
if goaddr is not None: #start user programm at specified address
|
||||
jtag.actionRun(goaddr) #load PC and execute
|
||||
|
||||
#upload datablock and output
|
||||
if startaddr is not None:
|
||||
if goaddr: #if a program was started...
|
||||
raise NotImplementedError
|
||||
#TODO:
|
||||
#sys.stderr.write("Waiting to device for reconnect for upload: ")
|
||||
data = jtag.uploadData(startaddr, size) #upload data
|
||||
if outputformat == HEX: #depending on output format
|
||||
hexdump( (startaddr, data) ) #print a hex display
|
||||
elif outputformat == INTELHEX:
|
||||
makeihex( (startaddr, data) ) #ouput a intel-hex file
|
||||
else:
|
||||
sys.stdout.write(data) #binary output w/o newline!
|
||||
wait = 0 #wait makes no sense as after the upload the device is still stopped
|
||||
|
||||
if wait: #wait at the end if desired
|
||||
sys.stderr.write("Press <ENTER> ...\n") #display a prompt
|
||||
raw_input() #wait for newline
|
||||
|
||||
_parjtag.reset(1, 1) #reset and release target
|
||||
#~ jtag.actionReset()
|
||||
jtag.close() #Release communication port
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except SystemExit:
|
||||
raise #let pass exit() calls
|
||||
except KeyboardInterrupt:
|
||||
if DEBUG: raise #show full trace in debug mode
|
||||
sys.stderr.write("user abort.\n") #short messy in user mode
|
||||
sys.exit(1) #set errorlevel for script usage
|
||||
except Exception, msg: #every Exception is caught and displayed
|
||||
if DEBUG: raise #show full trace in debug mode
|
||||
sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
|
||||
sys.exit(1) #set errorlevel for script usage
|
62
cpu/msp430/buildscripts/jtag/pyjtag/license.txt
Normal file
62
cpu/msp430/buildscripts/jtag/pyjtag/license.txt
Normal file
|
@ -0,0 +1,62 @@
|
|||
Copyright (c) 2001-2002 Chris Liechti <cliechti@gmx.net>
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
This is the Python license. In short, you can use this product in
|
||||
commercial and non-commercial applications, modify it, redistribute it.
|
||||
A notification to the author when you use and/or modify it is welcome.
|
||||
|
||||
TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING THIS SOFTWARE
|
||||
============================================
|
||||
|
||||
LICENSE AGREEMENT
|
||||
-----------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the copyright holder of this
|
||||
product, and the Individual or Organization ("Licensee") accessing
|
||||
and otherwise using this product in source or binary form and its
|
||||
associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement,
|
||||
the copyright holder hereby grants Licensee a nonexclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test,
|
||||
perform and/or display publicly, prepare derivative works, distribute,
|
||||
and otherwise use this product alone or in any derivative version,
|
||||
provided, however, that copyright holders License Agreement and
|
||||
copyright holders notice of copyright are retained in this product
|
||||
alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates this product or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to this product.
|
||||
|
||||
4. The copyright holder is making this product available to Licensee
|
||||
on an "AS IS" basis. THE COPYRIGHT HOLDER MAKES NO REPRESENTATIONS
|
||||
OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT
|
||||
LIMITATION, THE COPYRIGHT HOLDER MAKES NO AND DISCLAIMS ANY
|
||||
REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
ANY PARTICULAR PURPOSE OR THAT THE USE OF THIS PRODUCT WILL
|
||||
NOT INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. THE COPYRIGHT HOLDER SHALL NOT BE LIABLE TO LICENSEE OR ANY
|
||||
OTHER USERS OF THIS PRODUCT FOR ANY INCIDENTAL, SPECIAL, OR
|
||||
CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING,
|
||||
DISTRIBUTING, OR OTHERWISE USING THIS PRODUCT, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a
|
||||
material breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between the
|
||||
copyright holder and Licensee. This License Agreement does not grant
|
||||
permission to use trademarks or trade names from the copyright holder
|
||||
in a trademark sense to endorse or promote products or services of
|
||||
Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using this product, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
33
cpu/msp430/buildscripts/jtag/pyjtag/makefile
Normal file
33
cpu/msp430/buildscripts/jtag/pyjtag/makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
|
||||
.PHONY: all FORCE clean windist
|
||||
|
||||
all: windist
|
||||
|
||||
#wrap py to exe and build windows installer
|
||||
windist:
|
||||
python setup.py py2exe
|
||||
rm -r bin
|
||||
mv dist/jtag/jtag.exe dist/msp430-jtag.exe
|
||||
mv dist/jtag/* dist/
|
||||
rmdir dist/jtag
|
||||
mv dist bin
|
||||
rm -r build
|
||||
|
||||
|
||||
#generate test files
|
||||
fill60k.a43:
|
||||
python gen-ihex.py 60 >$@
|
||||
fill48k.a43:
|
||||
python gen-ihex.py 48 >$@
|
||||
fill32k.a43:
|
||||
python gen-ihex.py 32 >$@
|
||||
fill16k.a43:
|
||||
python gen-ihex.py 16 >$@
|
||||
fill8k.a43:
|
||||
python gen-ihex.py 8 >$@
|
||||
fill4k.a43:
|
||||
python gen-ihex.py 4 >$@
|
||||
|
||||
#clean up the mess...
|
||||
clean:
|
||||
rm -r dist build bin
|
182
cpu/msp430/buildscripts/jtag/pyjtag/readme.txt
Normal file
182
cpu/msp430/buildscripts/jtag/pyjtag/readme.txt
Normal file
|
@ -0,0 +1,182 @@
|
|||
pyJTAG
|
||||
------
|
||||
|
||||
Software to talk to the parallel port JTAG PCB as seen with the FET kits.
|
||||
It is released under a free software license,
|
||||
see license.txt for more details.
|
||||
|
||||
(C) 2002-2003 Chris Liechti <cliechti@gmx.net>
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- understands TI-Text and Intel-hex
|
||||
- download to Flash and/or RAM, erase, verify
|
||||
- reset device
|
||||
- load addres into R0/PC and run
|
||||
- upload a memory block MSP->PC (output as binary data or hex dump)
|
||||
- written in Python, runs on Win32, Linux, BSD
|
||||
- use per command line, or in a Python script
|
||||
|
||||
Requirements
|
||||
------------
|
||||
- Linux, BSD, Un*x or Windows PC
|
||||
- Python 2.0 or newer, 2.2 recomeded
|
||||
- Parallel JTAG hardware with an MSP430 device connected
|
||||
|
||||
Installation
|
||||
------------
|
||||
Python installations are available from www.python.org. On Windows simply
|
||||
use the installer. The win32all package has an installer too. These
|
||||
installations should run fine with the deafults.
|
||||
|
||||
On Linux just Python is needed. On some distributions is Python 1.5.2
|
||||
installed per default. You may meed to change the first line in the script
|
||||
from "python" to "python2". Maybe Python 2.x is in a separate package that
|
||||
has to be installed. There are rpm and deb binary packages and a source
|
||||
tarball available through the Python homepage.
|
||||
|
||||
The pyjtag archive can simply be unpacked to a directory, Windows users
|
||||
can use WinZip or WinRar among others to extract the gzipped tar file.
|
||||
If you want to run it from everywhere the directory where the file jtag.py
|
||||
is, should be added to the PATH.
|
||||
Look at "~/.profile", "/etc/profile" on Linux, "autoexec.bat" on Win9x/ME,
|
||||
System Properties/Environment in Win2000/NT/XP.
|
||||
|
||||
_parjtag.so/dll from the jtag archive must be copied to the same directory as
|
||||
jtag.py. On Windows also MSP430mspgcc.dll and HIL.dll must be located in the
|
||||
same dir or somewhere in the PATH.
|
||||
|
||||
Short introduction
|
||||
------------------
|
||||
This software uses the JTAG hardware that comes with the FET kits. It is
|
||||
connected to the parallel port.
|
||||
|
||||
The program can be started by typing "python jtag.py" in a console. Often
|
||||
it works also with just "jtag.py" or "./jtag.py".
|
||||
|
||||
USAGE: jtag.py [options] [file]
|
||||
If "-" is specified as file the data is read from the stdinput.
|
||||
A file ending with ".txt" is considered to be in TIText format all
|
||||
other filenames are considered IntelHex.
|
||||
|
||||
General options:
|
||||
-h, --help Show this help screen.
|
||||
-l, --lpt=name Specify an other parallel port.
|
||||
(defaults to LPT1 (/dev/parport0 on unix)
|
||||
-D, --debug Increase level of debug messages. This won't be
|
||||
very useful for the average user...
|
||||
-I, --intelhex Force fileformat to IntelHex
|
||||
-T, --titext Force fileformat to be TIText
|
||||
-f, --funclet The given file is a funclet (a small program to
|
||||
be run in RAM)
|
||||
-R, --ramsize Specify the amont of RAM to be used to program
|
||||
flash (default 256).
|
||||
|
||||
Program Flow Specifiers:
|
||||
|
||||
-e, --masserase Mass Erase (clear all flash memory)
|
||||
-m, --mainerase Erase main flash memory only
|
||||
--eraseinfo Erase info flash memory only (0x1000-0x10ff)
|
||||
--erase=address Selectively erase segment at the specified address
|
||||
-E, --erasecheck Erase Check by file
|
||||
-p, --program Program file
|
||||
-v, --verify Verify by file
|
||||
|
||||
The order of the above options matters! The table is ordered by normal
|
||||
execution order. For the options "Epv" a file must be specified.
|
||||
Program flow specifiers default to "p" if a file is given.
|
||||
Don't forget to specify "e" or "eE" when programming flash!
|
||||
"p" already verifies the programmed data, "v" adds an additional
|
||||
verification though uploading the written data for a 1:1 compare.
|
||||
No default action is taken if "p" and/or "v" is given, say specifying
|
||||
only "v" does a check by file of a programmed device.
|
||||
|
||||
Data retreiving:
|
||||
-u, --upload=addr Upload a datablock (see also: -s).
|
||||
-s, --size=num Size of the data block do upload. (Default is 2)
|
||||
-x, --hex Show a hexadecimal display of the uploaded data.
|
||||
(Default)
|
||||
-b, --bin Get binary uploaded data. This can be used
|
||||
to redirect the output into a file.
|
||||
-i, --ihex Uploaded data is output in Intel HEX format.
|
||||
This can be used to clone a device.
|
||||
|
||||
Do before exit:
|
||||
-g, --go=address Start programm execution at specified address.
|
||||
This implies option "w" (wait)
|
||||
-r, --reset Reset connected MSP430. Starts application.
|
||||
This is a normal device reset and will start
|
||||
the programm that is specified in the reset
|
||||
interrupt vector. (see also -g)
|
||||
-w, --wait Wait for <ENTER> before closing parallel port.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
These examples assume that you have added the installation directory to
|
||||
the PATH. Type the full path to jtag.py otherwise and maybe use
|
||||
"python jtag.py". Depending on installation it may also appear under the
|
||||
name "msp430-jtag".
|
||||
|
||||
jtag.py -e
|
||||
Only erase flash.
|
||||
|
||||
jtag.py -eErw 6port.a43
|
||||
Erase flash, erase check, download an executable, run it (reset)
|
||||
and wait.
|
||||
|
||||
jtag.py -mS -R 2048 6port.a43
|
||||
Use ramsize option on a device with 2k RAM to speed up
|
||||
download. Of course any value from 128B up to the maximum
|
||||
a device has is allowed.
|
||||
The progress and mainerase options are also activated.
|
||||
Only erasing the main memory is useful to keep calibration
|
||||
data in the information memory.
|
||||
|
||||
jtag.py 6port.a43
|
||||
Download of an executable to en empty (new or erased) device.
|
||||
(Note that in new devices some of the first bytes in the
|
||||
information memory are random data. If data should be
|
||||
downloaded there, specify -eE.)
|
||||
|
||||
jtag.py --go=0x220 ramtest.a43
|
||||
Download a program into RAM and run it, may not work
|
||||
with all devices.
|
||||
|
||||
jtag.py -f blinking.a43
|
||||
Download a program into RAM and run it. It must be
|
||||
a special format with "startadr", "entrypoint",
|
||||
"exitpoint" as the first three words in the data
|
||||
and it must end on "jmp $". See MSP430debug sources
|
||||
for more info.
|
||||
|
||||
jtag.py -u 0x0c00 -s 1024
|
||||
Get a memory dump in HEX, from the bootstrap loader.
|
||||
or save the binary in a file:
|
||||
"python jtag.py -u 0x0c00 -s 1024 -b >dump.bin"
|
||||
or as an intel-hex file:
|
||||
"python jtag.py -u 0x0c00 -s 1024 -i >dump.a43"
|
||||
|
||||
jtag.py -r
|
||||
Just start the user program (with a reset).
|
||||
|
||||
cat 6port.a43|jtag.py -e -
|
||||
Pipe the data from "cat" to jtag.py to erase and program the
|
||||
flash. (un*x example, don't forget the dash at the end of the
|
||||
line)
|
||||
|
||||
History
|
||||
-------
|
||||
1.0 public release
|
||||
1.1 fix of verify error
|
||||
1.2 use the verification during programming
|
||||
1.3 meinerase, progress options, ihex output
|
||||
|
||||
References
|
||||
----------
|
||||
- Python: http://www.python.org
|
||||
|
||||
- Texas Instruments MSP430 Homepage, links to Datasheets and Application
|
||||
Notes: http://www.ti.com/sc/msp430
|
||||
|
9
cpu/msp430/buildscripts/jtag/pyjtag/setup.py
Normal file
9
cpu/msp430/buildscripts/jtag/pyjtag/setup.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
# setup.py
|
||||
from distutils.core import setup
|
||||
import glob
|
||||
import py2exe
|
||||
|
||||
setup(
|
||||
name="msp430-jtag",
|
||||
scripts=["jtag.py"],
|
||||
)
|
Loading…
Reference in a new issue