예제 #1
0
 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
예제 #2
0
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))
예제 #3
0
 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))
예제 #4
0
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))