aboutsummaryrefslogtreecommitdiff
path: root/j1demo/firmware/intelhex.py
diff options
context:
space:
mode:
Diffstat (limited to 'j1demo/firmware/intelhex.py')
-rw-r--r--j1demo/firmware/intelhex.py643
1 files changed, 0 insertions, 643 deletions
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 <Alexander Belchenko>
-# 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))