📄 jtag.py
字号:
#!/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 sysimport _parjtagVERSION = "1.3"DEBUG = 0 #disable debug messages by default#frame specific constsERASE_MASS = 2ERASE_MAIN = 1ERASE_SGMT = 0#statesFREERUNNING = 0STOPPED = 1#Configurations of the MSP430 driverVERIFICATION_MODE = 0 #Verify data downloaded to FLASH memories.RAMSIZE_OPTION = 1 #Change RAM used to download and program flash blocksDEBUG_OPTION = 2 #Set debug level. Enables debug outputs.#enumeration of output formats for uploadsHEX = 0INTELHEX = 1BINARY = 2#exceptionsclass JTAGException(Exception): pass#for the use with memreaddef 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), " ", asciidef 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 linedef _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 resclass 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"""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -