From e2f00eca99a7069c2eede83b457bd18d761498b6 Mon Sep 17 00:00:00 2001 From: Ezra Maccabee Date: Tue, 30 Jun 2026 17:31:05 +0300 Subject: [PATCH] # firmware_test: TUI app current state --- .gitignore | 1 + tools/production/app/app.py | 14 +- tools/production/app/app.tcss | 13 + tools/production/app/firmware_client.py | 7 + tools/production/app/orchestrator.py | 80 +- .../app/screens/connection_watcher.py | 78 + tools/production/app/screens/diag/__init__.py | 71 +- tools/production/app/screens/diag/results.py | 65 +- .../production/app/screens/diag/test_list.py | 2 +- tools/production/app/screens/flash.py | 56 +- tools/production/app/screens/post_flash.py | 4 +- tools/production/app/screens/waiting.py | 35 +- tools/production/docs/INITIAL_PLAN.md | 488 +++++ tools/production/docs/TUI_PLAN.md | 7 + .../{TUI_REPORT.md => docs/TUI_REPORT_1.md} | 0 tools/production/docs/TUI_REPORT_2.md | 8 + tools/production/docs/TUI_SESSION.md | 121 ++ tools/production/docs/pics/FLASH.png | Bin 0 -> 56806 bytes tools/production/docs/pics/POST_FLASH.png | Bin 0 -> 45998 bytes tools/production/docs/pics/TEST_SCREEN.png | Bin 0 -> 88874 bytes tools/production/docs/pics/WAITING.png | Bin 0 -> 35099 bytes .../docs/pics/WAITING_AFTER_LOSS.png | Bin 0 -> 39786 bytes tools/production/service_tui.log | 1867 ----------------- 23 files changed, 1005 insertions(+), 1912 deletions(-) create mode 100644 tools/production/app/screens/connection_watcher.py create mode 100644 tools/production/docs/INITIAL_PLAN.md create mode 100644 tools/production/docs/TUI_PLAN.md rename tools/production/{TUI_REPORT.md => docs/TUI_REPORT_1.md} (100%) create mode 100644 tools/production/docs/TUI_REPORT_2.md create mode 100644 tools/production/docs/TUI_SESSION.md create mode 100644 tools/production/docs/pics/FLASH.png create mode 100644 tools/production/docs/pics/POST_FLASH.png create mode 100644 tools/production/docs/pics/TEST_SCREEN.png create mode 100644 tools/production/docs/pics/WAITING.png create mode 100644 tools/production/docs/pics/WAITING_AFTER_LOSS.png delete mode 100644 tools/production/service_tui.log diff --git a/.gitignore b/.gitignore index 36a74bd..342ec63 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ build* Testing/ !docs/testing !build.just +service_tui.log # Файлы настройки среды разработки .project diff --git a/tools/production/app/app.py b/tools/production/app/app.py index 51d95b5..f8085ca 100644 --- a/tools/production/app/app.py +++ b/tools/production/app/app.py @@ -59,8 +59,16 @@ class ServiceApp(App): """ После прошивки: - firmware_test + успех → PostFlashScreen (промпт смены BootMode) - - всё остальное (production/custom, либо ошибка) → сразу WaitingScreen + - всё остальное (production/custom, либо ошибка) → WaitingScreen + - target=None — маркер потери соединения (см. ConnectionWatcherMixin) + → WaitingScreen с явной причиной возврата """ + if event.target is None and not event.success: + self.switch_screen( + WaitingScreen(disconnect_reason="Соединение с платой потеряно") + ) + return + if event.success and event.target == FlashTarget.FIRMWARE_TEST: self.switch_screen(PostFlashScreen()) else: @@ -72,10 +80,10 @@ class ServiceApp(App): self.switch_screen(WaitingScreen()) @on(DiagScreen.DiagDone) - def _on_diag_done(self) -> None: + def _on_diag_done(self, event: DiagScreen.DiagDone) -> None: """После диагностики — отключиться, вернуться в Waiting.""" self._disconnect() - self.switch_screen(WaitingScreen()) + self.switch_screen(WaitingScreen(disconnect_reason=event.reason)) # ── Подключение к firmware_test ─────────────────────────────────────────── diff --git a/tools/production/app/app.tcss b/tools/production/app/app.tcss index b967115..969a812 100644 --- a/tools/production/app/app.tcss +++ b/tools/production/app/app.tcss @@ -38,6 +38,19 @@ AppFrame { text-style: bold; } +#waiting-reason { + margin-top: 1; + padding: 1 2; + border: round $warning; + color: $warning; + text-style: bold; + content-align: center middle; +} + +#waiting-reason.hidden { + display: none; +} + #waiting-hint { margin-top: 2; color: $text-muted; diff --git a/tools/production/app/firmware_client.py b/tools/production/app/firmware_client.py index b872bf6..aa01df0 100644 --- a/tools/production/app/firmware_client.py +++ b/tools/production/app/firmware_client.py @@ -159,6 +159,12 @@ class FirmwareClient: """ Читать события до получения одного из stop_types или таймаута. Генератор — yield каждого полученного события. + + При таймауте yield-ит синтетическое событие + {"type": "_timeout", "timeout_s": ...} перед завершением — вызывающий + код (Orchestrator) должен явно обработать этот тип и не путать его + с обрывом связи без объяснения причины. Префикс "_" отличает это + от реальных событий протокола firmware_test. """ loop = asyncio.get_running_loop() deadline = loop.time() + timeout_s @@ -171,6 +177,7 @@ class FirmwareClient: if event.get("type") in stop_types: return logger.warning("_recv_until timeout after %.1f s", timeout_s) + yield {"type": "_timeout", "timeout_s": timeout_s} # ── Public API ────────────────────────────────────────────────────────── diff --git a/tools/production/app/orchestrator.py b/tools/production/app/orchestrator.py index bb18905..95a1d06 100644 --- a/tools/production/app/orchestrator.py +++ b/tools/production/app/orchestrator.py @@ -28,6 +28,11 @@ orchestrator.py — оркестратор confirm_request для TUI. "btn*" → buttons (нет confirm, ждём test_result) всё остальное → operator (показать prompt) +Помимо confirm_request, протокол v2 определяет "progress" — внутришаговые +информационные события долгих тестов (сейчас только usd: card_detect, +mount, write, read_compare — см. docs/testing/PROTOCOL.md). Эти события +не требуют ответа, только отображаются как текущая фаза прогресса. + Публичный API: Orchestrator.run_tests(test_ids) — запустить тесты, yield OrchestratorEvent """ @@ -67,6 +72,9 @@ _CAN_RX_DATA = [0xDE, 0xAD, 0xBE, 0xEF] _CAN_TX_ID = 0x200 _CAN_TX_DATA = [0xCA, 0xFE, 0xBA, 0xBE] +# Тип события от FirmwareClient._recv_until() сигнализирующий таймаут чтения +_TIMEOUT_EVENT_TYPE = "_timeout" + # ── Типы событий оркестратора ──────────────────────────────────────────── @@ -74,11 +82,12 @@ _CAN_TX_DATA = [0xCA, 0xFE, 0xBA, 0xBE] class OrchestratorEventType(Enum): TEST_BEGIN = auto() # тест начался TEST_RESULT = auto() # тест завершился + TEST_PROGRESS = auto() # внутришаговый прогресс долгого теста (usd и т.п.) CONFIRM_NEEDED = auto() # нужен ответ оператора (standalone) CONFIRM_RESOLVED = auto() # HIL confirm выполнен автоматически BUTTONS_PROMPT = auto() # показать инструкцию для buttons (без confirm) SUMMARY = auto() # итог всей сессии - ERROR = auto() # ошибка протокола или M5 + ERROR = auto() # ошибка протокола, M5, или обрыв по таймауту @dataclass @@ -137,14 +146,24 @@ class Orchestrator: Yields OrchestratorEvent в порядке поступления событий от firmware_test. Блокируется на CONFIRM_NEEDED до вызова resolve_operator_confirm(). + + Гарантия для вызывающего кода: генератор ВСЕГДА заканчивается событием + SUMMARY — либо настоящим (от firmware), либо синтетическим при обрыве + потока (таймаут чтения порта истёк раньше, чем пришёл summary). + Без этой гарантии TUI не может надёжно понять, что прогон завершился + (именно это вызывало зависание кнопок при таймауте — см. отчёт). """ + current_test_id = "" + got_summary = False + async for raw in self._fw.run_selected(test_ids): event_type = raw.get("type", "") if event_type == "test_begin": + current_test_id = raw.get("id", "") yield OrchestratorEvent( type=OrchestratorEventType.TEST_BEGIN, - test_id=raw.get("id", ""), + test_id=current_test_id, test_name=raw.get("name", ""), ) @@ -161,12 +180,24 @@ class Orchestrator: duration_ms=raw.get("ms", 0), detail=raw.get("detail", ""), ) + current_test_id = "" yield OrchestratorEvent( type=OrchestratorEventType.TEST_RESULT, test_id=result.id, result=result, ) + elif event_type == "progress": + # Внутришаговый прогресс долгого теста (сейчас только usd). + # Не ошибка — информационное событие, не требует ответа. + step = raw.get("step", "") + pstat = raw.get("status", "") + yield OrchestratorEvent( + type=OrchestratorEventType.TEST_PROGRESS, + test_id=raw.get("test", current_test_id), + message=f"{step}: {pstat}" if step else "progress", + ) + elif event_type == "confirm_request": confirm = ConfirmRequest( id=raw.get("id", ""), @@ -177,16 +208,57 @@ class Orchestrator: yield ev elif event_type == "summary": + got_summary = True yield OrchestratorEvent( type=OrchestratorEventType.SUMMARY, summary=raw, ) - else: + elif event_type == _TIMEOUT_EVENT_TYPE: + # Чтение порта оборвалось по таймауту раньше, чем пришёл + # summary. Завершаем текущий тест (если он был в RUNNING) + # синтетическим FAIL, чтобы таблица результатов не осталась + # с тестом, навечно подвисшим в "выполняется". + timeout_s = raw.get("timeout_s", 0) + logger.error( + "Test run aborted: read timeout after %.0fs, current_test=%r", + timeout_s, + current_test_id, + ) + if current_test_id: + yield OrchestratorEvent( + type=OrchestratorEventType.TEST_RESULT, + test_id=current_test_id, + result=TestResult( + id=current_test_id, + status=TestStatus.FAIL, + duration_ms=0, + detail=f"таймаут связи ({timeout_s:.0f}с)", + ), + ) yield OrchestratorEvent( type=OrchestratorEventType.ERROR, - message=raw.get("error", f"unknown event: {event_type}"), + message=f"Связь с платой прервана (таймаут {timeout_s:.0f}с)", ) + # break, не return — нужно дойти до synthetic summary ниже + break + + else: + # Неизвестный, но не критичный тип события — логируем для + # разработчика, не показываем оператору как ошибку (см. + # отчёт замечание №2: ранее "progress" ошибочно считался + # неизвестным событием до того как протокол был сверен). + logger.debug("Unhandled protocol event: %r", raw) + + if not got_summary: + # Поток событий оборвался (таймаут или обрыв соединения) без + # настоящего summary от firmware — синтезируем его, чтобы + # вызывающий код (DiagScreen._run_worker) гарантированно вышел + # из ожидания и разблокировал кнопки/чекбоксы. + yield OrchestratorEvent( + type=OrchestratorEventType.SUMMARY, + summary={"overall": "fail", "passed": 0, "failed": 0, "aborted": True}, + ) # ── Маршрутизация confirm ──────────────────────────────────────────── diff --git a/tools/production/app/screens/connection_watcher.py b/tools/production/app/screens/connection_watcher.py new file mode 100644 index 0000000..742fcfb --- /dev/null +++ b/tools/production/app/screens/connection_watcher.py @@ -0,0 +1,78 @@ +""" +connection_watcher.py — мониторинг USB-соединения для экранов FlashScreen +и DiagScreen. + +Периодически (каждые _WATCH_INTERVAL_S) проверяет, виден ли таргет ещё +на шине USB. При потере соединения — экран обязан немедленно прекратить +любое взаимодействие (кроме кнопки "Выйти") и вернуться на WaitingScreen. +Решение архитектурно: при разрыве сессия считается недостоверной и +не восстанавливается — экран не пытается определить "вернулась ли та же +самая плата", просто стартует заново с нуля. + +Используется как миксин: класс экрана наследует ConnectionWatcherMixin +вторым родителем после Screen, вызывает self._start_connection_watch(check_fn) +в on_mount(), и переопределяет _on_connection_lost() для специфичной +очистки экрана перед уходом на WaitingScreen. +""" + +from __future__ import annotations + +from typing import Callable + +from textual.message import Message +from textual.timer import Timer + +_WATCH_INTERVAL_S = 1.5 + + +class ConnectionLost(Message): + """ + Соединение с платой потеряно во время нахождения на экране. + Экран должен прекратить взаимодействие и вернуться на WaitingScreen. + """ + + +class ConnectionWatcherMixin: + """ + Миксин периодической проверки USB-соединения. + + Использование в экране:: + + class FlashScreen(Screen, ConnectionWatcherMixin): + def on_mount(self) -> None: + self._start_connection_watch(Flasher.detect_sdp) + + def on_unmount(self) -> None: + self._stop_connection_watch() + """ + + _connection_watch_timer: Timer | None = None + _connection_lost: bool = False + + def _start_connection_watch(self, check_fn: Callable[[], bool]) -> None: + """ + Запустить периодическую проверку. check_fn должна вернуть True + пока устройство видно на шине (Flasher.detect_sdp / detect_cdc). + """ + self._connection_lost = False + self._connection_check_fn = check_fn + self._connection_watch_timer = self.set_interval( # type: ignore[attr-defined] + _WATCH_INTERVAL_S, self._check_connection + ) + + def _stop_connection_watch(self) -> None: + if self._connection_watch_timer is not None: + self._connection_watch_timer.stop() + self._connection_watch_timer = None + + def _check_connection(self) -> None: + if self._connection_lost: + return + try: + still_present = self._connection_check_fn() + except Exception: + still_present = False + if not still_present: + self._connection_lost = True + self._stop_connection_watch() + self.post_message(ConnectionLost()) # type: ignore[attr-defined] diff --git a/tools/production/app/screens/diag/__init__.py b/tools/production/app/screens/diag/__init__.py index b75f691..27cc051 100644 --- a/tools/production/app/screens/diag/__init__.py +++ b/tools/production/app/screens/diag/__init__.py @@ -7,6 +7,13 @@ DiagScreen координирует три виджета: ConfirmPanel — confirm_request оператора (нижняя панель) и Orchestrator — маршрутизатор confirm_request. + +Мониторинг соединения (см. отчёт, замечание №4): пока тесты не запущены, +каждые 1.5с проверяется наличие CDC-порта на шине. Во время активного +прогона мониторинг приостановлен — таймаут чтения порта внутри Orchestrator +уже детектирует обрыв связи надёжнее (видит реальную остановку потока +данных, а не просто исчезновение устройства из списка портов) и сам +формирует понятный результат для прерванного теста. """ from __future__ import annotations @@ -24,10 +31,12 @@ from textual.screen import Screen from textual.widgets import Button, Label, ProgressBar, Static from ...firmware_client import FirmwareClient +from ...flasher import Flasher from ...m5_client import M5Client from ...models import SessionState from ...orchestrator import Orchestrator, OrchestratorEvent, OrchestratorEventType from ...widgets import AppFrame +from ..connection_watcher import ConnectionLost, ConnectionWatcherMixin from .confirm_panel import ConfirmPanel from .results import ResultsPanel from .test_list import TestListPanel @@ -35,7 +44,7 @@ from .test_list import TestListPanel logger = logging.getLogger(__name__) -class DiagScreen(Screen): +class DiagScreen(Screen, ConnectionWatcherMixin): """ Экран диагностики. @@ -52,6 +61,10 @@ class DiagScreen(Screen): class DiagDone(Message): """Сессия диагностики завершена.""" + def __init__(self, reason: Optional[str] = None) -> None: + super().__init__() + self.reason = reason + def __init__( self, firmware: FirmwareClient, @@ -70,9 +83,9 @@ class DiagScreen(Screen): with AppFrame(id="diag-frame"): # Шапка — фиксированная высота 3 with Horizontal(id="diag-header"): - yield Static("firmware_test: —\nFw: —", id="diag-header-fw") + yield Static("fw: —", id="diag-header-fw") yield Static("MCU ID: —", id="diag-header-uid") - yield Static("M5: —", id="diag-header-m5") + yield Static("M5 Bench: —", id="diag-header-m5") # Рабочая зона: список тестов + результаты — занимает всё # оставшееся место (1fr), сама прокручивается при переполнении @@ -84,30 +97,50 @@ class DiagScreen(Screen): # имеет classes="hidden" по умолчанию — height: auto + display: # none даёт нулевую высоту, не отнимая место у остального layout. with Vertical(id="diag-progress-row", classes="hidden"): - yield ProgressBar(id="diag-progress-bar", show_eta=False) + yield ProgressBar( + id="diag-progress-bar", show_eta=False, show_percentage=False + ) yield Label("", id="diag-progress-label") # Кнопки запуска — фиксированная высота 3 (под border Button) with Horizontal(id="diag-btn-row"): yield Button( - "▶ Запустить выбранные", + "▶ Запустить выбранные тесты", id="diag-btn-run-selected", variant="primary", disabled=True, ) yield Button( - "▶▶ Все тесты", + "▶▶ Запустить все тесты", id="diag-btn-run-all", variant="default", disabled=True, ) - yield Button("✕ Выйти", id="diag-btn-quit", variant="default") + yield Button( + "✕ Выйти из приложения", id="diag-btn-quit", variant="default" + ) # Панель confirm — auto-высота, видна только когда есть запрос yield ConfirmPanel(id="diag-confirm", classes="hidden") def on_mount(self) -> None: self._init_session() + self._start_connection_watch(self._check_cdc_present) + + def on_unmount(self) -> None: + self._stop_connection_watch() + + def _check_cdc_present(self) -> bool: + # Не считаем потерей соединения во время активного прогона — + # Orchestrator сам детектирует обрыв через таймаут чтения порта + # (надёжнее: видит остановку потока данных, не просто список USB). + if self._tests_running: + return True + return Flasher.detect_cdc() + + @on(ConnectionLost) + def _on_connection_lost(self) -> None: + self.post_message(self.DiagDone(reason="Соединение с платой потеряно")) # ── Инициализация сессии ───────────────────────────────────────────────── @@ -118,7 +151,7 @@ class DiagScreen(Screen): uid = await self._fw.get_uid() except Exception as exc: logger.error("Session init failed: %s", exc) - self.post_message(self.DiagDone()) + self.post_message(self.DiagDone(reason="Не удалось получить список тестов")) return self._session.tests = tests @@ -135,17 +168,17 @@ class DiagScreen(Screen): def _update_header(self) -> None: self.query_one("#diag-header-fw", Static).update( - f"firmware_test: {self._session.fw_version or '?'}" + f"fw: {self._session.fw_version or '?'}" ) uid = self._session.chip_uid or "—" self.query_one("#diag-header-uid", Static).update(f"MCU ID: {uid}") m5_widget = self.query_one("#diag-header-m5", Static) if self._session.m5_connected: - m5_widget.update("M5: ✓ подключён") + m5_widget.update("M5 Bench: ✓ подключён") m5_widget.remove_class("m5-absent") else: - m5_widget.update("M5: ✕ не подключен") + m5_widget.update("M5 Bench: ✕ нет связи") m5_widget.add_class("m5-absent") # ── Кнопки ─────────────────────────────────────────────────────────────── @@ -234,6 +267,13 @@ class DiagScreen(Screen): self._session.set_result(event.result) results.set_result(event.result) + elif event.type == OrchestratorEventType.TEST_PROGRESS: + # Внутришаговый прогресс долгого теста (сейчас только usd): + # card_detect, mount, write, read_compare — см. PROTOCOL.md. + self._update_progress( + done, total, f"Тест: {event.test_id} — {event.message}" + ) + elif event.type == OrchestratorEventType.CONFIRM_NEEDED: assert event.confirm is not None confirm.show_operator( @@ -242,7 +282,7 @@ class DiagScreen(Screen): ) elif event.type == OrchestratorEventType.CONFIRM_RESOLVED: - self._update_progress(done, total, f"HIL: {event.message}") + self._update_progress(done, total, f"M5 Bench: {event.message}") elif event.type == OrchestratorEventType.BUTTONS_PROMPT: assert event.confirm is not None @@ -255,6 +295,13 @@ class DiagScreen(Screen): self._update_progress(done, total, f"⚠ {event.message}") def _on_summary(self, summary: dict) -> None: + aborted = summary.get("aborted", False) + if aborted: + self.query_one("#diag-progress-label", Label).update( + "⚠ Прогон прерван: связь с платой потеряна" + ) + return + overall = summary.get("overall", "fail") passed = summary.get("passed", 0) failed = summary.get("failed", 0) diff --git a/tools/production/app/screens/diag/results.py b/tools/production/app/screens/diag/results.py index 5879bd3..fadeecd 100644 --- a/tools/production/app/screens/diag/results.py +++ b/tools/production/app/screens/diag/results.py @@ -8,6 +8,10 @@ DataTable с колонками: Тест | HIL | Статус | Время | Д внутри групп статусов — исходный порядок реестра firmware_test. Строка с FAIL дополнительно подсвечивается красным фоном целиком. +Колонка "Детали" переносит длинный текст на несколько строк внутри ячейки +(а не обрезает) — высота строки для FAIL вычисляется по длине detail +относительно ширины колонки. Остальные статусы всегда однострочные. + Публичный API: ResultsPanel.populate(tests) — показать пустую таблицу (PENDING) ResultsPanel.set_running(test_id) — пометить тест как выполняющийся @@ -17,6 +21,8 @@ DataTable с колонками: Тест | HIL | Статус | Время | Д from __future__ import annotations +import math + from rich.style import Style from rich.text import Text from textual.app import ComposeResult @@ -47,6 +53,12 @@ _STATUS_DISPLAY: dict[TestStatus, tuple[str, str]] = { _FAIL_BG = "dark_red" +# Ширина колонки "Детали" в символах — должна совпадать с шириной, +# заданной явно в on_mount() через table.add_column("Детали", width=...). +# Используется для расчёта высоты строки под перенос текста. +_DETAIL_COL_WIDTH = 21 +_MAX_ROW_HEIGHT = 4 # не даём одной FAIL-строке занять весь экран + class ResultsPanel(Widget): """Правая колонка DiagScreen — таблица результатов тестов.""" @@ -70,7 +82,16 @@ class ResultsPanel(Widget): def on_mount(self) -> None: table = self.query_one("#results-table", DataTable) - table.add_columns("Тест", "M5", "Статус", "Время", "Детали") + # add_columns() (множественное число) не принимает width — без явной + # ширины колонка "Детали" сжимается до длины заголовка ("Детали" = 6 + # символов) и обрезает любой более длинный текст, даже однострочный. + # Используем add_column() по одной с явной шириной под каждую, + # рассчитанной под ResultsPanel { width: 70 } (см. app.tcss). + table.add_column("Тест", width=22) + table.add_column("M5 Bench", width=8) + table.add_column("Статус", width=8) + table.add_column("Время", width=6) + table.add_column("Детали", width=21) # ── Public API ──────────────────────────────────────────────────────────── @@ -124,12 +145,25 @@ class ResultsPanel(Widget): # ── Internal: строки таблицы ──────────────────────────────────────────── + def _row_height(self, detail: str) -> int: + """ + Сколько строк нужно ячейке "Детали" под перенос текста. + 1 строка по умолчанию; растёт пропорционально длине detail, + ограничено _MAX_ROW_HEIGHT чтобы один FAIL не съел весь экран + (очень длинный detail в этом случае обрежется — лучше, чем + одна строка съедает половину видимой таблицы). + """ + if not detail: + return 1 + needed = math.ceil(len(detail) / _DETAIL_COL_WIDTH) + return max(1, min(needed, _MAX_ROW_HEIGHT)) + def _add_row( self, test: TestInfo, status: TestStatus, duration_ms: int, detail: str ) -> None: table = self.query_one("#results-table", DataTable) cells = self._row_cells(test, status, duration_ms, detail) - table.add_row(*cells, key=test.id) + table.add_row(*cells, key=test.id, height=self._row_height(detail)) def _update_row( self, test_id: str, status: TestStatus, duration_ms: int, detail: str @@ -141,16 +175,28 @@ class ResultsPanel(Widget): table = self.query_one("#results-table", DataTable) cells = self._row_cells(test, status, duration_ms, detail) - col_keys = [c.key for c in table.ordered_columns] - for col_key, value in zip(col_keys, cells): - table.update_cell(test_id, col_key, value) + new_height = self._row_height(detail) + + # DataTable не предоставляет публичный API для изменения высоты + # уже добавленной строки (update_cell меняет только содержимое). + # Когда нужная высота отличается от текущей (например, тест перешёл + # в FAIL с многострочным detail) — пересоздаём строку: remove + add. + # Иначе — точечный update_cell, дешевле и не теряет курсор/scroll. + current_height = table.get_row_height(test_id) + if current_height != new_height: + table.remove_row(test_id) + table.add_row(*cells, key=test_id, height=new_height) + else: + col_keys = [c.key for c in table.ordered_columns] + for col_key, value in zip(col_keys, cells): + table.update_cell(test_id, col_key, value) self._resort(table) def _row_cells( self, test: TestInfo, status: TestStatus, duration_ms: int, detail: str ) -> tuple: - """Собрать пять ячеек строки с учётом подсветки FAIL.""" + """Собрать пять ячеек строки с учётом подсветки FAIL и переноса текста.""" status_text, status_color = _STATUS_DISPLAY[status] is_fail = status == TestStatus.FAIL @@ -166,12 +212,17 @@ class ResultsPanel(Widget): time_text = f"{duration_ms / 1000:.1f}с" if duration_ms > 0 else "" hil_text = "[*]" if test.requires_hil else "[-]" + # overflow="fold" — перенос по символам на границе ячейки вместо + # обрезания с многоточием (Textual default), detail виден целиком + # на нескольких строках, если высота строки это позволяет. + detail_cell = Text(detail, style=detail_style, overflow="fold") + return ( Text(test.name, style=name_style), Text(hil_text, style=hil_style), Text(status_text, style=status_style), Text(time_text, style=time_style), - Text(detail, style=detail_style), + detail_cell, ) def _resort(self, table: DataTable) -> None: diff --git a/tools/production/app/screens/diag/test_list.py b/tools/production/app/screens/diag/test_list.py index f3dfd49..068f8f9 100644 --- a/tools/production/app/screens/diag/test_list.py +++ b/tools/production/app/screens/diag/test_list.py @@ -32,7 +32,7 @@ class TestListPanel(Widget): self._hil_unavailable: dict[str, bool] = {} def compose(self) -> ComposeResult: - yield Label("Тесты", classes="section-title") + yield Label("Доступные тесты", classes="section-title") with Horizontal(id="test-list-select-row"): yield Button( "Выбрать все", id="test-list-select-all", classes="-textual-compact" diff --git a/tools/production/app/screens/flash.py b/tools/production/app/screens/flash.py index c5b0e92..96c3782 100644 --- a/tools/production/app/screens/flash.py +++ b/tools/production/app/screens/flash.py @@ -31,16 +31,24 @@ from textual.widgets import ( from ..flasher import Flasher from ..models import FlashProgress, FlashTarget from ..widgets import AppFrame +from .connection_watcher import ConnectionLost, ConnectionWatcherMixin logger = logging.getLogger(__name__) -class FlashScreen(Screen): +class FlashScreen(Screen, ConnectionWatcherMixin): """ Экран прошивки. Messages: FlashDone(success, target) — прошивка завершена + + Мониторинг соединения: пока плата не прошивается (self._flashing + == False), каждые 1.5с проверяется наличие BootROM SDP на шине. + Если плата физически отключена в простое — сессия считается + недостоверной, экран сразу уходит на WaitingScreen (см. замечание + №4 отчёта). Во время самой прошивки/erase мониторинг приостановлен — + обрыв в этом случае обнаружит и обработает сам flash_usb.py subprocess. """ BINDINGS = [ @@ -61,12 +69,12 @@ class FlashScreen(Screen): def compose(self) -> ComposeResult: with AppFrame(id="flash-frame"): yield Label( - "⚡ Загрузка прошивки на плату (BootROM SDP обнаружен)", + "⚡ Загрузка прошивки на плату индикатора (режим BootROM)", id="flash-title", ) with Vertical(id="flash-target-group"): - yield Label("Выберите файл для загрузки", classes="section-title") + yield Label("Выбор загружаемой прошивки", classes="section-title") with RadioSet(id="flash-radio"): yield RadioButton( "Диагностическая прошивка (firmware_test)", @@ -78,25 +86,47 @@ class FlashScreen(Screen): id="radio-production", ) yield RadioButton( - "Другое (подготовленный бинарный файл)", + "Другое", id="radio-custom", ) with Horizontal(id="flash-custom-path", classes="hidden"): yield Input( - placeholder="Путь к бинарному файлу (.bin)", + placeholder="Имя бинарного файла в custom_binaries/ (.bin)", id="flash-custom-input", ) with Horizontal(id="flash-btn-row"): - yield Button("▶ Загрузить ПО", id="flash-btn-flash", variant="warning") + yield Button("▶ Загрузить", id="flash-btn-flash", variant="warning") yield Button("⚠ Очистить память", id="flash-btn-erase", variant="error") yield Button( - "✕ Выйти из программы", id="flash-btn-quit", variant="default" + "✕ Выйти из приложения", id="flash-btn-quit", variant="default" ) - yield ProgressBar(id="flash-progress-bar", show_eta=False, classes="hidden") + yield ProgressBar( + id="flash-progress-bar", + show_eta=False, + show_percentage=False, + classes="hidden", + ) yield Log(id="flash-log", auto_scroll=True) + def on_mount(self) -> None: + self._start_connection_watch(self._check_sdp_present) + + def on_unmount(self) -> None: + self._stop_connection_watch() + + def _check_sdp_present(self) -> bool: + # Не считаем потерей соединения, если идёт активная операция — + # flash_usb.py сам обработает реальный обрыв через subprocess. + if self._flashing: + return True + return Flasher.detect_sdp() + + @on(ConnectionLost) + def _on_connection_lost(self) -> None: + self.post_message(self.FlashDone(success=False, target=None)) + # ── Обработчики ─────────────────────────────────────────────────────────── @on(RadioSet.Changed, "#flash-radio") @@ -114,7 +144,7 @@ class FlashScreen(Screen): return target, bin_path = self._resolve_target() if target is None: - self._log("⚠ Укажите путь к бинарному файлу!") + self._log("⚠ Укажите корректное имя бинарного файла") return self._do_flash(target, bin_path) @@ -153,15 +183,11 @@ class FlashScreen(Screen): async def _do_erase(self) -> None: self._set_busy(True) self._show_progress(True) - self._log("⚠ Очистка флеш памяти (~30 с)...") + self._log("⚠ Очистка памяти (~30 с)...") ok = await self._flasher.erase_chip(progress_cb=self._on_progress) self._set_busy(False) self._finish_progress(ok) - self._log( - "✅ Очистка флеш памяти завершена" - if ok - else "❌ Очистка флеш памяти: ошибка" - ) + self._log("✅ Очистка памяти завершена" if ok else "❌ Очистка памяти: ошибка") # ── Вспомогательные ─────────────────────────────────────────────────────── diff --git a/tools/production/app/screens/post_flash.py b/tools/production/app/screens/post_flash.py index 891ba3e..aaf103d 100644 --- a/tools/production/app/screens/post_flash.py +++ b/tools/production/app/screens/post_flash.py @@ -60,7 +60,9 @@ class PostFlashScreen(Screen): with Horizontal(id="post-flash-btn-row"): yield Button("✓ Готово", id="post-flash-btn-ok", variant="success") - yield Button("✕ Выйти", id="post-flash-btn-quit", variant="default") + yield Button( + "✕ Выйти из приложения", id="post-flash-btn-quit", variant="default" + ) def on_mount(self) -> None: self._update_countdown() diff --git a/tools/production/app/screens/waiting.py b/tools/production/app/screens/waiting.py index fbd9c42..12818c4 100644 --- a/tools/production/app/screens/waiting.py +++ b/tools/production/app/screens/waiting.py @@ -3,10 +3,19 @@ waiting.py — экран ожидания подключения платы. Опрашивает USB каждые _DETECT_INTERVAL_S секунд через Flasher. При обнаружении SDP или CDC отправляет DeviceDetected message в App. + +Принимает опциональный disconnect_reason — короткое сообщение о причине +возврата на этот экран (например, "Соединение с платой потеряно"), +показывается несколько секунд поверх обычной подсказки, затем исчезает +само. Нужно, чтобы потеря USB во время прошивки/диагностики (см. отчёт, +замечание №4) не выглядела как необъяснимый скачок экрана — сервисник +должен понимать, что это осознанное поведение, а не баг. """ from __future__ import annotations +from typing import Optional + from textual.app import ComposeResult from textual.css.query import NoMatches from textual.message import Message @@ -20,6 +29,7 @@ from ..widgets import AppFrame _DETECT_INTERVAL_S = 1.5 _SPIN_INTERVAL_S = 0.1 +_REASON_DISPLAY_S = 4.0 _SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] @@ -38,27 +48,46 @@ class WaitingScreen(Screen): super().__init__() self.mode = mode - def __init__(self, **kwargs) -> None: + def __init__(self, disconnect_reason: Optional[str] = None, **kwargs) -> None: super().__init__(**kwargs) + self._disconnect_reason = disconnect_reason self._spinner_idx: int = 0 self._detect_timer: Timer | None = None self._spin_timer: Timer | None = None + self._reason_timer: Timer | None = None def compose(self) -> ComposeResult: with AppFrame(id="waiting-frame"): yield Static("TFT Indicator Board\nService Tool", id="waiting-logo") - yield Static("Подключите плату к USB...", id="waiting-hint") + yield Static("", id="waiting-reason", classes="hidden") + yield Static("Подключите плату индикатора к USB...", id="waiting-hint") yield Static(_SPINNER_FRAMES[0], id="waiting-spinner") def on_mount(self) -> None: self._detect_timer = self.set_interval(_DETECT_INTERVAL_S, self._poll_usb) self._spin_timer = self.set_interval(_SPIN_INTERVAL_S, self._spin) + if self._disconnect_reason: + self._show_reason(self._disconnect_reason) def on_unmount(self) -> None: self._stop_timers() # ── Internal ────────────────────────────────────────────────────────────── + def _show_reason(self, reason: str) -> None: + try: + self.query_one("#waiting-reason", Static).update(f"⚠ {reason}") + self.query_one("#waiting-reason").remove_class("hidden") + except NoMatches: + return + self._reason_timer = self.set_timer(_REASON_DISPLAY_S, self._hide_reason) + + def _hide_reason(self) -> None: + try: + self.query_one("#waiting-reason").add_class("hidden") + except NoMatches: + pass + def _spin(self) -> None: self._spinner_idx = (self._spinner_idx + 1) % len(_SPINNER_FRAMES) try: @@ -81,3 +110,5 @@ class WaitingScreen(Screen): self._detect_timer.stop() if self._spin_timer: self._spin_timer.stop() + if self._reason_timer: + self._reason_timer.stop() diff --git a/tools/production/docs/INITIAL_PLAN.md b/tools/production/docs/INITIAL_PLAN.md new file mode 100644 index 0000000..7fa9d46 --- /dev/null +++ b/tools/production/docs/INITIAL_PLAN.md @@ -0,0 +1,488 @@ +# firmware_test — План разработки + +> Версия: 0.8 | Обновлён после завершения Этапа 6г (bsp_mqs + test_mqs, hardware-verified). + +--- + +## Контекст проекта + +**Цель прошивки:** диагностика платы MIMXRT1052CVJ5B на сервисе (возврат по рекламации). +Запускается через BootROM (USB SDP), без предварительной прошивки загрузчика. + +**Стенд:** + +- Хост подключается через USB CDC ACM — единственный канал firmware_test +- HIL-тесты управляются через M5StampPLC (опционально) +- TUI-приложение оркестрирует и firmware_test (CDC), и M5 (Serial) одновременно + +--- + +## Текущий статус + +| Компонент | Статус | Примечание | +| ------------------------------ | ------ | ------------------------------------------------ | +| `bsp_usb_cdc` | ✅ | HIL тест пройден | +| firmware_test скелет | ✅ | `main.c` + `cli.c` | +| Протокол v2 + test_runner | ✅ | JSON-lines event-driven | +| `bsp_sdram` + `test_sdram` | ✅ | 4 фазы: addr/data/seq/retention | +| `bsp_qspi_flash` + `test_qspi` | ✅ | JEDEC + erase + rw + addr range | +| `bsp_sd` + `test_usd` | ✅ | bsp_sd + FatFS, pre_confirm, 4 шага | +| `bsp_display` + `test_display` | ✅ | 4 цвета + ротация, hardware-verified | +| `bsp_button` + `test_buttons` | ✅ | 2 кнопки, physical detect, hardware-verified | +| Протокол: `list_tests` | ✅ | Этап 6а, hardware-verified | +| Протокол: `run_selected` | ✅ | Этап 6а, hardware-verified | +| `test_opto` | ✅ | Этап 6б, hardware-verified | +| `test_can` | ✅ | Этап 6в, hardware-verified | +| HIL pytest firmware_cdc | ✅ | Этап 6д, `FirmwareCdc` + `firmware_cdc` фикстура | +| HIL pytest firmware_opto | ✅ | Этап 6е, `06_test_firmware_opto.py` | +| HIL pytest firmware_can | ✅ | Этап 6ж, `06_test_firmware_can.py` | +| `bsp_mqs` + `test_mqs` | ✅ | Этап 6г, hardware-verified | +| Provisioning | ⬜ | Этап 7 | +| TUI сервисного инженера | ⬜ | Этап 8 | + +--- + +## Матрица тестов — итоговая + +| ID | Название | Critical | HIL | Тип | BSP | Статус | +| --------- | ------------------ | -------- | --- | ----------- | ------------------ | ------ | +| `sdram` | SDRAM 32 MB | ✅ | ❌ | self | `bsp_sdram` ✅ | ✅ | +| `qspi` | QSPI Flash W25Qxx | ✅ | ❌ | self | `bsp_qspi_flash` ✅ | ✅ | +| `usd` | microSD (SDIO) | ❌ | ❌ | interactive | `bsp_sd` ✅ | ✅ | +| `display` | TFT Display RGB888 | ❌ | ❌ | interactive | `bsp_display` ✅ | ✅ | +| `buttons` | Test Buttons 1/2 | ❌ | ❌ | interactive | `bsp_button` ✅ | ✅ | +| `mqs` | MQS Audio Out | ❌ | ❌ | interactive | `bsp_mqs` ✅ | ✅ | +| `can` | CAN loopback | ❌ | ✅ | HIL | `bsp_can` ✅ | ✅ | +| `opto` | Оптовходы IN1/2+RS | ❌ | ✅ | HIL | `bsp_opto` ✅ | ✅ | + +**Убранные тесты (закрытые решения):** + +- `uart_ttl` — LPUART1 dev-инструмент (MCU-Link VCOM), в сервисе не используется +- `uart_iso` — RS_RX физически тот же пин что IN в `test_opto`, избыточно + +--- + +## Закрытые архитектурные решения + +> Не пересматривать без явного запроса. + +### Этапы 1–5 (ранее зафиксированные) + +- **Транспорт:** USB CDC ACM — единственный канал. UART не используется в firmware_test. +- **Парсинг JSON:** без cJSON, строковый `strstr`. Входящее поле всегда `"type"` / `"cmd"`. +- **SDRAM и DCD:** SEMC инициализируется DCD до `main()`. `bsp_sdram_init()` только верифицирует. +- **QSPI-функции в ITCM:** `AT_QUICKACCESS_SECTION_CODE` + `__STARTUP_INITIALIZE_RAMFUNCTION`. +- **W25Q256/512:** dedicated 4-byte opcodes, без Enter 4-Byte Mode (0xB7). +- **bsp_button_init():** вызывается в `init()` тест-модуля, не в `main.c`. +- **Тест дисплея:** 4 цвета + 2 ротации. Таймаут confirm 15 с → FAIL. +- **Тест кнопок:** физическая детекция через `bsp_button`. Хост не отправляет JSON confirm. Таймаут 10 с → SKIP. + +### Этап 6 (новые решения) + +- **Разделение тестов:** `requires_hil=false` (standalone) vs `requires_hil=true` (HIL). + TUI фильтрует HIL-тесты если M5StampPLC не подключён. +- **`list_tests`:** таргет отдаёт реестр тестов с метаданными по запросу хоста. + TUI строит UI динамически, не хардкодит список тестов. +- **`run_selected`:** запуск произвольного подмножества тестов по списку ID. + Порядок выполнения — как в реестре таргета, не как в запросе. + Таргет принимает любой список без проверки `requires_hil` — ответственность на TUI. +- **TUI оркестрирует M5:** firmware_test не знает про M5. При `confirm_request` + от HIL-теста TUI командует M5, получает результат, отправляет confirm. +- **M5 опционален:** TUI при старте пробует найти M5. Не нашёл — HIL-тесты + недоступны (серые в UI, не входят в `run_selected`). +- **Фильтрация HIL на стороне TUI:** таргет не фильтрует по `requires_hil`. +- **MQS стерео:** MQS MIMXRT1052 требует стерео PCM-буфер. На плате выведен + один канал. Буфер всегда стерео (L+R идентичны). +- **MQS тест:** захардкоженная мелодия ~4 с (A4 + E5, по 2 с каждая), + `confirm_request("mqs_tone")`, оператор слышит → PASS/FAIL. + `critical=false`, `requires_hil=false`, `pre_confirm_prompt=NULL`. +- **MQS порядок init:** `bsp_mqs_amp_init()` → `bsp_delay(300)` → `bsp_mqs_init()`. + Усилитель запускается первым, чтобы успели зарядиться конденсаторы C103/C105 LM4875M. + Нарушение порядка приводит к щелчку при старте или отсутствию звука. +- **MQS USB keepalive:** воспроизведение через `bsp_mqs_play()` (async, не blocking), + параллельно крутится `bsp_usb_cdc_poll()`. Blocking-вариант голодает USB за ~4 с. +- **`pwmchannelenable` (NXP SDK ≥ 2.13):** поле в `pwm_signal_param_t` обязательно + выставлять в `true`. При инициализации через designated initializers без явного + указания равно `false` → `PWM_SetupPwm()` не выставляет `OUTEN` → ШИМ не выходит + на пин. Маскируется после отладочной сессии (отладчик оставляет `OUTEN` от прошлого + прогона). Воспроизводится только при cold reset. +- **ERRATA 50235 (FlexCAN + USB):** `FLEXCAN_Init()` содержит assert на + `CCM_CCGR5_CG12` (LPUART clock gate). После `bsp_usb_cdc_init()` gate + может быть закрыт → assert → HardFault. Workaround: `CLOCK_EnableClock(kCLOCK_Lpuart1)` + перед `FLEXCAN_Init()` внутри `bsp_can_init()`. Gate оставляется открытым — + закрывать не нужно, LPUART1 тактируется с минимальным потреблением. + `bsp_can_init()` вызывается из `main()` после `bsp_usb_cdc_init()`. +- **`firmware_cdc` фикстура:** не ждёт `session_start` (одноразовое событие при + старте, может быть пропущено). Проверяет живость через `ping → pong`. +- **`bsp_opto_force_read()`:** добавлен в BSP API для синхронного чтения пина + без дебаунса. Обновляет `confirmed_state`, сбрасывает `pending`. Используется + в `test_opto.c` после settle — обходит race condition когда чётное число ISR + при дребезге реле оставляет `pending=false` с устаревшим `confirmed_state`. +- **`bsp_opto_process()` в `test_opto.c`:** вызывается в settle loop после confirm, + но не в `test_runner_wait_confirm()`. Финальное чтение — через `bsp_opto_force_read()`. +- **Оркестратор оpto:** `RELAY_ON_S=0.15`, `RELAY_OFF_S=0.5` в `06_test_firmware_opto.py`. + Фиксированный sleep достаточен — реле переключается до отправки `confirmed:true`, + `bsp_opto_force_read()` читает финальное состояние пина напрямую. + +### Этап 8 (TUI решения) + +- **Прошивка — только USB SDP:** SWD недоступен сервиснику. spsdk (sdphost + blhost). + Оператор сам переставляет перемычку BOOT — это ок, документируется. +- **TUI автодетект:** определяет подключение по VID/PID — SDP BootROM (1FC9:0130) + или CDC firmware_test (session_start) — и показывает соответствующий экран. +- **Фреймворк TUI:** Textual (Python). Нативный async, реальные виджеты, + работает в SSH-сессии, вписывается в uv-экосистему. +- **tools/shared/m5_agent.py:** общая M5-логика, импортируется из `tools/hil/` + и `tools/production/`. + +--- + +## Этап 6 — test_can + test_opto + test_mqs + протокол ✅ ЗАВЕРШЁН + +### 6а — Расширение протокола ✅ + +**Файлы:** `protocol.h`, `protocol.c`, `cli.c`, `test_runner.c`, `PROTOCOL.md` + +#### Новая команда `list_tests` + +```json +→ {"type":"cmd","cmd":"list_tests"} +← {"type":"test_list","tests":[ + {"id":"sdram","name":"SDRAM 32 MB","critical":true,"requires_hil":false}, + {"id":"qspi","name":"QSPI Flash W25Qxx","critical":true,"requires_hil":false}, + {"id":"usd","name":"microSD (SDIO)","critical":false,"requires_hil":false}, + {"id":"display","name":"TFT Display RGB888","critical":false,"requires_hil":false}, + {"id":"buttons","name":"Test Buttons","critical":false,"requires_hil":false}, + {"id":"mqs","name":"MQS Audio Out","critical":false,"requires_hil":false}, + {"id":"can","name":"CAN loopback","critical":false,"requires_hil":true}, + {"id":"opto","name":"Opto Inputs","critical":false,"requires_hil":true} + ]} +``` + +#### Новая команда `run_selected` + +```json +→ {"type":"cmd","cmd":"run_selected","tests":["sdram","qspi","display"]} +← {"type":"test_begin","id":"sdram","name":"SDRAM 32 MB","critical":true} +← {"type":"test_result","id":"sdram","status":"pass","ms":312,"detail":""} +← {"type":"test_begin","id":"qspi",...} +← {"type":"test_result","id":"qspi",...} +← {"type":"test_begin","id":"display",...} +← {"type":"test_result","id":"display",...} +← {"type":"summary","passed":3,"failed":0,"skipped":0,"overall":"pass"} +``` + +Если хотя бы один ID не найден в реестре: + +```json +← {"ok":false,"error":"UNKNOWN_TEST"} +``` + +**Реализация в `test_runner.c`:** + +- Новый режим `RUNNER_MODE_SELECTED` +- Статический bool-массив `g_s_selected[REGISTRY_SIZE]` — без malloc +- `test_runner_run_selected(const char **pp_ids, size_t count)` — новая публичная функция + +### 6б — test_opto.c ✅ + +**Файл:** `firmware/test/src/tests/test_opto.c` + +6 шагов, попарно ACTIVE/INACTIVE для трёх каналов: + +| Шаг | confirm_request id | M5 действие | Проверка | +| --- | ------------------- | ----------- | -------------------------------- | +| 1 | `opto_in1_active` | RLY3 ON | `bsp_opto_read(IN1) == ACTIVE` | +| 2 | `opto_in1_inactive` | RLY3 OFF | `bsp_opto_read(IN1) == INACTIVE` | +| 3 | `opto_in2_active` | RLY4 ON | `bsp_opto_read(IN2) == ACTIVE` | +| 4 | `opto_in2_inactive` | RLY4 OFF | `bsp_opto_read(IN2) == INACTIVE` | +| 5 | `opto_rs_active` | RLY2 ON | `bsp_opto_read(RS) == ACTIVE` | +| 6 | `opto_rs_inactive` | RLY2 OFF | `bsp_opto_read(RS) == INACTIVE` | + +- Init: `bsp_opto_init()` единым вызовом для всех каналов +- Верификация синхронная после confirm (M5 переключил реле до отправки `confirmed:true`) +- FAIL при несоответствии: `detail = " state mismatch: expected ACTIVE got INACTIVE"` +- Таймаут: `PROTOCOL_CONFIRM_TIMEOUT_MS` (30 с) на каждый шаг + +### 6в — test_can.c ✅ + +**Файл:** `firmware/test/src/tests/test_can.c` + +2 шага, оба направления независимо: + +**Шаг 1 — RX (M5 → таргет):** + +```bash +confirm_request("can_rx_ready") +→ TUI: M5.can_send(id=0x100, data=[0xDE,0xAD,0xBE,0xEF]) +→ TUI: confirm(true) +→ таргет: bsp_can_receive(&frame, 500 мс) +→ верификация: frame.id==0x100, frame.data==[0xDE,0xAD,0xBE,0xEF] +→ FAIL если timeout или несовпадение +``` + +**Шаг 2 — TX (таргет → M5):** + +```bash +bsp_can_send(id=0x200, data=[0xCA,0xFE,0xBA,0xBE], timeout=100 мс) +confirm_request("can_tx_verify") +→ TUI: M5.can_recv(timeout=500 мс) → верификация id+data +→ TUI: confirm(true) если M5 принял корректно, confirm(false) если нет +→ FAIL если confirmed=false или timeout +``` + +- `disableSelfReception=true` — таргет не слышит свой TX, только M5 верифицирует +- Init: `bsp_can_init(&cfg)` + `bsp_can_accept_all()` + +### 6г — bsp_mqs + test_mqs.c ✅ + +**Файлы:** `bsp/mqs/` + `firmware/test/src/tests/test_mqs.c` + +**bsp_mqs:** + +- SAI3 + eDMA (DMA0 канал 0) + MQS периферия +- Стерео PCM16 буфер (L+R идентичны), один физический выход `MQS_RIGHT` +- Усилитель LM4875M управляется PWM4 SM0 через RC-фильтр и буферный ОУ LM358 +- API: `bsp_mqs_init/deinit`, `bsp_mqs_play/play_blocking`, `bsp_mqs_stop`, + `bsp_mqs_is_busy`, `bsp_mqs_amp_init/deinit`, `bsp_mqs_amp_set_volume` + +**test_mqs:** + +- Мелодия ~4 с: A4 (440 Гц) + E5 (659 Гц), по 2 с каждая, целочисленная LUT-синусоида +- Воспроизведение через `bsp_mqs_play()` (async) с `bsp_usb_cdc_poll()` в цикле +- `confirm_request("mqs_tone", "Do you hear a tone?", 15000)` → PASS/FAIL +- Порядок init: amp → delay 300 мс → mqs → build_melody (однократно, флаг) +- `critical=false`, `requires_hil=false`, `pre_confirm_prompt=NULL` + +### 6д — HIL pytest для firmware_test ✅ + +**Файлы:** + +``` +tools/hil/conftest.py ← фикстура firmware_cdc +tools/hil/06_test_firmware_opto.py +tools/hil/06_test_firmware_can.py +``` + +**Фикстура `firmware_cdc`:** + +```python +@pytest.fixture(scope="module") +def firmware_cdc(m5): + """ + Открывает USB CDC порт firmware_test. + firmware_test уже прошит в Flash (не загружается pyOCD). + Проверяет живость через ping → pong. + """ +``` + +**`FirmwareCdcClient`** — тонкий клиент: + +- `send_cmd(cmd_dict)` — отправить JSON команду +- `wait_event(type, timeout_s)` — ждать события нужного типа +- `confirm(id, ok)` — отправить `{"type":"confirm","id":"...","confirmed":true/false}` +- `run_test(id)` — запустить тест, вернуть test_result dict + +**Justfile:** + +```bash +hil-firmware-opto → pytest 06_test_firmware_opto.py -v +hil-firmware-can → pytest 06_test_firmware_can.py -v +``` + +--- + +## Этап 7 — Provisioning + +### Что нужно + +1. Читать `OCOTP_UNIQUE_ID` через SDK `fsl_ocotp` +2. Отправить `{"type":"provision_ready","chip_uid":"AABB..."}` после `summary` +3. Ждать `{"type":"cmd","cmd":"provision_ack"}` от хоста +4. Записывать статус в Flash (первый сектор после прошивки, вне XIP) + +### BSP (предварительно) + +```c +/* bsp/provisioning/include/bsp/provisioning.h */ +bsp_status_t bsp_prov_read_uid(uint8_t *p_uid, size_t len); /* 8 байт из OCOTP */ +``` + +### Открытые вопросы — Этап 7 + +- [ ] Что именно записывать как «пройдено»: флаг в Flash или только отправить UID? +- [ ] Нужна ли защита от повторного provisioning (write-once)? + +--- + +## Этап 8 — TUI сервисного инженера + +### Стек технологий + +| Компонент | Выбор | Обоснование | +| ------------- | ------------- | ----------------------------------------------------- | +| TUI фреймворк | **Textual** | Нативный async, виджеты, SSH-совместим, uv-экосистема | +| Serial | pyserial | Уже в стеке (tools/hil) | +| Прошивка | spsdk | sdphost + blhost, уже в tools/host | +| Конфигурация | python-dotenv | .env файл, совместим с существующим подходом | + +### Структура приложения + +```bash +tools/production/ +├── pyproject.toml ← зависимости: textual, pyserial, spsdk, python-dotenv +├── uv.lock +├── main.py ← точка входа +├── app/ +│ ├── tui.py ← Textual App, экраны, layout +│ ├── firmware_client.py ← USB CDC asyncio клиент firmware_test +│ ├── m5_client.py ← M5 Serial клиент (импортирует tools/shared/m5_agent.py) +│ ├── flasher.py ← USB SDP обёртка над spsdk +│ ├── orchestrator.py ← confirm_request → M5 action → confirm response +│ └── models.py ← TestInfo, TestResult, SessionState (dataclasses) +└── README.md + +tools/shared/ +└── m5_agent.py ← общая M5-логика для hil/ и production/ +``` + +### Два режима работы + +**Режим A — Прошивка** (триггер: VID/PID 1FC9:0130 обнаружен — BootROM SDP) + +``` +┌─ Прошивка платы ─────────────────────────────────┐ +│ Обнаружен BootROM (SDP режим) │ +│ │ +│ Что прошить? │ +│ ◉ firmware_test (диагностика) │ +│ ○ Production (bootloader + tft_app) │ +│ │ +│ Файл: [/path/to/firmware_test_hab.bin ···] │ +│ │ +│ [ Прошить ] │ +│ │ +│ ████████████░░░░░░ 64% Запись во Flash... │ +└────────────────────────────────────────────────────┘ +``` + +**Режим B — Диагностика** (триггер: session_start получен по CDC) + +``` +┌─ Диагностика платы fw:0.1.0 ─────────────────────┐ +│ M5StampPLC: ✓ подключён │ Плата: IMXRT1052 │ +├────────────────────────────────────────────────────┤ +│ Выбор тестов: │ Результаты: │ +│ ☑ SDRAM 32 MB │ sdram ✓ PASS │ +│ ☑ QSPI Flash │ qspi ✓ PASS │ +│ ☑ microSD │ usd ✗ FAIL │ +│ ☑ TFT Display │ mount failed: 5 │ +│ ☑ Кнопки │ display ✓ PASS │ +│ ☑ MQS Audio │ buttons ✓ PASS │ +│ ☑ CAN loopback [HIL] │ mqs ✓ PASS │ +│ ☑ Оптовходы [HIL] │ ... │ +├────────────────────────────────────────────────────┤ +│ [ Запустить выбранные ] [ Все тесты ] │ +│ ████████████████░░░░ 80% Тест: display │ +├────────────────────────────────────────────────────┤ +│ ⚠ Экран залит красным цветом? │ +│ [ ✓ Да ] [ ✗ Нет ] │ +└────────────────────────────────────────────────────┘ +``` + +### Поведение confirm_request в TUI + +| Тип теста | Источник confirm | Действие TUI | +| -------------------- | ------------------ | --------------------------------------------- | +| standalone (display) | оператор | показать prompt, кнопки OK/FAIL, countdown | +| standalone (mqs) | оператор | показать prompt, кнопки OK/FAIL, countdown | +| standalone (buttons) | физическое нажатие | показать инструкцию, ждать test_result | +| HIL (opto, can) | оркестратор | auto: M5 action → confirm (оператор не видит) | + +HIL confirm полностью автоматический — оператор видит только прогресс, не интерактивный prompt. + +### Конфигурация (.env) + +```ini +# Существующие переменные (tools/hil/.env): +HIL_VCOM_PORT=/dev/ttyACM0 +HIL_M5_PORT=/dev/ttyACM1 + +# Новые переменные для production TUI: +SERVICE_CDC_PORT=AUTO # AUTO = автодетект по session_start +SERVICE_M5_PORT=AUTO # AUTO = автодетект, пусто = без M5 +FIRMWARE_TEST_BIN=build/Release/firmware_test_hab.bin +PRODUCTION_BIN_BOOT=build/Release/bootloader_hab.bin +PRODUCTION_BIN_APP=build/Release/tft_app_hab.bin +``` + +### Запуск + +```bash +just host::service-tui # запустить TUI сервисного инженера +just host::service-flash # прошить без TUI (для автоматизации) +``` + +### Процесс работы сервисника + +**Диагностика (firmware_test уже в Flash):** + +```bash +1. Плата в нормальном режиме (BOOT_MOD_1 → GND) +2. Подключить USB к сервисному ПК +3. just host::service-tui → TUI обнаружил session_start → Режим B +4. Выбрать тесты → Запустить → Смотреть результаты +``` + +**Перепрошивка (нужна новая версия firmware_test или production):** + +```bash +1. Перемычка BOOT_MOD_1 → 3V3 +2. Reset, подключить USB +3. TUI обнаружил 1FC9:0130 → Режим A +4. Выбрать бинарь → Прошить +5. Перемычка BOOT_MOD_1 → GND → Reset → TUI переходит в Режим B +``` + +--- + +## Порядок реализации + +``` +✅ Этап 1 протокол v2 + runner +✅ Этап 2 bsp_sdram + test_sdram +✅ Этап 3 bsp_qspi_flash + test_qspi +✅ Этап 4 bsp_sd + test_usd +✅ Этап 5 display + buttons +✅ Этап 6а протокол: list_tests + run_selected +✅ Этап 6б test_opto.c + hardware верификация +✅ Этап 6в test_can.c + hardware верификация +✅ Этап 6д HIL pytest: firmware_cdc фикстура (FirmwareCdc + firmware_cdc) +✅ Этап 6е HIL pytest: 06_test_firmware_opto.py +✅ Этап 6ж HIL pytest: 06_test_firmware_can.py +✅ Этап 6г bsp_mqs + test_mqs.c + hardware верификация + +⬜ Этап 7 Provisioning (OCOTP UID + Flash-флаг) ← СЛЕДУЮЩИЙ ШАГ + +⬜ Этап 8а tools/production/ скелет + models + clients +⬜ Этап 8б orchestrator + базовый Textual UI (список тестов, запуск, результаты) +⬜ Этап 8в Экран прошивки (flasher + SDP автодетект) +⬜ Этап 8г Provisioning в TUI +⬜ Этап 8д tools/shared/m5_agent.py (рефакторинг общей M5-логики) + +⬜ Этап 9 Параллельно: обновить README + DEV_ARCH.md под финальную архитектуру +``` + +--- + +## Зависимости между этапами + +``` +✅ 6а (протокол) → ✅ 6б (opto) → ✅ 6в (can) → ✅ 6г (mqs) + ↓ + ✅ 6д (conftest) → ✅ 6е (opto pytest) → ✅ 6ж (can pytest) + ↓ + ⬜ 7 (provisioning) + ↓ + ⬜ 8 (TUI) +``` \ No newline at end of file diff --git a/tools/production/docs/TUI_PLAN.md b/tools/production/docs/TUI_PLAN.md new file mode 100644 index 0000000..1d996b6 --- /dev/null +++ b/tools/production/docs/TUI_PLAN.md @@ -0,0 +1,7 @@ +# TUI Service Tool Plan + +1. Навести порядок с экранами "USB-POLL", "TRANSFER", возможно сделать bootlogo с версией программы и лого компании +2. Уменьшить размер активной области до предела и сделать его равным для всех экранов +3. Добавить обратный отчет в тесте buttons (таймаут) +4. Выгрузка результатов тестов в json файл с привязкой к UID микроконтроллера +5. Возможно ли копировать UID с экрана терминала? \ No newline at end of file diff --git a/tools/production/TUI_REPORT.md b/tools/production/docs/TUI_REPORT_1.md similarity index 100% rename from tools/production/TUI_REPORT.md rename to tools/production/docs/TUI_REPORT_1.md diff --git a/tools/production/docs/TUI_REPORT_2.md b/tools/production/docs/TUI_REPORT_2.md new file mode 100644 index 0000000..68dae8d --- /dev/null +++ b/tools/production/docs/TUI_REPORT_2.md @@ -0,0 +1,8 @@ +# TUI Service Tools замечания №2 + +1. Тест usd проводится только один раз, при втором прогоне зависает намертво (возможно usdhc стек не деинициализируется корректно) +2. При выполнении теста psd в прогресс баре ошибка - unknown event progress +3. Нужно вообще убрать проценты в статус баре (при прохождении тестов) - лишняя история +4. Fallback при потере USB соединения в Flasher и Testing screen - возможно ли отображать статус поключения к таргету? (SDP, firmware_test) и есть статус отключен не давать взаимодействовать с элементами экранов (кроме выйти) +5. После таймаута по выполнению теста (recv_until timeout after 120s) нет никакой индикации о статусе теста в таблице (от по факту завален) + после этого не получается выйти из приложения с помощью кнопки и не получается запустить ни один тест +6. В таблице тестов в столбце Детали при неудачном выполнение теста обрезается часть информации \ No newline at end of file diff --git a/tools/production/docs/TUI_SESSION.md b/tools/production/docs/TUI_SESSION.md new file mode 100644 index 0000000..a01ae9b --- /dev/null +++ b/tools/production/docs/TUI_SESSION.md @@ -0,0 +1,121 @@ +# Отчёт: разработка и стабилизация service-tui + +**Период:** один рабочий тред, от architecture-планирования до прод-готовности +**Объект:** `tools/production/` — TUI-приложение для сервисного инженера (диагностика и прошивка платы MIMXRT1052CVJ5B) + +--- + +## 1. Архитектура и первичная разработка (Этап 8) + +Построено с нуля на Python + Textual, монорепо `tools/production/`: + +``` +tools/production/ +├── main.py — точка входа (10 строк) +├── pyproject.toml — textual, pyserial, python-dotenv, pyinstaller, pyusb +└── app/ + ├── app.py — ServiceApp, роутинг экранов + ├── app.tcss — единый файл стилей + ├── models.py — AppMode, TestStatus, FlashTarget, TestInfo, TestResult, SessionState, ConfirmRequest, FlashProgress + ├── firmware_client.py — async USB CDC клиент firmware_test + ├── m5_client.py — async M5StampPLC клиент (HIL) + ├── flasher.py — subprocess-обёртка над tools/host/flash_usb.py + ├── orchestrator.py — маршрутизация confirm_request, обработка progress/timeout + ├── widgets/ + │ └── app_frame.py — общий адаптивный контейнер для всех экранов + └── screens/ + ├── waiting.py — WaitingScreen (USB autodetect) + ├── flash.py — FlashScreen (прошивка/chip erase) + ├── post_flash.py — PostFlashScreen (промпт смены BootMode) + ├── connection_watcher.py — миксин мониторинга обрыва USB + └── diag/ + ├── __init__.py — DiagScreen (координатор) + ├── test_list.py — TestListPanel (чекбоксы тестов) + ├── results.py — ResultsPanel (DataTable результатов) + └── confirm_panel.py — ConfirmPanel (prompt + countdown) +``` + +### Ключевые архитектурные решения +- **Оркестрация confirm_request** по `id`: HIL (opto/CAN) → автоматически через M5, `btn*` → инструкция без JSON-ответа, остальное → оператор с countdown +- **Flasher** не дублирует spsdk-окружение — вызывает `tools/host/flash_usb.py` как subprocess +- **Standalone-сборка** через PyInstaller для сервисников без Python +- **Три режима прошивки**: firmware_test / Production / кастомный бинарь + chip erase + +--- + +## 2. Расширения протокола и инструментария + +| Что | Где | +| ------------------------------------------------------------------------------ | --------------------------------------------------------- | +| `--bin-path`, `--erase-chip` в `flash_usb.py` | `tools/host/flash_usb.py` | +| `get_version` команда + CMake-версионирование (`version.h.in`) | firmware (`protocol.c/h`, `cli.c`, `CMakeLists.txt`) | +| `FIRMWARE_BUILD_TYPE` из `.env` (Debug по умолчанию — Release пока нестабилен) | `flasher.py` | +| Поддержка кириллицы в названиях тестов/промптах | `firmware_client.py`, `m5_client.py` (UTF-8 вместо ASCII) | + +--- + +## 3. Найденные и исправленные баги (хронологически) + +### Линкер и сборка +- **`${PROJECT_SOURCE_DIR}` → `${CMAKE_SOURCE_DIR}`** в `firmware/test/CMakeLists.txt` — после добавления `project(VERSION)` путь к линкер-скрипту стал резолвиться неверно. + +### USB-детект +- На macOS BootROM SDP (`1FC9:0130`) не создаёт serial-порт → невидим через `pyserial.list_ports`. Добавлен **pyusb** как primary метод детекта с fallback на `list_ports`. + +### Textual-специфичные баги +- `Screen.Message` не существует в Textual 8.x → заменено на `from textual.message import Message`. +- `MountError` в `populate()` — `row.mount(child)` до прикрепления `row` к DOM → исправлено передачей детей в конструктор + `mount_all()`. +- `CSS_PATH` на каждом экране резолвился относительно файла класса и постоянно расходился с реальным расположением `.tcss` → **унифицировано**: один `app.tcss` с `CSS_PATH` только на `ServiceApp`. +- **Краш при drag мыши** (`assert isinstance(content_widget.parent, Widget)`) — `Screen` выступал `content_widget` напрямую → решено введением общего `AppFrame`-контейнера между `Screen` и содержимым. +- **`self._running`** в `DiagScreen` случайно совпало с приватным полем `MessagePump._running` из самого Textual → кнопка "Выйти" была перманентно заблокирована. Переименовано в `_tests_running`. +- `DataTable.sort(*columns, key=fn)` передаёт в `key()` кортеж **значений ячеек**, не `row_key` — пришлось сортировать по содержимому ячейки "Статус", которое сами полностью контролируем. +- `table.add_columns()` (множественное число) не принимает `width=` → колонка "Детали" обрезалась по длине заголовка. Исправлено через `add_column()` по одной с явной шириной. + +### Layout +- `AppFrame` с жёстким `width: 140; height: 44` обрезал контент на терминалах меньшего размера → сделан **адаптивным** (`width/height: 100%` с потолком `max-width: 160; max-height: 50`). +- `#diag-frame` на `layout: grid` с ручным расчётом `grid-rows` рассинхронизировался с реальным числом/высотой children (кнопки с `border: tall` не помещались в выделенную строку) → переход на `layout: vertical` с единственным `1fr` на рабочую зону. +- `#results-empty.hidden` не имел CSS-правила `display: none` → пустой контейнер с `height: 1fr` продолжал выталкивать таблицу результатов вниз даже будучи скрытым. + +### Логика приложения +- **`TestListPanel.set_enabled()`** путал постоянное состояние "HIL без M5" с временной блокировкой на время прогона → чекбоксы навсегда залипали disabled после первого запуска. Исправлено отдельным словарём `_hil_unavailable`. +- **Таймаут чтения порта** (`_recv_until`) тихо завершался без сигнала → зависший тест навсегда оставался в RUNNING, кнопки "Выйти"/запуска блокировались навсегда. Теперь генератор **гарантированно** завершается одним `SUMMARY` (настоящим или синтетическим), зависший тест получает `FAIL` с понятным detail. +- **`progress`-событие** протокола (документированное в PROTOCOL.md, используется тестом USD) ошибочно считалось неизвестным/ошибочным → теперь явно обрабатывается как `TEST_PROGRESS`. + +### Firmware (USD-тест) +- **USD зависает намертво на втором прогоне.** Причина: non-blocking USDHC host driver SDK оставался в состоянии "ожидание завершения транзакции" после `SD_HostDeinit()`, плюс структура `g_sd` не обнулялась между прогонами. Фикс: `USDHC_Reset(..., kUSDHC_ResetAll, ...)` + `memset(&g_sd, 0, ...)` в `bsp_sd_init()`/`bsp_sd_deinit()`. + +--- + +## 4. UX-доработки (по согласованному плану итераций) + +| Итерация | Что сделано | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Стабильность | `AppFrame`, скрытие ProgressBar в простое, кнопка "Выйти" на всех экранах | +| Workflow | `PostFlashScreen` (промпт смены BootMode после прошивки firmware_test — только для этого сценария), тесты изначально не выбраны + кнопки "Выбрать все"/"Снять все", полный UID в шапке | +| Polish | `ResultsPanel` переведён на `DataTable`: сортировка FAIL-наверх (стабильная внутри группы), подсветка FAIL-строки целиком, перенос длинных `detail` на несколько строк без обрезания, empty-state с подсказкой | +| Отчёт №2 | Убраны проценты в статус-баре (полоса осталась), мониторинг обрыва USB (`ConnectionWatcherMixin`) на `FlashScreen`/`DiagScreen` с разрывом сессии и понятным баннером причины на `WaitingScreen` | + +--- + +## 5. Текущее состояние + +**Готово и протестировано (headless):** +- Полный цикл: WaitingScreen → Flash/Diag → результат → возврат +- Прошивка (3 варианта) + chip erase + версионирование +- Диагностика: список тестов, выборочный/полный запуск, HIL через M5, кириллица +- Обработка обрывов: таймаут теста, потеря USB, повторные прогоны +- Адаптивная вёрстка на диапазоне терминалов 80×24 → 220×60 + +**Известные открытые вопросы / не доделано:** +- Release-сборка firmware нестабильна (медленное мигание — подозрение на проблему с FCB/clock конфигурацией в Release HAB-образе) — TUI временно форсирует Debug через `FIRMWARE_BUILD_TYPE` +- `docs/DEV_ARCH.md`, `CHANGELOG.md`, `PLAN.md` — подготовлены диффы для финализации документации, но не применялись по твоему решению ("пока не буду обновлять документацию, нужно всё проверить") +- `tools/shared/m5_agent.py` — сознательно не делался: pytest HIL-окружение и TUI используют независимые M5-клиенты, признано правильным архитектурным решением, а не техдолгом + +--- + +## 6. Рекомендации для следующего треда + +1. Перед стартом — синхронизировать единую копию репозитория со всеми патчами из этого треда (было замечено расхождение версий файлов между чатом и локальной копией один раз, см. эпизод с TUI_REPORT.md). +2. Дальнейшее тестирование на реальном железе: полный цикл diagnostics с HIL (M5 подключён), повторные циклы прошивки/chip erase, граничные случаи USB-отключения во время разных операций. +3. Когда стабильность подтверждена — вернуться к обновлению `DEV_ARCH.md`/`CHANGELOG.md`/`PLAN.md` под финальную архитектуру. +4. Разобрать Release-сборку firmware (сравнить `hab_firmware_test_debug.yaml` vs `hab_firmware_test_release.yaml`). \ No newline at end of file diff --git a/tools/production/docs/pics/FLASH.png b/tools/production/docs/pics/FLASH.png new file mode 100644 index 0000000000000000000000000000000000000000..19c5216f6c7037c9be6bbbe0f80c1b91d0758d02 GIT binary patch literal 56806 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%0ASlw_F^& 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 literal 0 HcmV?d00001 diff --git a/tools/production/docs/pics/POST_FLASH.png b/tools/production/docs/pics/POST_FLASH.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c5998a3cc2da0fc383527046d75f0432c9b83c GIT binary patch literal 45998 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 F{ttK2x+VYs literal 0 HcmV?d00001 diff --git a/tools/production/docs/pics/TEST_SCREEN.png b/tools/production/docs/pics/TEST_SCREEN.png new file mode 100644 index 0000000000000000000000000000000000000000..32c74c02c22b458aefaa1980fe63166a12b6d07e GIT binary patch literal 88874 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

jn0;@#0L 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 literal 0 HcmV?d00001 diff --git a/tools/production/docs/pics/WAITING.png b/tools/production/docs/pics/WAITING.png new file mode 100644 index 0000000000000000000000000000000000000000..f13b869a32eec1774c7e40a13b55c17f798306f2 GIT binary patch literal 35099 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 literal 0 HcmV?d00001 diff --git a/tools/production/docs/pics/WAITING_AFTER_LOSS.png b/tools/production/docs/pics/WAITING_AFTER_LOSS.png new file mode 100644 index 0000000000000000000000000000000000000000..52544add14705af095a5f5878c73927e5b5c616d GIT binary patch literal 39786 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 python -2026-06-29 18:36:18,046 DEBUG app.flasher flash_usb [erase]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-29 18:36:18,224 DEBUG app.flasher flash_usb [erase]: Removed virtual environment at: .venv -2026-06-29 18:36:18,224 DEBUG app.flasher flash_usb [erase]: Creating virtual environment at: .venv -2026-06-29 18:36:18,344 DEBUG app.flasher flash_usb [erase]: Installed 66 packages in 93ms -2026-06-29 18:36:23,001 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:36:23,001 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 18:36:23,177 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:23,197 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 18:36:23,198 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 18:36:23,198 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:24,586 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 18:36:24,760 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 18:36:59,315 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 18:36:59,571 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 18:36:59,591 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: -2026-06-29 18:36:59,592 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-29 18:37:20,822 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-29 18:37:20,836 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 18:37:21,381 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:37:21,381 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 18:37:21,559 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:21,582 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 18:37:21,583 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 18:37:21,583 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:22,972 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 18:37:23,148 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:23,979 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:24,183 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:24,357 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:24,534 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 18:37:24,594 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:24,594 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 22616 (0x5858) -2026-06-29 18:37:24,779 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,798 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Размер: 22616 байт -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +28672 байт -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 28672 0 -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 18:37:24,799 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:24,800 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 18:37:46,867 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-29 18:37:46,883 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 18:37:47,377 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:37:47,377 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 18:37:47,548 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:47,568 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 18:37:47,569 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 18:37:47,569 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:48,972 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 18:37:49,154 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:49,987 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:50,206 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:50,386 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:50,560 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 18:37:50,621 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:50,621 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 22616 (0x5858) -2026-06-29 18:37:50,800 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,818 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Размер: 22616 байт -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +28672 байт -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 28672 0 -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,819 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 18:37:50,820 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:37:50,820 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 18:37:50,820 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:37:50,820 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 18:38:46,907 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:40:26,915 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:40:28,552 INFO app.m5_client M5StampPLC не найден -2026-06-29 18:41:26,213 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-29 18:44:38,127 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:44:39,837 INFO app.m5_client M5StampPLC не найден -2026-06-29 18:45:28,221 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-29 18:46:57,397 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:46:58,957 INFO app.m5_client M5StampPLC не найден -2026-06-29 18:50:48,270 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:51:01,877 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-29 18:51:01,900 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 18:51:01,900 DEBUG app.flasher flash_usb [firmware_test]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-29 18:51:01,900 DEBUG app.flasher flash_usb [firmware_test]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-29 18:51:02,032 DEBUG app.flasher flash_usb [firmware_test]: Removed virtual environment at: .venv -2026-06-29 18:51:02,032 DEBUG app.flasher flash_usb [firmware_test]: Creating virtual environment at: .venv -2026-06-29 18:51:02,130 DEBUG app.flasher flash_usb [firmware_test]: Installed 66 packages in 75ms -2026-06-29 18:51:06,727 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:51:06,727 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 18:51:06,903 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 18:51:06,923 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 18:51:06,924 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:08,331 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 18:51:08,506 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:09,215 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:09,429 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:09,621 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:09,804 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 18:51:09,985 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:09,985 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 72116 (0x119b4) -2026-06-29 18:51:10,173 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 18:51:10,191 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Размер: 72116 байт -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +77824 байт -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 77824 0 -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,192 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 18:51:10,193 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 18:51:36,969 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:57:30,698 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 18:57:32,409 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:00:37,411 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:00:38,953 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:04:04,441 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:04:12,903 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-29 19:04:12,918 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:04:12,919 DEBUG app.flasher flash_usb [erase]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-29 19:04:12,921 DEBUG app.flasher flash_usb [erase]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-29 19:04:13,106 DEBUG app.flasher flash_usb [erase]: Removed virtual environment at: .venv -2026-06-29 19:04:13,106 DEBUG app.flasher flash_usb [erase]: Creating virtual environment at: .venv -2026-06-29 19:04:13,225 DEBUG app.flasher flash_usb [erase]: Installed 66 packages in 93ms -2026-06-29 19:04:17,826 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:04:17,826 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:04:18,001 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:04:18,019 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:18,019 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:04:18,020 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:19,412 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:04:19,586 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:04:54,910 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:04:55,150 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,168 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-29 19:04:55,169 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:04:55,170 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-29 19:04:58,515 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Debug -2026-06-29 19:04:58,542 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:04:58,955 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:04:58,955 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:04:59,131 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:04:59,150 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Debug] -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:04:59,151 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:00,537 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:05:00,713 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:01,631 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:01,832 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:02,011 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:02,191 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 19:05:02,527 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:02,527 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 135240 (0x21048) -2026-06-29 19:05:02,734 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:05:02,752 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Размер: 135240 байт -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +143360 байт -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 143360 0 -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin 0 -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:05:02,753 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:05:02,754 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 19:05:23,969 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:05:25,545 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:07:57,549 WARNING app.firmware_client _recv_until timeout after 120.0 s -2026-06-29 19:17:54,908 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:18:31,735 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-29 19:18:31,752 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:18:31,752 DEBUG app.flasher flash_usb [erase]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-29 19:18:31,755 DEBUG app.flasher flash_usb [erase]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-29 19:18:31,934 DEBUG app.flasher flash_usb [erase]: Removed virtual environment at: .venv -2026-06-29 19:18:31,935 DEBUG app.flasher flash_usb [erase]: Creating virtual environment at: .venv -2026-06-29 19:18:32,066 DEBUG app.flasher flash_usb [erase]: Installed 66 packages in 98ms -2026-06-29 19:18:36,600 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:18:36,600 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:18:36,776 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:18:36,796 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:18:36,797 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:18:36,797 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:18:36,797 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:18:38,238 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:18:38,414 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:19:13,145 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:19:13,403 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,422 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,423 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:19:13,424 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-29 19:20:01,708 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Debug -2026-06-29 19:20:01,724 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:20:02,300 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:20:02,300 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:20:02,473 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Debug] -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:20:02,493 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:03,887 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:20:04,068 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:04,968 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:05,182 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:05,355 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:05,534 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 19:20:05,873 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:05,873 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 135240 (0x21048) -2026-06-29 19:20:06,062 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Размер: 135240 байт -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +143360 байт -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 143360 0 -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 19:20:06,081 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin 0 -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:20:06,082 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 19:20:59,572 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Debug -2026-06-29 19:20:59,595 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:21:00,152 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:21:00,152 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:21:00,330 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Debug] -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:21:00,350 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:21:00,351 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:01,734 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:21:01,904 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:02,832 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:03,049 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:03,224 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:03,447 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 19:21:03,786 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:03,787 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 135240 (0x21048) -2026-06-29 19:21:04,008 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,028 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Размер: 135240 байт -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +143360 байт -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 143360 0 -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin 0 -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:21:04,029 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 19:21:20,423 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-29 19:21:20,437 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:21:20,936 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:21:20,936 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:21:21,112 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:21,133 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:21:21,134 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:21:21,134 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:22,510 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:21:22,685 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:21:57,783 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:21:58,044 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:58,064 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: -2026-06-29 19:21:58,065 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-29 19:31:03,319 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:31:12,383 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Debug -2026-06-29 19:31:12,399 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-29 19:31:12,928 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:31:12,928 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-29 19:31:13,096 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Debug] -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:13,117 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-29 19:31:13,118 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-29 19:31:13,118 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:14,509 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-29 19:31:14,679 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:15,624 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:15,830 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:16,009 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:16,183 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-29 19:31:16,518 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:16,518 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 135240 (0x21048) -2026-06-29 19:31:16,724 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Размер: 135240 байт -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +143360 байт -2026-06-29 19:31:16,744 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 143360 0 -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Debug/firmware_test_hab.bin 0 -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-29 19:31:16,745 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-29 19:31:45,595 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:31:54,684 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:31:57,741 WARNING app.firmware_client _recv_until timeout after 3.0 s -2026-06-29 19:34:42,219 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-29 19:36:35,663 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:36:37,208 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:36:40,255 WARNING app.firmware_client _recv_until timeout after 3.0 s -2026-06-29 19:36:47,180 DEBUG asyncio Using selector: KqueueSelector -2026-06-29 19:41:53,210 INFO app.m5_client M5StampPLC не найден -2026-06-29 19:41:56,267 WARNING app.firmware_client _recv_until timeout after 3.0 s -2026-06-30 11:07:04,658 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:07:32,037 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:07:38,901 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 11:07:38,923 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 11:07:38,923 DEBUG app.flasher flash_usb [erase]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-30 11:07:38,925 DEBUG app.flasher flash_usb [erase]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-30 11:07:39,117 DEBUG app.flasher flash_usb [erase]: Removed virtual environment at: .venv -2026-06-30 11:07:39,117 DEBUG app.flasher flash_usb [erase]: Creating virtual environment at: .venv -2026-06-30 11:07:39,247 DEBUG app.flasher flash_usb [erase]: Installed 66 packages in 100ms -2026-06-30 11:07:43,943 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:07:43,943 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 11:07:44,116 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 11:07:44,134 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 11:07:44,135 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:07:45,522 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 11:07:45,698 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:08:20,418 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:08:20,670 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,689 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:08:20,690 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 11:09:41,208 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 11:09:41,239 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 11:09:41,805 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:09:41,805 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 11:09:41,995 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 11:09:42,014 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:43,425 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 11:09:43,598 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:44,216 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:44,426 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:44,610 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:44,789 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 11:09:44,957 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:44,957 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 11:09:45,207 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,229 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:09:45,230 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:09:45,231 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 11:10:12,371 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:10:16,917 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:10:57,370 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 11:12:15,443 WARNING app.orchestrator Operator confirm timeout: display_red -2026-06-30 11:12:25,456 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 11:14:57,478 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:14:59,027 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:16:37,862 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:17:04,481 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 11:17:04,488 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 11:17:05,064 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:17:05,064 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 11:17:05,238 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:05,257 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 11:17:05,258 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:05,258 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 11:17:05,258 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 11:17:05,258 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:06,649 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 11:17:06,832 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:17:41,515 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:17:41,755 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,774 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: -2026-06-30 11:17:41,775 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 11:17:45,454 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 11:17:45,472 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 11:17:45,888 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:17:45,888 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 11:17:46,064 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 11:17:46,084 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:47,468 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 11:17:47,641 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:48,263 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:48,472 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:48,646 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:48,815 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 11:17:48,986 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:48,986 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 11:17:49,175 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 11:17:49,195 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 11:17:49,196 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 11:17:49,197 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 11:18:16,295 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:18:18,011 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:20:23,814 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 11:22:00,580 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:22:02,131 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:24:08,449 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:24:09,999 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:24:39,035 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:24:40,580 INFO app.m5_client M5StampPLC не найден -2026-06-30 11:25:23,410 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:25:58,243 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:26:30,720 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 11:26:58,255 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:12:49,218 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:12:57,749 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 12:12:57,771 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:12:58,350 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:12:58,350 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:12:58,522 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:12:58,543 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:12:59,916 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:13:00,092 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:13:08,189 DEBUG app.flasher flash_usb [erase]: Response status = 10004 (0x2714) No response packet from target device. -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:13:08,242 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:13:08,243 DEBUG app.flasher flash_usb [erase]: [ERROR] Команда завершилась с кодом 1 -2026-06-30 12:13:12,578 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:13:12,604 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:13:13,005 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:13:13,005 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:13:13,178 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:13:13,198 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:14,579 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:13:14,753 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:15,335 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:15,546 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:15,722 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:15,893 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:13:16,067 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:16,067 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:13:16,282 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:13:16,301 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,302 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:13:16,303 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:13:16,303 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:13:16,303 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:13:16,303 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:13:46,755 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:13:48,420 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:14:17,920 ERROR app.screens.diag run_worker error: read failed: [Errno 6] Device not configured -2026-06-30 12:14:50,713 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:14:52,420 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:15:19,761 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:15:21,306 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:15:23,620 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:15:31,588 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:16:53,965 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:16:56,990 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 12:16:57,017 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:16:57,543 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:16:57,543 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:16:57,715 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:16:57,735 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:16:57,736 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:16:59,225 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:16:59,405 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:17:34,744 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:17:35,036 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,055 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:17:35,056 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:17:35,057 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 12:17:38,393 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:17:38,415 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:17:38,820 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:17:38,821 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:17:38,996 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:39,015 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:17:39,016 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:40,400 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:17:40,575 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:41,209 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:41,417 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:41,589 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:41,758 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:17:41,926 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:41,926 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:17:42,112 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,130 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:17:42,131 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:18:16,089 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:18:17,817 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:19:51,239 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 12:20:11,226 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:20:12,767 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:20:46,816 WARNING app.orchestrator Operator confirm timeout: mqs_tone -2026-06-30 12:23:08,021 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:23:09,570 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:24:19,465 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 12:28:29,368 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:28:32,469 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 12:28:32,491 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:28:33,043 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:28:33,043 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:28:33,212 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:28:33,230 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:28:33,231 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:28:33,231 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:28:33,231 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:28:34,621 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:28:34,792 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:29:10,122 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:29:10,362 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:29:10,381 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:29:10,382 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 12:29:42,254 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:29:42,274 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:29:42,779 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:29:42,779 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:29:42,951 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:29:42,971 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:44,350 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:29:44,519 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:45,125 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:45,328 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:45,502 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:45,675 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:29:45,847 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:45,847 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:29:46,038 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,057 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:29:46,058 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:29:46,059 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:30:13,179 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:30:57,597 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:31:07,114 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 12:31:07,127 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:31:07,633 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:31:07,634 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:31:07,805 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:07,824 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:31:07,825 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:31:07,825 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:09,209 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:31:09,387 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:31:43,890 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:31:44,130 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,148 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:44,149 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: -2026-06-30 12:31:44,150 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 12:31:54,530 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:31:54,544 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:31:54,994 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:31:54,994 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:31:55,169 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:31:55,189 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:56,575 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:31:56,748 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:57,367 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:57,577 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:57,752 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:57,923 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:31:58,094 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:58,094 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:31:58,282 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:31:58,301 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:31:58,302 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:32:39,880 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:34:28,288 WARNING app.orchestrator Operator confirm timeout: mqs_tone -2026-06-30 12:36:10,339 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:36:12,274 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:36:16,715 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:36:17,666 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 12:36:20,059 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:36:21,609 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:37:39,767 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:37:42,638 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:37:42,653 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:37:43,208 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:37:43,208 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:37:43,385 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:43,403 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:37:43,404 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:37:43,404 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:44,787 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:37:44,965 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:45,567 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:45,775 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:45,949 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:46,123 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:37:46,295 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:46,295 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:37:46,484 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,502 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:37:46,503 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:37:46,504 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:38:28,112 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:39:00,162 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:39:01,711 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:39:16,105 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:39:29,578 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:39:29,591 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:39:30,119 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:39:30,119 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:39:30,293 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:39:30,312 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:39:30,313 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:31,690 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:39:31,867 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:32,499 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:32,710 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:32,885 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:33,057 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:39:33,232 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:33,232 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:39:33,420 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,440 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:39:33,441 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:33,442 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:39:42,605 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:39:45,866 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:39:45,892 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:39:46,402 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:39:46,402 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:39:46,575 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:46,593 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:39:46,594 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:39:46,594 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:47,978 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:39:48,156 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:48,777 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:48,988 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:49,163 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:49,340 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:39:49,511 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:49,511 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:39:49,695 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,713 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:39:49,714 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:40:34,546 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 12:40:34,566 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 12:40:35,182 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:40:35,182 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 12:40:35,411 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 12:40:35,450 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:35,451 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 12:40:35,452 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 12:40:35,452 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:36,857 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 12:40:37,029 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:37,659 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:37,878 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:38,054 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:38,226 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 12:40:38,396 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:38,396 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68380 (0x10b1c) -2026-06-30 12:40:38,581 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:40:38,599 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68380 байт -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 12:40:38,600 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 12:41:20,289 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:41:45,632 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:41:47,180 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:50:05,155 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:50:06,706 INFO app.m5_client M5StampPLC не найден -2026-06-30 12:53:12,550 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:53:19,153 ERROR app.app CDC connect failed: firmware_test не отвечает на ping: /dev/cu.usbmodem11301 -2026-06-30 12:53:34,236 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 12:53:35,947 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:00:39,178 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:00:40,865 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:32:56,441 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:32:57,988 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:35:28,536 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:35:45,185 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 13:35:45,204 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 13:35:45,204 DEBUG app.flasher flash_usb [firmware_test]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-30 13:35:45,206 DEBUG app.flasher flash_usb [firmware_test]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-30 13:35:45,381 DEBUG app.flasher flash_usb [firmware_test]: Removed virtual environment at: .venv -2026-06-30 13:35:45,381 DEBUG app.flasher flash_usb [firmware_test]: Creating virtual environment at: .venv -2026-06-30 13:35:45,517 DEBUG app.flasher flash_usb [firmware_test]: Installed 66 packages in 104ms -2026-06-30 13:35:50,049 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 13:35:50,049 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 13:35:50,221 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 13:35:50,241 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:51,617 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 13:35:51,786 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:52,392 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:52,603 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:52,777 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:52,951 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 13:35:53,121 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:53,122 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68364 (0x10b0c) -2026-06-30 13:35:53,309 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68364 байт -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 13:35:53,327 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 13:35:53,328 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 13:36:18,782 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:40:43,635 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 13:40:50,292 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:40:51,840 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:42:37,034 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 13:42:42,356 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:42:43,901 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:43:43,721 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 13:43:48,120 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 13:43:50,861 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:43:52,409 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:44:36,067 ERROR app.screens.diag run_worker error: read failed: [Errno 6] Device not configured -2026-06-30 13:48:46,897 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:49:26,682 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:50:01,537 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:50:49,483 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 13:50:51,216 INFO app.m5_client M5StampPLC не найден -2026-06-30 13:56:22,896 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 14:13:37,172 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:13:38,722 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:16:04,892 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:16:11,539 ERROR app.app CDC connect failed: firmware_test не отвечает на ping: /dev/cu.usbmodem11301 -2026-06-30 14:16:18,139 ERROR app.app CDC connect failed: firmware_test не отвечает на ping: /dev/cu.usbmodem11301 -2026-06-30 14:16:20,826 ERROR app.app CDC connect failed: read failed: [Errno 6] Device not configured -2026-06-30 14:16:23,904 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:17:25,582 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 14:18:32,310 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:18:33,929 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:19:27,641 ERROR app.screens.diag run_worker error: read failed: [Errno 6] Device not configured -2026-06-30 14:19:57,182 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:19:58,730 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:36:34,945 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:36:36,495 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:38:19,642 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:38:21,192 INFO app.m5_client M5StampPLC не найден -2026-06-30 14:38:26,849 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 14:38:58,972 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:43:53,430 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:45:10,133 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:45:51,286 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:55:19,262 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:55:56,114 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:56:46,050 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 14:57:28,802 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --erase-chip -2026-06-30 14:57:28,820 DEBUG app.flasher flash_usb [erase]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 14:57:28,822 DEBUG app.flasher flash_usb [erase]: warning: Ignoring existing virtual environment linked to non-existent Python interpreter: .venv/bin/python3 -> python -2026-06-30 14:57:28,825 DEBUG app.flasher flash_usb [erase]: Using CPython 3.10.11 interpreter at: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -2026-06-30 14:57:29,003 DEBUG app.flasher flash_usb [erase]: Removed virtual environment at: .venv -2026-06-30 14:57:29,003 DEBUG app.flasher flash_usb [erase]: Creating virtual environment at: .venv -2026-06-30 14:57:29,120 DEBUG app.flasher flash_usb [erase]: Installed 66 packages in 86ms -2026-06-30 14:57:33,713 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 14:57:33,713 DEBUG app.flasher flash_usb [erase]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 14:57:33,888 DEBUG app.flasher flash_usb [erase]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: Операция: chip erase -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: SDP USB: 0x1FC9,0x130 -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: BL USB: 0x15A2,0x73 -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: ════════════════════════════════════════════════════════════ -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:57:33,906 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 14:57:33,907 DEBUG app.flasher flash_usb [erase]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 14:57:33,907 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:57:35,315 DEBUG app.flasher flash_usb [erase]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 14:57:35,485 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 14:58:10,903 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 14:58:11,146 DEBUG app.flasher flash_usb [erase]: Response status = 0 (0x0) Success. -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: OK (1с) -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,165 DEBUG app.flasher flash_usb [erase]: Полная очистка Flash (chip erase, ~30 с) -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: ⚠️ После chip erase BootROM не сможет загрузить прошивку. -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: ⚠️ Используй flash_usb.py для восстановления. -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: $ blhost -t 100000 -u 0x15A2,0x73 -- flash-erase-all 9 -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: Reset -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:11,166 DEBUG app.flasher flash_usb [erase]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 14:58:11,167 DEBUG app.flasher flash_usb [erase]: -2026-06-30 14:58:11,167 DEBUG app.flasher flash_usb [erase]: ✅ Chip erase завершён -2026-06-30 14:58:17,157 INFO app.flasher Running: uv run --directory /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host python /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/flash_usb.py --firmware firmware_test --build-type Release -2026-06-30 14:58:17,178 DEBUG app.flasher flash_usb [firmware_test]: warning: `VIRTUAL_ENV=/Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/production/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead -2026-06-30 14:58:17,661 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 14:58:17,661 DEBUG app.flasher flash_usb [firmware_test]: Response status = 2290649224 (0x88888888) Write File Success. -2026-06-30 14:58:17,832 DEBUG app.flasher flash_usb [firmware_test]: Status (HAB mode) = 1450735702 (0x56787856) Hab Is Disabled (Unlocked). -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: MIMXRT1052 Flash Tool (USB SDP) -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: Прошивка: firmware_test [Release] -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: SDP USB: 0x1FC9,0x130 -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: BL USB: 0x15A2,0x73 -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: ════════════════════════════════════════════════════════════ -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: Загрузка Flashloader через SDP (1FC9:0130) -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- write-file 0x20001C00 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/tools/host/dcd/ivt_flashloader.bin -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: $ sdphost -u 0x1FC9,0x130 -j -- jump-address 0x20001C00 -2026-06-30 14:58:17,851 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:19,246 DEBUG app.flasher flash_usb [firmware_test]: Ожидание Flashloader (до 10с)...Response status = 0 (0x0) Success. -2026-06-30 14:58:19,423 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,055 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,265 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,440 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,618 DEBUG app.flasher flash_usb [firmware_test]: Writing memory -2026-06-30 14:58:20,789 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,789 DEBUG app.flasher flash_usb [firmware_test]: Response word 1 = 68364 (0x10b0c) -2026-06-30 14:58:20,971 DEBUG app.flasher flash_usb [firmware_test]: Response status = 0 (0x0) Success. -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: OK (1с) -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: Конфигурация FlexSPI NOR (инициализация контроллера) -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,995 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xC0000007 word -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Прошивка Flash: firmware_test_hab.bin -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Образ: /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Размер: 68364 байт -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Адрес: 0x60001000 -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Стирание: 0x60000000 .. +73728 байт -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- flash-erase-region 0x60000000 73728 0 -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: Запись FCB в Flash[0x60000000] -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- fill-memory 0x2000 4 0xF000000F word -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- configure-memory 9 0x2000 -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- write-memory 0x60001000 /Users/von_akimow/Desktop/TFT_ENV/tft_manufacture_test/build/Release/firmware_test_hab.bin 0 -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:20,996 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,997 DEBUG app.flasher flash_usb [firmware_test]: Reset -2026-06-30 14:58:20,997 DEBUG app.flasher flash_usb [firmware_test]: ──────────────────────────────────────────────────────────── -2026-06-30 14:58:20,997 DEBUG app.flasher flash_usb [firmware_test]: $ blhost -u 0x15A2,0x73 -- reset -2026-06-30 14:58:20,997 DEBUG app.flasher flash_usb [firmware_test]: -2026-06-30 14:58:20,997 DEBUG app.flasher flash_usb [firmware_test]: ✅ Прошивка завершена успешно -2026-06-30 14:58:47,116 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:02:20,779 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:02:22,328 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:03:07,785 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:03:09,333 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:03:56,019 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:03:57,569 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:05:47,811 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:05:49,358 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:07:27,853 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:07:29,401 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:08:24,771 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:08:26,321 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:08:55,013 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:08:56,561 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:09:59,613 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:10:01,161 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:12:33,081 WARNING app.firmware_client _recv_until timeout after 120.0 s -2026-06-30 15:14:40,777 WARNING app.firmware_client _recv_until timeout after 120.0 s -2026-06-30 15:33:29,207 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:33:54,602 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:33:56,280 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:37:25,364 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:37:27,091 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:42:36,030 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:42:37,715 INFO app.m5_client M5StampPLC не найден -2026-06-30 15:43:19,205 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 15:43:22,852 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 15:43:23,345 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 15:43:23,701 ERROR app.screens.diag run_worker error: write failed: [Errno 6] Device not configured -2026-06-30 15:43:28,104 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 15:43:29,654 INFO app.m5_client M5StampPLC не найден -2026-06-30 16:19:09,052 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 16:19:10,697 INFO app.m5_client M5StampPLC не найден -2026-06-30 16:20:10,951 ERROR app.orchestrator HIL confirm без M5: opto_in1_active -2026-06-30 16:27:42,558 DEBUG asyncio Using selector: KqueueSelector -2026-06-30 16:27:44,211 INFO app.m5_client M5StampPLC не найден