Подключить профили прошивки из JSON и подготовку Python для CCS/Keil. Добавить SCI-программатор F28335 и поддержку STM32 через J-Link. Обновить Linux-консоль, CAN485 и Modbus и проверки общих портов.
64 lines
9.1 KiB
Python
64 lines
9.1 KiB
Python
"""Тонкий ctypes-порт общего автомата SCI Boot F28335 и TI Flash Kernel A.""" # Формат таблицы, checksum и порядок обменов реализованы только в C99 templates.
|
|
import ctypes # Передаёт байтовые буферы и состояние через стабильный C ABI.
|
|
from .native import get_native_protocol # Использует ту же общую библиотеку, что остальные протоколы SETGUI.
|
|
|
|
|
|
def _api(): # Настраивает только сигнатуры новых функций без изменения существующего ABI.
|
|
lib = get_native_protocol().lib # Отсутствующее C-ядро остаётся явной ошибкой сборки приложения.
|
|
pointer, size, uint = ctypes.c_void_p, ctypes.c_size_t, ctypes.c_uint32 # Фиксированные типы отделяют порт от внутренней структуры C.
|
|
try: # Старый runtime должен сообщить о необходимости обновления вместо Python-fallback протокола.
|
|
signatures = {"c2000_sci_decode": ([pointer, size, pointer, size, ctypes.POINTER(size)], ctypes.c_int), "c2000_sci_validate": ([pointer, size, ctypes.c_int, ctypes.POINTER(uint), ctypes.POINTER(ctypes.c_uint16)], ctypes.c_int), "c2000_sci_session_size": ([], size), "c2000_sci_begin": ([pointer, size, pointer, size, pointer, size], ctypes.c_int), "c2000_sci_next": ([pointer, pointer, size, ctypes.POINTER(size), ctypes.POINTER(size), ctypes.POINTER(uint)], ctypes.c_int), "c2000_sci_accept": ([pointer, pointer, size], ctypes.c_int), "c2000_sci_progress": ([pointer], ctypes.c_uint), "c2000_sci_ulitco_enter": ([pointer, size], size)} # Сигнатуры соответствуют публичному c2000_sci.h.
|
|
for name, (arguments, result) in signatures.items(): # Настройка повторно безопасна для нескольких форм загрузчика.
|
|
function = getattr(lib, name) # Все символы обязаны присутствовать в собранной общей библиотеке.
|
|
function.argtypes, function.restype = arguments, result # ctypes проверяет типы и не усечёт указатели на x64.
|
|
except AttributeError as error: raise RuntimeError("Обновите библиотеку setprotocol: поддержка C2000 SCI отсутствует") from error # Запрещает незаметную подмену общего алгоритма кодом порта.
|
|
return lib # Возвращает библиотеку с проверенными экспортами нового протокола.
|
|
|
|
|
|
def _check(status): # Переводит детерминированные ошибки C в локализованное сообщение интерфейса.
|
|
messages = {-1: "Неверные параметры SCI", -2: "Недостаточный буфер SCI", -3: "Неверный ASCII SCI8 TI", -4: "Неверный заголовок SCI8", -5: "Обрезанная таблица SCI8 или отсутствующая точка входа", -6: "SCI8 содержит недопустимые адреса RAM/Flash или область CSM", -7: "SCI8 содержит пересекающиеся секции", -8: "Нарушена последовательность SCI Boot", -9: "Эхо или контрольная сумма загрузчика не совпали"} # Сообщения не повторяют проверку пакетов или вычисление checksum.
|
|
if status < 0: raise ValueError(messages.get(status, "Ошибка C2000 SCI: " + str(status))) # Любой отказ C останавливает передачу в аппаратном порту.
|
|
|
|
|
|
def decode(data): # Преобразует представление SCI8 общим C-декодером до работы с COM.
|
|
lib, raw = _api(), ctypes.create_string_buffer(data) # Сохраняет исходные байты на время вызова C.
|
|
output, written = ctypes.create_string_buffer(max(1, len(data))), ctypes.c_size_t() # Декодированный поток никогда не длиннее ASCII-источника.
|
|
_check(lib.c2000_sci_decode(raw, len(data), output, len(output), ctypes.byref(written))) # Проверку STX/ETX и шестнадцатеричных октетов выполняет общий модуль.
|
|
return output.raw[:written.value] # Возвращает только опубликованную C длину полного результата.
|
|
|
|
|
|
def validate(data, flash=True): # Получает сведения об образе без повторного разбора его полей в Python.
|
|
raw, entry, sectors = ctypes.create_string_buffer(data), ctypes.c_uint32(), ctypes.c_uint16() # Указатели результата имеют фиксированную разрядность ABI.
|
|
_check(_api().c2000_sci_validate(raw, len(data), int(flash), ctypes.byref(entry), ctypes.byref(sectors))) # Адреса, перекрытия и entry проверяются до загрузки ядра.
|
|
return entry.value, sectors.value # Адрес выражен словами C28x, sectors — маской TI Flash API.
|
|
|
|
|
|
def ulitco_enter(): # Возвращает штатный пакет перехода приложения UlitCo в загрузчик.
|
|
output = ctypes.create_string_buffer(10) # Формат текущего Monitor содержит ровно десять октетов.
|
|
size = _api().c2000_sci_ulitco_enter(output, len(output)) # Адрес параметра и формат команды остаются в общем C-ядре.
|
|
if size != 10: raise ValueError("Не удалось подготовить команду Monitor UlitCo") # Не передаёт устройству частичный управляющий запрос.
|
|
return output.raw[:size] # Порт отправляет байты без повторной сборки кадра.
|
|
|
|
|
|
class Session: # Владеет C-контекстом и буферами двух образов на всё время прошивки.
|
|
def __init__(self, kernel, image): # Проверяет оба образа до первого аппаратного действия.
|
|
self.lib = _api() # Одна библиотека обслуживает все шаги данного сеанса.
|
|
self.kernel, self.image = ctypes.create_string_buffer(kernel), ctypes.create_string_buffer(image) # Буферы не перемещаются и не освобождаются до завершения сеанса.
|
|
size = self.lib.c2000_sci_session_size() # Размер внутренней C-структуры не дублируется в ctypes.
|
|
self.storage = (ctypes.c_uint64 * ((size + 7) // 8))() # Выравнивает непрозрачный контекст минимум на восемь октетов для указателей x64.
|
|
_check(self.lib.c2000_sci_begin(self.storage, ctypes.sizeof(self.storage), self.kernel, len(kernel), self.image, len(image))) # Общая инициализация запрещает ошибочные таблицы до autobaud.
|
|
|
|
def next(self): # Получает готовое действие от детерминированного C-автомата.
|
|
tx, tx_size, rx_size, delay = ctypes.create_string_buffer(2054), ctypes.c_size_t(), ctypes.c_size_t(), ctypes.c_uint32() # 1024 слова и шесть октетов заголовка секции покрывают максимальную порцию TI.
|
|
state = self.lib.c2000_sci_next(self.storage, tx, len(tx), ctypes.byref(tx_size), ctypes.byref(rx_size), ctypes.byref(delay)) # Порт не вычисляет длину wire-пакета или checksum.
|
|
_check(state) # Ошибка последовательности запрещает дальнейшую передачу.
|
|
return state, tx.raw[:tx_size.value], rx_size.value, delay.value # Возвращает только операционные параметры ввода-вывода.
|
|
|
|
def accept(self, reply): # Передаёт полный ответ для проверки общему C-ядру.
|
|
raw = ctypes.create_string_buffer(reply) # Сохраняет исходные октеты без преобразования в Python-число checksum.
|
|
_check(self.lib.c2000_sci_accept(self.storage, raw, len(reply))) # Успешная проверка разрешает следующий шаг автомата.
|
|
|
|
@property # Прогресс отражает только подтверждённые этапы передачи.
|
|
def progress(self): # Представление не повторяет состояния алгоритма в Python.
|
|
return int(self.lib.c2000_sci_progress(self.storage)) # Значение 0..100 пригодно для штатной полосы GUI.
|