From a76977af62010a392c16010c367185e61e856ffe Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 30 Oct 2019 20:04:56 +0100 Subject: mv to docs --- j1demo/firmware/intelhex.py | 643 -------------------------------------------- 1 file changed, 643 deletions(-) delete mode 100644 j1demo/firmware/intelhex.py (limited to 'j1demo/firmware/intelhex.py') diff --git a/j1demo/firmware/intelhex.py b/j1demo/firmware/intelhex.py deleted file mode 100644 index ecf8b28..0000000 --- a/j1demo/firmware/intelhex.py +++ /dev/null @@ -1,643 +0,0 @@ -#!/usr/bin/python - -# Copyright (c) 2005-2007, Alexander Belchenko -# All rights reserved. -# -# Redistribution and use in source and binary forms, -# with or without modification, are permitted provided -# that the following conditions are met: -# -# * Redistributions of source code must retain -# the above copyright notice, this list of conditions -# and the following disclaimer. -# * Redistributions in binary form must reproduce -# the above copyright notice, this list of conditions -# and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the -# nor the names of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -'''Intel HEX file format reader and converter. - -This script also may be used as hex2bin convertor utility. - -@author Alexander Belchenko (bialix AT ukr net) -@version 0.8.6 -@date 2007/04/26 -''' - - -__docformat__ = "javadoc" - - -from array import array -from binascii import hexlify, unhexlify - - -class IntelHex: - ''' Intel HEX file reader. ''' - - def __init__(self, fname): - ''' Constructor. - @param fname file name of HEX file or file object. - ''' - #public members - self.Error = None - self.AddrOverlap = None - self.padding = 0x0FF - # Start Address - self.start_addr = None - - # private members - self._fname = fname - self._buf = {} - self._readed = False - self._eof = False - self._offset = 0 - - def readfile(self): - ''' Read file into internal buffer. - @return True if successful. - ''' - if self._readed: - return True - - if not hasattr(self._fname, "read"): - f = file(self._fname, "rU") - fclose = f.close - else: - f = self._fname - fclose = None - - self._offset = 0 - self._eof = False - - result = True - - for s in f: - if not self.decode_record(s): - result = False - break - - if self._eof: - break - - if fclose: - fclose() - - self._readed = result - return result - - def decode_record(self, s): - ''' Decode one record of HEX file. - @param s line with HEX record. - @return True if line decode OK, or this is not HEX line. - False if this is invalid HEX line or checksum error. - ''' - s = s.rstrip('\r\n') - if not s: - return True # empty line - - if s[0] == ':': - try: - bin = array('B', unhexlify(s[1:])) - except TypeError: - # this might be raised by unhexlify when odd hexascii digits - self.Error = "Odd hexascii digits" - return False - length = len(bin) - if length < 5: - self.Error = "Too short line" - return False - else: - return True # first char must be ':' - - record_length = bin[0] - - if length != (5 + record_length): - self.Error = "Invalid line length" - return False - - addr = bin[1]*256 + bin[2] - - record_type = bin[3] - if not (0 <= record_type <= 5): - self.Error = "Invalid type of record: %d" % record_type - return False - - crc = sum(bin) - crc &= 0x0FF - if crc != 0: - self.Error = "Invalid crc" - return False - - if record_type == 0: - # data record - addr += self._offset - for i in xrange(4, 4+record_length): - if not self._buf.get(addr, None) is None: - self.AddrOverlap = addr - self._buf[addr] = bin[i] - addr += 1 # FIXME: addr should be wrapped on 64K boundary - - elif record_type == 1: - # end of file record - if record_length != 0: - self.Error = "Bad End-of-File Record" - return False - self._eof = True - - elif record_type == 2: - # Extended 8086 Segment Record - if record_length != 2 or addr != 0: - self.Error = "Bad Extended 8086 Segment Record" - return False - self._offset = (bin[4]*256 + bin[5]) * 16 - - elif record_type == 4: - # Extended Linear Address Record - if record_length != 2 or addr != 0: - self.Error = "Bad Extended Linear Address Record" - return False - self._offset = (bin[4]*256 + bin[5]) * 65536 - - elif record_type == 3: - # Start Segment Address Record - if record_length != 4 or addr != 0: - self.Error = "Bad Start Segment Address Record" - return False - if self.start_addr: - self.Error = "Start Address Record appears twice" - return False - self.start_addr = {'CS': bin[4]*256 + bin[5], - 'IP': bin[6]*256 + bin[7], - } - - elif record_type == 5: - # Start Linear Address Record - if record_length != 4 or addr != 0: - self.Error = "Bad Start Linear Address Record" - return False - if self.start_addr: - self.Error = "Start Address Record appears twice" - return False - self.start_addr = {'EIP': (bin[4]*16777216 + - bin[5]*65536 + - bin[6]*256 + - bin[7]), - } - - return True - - def _get_start_end(self, start=None, end=None): - """Return default values for start and end if they are None - """ - if start is None: - start = min(self._buf.keys()) - if end is None: - end = max(self._buf.keys()) - if start > end: - start, end = end, start - return start, end - - def tobinarray(self, start=None, end=None, pad=None): - ''' Convert to binary form. - @param start start address of output bytes. - @param end end address of output bytes. - @param pad fill empty spaces with this value - (if None used self.padding). - @return array of unsigned char data. - ''' - if pad is None: - pad = self.padding - - bin = array('B') - - if self._buf == {}: - return bin - - start, end = self._get_start_end(start, end) - - for i in xrange(start, end+1): - bin.append(self._buf.get(i, pad)) - - return bin - - def tobinstr(self, start=None, end=None, pad=0xFF): - ''' Convert to binary form. - @param start start address of output bytes. - @param end end address of output bytes. - @param pad fill empty spaces with this value - (if None used self.padding). - @return string of binary data. - ''' - return self.tobinarray(start, end, pad).tostring() - - def tobinfile(self, fobj, start=None, end=None, pad=0xFF): - '''Convert to binary and write to file. - - @param fobj file name or file object for writing output bytes. - @param start start address of output bytes. - @param end end address of output bytes. - @param pad fill empty spaces with this value - (if None used self.padding). - ''' - if not hasattr(fobj, "write"): - fobj = file(fobj, "wb") - fclose = fobj.close - else: - fclose = None - - fobj.write(self.tobinstr(start, end, pad)) - - if fclose: - fclose() - - def minaddr(self): - ''' Get minimal address of HEX content. ''' - aa = self._buf.keys() - if aa == []: - return 0 - else: - return min(aa) - - def maxaddr(self): - ''' Get maximal address of HEX content. ''' - aa = self._buf.keys() - if aa == []: - return 0 - else: - return max(aa) - - def __getitem__(self, addr): - ''' Get byte from address. - @param addr address of byte. - @return byte if address exists in HEX file, or self.padding - if no data found. - ''' - return self._buf.get(addr, self.padding) - - def __setitem__(self, addr, byte): - self._buf[addr] = byte - - def writefile(self, f, write_start_addr=True): - """Write data to file f in HEX format. - - @param f filename or file-like object for writing - @param write_start_addr enable or disable writing start address - record to file (enabled by default). - If there is no start address nothing - will be written. - - @return True if successful. - """ - fwrite = getattr(f, "write", None) - if fwrite: - fobj = f - fclose = None - else: - fobj = file(f, 'w') - fwrite = fobj.write - fclose = fobj.close - - # start address record if any - if self.start_addr and write_start_addr: - keys = self.start_addr.keys() - keys.sort() - bin = array('B', '\0'*9) - if keys == ['CS','IP']: - # Start Segment Address Record - bin[0] = 4 # reclen - bin[1] = 0 # offset msb - bin[2] = 0 # offset lsb - bin[3] = 3 # rectyp - cs = self.start_addr['CS'] - bin[4] = (cs >> 8) & 0x0FF - bin[5] = cs & 0x0FF - ip = self.start_addr['IP'] - bin[6] = (ip >> 8) & 0x0FF - bin[7] = ip & 0x0FF - bin[8] = (-sum(bin)) & 0x0FF # chksum - fwrite(':') - fwrite(hexlify(bin.tostring()).upper()) - fwrite('\n') - elif keys == ['EIP']: - # Start Linear Address Record - bin[0] = 4 # reclen - bin[1] = 0 # offset msb - bin[2] = 0 # offset lsb - bin[3] = 5 # rectyp - eip = self.start_addr['EIP'] - bin[4] = (eip >> 24) & 0x0FF - bin[5] = (eip >> 16) & 0x0FF - bin[6] = (eip >> 8) & 0x0FF - bin[7] = eip & 0x0FF - bin[8] = (-sum(bin)) & 0x0FF # chksum - fwrite(':') - fwrite(hexlify(bin.tostring()).upper()) - fwrite('\n') - else: - self.Error = ('Invalid start address value: %r' - % self.start_addr) - return False - - # data - minaddr = IntelHex.minaddr(self) - maxaddr = IntelHex.maxaddr(self) - if maxaddr > 65535: - offset = (minaddr/65536)*65536 - else: - offset = None - - while True: - if offset != None: - # emit 32-bit offset record - high_ofs = offset / 65536 - offset_record = ":02000004%04X" % high_ofs - bytes = divmod(high_ofs, 256) - csum = 2 + 4 + bytes[0] + bytes[1] - csum = (-csum) & 0x0FF - offset_record += "%02X\n" % csum - - ofs = offset - if (ofs + 65536) > maxaddr: - rng = xrange(maxaddr - ofs + 1) - else: - rng = xrange(65536) - else: - ofs = 0 - offset_record = '' - rng = xrange(maxaddr + 1) - - csum = 0 - k = 0 - record = "" - for addr in rng: - byte = self._buf.get(ofs+addr, None) - if byte != None: - if k == 0: - # optionally offset record - fobj.write(offset_record) - offset_record = '' - # start data record - record += "%04X00" % addr - bytes = divmod(addr, 256) - csum = bytes[0] + bytes[1] - - k += 1 - # continue data in record - record += "%02X" % byte - csum += byte - - # check for length of record - if k < 16: - continue - - if k != 0: - # close record - csum += k - csum = (-csum) & 0x0FF - record += "%02X" % csum - fobj.write(":%02X%s\n" % (k, record)) - # cleanup - csum = 0 - k = 0 - record = "" - else: - if k != 0: - # close record - csum += k - csum = (-csum) & 0x0FF - record += "%02X" % csum - fobj.write(":%02X%s\n" % (k, record)) - - # advance offset - if offset is None: - break - - offset += 65536 - if offset > maxaddr: - break - - # end-of-file record - fobj.write(":00000001FF\n") - if fclose: - fclose() - - return True -#/IntelHex - - -class IntelHex16bit(IntelHex): - """Access to data as 16-bit words.""" - - def __init__(self, source): - """Construct class from HEX file - or from instance of ordinary IntelHex class. - - @param source file name of HEX file or file object - or instance of ordinary IntelHex class - """ - if isinstance(source, IntelHex): - # from ihex8 - self.Error = source.Error - self.AddrOverlap = source.AddrOverlap - self.padding = source.padding - - # private members - self._fname = source._fname - self._buf = source._buf - self._readed = source._readed - self._eof = source._eof - self._offset = source._offset - else: - IntelHex.__init__(self, source) - - if self.padding == 0x0FF: - self.padding = 0x0FFFF - - def __getitem__(self, addr16): - """Get 16-bit word from address. - Raise error if found only one byte from pair. - - @param addr16 address of word (addr8 = 2 * addr16). - @return word if bytes exists in HEX file, or self.padding - if no data found. - """ - addr1 = addr16 * 2 - addr2 = addr1 + 1 - byte1 = self._buf.get(addr1, None) - byte2 = self._buf.get(addr2, None) - - if byte1 != None and byte2 != None: - return byte1 | (byte2 << 8) # low endian - - if byte1 == None and byte2 == None: - return self.padding - - raise Exception, 'Bad access in 16-bit mode (not enough data)' - - def __setitem__(self, addr16, word): - addr_byte = addr16 * 2 - bytes = divmod(word, 256) - self._buf[addr_byte] = bytes[1] - self._buf[addr_byte+1] = bytes[0] - - def minaddr(self): - '''Get minimal address of HEX content in 16-bit mode.''' - aa = self._buf.keys() - if aa == []: - return 0 - else: - return min(aa)/2 - - def maxaddr(self): - '''Get maximal address of HEX content in 16-bit mode.''' - aa = self._buf.keys() - if aa == []: - return 0 - else: - return max(aa)/2 - -#/class IntelHex16bit - - -def hex2bin(fin, fout, start=None, end=None, size=None, pad=0xFF): - """Hex-to-Bin convertor engine. - @return 0 if all OK - - @param fin input hex file (filename or file-like object) - @param fout output bin file (filename or file-like object) - @param start start of address range (optional) - @param end end of address range (optional) - @param size size of resulting file (in bytes) (optional) - @param pad padding byte (optional) - """ - h = IntelHex(fin) - if not h.readfile(): - print "Bad HEX file" - return 1 - - # start, end, size - if size != None and size != 0: - if end == None: - if start == None: - start = h.minaddr() - end = start + size - 1 - else: - if (end+1) >= size: - start = end + 1 - size - else: - start = 0 - - try: - h.tobinfile(fout, start, end, pad) - except IOError: - print "Could not write to file: %s" % fout - return 1 - - return 0 -#/def hex2bin - - -if __name__ == '__main__': - import getopt - import os - import sys - - usage = '''Hex2Bin python converting utility. -Usage: - python intelhex.py [options] file.hex [out.bin] - -Arguments: - file.hex name of hex file to processing. - out.bin name of output file. - If omitted then output write to file.bin. - -Options: - -h, --help this help message. - -p, --pad=FF pad byte for empty spaces (ascii hex value). - -r, --range=START:END specify address range for writing output - (ascii hex value). - Range can be in form 'START:' or ':END'. - -l, --length=NNNN, - -s, --size=NNNN size of output (decimal value). -''' - - pad = 0xFF - start = None - end = None - size = None - - try: - opts, args = getopt.getopt(sys.argv[1:], "hp:r:l:s:", - ["help", "pad=", "range=", - "length=", "size="]) - - for o, a in opts: - if o in ("-h", "--help"): - print usage - sys.exit(0) - elif o in ("-p", "--pad"): - try: - pad = int(a, 16) & 0x0FF - except: - raise getopt.GetoptError, 'Bad pad value' - elif o in ("-r", "--range"): - try: - l = a.split(":") - if l[0] != '': - start = int(l[0], 16) - if l[1] != '': - end = int(l[1], 16) - except: - raise getopt.GetoptError, 'Bad range value(s)' - elif o in ("-l", "--lenght", "-s", "--size"): - try: - size = int(a, 10) - except: - raise getopt.GetoptError, 'Bad size value' - - if start != None and end != None and size != None: - raise getopt.GetoptError, 'Cannot specify START:END and SIZE simultaneously' - - if not args: - raise getopt.GetoptError, 'Hex file is not specified' - - if len(args) > 2: - raise getopt.GetoptError, 'Too many arguments' - - except getopt.GetoptError, msg: - print msg - print usage - sys.exit(2) - - fin = args[0] - if len(args) == 1: - import os.path - name, ext = os.path.splitext(fin) - fout = name + ".bin" - else: - fout = args[1] - - if not os.path.isfile(fin): - print "File not found" - sys.exit(1) - - sys.exit(hex2bin(fin, fout, start, end, size, pad)) -- cgit v1.2.3