Добавить защищённое обновление приложения через RS и CAN с сохранением загрузчика, проверкой CRC, восстановлением передачи и защитой EEPROM. Подключить общий процесс сборки C2000 и автоматический счётчик версии для согласованных RAM, Flash, CAN и паспортов бинарных образов. Уточнить запуск ЦАП, обработку измерений и параметров нагрузки, начальную индикацию и документацию регистров GAS. Дополнить модели аппаратуры и изолировать заголовки CAN в тестах. Проверка: 26 тестов выпуска, 4 теста восстановления CAN и восемь программных моделей CAN, Flash, EEPROM, ЦАП, параметров и TESTLAMP.
54 lines
10 KiB
Python
54 lines
10 KiB
Python
"""Компилирует реальные декодеры Flash RS на host и проверяет формат готового образа.""" # Проверяет производственную проверку границ независимо от реализации GUI.
|
|
import ctypes # Вызывает декодер C с точными 16- и 32-битными типами, соответствующими ABI C28x.
|
|
import importlib.util # Подключает общий подписыватель FAB1 из фактически компилируемой зависимости templates.
|
|
import os # Даёт GCC доступ к DLL установленного runtime Windows.
|
|
from pathlib import Path # Находит производственный источник и результаты сборки относительно теста.
|
|
import struct # Создаёт таблицы TI с заведомо известными допустимыми и запрещёнными адресами.
|
|
import subprocess # Компилирует настоящие функции производственного загрузчика.
|
|
import tempfile # Изолирует временный C-модуль и библиотеку от исходников прошивки.
|
|
ROOT = Path(__file__).resolve().parents[2] # Корень содержит проверяемый flash_rs.c и транспортный BIN текущей сборки.
|
|
PORT = ROOT.parent / 'newProject/SETGUI/third_party/templates/c/protocan-boot/ports/tms320f28335' # Общий C-валидатор совпадает с кодом постоянного boot.
|
|
spec = importlib.util.spec_from_file_location('flash_contract', ROOT.parent / 'newProject/SETGUI/third_party/templates/python/protocan/f28335_flash.py') # Тестовые данные подписываются производственным форматом FAB1.
|
|
contract = importlib.util.module_from_spec(spec) # Изолирует импорт от установленного пакета protocan.
|
|
spec.loader.exec_module(contract) # Отсутствующая новая зависимость останавливает проверку вместо принятия старого Flash.
|
|
GCC = Path('C:/msys64/mingw64/bin/gcc.exe') # Использует тот же host-компилятор, что существующие проверки прошивки.
|
|
os.environ['PATH'] = str(GCC.parent) + os.pathsep + os.environ['PATH'] # Подключает runtime DLL GCC только к процессам проверки.
|
|
source = (ROOT / 'Source/Internal/flash_rs.c').read_text(encoding='utf-8') # Читает реальные функции, а не переписывает алгоритм в тестовой модели.
|
|
helpers = source[source.index('#pragma CODE_SECTION(byte_at'):source.index('#pragma CODE_SECTION(reply_status')] # Берёт производственное преобразование упаковки RS и расчёт CRC.
|
|
validator = source[source.index('#pragma CODE_SECTION(validate_image'):source.index('#pragma CODE_SECTION(program_image')] # Берёт производственную проверку всех блоков и запрещённых диапазонов.
|
|
prefix = '#include <stdint.h> /* Задаёт точные типы host-модели ABI C28x. */\ntypedef uint16_t Uint16; /* Слово C28x содержит 16 бит. */\ntypedef uint32_t Uint32; /* Адрес и длина C28x занимают 32 бита. */\nvoid ServiceDog(void) {} /* Предварительная CRC обслуживает watchdog платы; у host таймера нет. */\n' # Сохраняет арифметические размеры и точку аппаратного обслуживания оригинального кода.
|
|
wrapper = '__declspec(dllexport) Uint16 check_image(const Uint16 *octets, Uint32 length) /* Открывает реальный валидатор для Python. */\n{ /* Начинает упаковку RS-октетов host-модели. */\nstatic Uint16 packed[64512]; /* Внешняя RAM ZONE7A содержит 0xFC00 слов. */\nUint32 i; /* Счётчик октетов проверяемого массива. */\nfor(i=0;i<(length+1)/2;++i) packed[i]=0; /* Исключает остатки предыдущего сценария. */\nfor(i=0;i<length;++i) packed[i/2] |= octets[i] << ((i&1)?0:8); /* Повторяет реальную упаковку RS_RX_Handler. */\nreturn validate_image(packed,length); /* Вызывает производственную проверку таблицы. */\n} /* Завершает экспортируемый тестовый адаптер. */\n' # Адаптер меняет только упаковку входа, не критерии проверки образа.
|
|
|
|
|
|
def block(address, words): # Формирует одну секцию таблицы SCI8 для проверок адресных границ.
|
|
return struct.pack('<HHH', len(words), address >> 16, address & 65535) + struct.pack('<' + 'H' * len(words), *words) # Длина выражена словами, адрес содержит старшую половину перед младшей.
|
|
|
|
|
|
header = b'\xaa\x08' + bytes(16) + struct.pack('<HH', 0x30, 0x10) # Точка входа 0x300010 следует после фиксированного FAB1.
|
|
signed = struct.unpack('<16H', contract.descriptor(0x300010, {0x300010: 0x1234, 0x300011: 0x5678})) # Формирует описание и CRC точных слов тестового кода.
|
|
valid = header + block(0x300000, signed) + block(0x300010, [0x1234, 0x5678]) + bytes(2) # Полный образ содержит FAB1, код ниже сектора A и терминатор SCI8.
|
|
with tempfile.TemporaryDirectory(prefix='flash-rs-test-') as directory: # Все промежуточные host-файлы принадлежат только текущей проверке.
|
|
directory = Path(directory) # Строит пути временной C-библиотеки и исходника.
|
|
model = directory / 'validator.c' # Модель содержит извлечённые производственные функции без аппаратных регистров.
|
|
model.write_text(prefix + helpers + validator + wrapper, encoding='utf-8') # Сохраняет русский текст комментариев в UTF-8.
|
|
library = directory / 'validator.dll' # Вызывает C-код через DLL вместо имитации алгоритма на Python.
|
|
subprocess.run([str(GCC), '-shared', '-std=c99', '-Wno-unknown-pragmas', '-include', str(PORT / 'f28335_flash_app.c'), str(model), '-o', str(library)], check=True) # Компилирует настоящий FAB1/CRC вместе с извлечённой структурной проверкой RS.
|
|
native = ctypes.CDLL(str(library)) # Загружает скомпилированную производственную проверку.
|
|
native.check_image.argtypes = [ctypes.POINTER(ctypes.c_uint16), ctypes.c_uint32] # Каждая октета тестового входа передаётся как отдельное слово адаптера.
|
|
native.check_image.restype = ctypes.c_uint16 # Сохраняет точный 16-битный код отказа загрузчика.
|
|
scenarios = [(valid, 0), (valid[:-2], 0x1002), (valid + bytes(2), 0x1002), (header + block(0x33FFF6, [1, 2]) + bytes(2), 0x1002)] # Проверяет структуру, терминатор, хвост и наличие загружаемого C runtime независимо от наличия локального build.
|
|
image = Path(os.environ.get('FLASH_RS_IMAGE', ROOT / 'Bin/ProtectedBoot20261019/application/rs/firmware_flash_rs.bin')) # Старый самостоятельный Flash намеренно не принимается новым защищённым контрактом.
|
|
if image.is_file(): # На компьютере без TI-сборки остаются обязательными все искусственные граничные сценарии.
|
|
scenarios.append((image.read_bytes(), 0)) # Production-валидатор MCU дополнительно принимает настоящий проверяемый SCI8, созданный hex2000.
|
|
for address in (0x2FFFFF, 0x340000, 0x33FF80, 0x33FFF8, 0x380400): # Адреса охватывают нижнюю/верхнюю границы, CSM и OTP в словах C28x.
|
|
scenarios.append((header + block(0x300000, [1]) + block(address, [1]) + block(0x33FFF6, [1, 2]) + bytes(2), 0x1002)) # Каждая запрещённая секция должна остановить запись до стирания.
|
|
scenarios.append((valid[:-2] + block(0x300000, [1]) + bytes(2), 0x1002)) # Перекрытие слов программы запрещено даже при правильном общем формате.
|
|
for payload, expected in scenarios: # Выполняет каждый сценарий на одном и том же производственном C-алгоритме.
|
|
octets = (ctypes.c_uint16 * len(payload))(*payload) # Предоставляет байты адаптеру с контролируемым размером.
|
|
assert native.check_image(octets, len(payload)) == expected # Код отказа должен совпадать с контрактом GUI и BIOS.
|
|
unload = ctypes.WinDLL('kernel32').FreeLibrary # Windows не позволяет удалить временный DLL, пока библиотека загружена процессом.
|
|
unload.argtypes = [ctypes.c_void_p] # Передаёт полный размер указателя на DLL в 64-битной среде Windows.
|
|
unload.restype = ctypes.c_int # Проверяет результат освобождения библиотеки перед очисткой каталога.
|
|
assert unload(native._handle) # Освобождает только DLL этой проверки, не затрагивая реальные файлы сборки.
|
|
print('PASS: production Flash RS validator, real image, CSM/OTP/range/overlap rejection') # Сообщает проверенные свойства без заявления о физической записи платы.
|