Files
templates/python/protocan/stm32_boot.py

48 lines
1.6 KiB
Python

"""Packets and constants for the STM32 system-memory UART bootloader (AN3155)."""
from __future__ import annotations
ACK = 0x79
NACK = 0x1F
SYNC = b"\x7f"
def command(code: int) -> bytes:
"""Encode an AN3155 command and its one's-complement checksum."""
if not 0 <= code <= 0xFF:
raise ValueError("Код команды вне диапазона байта")
return bytes((code, code ^ 0xFF))
def address(value: int) -> bytes:
"""Encode a big-endian 32-bit address followed by XOR checksum."""
if not 0 <= value <= 0xFFFFFFFF:
raise ValueError("Адрес вне диапазона u32")
raw = value.to_bytes(4, "big")
return raw + bytes((raw[0] ^ raw[1] ^ raw[2] ^ raw[3],))
def write_payload(data: bytes) -> bytes:
"""Encode one Write Memory payload (1..256 bytes)."""
if not 1 <= len(data) <= 256:
raise ValueError("Блок STM32 должен содержать от 1 до 256 байт")
count = len(data) - 1
checksum = count
for value in data:
checksum ^= value
return bytes((count,)) + data + bytes((checksum,))
MASS_ERASE = b"\xff\x00"
def erase_pages_payload(pages: list[int]) -> bytes:
"""Encode the standard Erase Memory page list used by STM32F1."""
if not pages or len(pages) > 256 or any(not 0 <= page <= 0xFF for page in pages):
raise ValueError("Список страниц STM32 должен содержать 1..256 номеров")
body = bytes((len(pages) - 1, *pages))
checksum = 0
for value in body:
checksum ^= value
return body + bytes((checksum,))