def __init__(self, buf, endianness='<'): """Parse a bytestring buf containing a BootInfo struct. Endianness may be provided using Python's struct module notation, but should always be little-endian for all current Mikroe kits, at least from what I know.""" def unpack(fmt, buf): return struct.unpack(endianness + fmt, buf) # Get sizeof struct and truncate it bSize = bord(buf[0]) buf = buf[:bSize] pos = 1 while pos < len(buf): # Skip initial field padding pad = 0 while pos < len(buf) and bord(buf[pos]) == 0: pos += 1 pad += 1 if pos >= len(buf): break # Parse field type field_type = bord(buf[pos]) if field_type not in _field: logger.error('Field %d not recognized -- aborting parsing' % field_type) break name, num_bytes, enum_map = _field[field_type] pad_bytes = min(num_bytes, 4) # Check for any alignment override if 'McuType' in self and name in _fieldalign_override: pad_bytes = _fieldalign_override[name].get(self['McuType'], pad_bytes) # Sanity check the detected initial padding if pad >= pad_bytes or (num_bytes <= 4 and pos % pad_bytes != 0): logger.warn('Initial padding of %d inadequate in field "%s" (%d)' % (pad, name, field_type)) # Go to data (skip the internal padding) pos += 1 if num_bytes <= 4: pad = (pad_bytes - pos % pad_bytes) % pad_bytes pos += pad # Read the value fmt = {1: 'B', 2: 'H', 4: 'L'} value = buf[pos:pos+num_bytes] if num_bytes in fmt: value, = unpack(fmt[num_bytes], value) pos += num_bytes # Fill the field if enum_map: if value in enum_map: value = enum_map[value] else: logger.warn('Field "%s" (%d) contains value %d not mapped in its enum' % (name, field_type, value)) if name in self: logger.warn('Field "%s" (%d) duplicated -- discarding old value: %s' % (name, field_type, repr(fields[name]))) self[name] = value
def load(f, devkit): """Load a Intel HEX File from a file object into a devkit. The devkit must implement a write(address,data) method.""" lineno = 0 base_addr = 0 for line in f.xreadlines(): lineno += 1 line = line.strip() if line == '': continue if bord(line[0]) != ord(':'): raise IOError('line %d: malformed' % lineno) line = unhexlify(line[1:]) byte_count, address, record_type = struct.unpack('>BHB', line[:4]) correct_len = byte_count + 5 if len(line) != correct_len: logger.warn('line %d: should have %d bytes -- truncating' % (lineno, correct_len)) line = line[:correct_len] if sum(map(bord,line)) & 0xFF != 0: raise IOError('line %d: incorrect checksum' % lineno) data = line[4:-1] if record_type == 0x00: # data record devkit.write(base_addr + address, data) elif record_type == 0x01: # end of file record break elif record_type == 0x04: # extended linear address record if byte_count != 2: raise IOError('line %d: extended linear address record must have 2 bytes of data' % lineno) base_addr, = struct.unpack('>H', data) base_addr <<= 16 elif record_type == 0x02: # extended segment address record base_addr, = struct.unpack('>H', data) base_addr <<= 4 elif record_type not in [0x03, 0x05]: # used for the initial PC (ignored) raise IOError('line %d: unsupported record type %d' % (lineno, record_type))
def write(self, addr, data): if addr >= self.config_data_addr: return assert(len(data) % 4 == 0) newd = [] # discard padding bytes (at every fourth byte) for i in xrange(0, len(data), 4): newd += list(data[i:i+3]) padbyte = bord(data[i+3]) if padbyte != 0: logger.warning('padding byte at addr 0x%x (%02X) is not null' % (addr+i+3, padbyte)) # write the new data array self._write_phy(self._hex_addr_to_phy(addr), bytearray(newd))
def load(f, devkit): """Load a Intel HEX File from a file object into a devkit. The devkit must implement a write(address,data) method.""" lineno = 0 base_addr = 0 for line in f.xreadlines(): lineno += 1 line = line.strip() if line == '': continue if bord(line[0]) != ord(':'): raise IOError('line %d: malformed' % lineno) line = unhexlify(line[1:]) byte_count, address, record_type = struct.unpack('>BHB', line[:4]) correct_len = byte_count + 5 if len(line) != correct_len: logger.warn('line %d: should have %d bytes -- truncating' % (lineno, correct_len)) line = line[:correct_len] if sum(map(bord, line)) & 0xFF != 0: raise IOError('line %d: incorrect checksum' % lineno) data = line[4:-1] if record_type == 0x00: # data record devkit.write(base_addr + address, data) elif record_type == 0x01: # end of file record break elif record_type == 0x04: # extended linear address record if byte_count != 2: raise IOError( 'line %d: extended linear address record must have 2 bytes of data' % lineno) base_addr, = struct.unpack('>H', data) base_addr <<= 16 elif record_type == 0x02: # extended segment address record base_addr, = struct.unpack('>H', data) base_addr <<= 4 elif record_type not in [0x03, 0x05]: # used for the initial PC (ignored) raise IOError('line %d: unsupported record type %d' % (lineno, record_type))