From 80d8fe1794a472a76c5712a3d8b20c32571e7aaa Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 13 Nov 2026 17:06:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B2=D1=85=D0=BE=D0=B4=20UlitCo=20=D0=B2=20SCI?= =?UTF-8?q?=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20Monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Передавать контрольную сумму команды перехода в загрузчик. Отправлять Monitor на 468750 бод и затем включать скорость SCI из JSON. Обновить эталонные проверки входа в загрузчик. --- c/set-protocol/src/c2000_sci.c | 2 +- c/set-protocol/tests/test_c2000_sci.c | 2 +- python/set_devices/qt_ports/c2000_sci_panel.py | 6 ++++-- python/tests/test_c2000_sci.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/c/set-protocol/src/c2000_sci.c b/c/set-protocol/src/c2000_sci.c index b72e00b..4f03e6f 100644 --- a/c/set-protocol/src/c2000_sci.c +++ b/c/set-protocol/src/c2000_sci.c @@ -101,6 +101,6 @@ int c2000_sci_accept(void *storage, const uint8_t *rx, size_t size) { /* Про } /* Завершает обработку подтверждения. */ unsigned c2000_sci_progress(const void *storage) { const sci_session_t *s = (const sci_session_t *)storage; return !s || !s->image_size ? 0 : s->phase == 9 ? 100 : (unsigned)((s->kernel_at * 20) / s->kernel_size + (s->image_at * 80) / s->image_size); } /* Передача ядра занимает 20 процентов, приложение — остальные 80 процентов шкалы. */ size_t c2000_sci_ulitco_enter(uint8_t *output, size_t capacity) { /* Использует только подтверждённую команду Monitor UlitCo из talk_with_monitor.c и param.c. */ - static const uint8_t request[10] = {247, 213, 255, 93, 0, 0, 1, 0, 0, 0}; /* Заголовок F7/D5, MONITOR_WRITE=255, FLASH_NUM=93, значение 1; текущая прошивка читает два последних октета без проверки CRC. */ + static const uint8_t request[10] = {247, 213, 255, 93, 0, 0, 1, 0, 93, 1}; /* Заголовок F7/D5, MONITOR_WRITE=255, FLASH_NUM=93, значение 1; контрольная сумма 255+93+1=349 (0x015D) передаётся младшим октетом вперёд и проверяется talk_with_monitor.c. */ if (!output || capacity < sizeof(request)) return 0; memcpy(output, request, sizeof(request)); return sizeof(request); /* Возвращает полный штатный десятиоктетный запрос без отправки на устройство. */ } /* Завершает общий кодек перехода UlitCo в первичный загрузчик. */ diff --git a/c/set-protocol/tests/test_c2000_sci.c b/c/set-protocol/tests/test_c2000_sci.c index f29e901..0f9fdbe 100644 --- a/c/set-protocol/tests/test_c2000_sci.c +++ b/c/set-protocol/tests/test_c2000_sci.c @@ -17,7 +17,7 @@ static void pause_ti(void *session) { /* Ожидание проверяется } /* Завершает проверку обязательной паузы. */ int main(void) { /* Выполняет эталонный сеанс и основные ошибочные случаи на общем C-ядре. */ void *session = malloc(c2000_sci_session_size()); uint8_t changed[sizeof(flash)], tx[2054], decoded[34]; size_t sent, received, written, i; uint32_t delay, entry; uint16_t sectors; /* Хранилище и выходные значения принадлежат host-тесту. */ - static const uint8_t sync[] = {'A'}, header_ack[] = {0x64,1}, block_ack[] = {0xC8,1}, monitor[] = {247,213,255,93,0,0,1,0,0,0}; /* Суммы эталона: заголовок 0x0164, секция 0x01C8; Monitor пишет параметр 93 значением 1. */ + static const uint8_t sync[] = {'A'}, header_ack[] = {0x64,1}, block_ack[] = {0xC8,1}, monitor[] = {247,213,255,93,0,0,1,0,93,1}; /* Суммы эталона: заголовок 0x0164, секция 0x01C8; Monitor пишет параметр 93 значением 1 и передаёт сумму 255+93+1=349 (0x015D) младшим октетом вперёд. */ static const uint8_t ascii[] = "\002 AA 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 02 00 00 00 00 90 12 34 56 78 00 00 \003\r\n"; /* Независимый ASCII-вектор TI содержит STX/ETX, а управляющие октеты не передаются MCU. */ CHECK(session != NULL); CHECK(c2000_sci_validate(ram, sizeof(ram), 0, &entry, §ors) == 0 && entry == 0x9000 && sectors == 0); /* RAM-ядро должно иметь реально загруженный entry и не включать Flash-секторы. */ CHECK(c2000_sci_validate(flash, sizeof(flash), 1, &entry, §ors) == 0 && entry == 0x328000 && sectors == 4); /* Прикладной эталон относится именно к сектору C F28335. */ diff --git a/python/set_devices/qt_ports/c2000_sci_panel.py b/python/set_devices/qt_ports/c2000_sci_panel.py index 239ec24..77d423b 100644 --- a/python/set_devices/qt_ports/c2000_sci_panel.py +++ b/python/set_devices/qt_ports/c2000_sci_panel.py @@ -56,13 +56,15 @@ class SciWorker(QThread): # Один сеанс владеет COM-портом serial = None # Ошибка проверки образа не должна даже открывать аппаратный интерфейс. try: # Все исключения превращаются в конечный результат GUI. session = Session(self.kernel, self.image) # Проверяет RAM-ядро и Flash-таблицу до любой управляющей команды. - serial = QSerialPort(); serial.setPortName(self.port); serial.setBaudRate(self.baud) # Использует точный COM-порт и скорость из формы/manifest. + serial = QSerialPort(); serial.setPortName(self.port); serial.setBaudRate(468750 if self.enter else self.baud) # Штатный Monitor ИБП работает на 468750 бит/с (MONITOR_BRR=9, LSPCLK=37,5 МГц); при ручном входе сразу используется скорость загрузчика из manifest. serial.setDataBits(QSerialPort.DataBits.Data8); serial.setParity(QSerialPort.Parity.NoParity); serial.setStopBits(QSerialPort.StopBits.OneStop); serial.setFlowControl(QSerialPort.FlowControl.NoFlowControl) # TI SCI Boot и первичный загрузчик UlitCo используют 8N1 без аппаратного управления потоком. if not serial.open(QIODevice.OpenModeFlag.ReadWrite): raise OSError(serial.errorString()) # Занятый терминалом порт не открывается вторым владельцем. serial.clear() # Старые данные терминала не должны стать ложным эхо autobaud. if self.enter: # Приложение UlitCo принимает переход в загрузчик лишь в разрешённом остановленном состоянии. self.progress.emit(0, "Переход UlitCo в первичный загрузчик…") # Показывает отдельный этап до передачи RAM-ядра. - self._write(serial, ulitco_enter()); self._pause(500); serial.clear() # Штатная команда Monitor №93 не подменяется BIOS ПМ35. + self._write(serial, ulitco_enter()); self._pause(500) # Отправляет проверенную команду Monitor №93 на скорости приложения и даёт штатному SCI-приёмнику 500 мс на подготовку autobaud. + if not serial.setBaudRate(self.baud): raise OSError("Не удалось переключить COM на скорость загрузчика SCI") # Только после выхода из приложения включает скорость RAM-ядра из manifest; отказ запрещает дальнейшую передачу. + serial.clear() # Остатки ответов Monitor не должны стать ложным эхом нового autobaud. while True: # Порядок обменов полностью определяется общим C-автоматом. self._cancelled(); state, tx, expected, delay = session.next() # Порт не вычисляет пакетные поля или checksum. if state == 0: break # Подтверждённые порции и отправленный терминатор завершили поток. diff --git a/python/tests/test_c2000_sci.py b/python/tests/test_c2000_sci.py index 855da8e..7921828 100644 --- a/python/tests/test_c2000_sci.py +++ b/python/tests/test_c2000_sci.py @@ -48,4 +48,4 @@ def test_ascii_decode_memory_ranges_and_monitor_command(): # Проверяет 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, 0, 0]) # Эталон совпадает с десятиоктетным Monitor-запросом FLASH_NUM=93 текущей прошивки UlitCo. + assert ulitco_enter() == bytes([247, 213, 255, 93, 0, 0, 1, 0, 93, 1]) # Эталон совпадает с десятиоктетным Monitor-запросом FLASH_NUM=93 текущей прошивки UlitCo.