Files
templates/python/firmware_image/native.py

49 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Models for the C99 Intel HEX parser. No Python parser fallback."""
import ctypes as ct
from functools import lru_cache
from protocan.native import _load_library
class Cell(ct.Structure):
_fields_ = [('address', ct.c_uint32), ('value', ct.c_uint8)]
@lru_cache(maxsize=1)
def library():
lib = _load_library()
try:
lib.firmware_hex_parse.argtypes = [ct.c_char_p, ct.c_size_t, ct.POINTER(Cell),
ct.c_size_t, ct.c_size_t, ct.POINTER(ct.c_size_t), ct.POINTER(ct.c_size_t)]
lib.firmware_hex_parse.restype = ct.c_int
lib.firmware_hex_segment_size.argtypes = [ct.POINTER(Cell), ct.c_size_t, ct.c_size_t]
lib.firmware_hex_segment_size.restype = ct.c_size_t
except AttributeError as exc:
raise RuntimeError('Rebuild SETProtocol: native firmware image API is missing') from exc
return lib
def parse_segments(text, max_records, error_type, segment_type):
try:
raw = bytes(text) if isinstance(text, (bytes, bytearray)) else str(text or '').encode('ascii')
except UnicodeError as exc:
raise error_type('Intel HEX должен состоять из ASCII') from exc
if max_records < 1 or len(raw) > 64 * 1024 * 1024:
raise error_type('Файл Intel HEX превышает допустимый размер')
cells = (Cell * max(1, len(raw) // 2))()
count, line = ct.c_size_t(), ct.c_size_t()
lib = library()
status = lib.firmware_hex_parse(raw, len(raw), cells, len(cells), max_records,
ct.byref(count), ct.byref(line))
if status:
messages = {1: 'неверный формат', 2: 'неверная checksum записи',
3: 'неизвестный тип или неверная длина записи', 4: 'нет данных/EOF или данные после записи EOF',
5: 'адрес описан повторно', 6: 'адрес выходит за uint32',
7: 'превышено допустимое число записей',
8: "запись должна начинаться с ':'", 9: 'запись содержит не пары HEX-символов',
10: 'длина записи не совпадает с полем count'}
raise error_type('Intel HEX, строка %d: %s' % (line.value, messages.get(status, 'ошибка')))
result, offset = [], 0
while offset < count.value:
size = lib.firmware_hex_segment_size(cells, count.value, offset)
result.append(segment_type(cells[offset].address,
bytes(cells[i].value for i in range(offset, offset + size))))
offset += size
return result