📄 tos-bsl.in
字号:
def bslTxRx(self, cmd, addr, length = 0, blkout = None, wait=0):
"""Transmits a command (cmd) with its parameters:
start-address (addr), length (len) and additional
data (blkout) to boot loader.
wait specified if the bsl sync should be tried once or
repeated, forever
Parameters return by boot loader are passed via blkin.
"""
if DEBUG > 1: sys.stderr.write("* bslTxRx()\n")
if cmd == self.BSL_TXBLK:
#Align to even start address
if (addr % 2) != 0:
addr = addr - 1 #Decrement address and
blkout = chr(0xFF) + blkOut #fill first byte of blkout with 0xFF
length = length + 1
#Make sure that len is even
if (length % 2) != 0:
blkout = blkout + chr(0xFF) #Inc. len and fill last byte of blkout with 0xFF
length = length + 1
elif cmd == self.BSL_RXBLK:
#Align to even start address
if (addr % 2) != 0:
addr = addr - 1 #Decrement address but
length = length + 1 #request an additional byte
#Make sure that len is even
if (length % 2) != 0:
length = length + 1
#if cmd == self.BSL_TXBLK or cmd == self.BSL_TXPWORD:
# length = len + 4
#Add necessary information data to frame
dataOut = struct.pack("<HH", addr, length)
if blkout: #Copy data out of blkout into frame
dataOut = dataOut + blkout
self.bslSync(wait) #synchronize BSL
rxFrame = self.comTxRx(cmd, dataOut, len(dataOut)) #Send frame
if rxFrame: #test answer
return rxFrame[4:] #return only data w/o [hdr,null,len,len]
else:
return rxFrame
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 l[0] != ':': raise BSLException("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, string.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, string.join(segmentdata,'')) )
def loadTIText(self, file):
"""load data from a (opened) file in TI-Text format"""
next = 1
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, string.join(segmentdata,'')) )
startAddr = int(l[1:],16)
segmentdata = []
else:
for i in string.split(l):
segmentdata.append(chr(int(i,16)))
if segmentdata:
self.segments.append( Segment(startAddr, string.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:
#print "fromto: %04x %04x" % (fromadr, toadr)
for seg in self.segments:
#print seg
segend = seg.startaddress + len(seg.data)
if seg.startaddress <= fromadr and fromadr < segend:
#print "startok 0x%04x %d" % (seg.startaddress, len(seg.data))
#print ("0x%04x "*3) % (segend, fromadr, toadr)
if toadr > segend: #not all data in segment
#print "out of segment"
catchlength = segend-fromadr
else:
catchlength = toadr-fromadr
#print toadr-fromadr
#print catchlength
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:
res = res + chr(255)
fromadr = fromadr + 1 #adjust start
#print "fill FF"
#print "res: %r" % res
return res
class BootStrapLoader(LowLevel):
"""higher level Bootstrap Loader functions."""
ERR_VERIFY_FAILED = "Error: verification failed"
ERR_ERASE_CHECK_FAILED = "Error: erase check failed"
ACTION_PROGRAM = 0x01 #Mask: program data
ACTION_VERIFY = 0x02 #Mask: verify data
ACTION_ERASE_CHECK = 0x04 #Mask: erase check
#Max. bytes sent within one frame if parsing a TI TXT file.
#( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
MAXDATA = 240-16
def __init__(self, *args, **kargs):
LowLevel.__init__(self, *args, **kargs)
self.byteCtr = 0
self.meraseCycles = 1
self.patchRequired = 0
self.patchLoaded = 0
self.bslVer = 0
self.passwd = None
self.data = None
self.maxData = self.MAXDATA
self.cpu = None
def preparePatch(self):
"""prepare to download patch"""
if DEBUG > 1: sys.stderr.write("* preparePatch()\n")
if self.patchLoaded:
#Load PC with 0x0220.
#This will invoke the patched bootstrap loader subroutines.
self.bslTxRx(self.BSL_LOADPC, #Command: Load PC
0x0220) #Address to load into PC
self.BSLMemAccessWarning = 0 #Error is removed within workaround code
return
def postPatch(self):
"""setup after the patch is loaded"""
if DEBUG > 1: sys.stderr.write("* postPatch()\n")
if self.patchLoaded:
self.BSLMemAccessWarning = 1 #Turn warning back on.
def verifyBlk(self, addr, blkout, action):
"""verify memory against data or 0xff"""
if DEBUG > 1: sys.stderr.write("* verifyBlk()\n")
if action & self.ACTION_VERIFY or action & self.ACTION_ERASE_CHECK:
if DEBUG: sys.stderr.write(" Check starting at 0x%04x, %d bytes ... \n" % (addr, len(blkout)))
self.preparePatch()
blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
self.postPatch()
for i in range(len(blkout)):
if action & self.ACTION_VERIFY:
#Compare data in blkout and blkin
if blkin[i] != blkout[i]:
sys.stderr.write("Verification failed at 0x%04x (0x%02x, 0x%02x)\n" % (addr+i, ord(blkin[i]), ord(blkout[i])))
sys.stderr.flush()
raise BSLException(self.ERR_VERIFY_FAILED) #Verify failed!
continue
elif action & self.ACTION_ERASE_CHECK:
#Compare data in blkin with erase pattern
if blkin[i] != chr(0xff):
sys.stderr.write("Erase Check failed at 0x%04x (0x%02x)\n" % (addr+i, ord(blkin[i])))
sys.stderr.flush()
raise BSLException(self.ERR_ERASE_CHECK_FAILED) #Erase Check failed!
continue
def programBlk(self, addr, blkout, action):
"""programm a memory block"""
if DEBUG > 1: sys.stderr.write("* programBlk()\n")
#Check, if specified range is erased
self.verifyBlk(addr, blkout, action & self.ACTION_ERASE_CHECK)
if action & self.ACTION_PROGRAM:
if DEBUG: sys.stderr.write(" Program starting at 0x%04x, %i bytes ...\n" % (addr, len(blkout)))
self.preparePatch()
#Program block
self.bslTxRx(self.BSL_TXBLK, addr, len(blkout), blkout)
self.postPatch()
#Verify block
self.verifyBlk(addr, blkout, action & self.ACTION_VERIFY)
#segments:
#list of tuples or lists:
#segements = [ (addr1, [d0,d1,d2,...]), (addr2, [e0,e1,e2,...])]
def programData(self, segments, action):
"""programm or verify data"""
if DEBUG > 1: sys.stderr.write("* programData()\n")
for seg in segments:
currentAddr = seg.startaddress
pstart = 0
while pstart<len(seg.data):
length = self.MAXDATA
if pstart+length > len(seg.data):
length = len(seg.data) - pstart
self.programBlk(currentAddr, seg.data[pstart:pstart+length], action)
pstart = pstart + length
currentAddr = currentAddr + length
self.byteCtr = self.byteCtr + length #total sum
def uploadData(self, startaddress, size, wait=0):
"""upload a datablock"""
if DEBUG > 1: sys.stderr.write("* uploadData()\n")
data = ''
pstart = 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -