view python/hexfile.py @ 119:f51791638cae

Simplified flashing
author Windel Bouwman
date Sat, 12 Jan 2013 10:23:33 +0100
parents ed230e947dc6
children d3dccf12ca88
line wrap: on
line source

import os

class HexFileException(Exception):
   pass

def parseHexLine(line):
   """ Parses a hexfile line into three parts """
   line = line[1:] # Remove ':'
   nums = bytes.fromhex(line)
   bytecount = nums[0]
   if len(nums) != bytecount + 5:
      raise HexFileException('byte count field incorrect')
   crc = sum(nums)
   if (crc & 0xFF) != 0:
      raise HexFileException('crc incorrect')
   address = nums[1] * 256 + nums[2]
   typ = nums[3]
   data = nums[4:-1]
   return (address, typ, data)

class HexFile:
   """ Represents an intel hexfile """
   def __init__(self, filename=None):
      self.regions = []
      self.startAddress = 0
      self.filename = None
      if filename:
         self.load(filename)

   def load(self, filename):
      with open(filename, 'r') as f:
         endOfFile = False
         offset = 0
         startAddress = 0
         curAddress = 0
         curData = bytearray()
         for line in f:
            line = line.strip() # Strip spaces and newlines
            if not line: continue # Skip empty lines
            if line[0] != ':': continue # Skip lines that do not start with a ':'
            if endOfFile: raise HexFileException('hexfile line after end of file record')
            address, typ, data = parseHexLine(line)
            if typ == 0x0: # Data record
               address += offset # Fix address with offset
               # Append data
               if address == curAddress:
                  curData += data
                  curAddress += len(data)
               else:
                  if curData:
                     self.regions.append(HexFileRegion(startAddress, bytes(curData)))
                  startAddress = address
                  curAddress = address + len(data)
                  curData = bytearray(data)
            elif typ == 0x4: # Extended linear address record
               offset = ((data[0] << 8) + data[1]) << 16
            elif typ == 0x1: # End of file record
               if len(data) != 0:
                  raise HexFileException('end of file record must contain no data')
               endOfFile = True
            elif typ == 0x5: # Start address record (where IP goes after loading)
               self.startAddress = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]
            else:
               raise HexFileException('record type {0} not implemented'.format(typ))
               print(hex(address), typ, data)
         # After all lines:
         if curData:
            self.regions.append(HexFileRegion(startAddress, bytes(curData)))
         # Store the filename:
         self.filename = filename
   def __repr__(self):
      i = []
      i.append(super().__repr__())
      i.append('Start address {0}'.format(hex(self.startAddress)))
      i.append('Filename: {0}'.format(self.filename))
      for r in self.regions:
         i.append(str(r))
      return os.linesep.join(i)
   def save(self, filename):
      with open(filename, 'w') as f:
         for line in f:
            pass
     
class HexFileRegion:
   def __init__(self, address, data = bytes()):
      self.address = address
      self.data = data
   def __repr__(self):
      return 'Region at 0x{0:X} of {1} bytes'.format(self.address, len(self.data))

if __name__ == '__main__':
   h = HexFile()
   print(h)
   """ Test hexfile implementation with some hexfile """
   h1 = HexFile('audio.hex')
   print(h1)