Передавать контрольную сумму команды перехода в загрузчик. Отправлять Monitor на 468750 бод и затем включать скорость SCI из JSON. Обновить эталонные проверки входа в загрузчик.
52 lines
7.1 KiB
Python
52 lines
7.1 KiB
Python
"""Эталонные обмены SCI ROM и TI Flash Kernel A без настоящей платы.""" # Проверки не открывают COM и не вызывают внешнюю программу C2Prog.
|
|
import struct # Формирует независимые тестовые SCI8-векторы с явно заданными словами и адресами.
|
|
import pytest # Проверяет отказ при повреждениях и граничные размеры порций ядра TI.
|
|
from protocan.c2000_sci import Session, decode, validate, ulitco_enter # Испытывает настоящий ctypes-порт общего C99-ядра.
|
|
|
|
|
|
def sci8(address, words): # Готовит минимальную адресную таблицу для эталонных данных теста.
|
|
pointer = struct.pack("<HH", address >> 16, address & 65535) # SCI8 хранит старшее слово адреса перед младшим.
|
|
return b"\xaa\x08" + bytes(16) + pointer + struct.pack("<H", len(words)) + pointer + struct.pack("<" + "H" * len(words), *words) + bytes(2) # Вектор содержит ключ, резерв, entry, одну секцию и терминатор.
|
|
|
|
|
|
@pytest.mark.parametrize("words", [1, 1024, 1025, 2048, 2050]) # Границы проверяют обычную порцию, остаток и дополнительный нулевой ACK официального TI kernel.
|
|
def test_complete_echo_and_checksum_transcript(words): # Фактические ответы подтверждают порядок и неизменность всего приложения.
|
|
kernel, image = sci8(0x9000, [0x1234, 0x5678]), sci8(0x328000, [0xA55A] * words) # RAM-ядро и Flash занимают разные разрешённые области.
|
|
session, received, pauses, zero_acks = Session(kernel, image), bytearray(), [], 0 # Наблюдения не используют внутреннюю структуру C-контекста.
|
|
for _ in range(len(kernel) + words + 100): # Конечный предел выявляет зацикливание автомата.
|
|
state, tx, expected, delay = session.next() # Проверяет настоящий сформированный C-пакет.
|
|
if state == 0: break # Успех допустим лишь после отправки нулевого терминатора приложения.
|
|
if state == 2: pauses.append(delay); continue # Внешний транспорт выполняет только заданную алгоритмом задержку.
|
|
if expected == 1: session.accept(tx) # ROM и autobaud должны вернуть точное эхо отправленного октета.
|
|
else: # Kernel A подтверждает сумму октетов после erase/program, без побайтового эха приложения.
|
|
received.extend(tx) # Снимок подтверждает отсутствие пропущенных, повторённых либо изменённых октетов SCI8.
|
|
if expected: session.accept(struct.pack("<H", sum(tx) & 65535)) # Независимый эталон суммы следует опубликованному исходнику TI SendCheckSum.
|
|
if not tx: zero_acks += 1 # Пустой остаток TI подтверждается отдельным нулевым словом.
|
|
else: pytest.fail("Автомат SCI не завершился") # Отсутствие терминального перехода считается ошибкой протокола.
|
|
assert bytes(received) == image # MCU получил ровно исходный Flash SCI8 без переименования или подмены содержимого.
|
|
assert pauses == [3000, 3000] and session.progress == 100 # Порядок ожиданий совпадает с TI f05_DownloadImage.
|
|
assert zero_acks == int(words > 1024 and words % 1024 == 0) # Обрабатывает особенность исходного TI Kernel A на кратной порции.
|
|
|
|
|
|
def test_corrupt_echo_and_checksum_stop_transfer(): # Повреждённое подтверждение не должно разрешать следующий пакет.
|
|
kernel, image = sci8(0x9000, [1]), sci8(0x328000, [2]) # Минимальные векторы отделяют проверку ответа от больших файлов.
|
|
session = Session(kernel, image); session.next() # Первый пакет требует эхо ASCII A.
|
|
with pytest.raises(ValueError, match="не совпали"): session.accept(b"B") # Чужой байт autobaud не принимается как связь с ROM.
|
|
session = Session(kernel, image) # Независимый сеанс проверяет повреждение двухоктетной суммы Flash.
|
|
while True: # Доходит до первой операции erase/header без использования внутренних фаз автомата.
|
|
state, tx, expected, _ = session.next() # Паузы не требуют аппаратного ответа.
|
|
if state == 2: continue # Номер стадии остаётся внутри C-ядра.
|
|
if expected == 1: session.accept(tx) # Корректный ROM позволяет загрузить RAM-ядро.
|
|
else: break # Первый двухоктетный ответ должен подтвердить заголовок приложения.
|
|
with pytest.raises(ValueError, match="не совпали"): session.accept(b"\xff\xff") # Неверная сумма не разрешает программирование следующей секции.
|
|
|
|
|
|
def test_ascii_decode_memory_ranges_and_monitor_command(): # Проверяет переносимость форматов и аппаратные границы до открытия порта.
|
|
image = sci8(0x328000, [0x1234]) # Обычный Flash-вектор не пересекает CSM.
|
|
ascii_image = b"\x02\n" + " ".join(f"{value:02X}" for value in image).encode("ascii") + b"\n\x03\n" # Формат соответствует выводу TI hex2000 -boot -sci8 -a.
|
|
assert decode(ascii_image) == image and validate(image) == (0x328000, 4) # Сектор C имеет маску 0x0004 в TI Flash API.
|
|
with pytest.raises(ValueError): decode(ascii_image[:-2]) # Усечённый ETX не должен оставить частично декодированное ядро.
|
|
with pytest.raises(ValueError): validate(sci8(0x33FFF8, [0x1234])) # Область CSM-паролей запрещена независимо от имени файла.
|
|
with pytest.raises(ValueError): validate(sci8(0x8000, [0x1234])) # RAM-образ не может стать Flash-приложением из-за выбранного loader.
|
|
assert ulitco_enter() == bytes([247, 213, 255, 93, 0, 0, 1, 0, 93, 1]) # Эталон совпадает с десятиоктетным Monitor-запросом FLASH_NUM=93 текущей прошивки UlitCo.
|