Skip to content

Commit

Permalink
Added Microchip SQTP parsing + minor fixes
Browse files Browse the repository at this point in the history
Microchip SQTP derives from Interl HEX, but it isn't properly supported because it addresses by 2 or 4 bytes per word, instead of direct bytes.
Microchip SQTP will likely become a separate format in the future.
  • Loading branch information
TexZK committed Feb 14, 2024
1 parent 9526aa4 commit 9c8a344
Show file tree
Hide file tree
Showing 17 changed files with 107 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/hexrec/formats/ihex.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ def validate_records(
>>> from hexrec import IhexFile
>>> records = [IhexFile.Record.create_data(123, b'abc')]
>>> file = IhexFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: missing end of file record
Expand Down
2 changes: 1 addition & 1 deletion src/hexrec/formats/mos.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ def validate_records(
>>> from hexrec import MosFile
>>> records = [MosFile.Record.create_data(123, b'abc')]
>>> file = MosFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: missing end of file record
Expand Down
2 changes: 1 addition & 1 deletion src/hexrec/formats/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def validate_records(
>>> from hexrec import RawFile
>>> records = [RawFile.Record.create_data(123, b'abc')]
>>> file = RawFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: first record address not zero
Expand Down
2 changes: 1 addition & 1 deletion src/hexrec/formats/srec.py
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ def validate_records(
>>> from hexrec import SrecFile
>>> records = [SrecFile.Record.create_data(123, b'abc')]
>>> file = SrecFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: missing start record
Expand Down
5 changes: 4 additions & 1 deletion src/hexrec/formats/titxt.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from typing import Any
from typing import Mapping
from typing import Optional
from typing import Sequence
from typing import Type
from typing import TypeVar
from typing import cast as _cast
Expand Down Expand Up @@ -396,6 +397,8 @@ def validate(
class TiTxtFile(BaseFile):
r"""Texas Instruments TI-TXT file object."""

FILE_EXT: Sequence[str] = ['.txt']

Record: Type[TiTxtRecord] = TiTxtRecord

@classmethod
Expand Down Expand Up @@ -537,7 +540,7 @@ def validate_records(
>>> from hexrec import TiTxtFile
>>> records = [TiTxtFile.Record.create_data(456, b'abc')]
>>> file = TiTxtFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: missing end of file record
Expand Down
2 changes: 1 addition & 1 deletion src/hexrec/formats/xtek.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ def validate_records(
>>> from hexrec import XtekFile
>>> records = [XtekFile.Record.create_data(123, b'abc')]
>>> file = XtekFile.from_records(records)
>>> file.validate_records()
>>> _ = file.validate_records()
Traceback (most recent call last):
...
ValueError: missing end of file record
Expand Down
40 changes: 40 additions & 0 deletions tests/test_formats_ihex.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,27 @@ def test_parse_syntax(self):
record = IhexRecord.parse(line)
record.validate()

# https://developerhelp.microchip.com/xwiki/bin/view/software-tools/ipe/sqtp-file-format-specification/example/
def test_parse_microchip_sqtp(self):
lines = [
b':02000004740086\r\n',
b':04000000BF7087ED59\r\n',
b':0400000043BD7F3449\r\n',
b':00000001FF\r\n',
]
records = [
IhexRecord(ELA, count=0x02, address=0x0000, checksum=0x86, data=b'\x74\x00'),
IhexRecord(DATA, count=0x04, address=0x0000, checksum=0x59, data=b'\xBF\x70\x87\xED'),
IhexRecord(DATA, count=0x04, address=0x0000, checksum=0x49, data=b'\x43\xBD\x7F\x34'),
IhexRecord(EOF, count=0x00, address=0x0000, checksum=0xFF, data=b''),
]
for line, expected in zip(lines, records):
actual = IhexRecord.parse(line)
actual.validate()
expected = _cast(IhexRecord, expected)
expected.validate()
assert actual == expected

# https://en.wikipedia.org/wiki/Intel_HEX#Record_types
def test_parse_wikipedia(self):
lines = [
Expand Down Expand Up @@ -789,6 +810,25 @@ def test_parse_errors(self):
with io.BytesIO(buffer) as stream:
IhexFile.parse(stream, ignore_errors=False)

# https://developerhelp.microchip.com/xwiki/bin/view/software-tools/ipe/sqtp-file-format-specification/examples/
# FIXME: Microchip SQTP addresses are word-/dword-based --> add 'addressing' meta & property to apply/update records
def test_parse_file_microchip_sqtp(self, datapath):
filenames = [
'microchip_auxmem_dsPIC33EP256MU806.hex',
'microchip_bootmem_PIC32MX110F016B.hex',
'microchip_eeprom_PIC12F1840.hex',
'microchip_eeprom_PIC18F1220.hex',
'microchip_progmem_PIC18F1220.hex',
'microchip_progmem_PIC32MX360F512L.hex',
'microchip_userid_PIC12F1501.hex', # fixed checksums
'microchip_userid_PIC32MX360F512L.hex',
]
for filename in filenames:
path = str(datapath / filename)
with open(path, 'rb') as stream:
file = IhexFile.parse(stream)
file.validate_records()

# https://en.wikipedia.org/wiki/Intel_HEX#File_example
def test_parse_file_wikipedia(self, datapath):
path = str(datapath / 'wikipedia.hex')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:0200000401FFFA
:0400000000000000FC
:0400000001000000FB
:0400000002000000FA
:0400000003000000F9
:0400000004000000F8
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_bootmem_PIC32MX110F016B.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:020000047F007B
:0400000039268EC748
:040000001FB777E2CD
:04000000031E7E3D20
:04000000D56F64E272
:04000000F993C2A707
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_eeprom_PIC12F1840.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:020000040000FA
:02F0000000000E
:02F0000001000D
:02F0000002000C
:02F0000003000B
:02F0000004000A
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_eeprom_PIC18F1220.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:0200000400F00A
:020000000000FE
:020000000100FD
:020000000200FC
:020000000300FB
:020000000400FA
:00000001FF
6 changes: 6 additions & 0 deletions tests/test_formats_ihex/microchip_progmem_PIC18F1220.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:04000000000C000CE4
:04000000010C000CE3
:04000000020C000CE2
:04000000030C000CE1
:04000000040C000CE0
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_progmem_PIC32MX360F512L.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:02000004740086
:0400000000000000FC
:0400000001000000FB
:0400000002000000FA
:0400000003000000F9
:0400000004000000F8
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_userid_PIC12F1501.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:020000040001F9
:040000007E34CF3447
:040000009034C5343F
:040000000B34113478
:04000000F234F334AF
:040000001C34683410
:00000001FF
7 changes: 7 additions & 0 deletions tests/test_formats_ihex/microchip_userid_PIC32MX360F512L.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:020000047F007B
:04BFC000000000007D
:04BFC000010000007C
:04BFC000020000007B
:04BFC000030000007A
:04BFC0000400000079
:00000001FF
2 changes: 2 additions & 0 deletions tests/test_formats_mos.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,12 +682,14 @@ def test_validate_records_data_order(self):
MosRecord.create_eof(2)]
file = MosFile.from_records(records)
file.validate_records(data_ordering=True)
file.validate_records(data_ordering=False)

records = [MosRecord.create_data(10, b'xyz'),
MosRecord.create_data(14, b'abc'),
MosRecord.create_eof(2)]
file = MosFile.from_records(records)
file.validate_records(data_ordering=True)
file.validate_records(data_ordering=False)

def test_validate_records_raises_records(self):
file = MosFile()
Expand Down
1 change: 1 addition & 0 deletions tests/test_formats_xtek.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,3 +855,4 @@ def test_validate_records_start_within_data(self):
file = XtekFile.from_records(records)
assert file.startaddr == 0x1234
file.validate_records(start_within_data=True)
file.validate_records(start_within_data=False)

0 comments on commit 9c8a344

Please sign in to comment.