Skip to content

Add overlap parameter to constructor #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions intelhex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,21 @@ class _DeprecatedParam(object):
class IntelHex(object):
''' Intel HEX file reader. '''

def __init__(self, source=None):
def __init__(self, source=None, overlap='error'):
''' Constructor. If source specified, object will be initialized
with the contents of source. Otherwise the object will be empty.

@param source source for initialization
(file name of HEX file, file object, addr dict or
other IntelHex object)
@param overlap defines behavior for overlapping addresses
during hex file loading:
- 'error': raises AddressOverlapError (default)
- 'ignore': keeps the original data, discards new data
- 'replace': replaces the original data with new data

Note: this parameter currently only affects loading
from HEX files via loadhex or during initialization.
'''
# public members
self.padding = 0x0FF
Expand All @@ -84,6 +92,11 @@ def __init__(self, source=None):
self._buf = {}
self._offset = 0

# overlap setting for hex loading
if overlap not in ('error', 'ignore', 'replace'):
raise ValueError("overlap argument should be either 'error', 'ignore' or 'replace'")
self._overlap_check = overlap

if source is not None:
if isinstance(source, StrType) or getattr(source, "read", None):
# load hex file
Expand Down Expand Up @@ -140,11 +153,17 @@ def _decode_record(self, s, line=0):
if record_type == 0:
# data record
addr += self._offset
for i in range_g(4, 4+record_length):
if not self._buf.get(addr, None) is None:
raise AddressOverlapError(address=addr, line=line)
self._buf[addr] = bin[i]
addr += 1 # FIXME: addr should be wrapped
base_addr = addr # Start address for this record's data
for i in range_g(record_length):
current_addr = base_addr + i
# Check for overlap based on self._overlap_check setting
if current_addr in self._buf:
if self._overlap_check == 'error':
raise AddressOverlapError(address=current_addr, line=line)
elif self._overlap_check == 'ignore':
continue # Skip assignment for this byte
# Assign if address doesn't exist OR if overlap is 'replace'
self._buf[current_addr] = bin[4+i]
# BUT after 02 record (at 64K boundary)
# and after 04 record (at 4G boundary)

Expand Down Expand Up @@ -184,8 +203,8 @@ def _decode_record(self, s, line=0):
raise DuplicateStartAddressRecordError(line=line)
self.start_addr = {'EIP': (bin[4]*16777216 +
bin[5]*65536 +
bin[6]*256 +
bin[7]),
bin[6]*256 +
bin[7]),
}

def loadhex(self, fobj):
Expand Down
30 changes: 30 additions & 0 deletions intelhex/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,36 @@ def test_eof(self):
# EOF should raise special exception
self.assertRaises(_EndOfFile, self.decode_record, ':00000001FF')

def test_overlap_options(self):
# Hex file with overlapping data
overlapping_hex = """\
:020000001122CB
:02000100334486
:00000001FF
"""
# Test 'error' (default)
ih_error = IntelHex()
ih_error._decode_record(':020000001122CB') # First record ok
self.assertRaisesMsg(AddressOverlapError,
'Hex file has data overlap at address 0x1 '
'on line 1',
ih_error._decode_record,
':02000100334486', 1)

# Test 'ignore'
ih_ignore = IntelHex(overlap='ignore')
ih_ignore.loadhex(StringIO(overlapping_hex))
self.assertEqual(ih_ignore[0], 0x11)
self.assertEqual(ih_ignore[1], 0x22) # Should keep the first value (0x22)
self.assertEqual(ih_ignore[2], 0x44)

# Test 'replace'
ih_replace = IntelHex(overlap='replace')
ih_replace.loadhex(StringIO(overlapping_hex))
self.assertEqual(ih_replace[0], 0x11)
self.assertEqual(ih_replace[1], 0x33) # Should be replaced with the second value (0x33)
self.assertEqual(ih_replace[2], 0x44)

#/class TestDecodeHexRecords


Expand Down