diff --git a/bsp/CMakeLists.txt b/bsp/CMakeLists.txt index a200399..d8bc15f 100644 --- a/bsp/CMakeLists.txt +++ b/bsp/CMakeLists.txt @@ -16,8 +16,9 @@ set_source_files_properties(board/board.c board/pin_mux.c PROPERTIES COMPILE_OPTIONS "-w") # Дефайны PUBLIC — транзитивно подтянутся во все firmware таргеты TODO: для # каждого приложения свои дефайны -target_compile_definitions(bsp_board PUBLIC CPU_MIMXRT1052CVJ5B - SKIP_SYSCLK_INIT) +target_compile_definitions( + bsp_board PUBLIC CPU_MIMXRT1052CVJ5B SKIP_SYSCLK_INIT XIP_EXTERNAL_FLASH=1 + XIP_BOOT_HEADER_ENABLE=1 XIP_BOOT_HEADER_DCD_ENABLE=1) # Сценарий A: XIP — код исполняется прямо из Flash add_library(bsp_boot_xip INTERFACE) diff --git a/docs/HAB_GUIDE.md b/docs/HAB_GUIDE.md new file mode 100644 index 0000000..291aadb --- /dev/null +++ b/docs/HAB_GUIDE.md @@ -0,0 +1,223 @@ +# High Assurance Boot (HAB) — Принцип работы и применение на MIMXRT1052 + +## 1. Что такое HAB + +**High Assurance Boot (HAB)** — механизм безопасной загрузки, встроенный в BootROM микроконтроллеров семейства NXP i.MX/RT. Его цель — криптографически гарантировать, что на чипе запустится только авторизованный код. + +HAB работает на уровне кремния: BootROM прошит на заводе и не может быть изменён. Вся цепочка доверия строится от него. + +--- + +## 2. Угрозы без HAB + +Без механизма защищённой загрузки любой, имеющий физический доступ к устройству, может: + +- подключить программатор и залить произвольную прошивку +- загрузить вредоносный код через USB в режиме Serial Download Protocol (SDP) +- модифицировать прошивку во Flash между производством и эксплуатацией + +HAB устраняет эти угрозы на аппаратном уровне. + +--- + +## 3. Структура HAB-образа + +HAB-образ — это не просто бинарник прошивки, а обёртка с метаданными вокруг него. BootрOM ищет обязательные структуры по фиксированным смещениям. + +### Карта памяти Flash (FlexSPI NOR, XIP) + +```bash +0x60000000 ┌──────────────────────────────────┐ + │ FCB — Flash Configuration Block │ 512 байт + │ (конфигурация FlexSPI контроллера│ + │ записывается Flashloader'ом) │ +0x60001000 ├──────────────────────────────────┤ + │ IVT — Image Vector Table │ 32 байта +0x60001020 ├──────────────────────────────────┤ + │ BDT — Boot Data Table │ 12 байт +0x60001030 ├──────────────────────────────────┤ + │ DCD — Device Config Data │ опционально + │ (инициализация SDRAM и др.) │ + ├──────────────────────────────────┤ +0x60003000 │ Код прошивки (.text, .data, ...) │ + │ │ + ├──────────────────────────────────┤ + │ CSF — Command Sequence File │ только в signed-образе + │ (подпись, ключи, хэши) │ + └──────────────────────────────────┘ +``` + +### 3.1 IVT — Image Vector Table + +Главная точка входа для BootROM. Структура фиксирована, 32 байта, тег `0xD1`: + +```c +typedef struct { + uint32_t header; // тег 0xD1, длина, версия + uint32_t entry; // адрес Reset_Handler прошивки + uint32_t reserved1; + uint32_t dcd; // адрес DCD (0 если не нужен) + uint32_t boot_data; // адрес BDT + uint32_t self; // адрес самого IVT + uint32_t csf; // адрес CSF (0 если unsigned) + uint32_t reserved2; +} ivt_t; +``` + +BootROM находит IVT по фиксированному смещению от начала Flash (`ivtOffset = 0x1000` для FlexSPI NOR), читает его и получает адреса всех остальных структур. + +### 3.2 BDT — Boot Data Table + +Сообщает BootROM, где начинается образ и каков его полный размер: + +```c +typedef struct { + uint32_t start; // 0x60000000 — начало образа во Flash + uint32_t length; // полный размер в байтах + uint32_t plugin; // 0 для обычного образа +} boot_data_t; +``` + +### 3.3 DCD — Device Configuration Data + +Опциональная секция с командами инициализации периферии, которые BootROM выполняет **до** передачи управления прошивке. Типичное применение — инициализация SDRAM (SEMC), чтобы к моменту старта первой инструкции прошивки память уже была доступна. + +DCD содержит последовательность команд двух типов: + +| Команда | Тег | Назначение | +|---|---|---| +| `Write Data` | `0xCC` | Записать значение по адресу | +| `Check Bits Set` | `0xCF` | Ждать пока бит станет `1` (poll) | + +Формат бинарника: `Tag(1) | Length(2 BE) | Parameter(1) | данные`. + +### 3.4 CSF — Command Sequence File + +Криптографическая секция. Присутствует только в подписанных образах. Содержит: + +- таблицу публичных ключей (SRK table) +- хэши защищённых регионов образа (IVT, BDT, код) +- подпись RSA 2048/4096 или ECDSA + +--- + +## 4. Режимы HAB + +### 4.1 По типу образа + +| Режим | `flags` | CSF | Применение | +|---|---|---|---| +| Unsigned | `0x00` | отсутствует | разработка, отладка | +| Signed | `0x08` | RSA/ECDSA подпись | производство | +| Signed + Encrypted | `0x0C` | подпись + шифрование кода | максимальная защита | + +### 4.2 По состоянию чипа (OTP fuse) + +Независимо от типа образа, чип может находиться в одном из двух состояний: + +**HAB Open** (fuse `SEC_CONFIG = 0`, заводское состояние): +BootROM проверяет подпись, но **игнорирует ошибки** — запуск происходит в любом случае. Это позволяет работать с unsigned образами на этапе разработки. + +**HAB Closed** (fuse `SEC_CONFIG = 1`): +При ошибке проверки подписи BootROM **отказывает в запуске** безвозвратно. Запись fuse необратима — чип нельзя вернуть в Open состояние. + +--- + +## 5. Цепочка доверия (Trust Chain) + +```bash +Производитель устройства + │ + ├── Генерирует пару ключей RSA 4096 + │ private.pem → хранится в защищённом месте (HSM / vault) + │ public.pem → включается в образ (SRK table) + │ + ├── SHA256(public.pem) записывается в OTP fuses (SRK_HASH) + │ ↑ необратимо, выполняется один раз при производстве + │ + └── При сборке каждого релиза: + nxpimage hab export (flags=0x08) + → хэшируются IVT + BDT + код + → подписывается private.pem + → CSF встраивается в образ + +При загрузке на чипе: + BootROM + → читает IVT → находит CSF + → извлекает public key из CSF + → SHA256(public key) == SRK_HASH из fuses? → ДА + → проверяет подпись хэшей регионов → ОК + → прыгает на entry point +``` + +--- + +## 6. Почему Unsigned-образ требует HAB-контейнер + +Распространённое заблуждение: "раз образ без подписи, зачем вообще HAB?". Ответ прост: + +**BootROM всегда ищет IVT по фиксированному смещению.** Это не опциональная безопасность — это формат загрузки. Без IVT и BDT BootROM не знает: + +- куда прыгать (entry point) +- где находится DCD для инициализации SDRAM +- каков размер образа + +`nxpimage hab export` для unsigned образа выполняет именно эту работу — добавляет IVT, BDT, встраивает DCD — без какой-либо криптографии. CSF при этом равен нулю. + +--- + +## 7. Процесс прошивки MIMXRT1052 (USB, без JTAG) + +BootROM в режиме SDP умеет только писать в RAM и прыгать. Для записи во Flash необходим **Flashloader** — специальная программа от NXP. + +``` +Плата в SDP режиме (BOOT_MOD_1 = 3V3) + │ + │ sdphost -u 0x1FC9,0x0130 + ├─ write-file 0x20001C00 ivt_flashloader.bin + └─ jump-address 0x20001C00 + │ + │ (ожидание ~3с инициализации) + │ + Flashloader запущен + │ blhost -u 0x15A2,0x0073 + ├─ fill-memory 0x2000 4 0xC0000007 ← option word для FlexSPI NOR + ├─ configure-memory 9 0x2000 ← Flashloader пишет FCB в Flash + ├─ flash-erase-region 0x60000000 … + ├─ write-memory 0x60002000 firmware_hab.bin ← HAB образ + └─ reset +``` + +--- + +## 8. Жизненный цикл для проекта TFT + +| Стадия | Режим HAB | Подпись | Fuse | +|---|---|---|---| +| Разработка | Open | Unsigned (`0x00`) | не трогаем | +| Входной контроль | Open | Unsigned (`0x00`) | не трогаем | +| Предсерийные образцы | Open | Signed (`0x08`) | не трогаем | +| Серийное производство | **Closed** | Signed (`0x08`) | `SEC_CONFIG = 1` | + +> ⚠️ Запись `SEC_CONFIG = 1` необратима. Перед закрытием HAB необходимо убедиться, что подписанный образ успешно проходит верификацию на реальном железе. + +--- + +## 9. Инструменты + +| Инструмент | Назначение | +|---|---| +| `nxpimage hab export` | Сборка HAB-образа (IVT + BDT + DCD + опционально CSF) | +| `nxpimage hab parse` | Разбор готового образа для проверки | +| `sdphost` | Связь с BootROM в SDP режиме (запись в RAM, прыжок) | +| `blhost` | Связь с Flashloader (запись во Flash, конфигурация памяти) | +| `nxpdevscan` | Обнаружение подключённых NXP устройств | + +--- + +## 10. Литература + +- **NXP AN12263** — "HAB Code Signing for i.MX RT" — пошаговая инструкция по подписи образов +- **MIMXRT1052 Reference Manual** — Chapter 9: System Boot (структуры IVT, BDT, DCD, CSF) +- [**SPSDK Documentation**](https://spsdk.readthedocs.io) — документация по nxpimage, blhost, sdphost +- **NXP Application Note AN4581** — "Secure Boot on i.MX50, i.MX53, and i.MX 6 Series" diff --git a/firmware/test/CMakeLists.txt b/firmware/test/CMakeLists.txt index cb8e78c..757555f 100644 --- a/firmware/test/CMakeLists.txt +++ b/firmware/test/CMakeLists.txt @@ -13,7 +13,6 @@ target_sources(firmware_test PRIVATE main.c target_link_libraries( firmware_test PRIVATE bsp_board - bsp_boot_xip # SDK драйверы периферии — добавляй по мере написания тестов sdk_lpuart # UART тест sdk_flexcan # CAN тест diff --git a/firmware/test/main.c b/firmware/test/main.c index 642ecdc..889c3da 100644 --- a/firmware/test/main.c +++ b/firmware/test/main.c @@ -11,7 +11,6 @@ #include "fsl_gpio.h" #include "pin_mux.h" - /******************************************************************************* * Definitions ******************************************************************************/ diff --git a/tools/README.md b/tools/README.md index b7ac870..49a260b 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,164 +1,257 @@ -# Host Tools — окружение для прошивки +# tools/host — Окружение прошивки MIMXRT1052CVJ5B -Изолированное Python-окружение на базе [uv](https://docs.astral.sh/uv/). -Устанавливается на хост-машине разработчика — **не внутри devcontainer**. +Изолированное Python-окружение на базе [uv](https://docs.astral.sh/uv/) для сборки +HAB-образов и прошивки платы через USB. Запускается на хост-машине разработчика — +**не внутри devcontainer**. + +--- ## Структура ```bash tools/host/ ├── dcd/ -│ ├── dcd_mt48lc16m16a2.cfg ← источник истины для DCD (коммитить) -│ ├── dcd_compiler.py ← скрипт: .cfg → .bin -│ └── dcd.bin ← артефакт (пересобирается из .cfg) -│ -├── fdcb/ -│ ├── fcb_w25q64_quad.yaml ← конфиг FCB: W25Q64, Quad I/O, 133 MHz -│ └── fcb.bin ← артефакт (пересобирается из .yaml) -│ +│ ├── dcd.bin ← DCD бинарник (инициализация SDRAM, коммитить как есть) +│ └── ivt_flashloader.bin ← NXP Flashloader (коммитить) ├── hab/ │ ├── hab_firmware_test.yaml ← HAB: Debug + DCD (входной контроль) │ ├── hab_bootloader.yaml ← HAB: Release, без DCD │ └── hab_app.yaml ← HAB: Release + DCD (боевая прошивка) -│ -├── image/ -│ ├── bootimg_firmware_test.yaml -│ ├── bootimg_bootloader.yaml -│ └── bootimg_app.yaml -│ -├── pyproject.toml ← зависимости (spsdk, версия зафиксирована) +├── flash_usb.py ← скрипт прошивки через USB +├── pyproject.toml ← зависимости (spsdk==3.7.x) ├── uv.lock ← lockfile (коммитить) -├── .python-version └── README.md ``` -## Установка uv (один раз на машину) +## Предварительные требования + +### 1. uv — один раз на машину ```bash -# Linux/macOS +# macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh # Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex" ``` -## Первый запуск (один раз на репозиторий) +### 2. Зависимости проекта — один раз на репозиторий ```bash cd tools/host uv sync ``` -### udev правило для USB SDP — только Linux, один раз на машину +### 3. udev правила — только Linux, один раз на машину -Без этого правила `blhost` требует `sudo`: +Без этого для работы с USB нужен `sudo`: ```bash -echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="0135", MODE="0666", GROUP="plugdev"' \ - | sudo tee /etc/udev/rules.d/99-nxp-sdp.rules +sudo tee /etc/udev/rules.d/99-nxp-mimxrt.rules << 'EOF' +# NXP BootROM — SDP режим (BOOT_MOD_1 = 3V3) +SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="0130", MODE="0666", GROUP="plugdev" +# NXP Flashloader — после jump-address +SUBSYSTEM=="usb", ATTR{idVendor}=="15a2", ATTR{idProduct}=="0073", MODE="0666", GROUP="plugdev" +EOF + sudo udevadm control --reload-rules && sudo udevadm trigger sudo usermod -a -G plugdev $USER -# Перелогиниться после usermod! +# После usermod — перелогиниться! ``` -## Пайплайн сборки загрузочного образа +--- -### Шаг 1 — DCD (пересобирать при изменении dcd_mt48lc16m16a2.cfg) +## Карта Flash (W25Q64FVSSIG, 8 MB) ```bash -cd tools/host/dcd -uv run python3 dcd_compiler.py dcd_mt48lc16m16a2.cfg dcd.bin +0x60000000 ┌─────────────────────────────┐ + │ FCB — Flash Config Block │ 512 байт + │ (пишет Flashloader, │ + │ не входит в HAB образ) │ +0x60001000 ├─────────────────────────────┤ + │ IVT — Image Vector Table │ ← начало HAB образа + │ BDT — Boot Data Table │ +0x60001040 ├─────────────────────────────┤ + │ DCD — SDRAM init │ ~1088 байт (для fw_test и app) +0x60003000 ├─────────────────────────────┤ + │ Код прошивки │ + │ (.text, .data, ...) │ + └─────────────────────────────┘ ``` -### Шаг 2 — FCB (пересобирать при изменении fcb_w25q64_quad.yaml) +--- + +## Пайплайн: сборка HAB образа ```bash -cd tools/host/fdcb -uv run nxpimage bootable-image fcb export -c fcb_w25q64_quad.yaml -o fcb.bin -``` +cd tools/host/hab -### Шаг 3 — Загрузочный образ - -```bash -cd tools/host/image - -# firmware_test (Debug, входной контроль) -uv run nxpimage bootable-image export -c bootimg_firmware_test.yaml +# firmware_test (Debug) — входной контроль платы +uv run nxpimage hab export --force \ + -c hab_firmware_test.yaml \ + -o ../../../../build/Debug/firmware_test_hab.bin # bootloader (Release) -uv run nxpimage bootable-image export -c bootimg_bootloader.yaml +uv run nxpimage hab export --force \ + -c hab_bootloader.yaml \ + -o ../../../../build/Release/bootloader_hab.bin -# app (Release, боевая прошивка) -uv run nxpimage bootable-image export -c bootimg_app.yaml +# app (Release) — боевая прошивка +uv run nxpimage hab export --force \ + -c hab_app.yaml \ + -o ../../../../build/Release/app_hab.bin ``` -Артефакты попадают в `build/Debug/` и `build/Release/` соответственно. - -### Проверка образа +### Проверка образа после сборки ```bash -cd tools/host/image -uv run nxpimage bootable-image parse \ - -b ../../../../build/Debug/firmware_test_bootable.bin \ - -f mimxrt1050 +uv run nxpimage hab parse -b ../../../../build/Debug/firmware_test_hab.bin ``` -В выводе должны присутствовать секции `FCB`, `IVT`, `BDT`, `DCD`, `App`. +Ожидаемый результат: IVT с корректным `entry`, DCD с тегом `0xD2`, +`csf = 0x00000000` (unsigned). -## Прошивка через USB (BootROM SDP режим) +--- -Перевести плату в SDP режим: `BOOT_MOD_1 = 1` (подтянуть к 3V3), затем подать питание или нажать Reset. +## Пайплайн: прошивка через USB + +### Подготовка платы + +Перевести плату в режим SDP (Serial Download Protocol): + +1. Подтянуть `BOOT_MOD_1` к `3V3` +2. Reset +3. Подключить USB к ПК + +В этом режиме плата определяется как `VID:PID = 1FC9:0130`. + +### Запуск скрипта ```bash cd tools/host -# Проверить что устройство определилось (VID:PID 1FC9:0135) -export VID_PID=0x1fc9:0x0130 -uv run nxpdevscan +# firmware_test +uv run python3 flash_usb.py --firmware firmware_test --build-type Debug -# Версия BootROM на таргете -uv run blhost -u $VID_PID get-property 1 -# Доступные BootROM области памяти -uv run blhost -u $VID_PID list-memory +# app +uv run python3 flash_usb.py --firmware app --build-type Release -# Прошить firmware_test -uv run blhost -u $VID_PID flash-erase-all -uv run blhost -u $VID_PID write-memory 0x60000000 \ - ../../build/Debug/firmware_test_bootable.bin -uv run blhost -u $VID_PID reset - -# Загрузить в RAM без записи во Flash (для быстрой отладки) -uv run blhost -u $VID_PID load-image ../../build/Debug/firmware_test_bootable.bin +# bootloader +uv run python3 flash_usb.py --firmware bootloader --build-type Release ``` -После прошивки вернуть `BOOT_MOD_1 = 0` (подтянуть к GND) для нормального старта из Flash. +После прошивки: вернуть `BOOT_MOD_1` к `GND`, Reset — плата стартует из Flash. -## Удалённая прошивка (сервер) +### Последовательность команд внутри скрипта ```bash -# Из devcontainer или локально — копируем образ на сервер и прошиваем -./tools/host/flash_remote.sh firmware_test Debug +Плата в SDP режиме (1FC9:0130) + │ + ├─ sdphost write-file 0x20001C00 ivt_flashloader.bin + └─ sdphost jump-address 0x20001C00 + │ + │ (ожидание до 10с пока Flashloader поднимется на 15A2:0073) + │ + Flashloader (15A2:0073) + │ + │ Шаг 1 — инициализация FlexSPI NOR контроллера + ├─ blhost fill-memory 0x2000 4 0xC0000007 word + ├─ blhost configure-memory 9 0x2000 + │ + │ Шаг 2 — стирание Flash + ├─ blhost flash-erase-region 0x60000000 0 (memoryId=0, XIP) + │ + │ Шаг 3 — запись FCB в 0x60000000 + │ (ПОСЛЕ стирания! Flashloader генерирует FCB из параметров шага 1) + ├─ blhost fill-memory 0x2000 4 0xF000000F word + ├─ blhost configure-memory 9 0x2000 + │ + │ Шаг 4 — запись HAB образа начиная с 0x60001000 + ├─ blhost write-memory 0x60001000 *_hab.bin 0 (memoryId=0, XIP) + └─ blhost reset ``` +> **Почему FCB не в образе?** +> Flashloader генерирует FCB автоматически из параметров FlexSPI (option word +> `0xC0000007`). Запись FCB через `0xF000000F` — это отдельная команда, +> выполняемая строго после `flash-erase-region`, иначе FCB будет затёрт следующим +> стиранием. + +--- + +## DCD — инициализация SDRAM + +`dcd/dcd.bin` — бинарный блоб команд, который BootROM выполняет до передачи +управления прошивке. Инициализирует PLL, CCM clock gates, SEMC контроллер +и микросхему SDRAM (MT48LCxxM4). + +Файл хранится в репозитории в бинарном виде и **не требует пересборки** — он +меняется только при изменении схемотехники. + +```bash +Цель: MT48LC16M16A2P-6A, 32 MB, шина 16 бит, CS0 + SEMC BR0: base=0x80000000, size=32MB, VLD=1 + SEMC BR1–BR3: VLD=0 (один чип, один CS) +``` + +Использование DCD по прошивкам: + +| Прошивка | DCD | Причина | +|---|---|---| +| `firmware_test` | ✓ | тесты работают с SDRAM | +| `app` | ✓ | FreeRTOS heap и буферы LCDIF размещены в SDRAM | +| `bootloader` | ✗ | загрузчик не использует SDRAM, инициализация в app | + +--- + +## Flashloader + +`dcd/ivt_flashloader.bin` — NXP-программа, загружаемая в RAM через SDP. +Предоставляет `blhost` доступ к Flash, которого нет через BootROM напрямую. + +```bash +Entry point: 0x20002401 +Загрузка по: 0x20001C00 +VID:PID после старта: 15A2:0073 +Источник: MCUXpresso Secure Provisioning Tool 25.12 +``` + +--- + ## Диагностика ```bash -# Список поддерживаемых семейств (проверка установки) -uv run nxpimage bootable-image get-families +# Найти подключённые NXP устройства +uv run nxpdevscan -# Список доступных шаблонов для mimxrt1050 -uv run nxpimage bootable-image list-templates -f mimxrt1050 +# Проверить связь с BootROM через SDP +sdphost -u 0x1FC9,0x0130 -- error-status -# Версия SPSDK +# Проверить что Flashloader отвечает (после jump-address) +blhost -u 0x15A2,0x0073 -- get-property 1 0 + +# Версии инструментов uv run nxpimage --version uv run blhost --version ``` +### Типичные ошибки + +| Симптом | Причина | Решение | +|---|---|---| +| `USB HID device not found: 1FC9:0130` | Плата не в SDP режиме | Проверить `BOOT_MOD_1` → 3V3 и Reset | +| Flashloader timeout после jump | `ivt_flashloader.bin` повреждён или не тот | Взять из SPT 25.12 | +| Плата не стартует после прошивки | `BOOT_MOD_1` не переключён обратно | Вернуть `BOOT_MOD_1` → GND, Reset | +| Плата зависает сразу после старта | DCD завис (неверный `dcd.bin`) | Использовать только верифицированный `dcd.bin` | +| Плата стартует, периферия не работает | CCM clock gates в DCD отключают нужные клоки | Проверить `dcd.bin` — только верифицированный вариант | + +--- + ## Обновление зависимостей ```bash cd tools/host uv add "spsdk==X.Y.Z" uv sync -git add uv.lock +git add uv.lock pyproject.toml ``` diff --git a/tools/host/dcd/dcd.bin b/tools/host/dcd/dcd.bin index d8fff95..ccdf387 100644 Binary files a/tools/host/dcd/dcd.bin and b/tools/host/dcd/dcd.bin differ diff --git a/tools/host/dcd/dcd_compiler.py b/tools/host/dcd/dcd_compiler.py deleted file mode 100644 index 866ba8b..0000000 --- a/tools/host/dcd/dcd_compiler.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env python3 -""" -dcd_cfg_to_bin.py — конвертация DCD .cfg (NXP Config Tools) в .bin (BootROM формат) - -Формат DCD бинарника (IMX RT RM, Chapter 9.7): - [Header] - 0xD2 — DCD tag - length[1:0] — общая длина в байтах (big-endian, 2 байта) - 0x41 — version - - [Commands] — последовательно: - Write Data (0xCC): - 0xCC tag, length BE16, parameter (ширина: 4=word) - [addr BE32, value BE32] × N — группируются подряд идущие записи - - Check Bits Set (0xCF) — wait_until (expr & mask) != 0: - 0xCF tag, 0x000C length, parameter (4=word) - addr BE32, mask BE32, count BE32 (0 = бесконечно) - -Использование: - python3 dcd_cfg_to_bin.py dcd.cfg dcd.bin - python3 dcd_cfg_to_bin.py dcd.cfg # выведет dcd.bin рядом с cfg -""" - -import re -import struct -import sys -from pathlib import Path -from dataclasses import dataclass, field -from typing import Union - -# ─── Константы DCD ──────────────────────────────────────────────────────────── -DCD_TAG = 0xD2 -DCD_VERSION = 0x41 -CMD_WRITE = 0xCC -CMD_CHECK_SET = 0xCF # wait_until (reg & mask) != 0 -CMD_CHECK_CLEAR = 0xD0 # wait_until (reg & mask) == 0 -WIDTH_WORD = 0x04 # 32-bit - - -# ─── Типы команд ────────────────────────────────────────────────────────────── -@dataclass -class WriteEntry: - addr: int - value: int - - -@dataclass -class WriteCmd: - entries: list[WriteEntry] = field(default_factory=list) - - def to_bytes(self) -> bytes: - length = 4 + len(self.entries) * 8 - # NXP RM format: Tag(1) | Length(2 BE) | Parameter(1) - hdr = struct.pack(">BHB", CMD_WRITE, length, WIDTH_WORD) - data = b"".join( - struct.pack(">II", e.addr, e.value) for e in self.entries - ) - return hdr + data - - -@dataclass -class CheckCmd: - addr: int - mask: int - check_set: bool = True # True = wait != 0, False = wait == 0 - - def to_bytes(self) -> bytes: - tag = CMD_CHECK_SET if self.check_set else CMD_CHECK_CLEAR - # NXP RM format: Tag(1) | Length(2 BE=12) | Parameter(1) | Addr(4) | Mask(4) - # Parameter: bits[2:0]=width(4=32bit), bit[3]=check_set → 0x1C / check_clear → 0x14 - # No count field — poll indefinitely is the default (length=12, not 16) - param = 0x1C if self.check_set else 0x14 - length = 12 # 4 header + 4 addr + 4 mask - return struct.pack(">BHBII", tag, length, param, self.addr, self.mask) - - -# ─── Парсер .cfg ───────────────────────────────────────────────────────────── -def parse_hex(s: str) -> int: - return int(s, 16) if s.startswith("0x") or s.startswith("0X") else int(s) - - -def parse_cfg(text: str) -> list[Union[WriteCmd, CheckCmd]]: - """ - Парсит .cfg и возвращает список команд DCD. - Соседние write-записи группируются в одну WriteCmd. - """ - # Убираем блочные комментарии /* ... */ - text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL) - # Убираем строчные комментарии // ... - text = re.sub(r"//[^\n]*", "", text) - - commands: list[Union[WriteCmd, CheckCmd]] = [] - current_write: WriteCmd | None = None - - # Паттерн: *(uint32_t*)0xADDR = 0xVALUE; - re_write = re.compile( - r"\*\s*\(\s*uint32_t\s*\*\s*\)\s*(0x[0-9A-Fa-f]+)\s*=\s*(0x[0-9A-Fa-f]+)\s*;" - ) - - # Паттерн: (*(uint32_t*)0xADDR & 0xMASK) != 0; - re_check_set = re.compile( - r"\(\s*\*\s*\(\s*uint32_t\s*\*\s*\)\s*(0x[0-9A-Fa-f]+)\s*&\s*(0x[0-9A-Fa-f]+)\s*\)\s*!=\s*0\s*;" - ) - - # Паттерн: (*(uint32_t*)0xADDR & 0xMASK) == 0; - re_check_clear = re.compile( - r"\(\s*\*\s*\(\s*uint32_t\s*\*\s*\)\s*(0x[0-9A-Fa-f]+)\s*&\s*(0x[0-9A-Fa-f]+)\s*\)\s*==\s*0\s*;" - ) - - for line in text.splitlines(): - line = line.strip() - if not line: - continue - - m = re_write.search(line) - if m: - addr = parse_hex(m.group(1)) - value = parse_hex(m.group(2)) - if current_write is None: - current_write = WriteCmd() - commands.append(current_write) - current_write.entries.append(WriteEntry(addr, value)) - continue - - m = re_check_set.search(line) - if m: - if current_write is not None: - current_write = None # разрываем группу write - addr = parse_hex(m.group(1)) - mask = parse_hex(m.group(2)) - commands.append(CheckCmd(addr, mask, check_set=True)) - continue - - m = re_check_clear.search(line) - if m: - if current_write is not None: - current_write = None - addr = parse_hex(m.group(1)) - mask = parse_hex(m.group(2)) - commands.append(CheckCmd(addr, mask, check_set=False)) - continue - - # Не write и не check — разрываем текущую write-группу - # (на случай если между записями есть другой синтаксис) - if current_write is not None: - current_write = None - - return commands - - -# ─── Сборка бинарника ───────────────────────────────────────────────────────── -def build_dcd_binary(commands: list[Union[WriteCmd, CheckCmd]]) -> bytes: - body = b"".join(cmd.to_bytes() for cmd in commands) - total_length = 4 + len(body) # 4 байта header - # NXP RM format: Tag(1) | Length(2 BE) | Version(1) - header = struct.pack(">BHB", DCD_TAG, total_length, DCD_VERSION) - return header + body - - -# ─── Отчёт ──────────────────────────────────────────────────────────────────── -def print_report(commands: list[Union[WriteCmd, CheckCmd]], out_size: int) -> None: - writes = sum(1 for c in commands if isinstance(c, WriteCmd)) - checks = sum(1 for c in commands if isinstance(c, CheckCmd)) - entries = sum(len(c.entries) for c in commands if isinstance(c, WriteCmd)) - - print(f"\n{'─'*52}") - print(f" DCD конвертация завершена") - print(f"{'─'*52}") - print(f" Write команд (групп) : {writes}") - print(f" Write записей всего : {entries}") - print(f" Check команд : {checks}") - print(f" Размер бинарника : {out_size} байт (0x{out_size:04X})") - print(f"{'─'*52}") - - print("\n Команды:") - for i, cmd in enumerate(commands): - if isinstance(cmd, WriteCmd): - print(f" [{i:02d}] WRITE × {len(cmd.entries):3d} entries" - f" (0x{cmd.entries[0].addr:08X} … 0x{cmd.entries[-1].addr:08X})") - else: - kind = "CHECK_SET (!= 0)" if cmd.check_set else "CHECK_CLR (== 0)" - print(f" [{i:02d}] {kind} addr=0x{cmd.addr:08X} mask=0x{cmd.mask:08X}") - print() - - -# ─── main ───────────────────────────────────────────────────────────────────── -def main(): - if len(sys.argv) < 2: - print(__doc__) - sys.exit(1) - - cfg_path = Path(sys.argv[1]) - if not cfg_path.exists(): - print(f"[ERROR] Файл не найден: {cfg_path}") - sys.exit(1) - - out_path = Path(sys.argv[2]) if len(sys.argv) >= 3 else cfg_path.with_suffix(".bin") - - text = cfg_path.read_text(encoding="utf-8", errors="replace") - commands = parse_cfg(text) - - if not commands: - print("[ERROR] Ни одной команды не найдено. Проверь формат .cfg файла.") - sys.exit(1) - - binary = build_dcd_binary(commands) - out_path.write_bytes(binary) - - print(f"[OK] Входной файл : {cfg_path}") - print(f"[OK] Выходной файл: {out_path}") - print_report(commands, len(binary)) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/host/dcd/dcd_mt48lc16m16a2.cfg b/tools/host/dcd/dcd_mt48lc16m16a2.cfg deleted file mode 100644 index aae92f9..0000000 --- a/tools/host/dcd/dcd_mt48lc16m16a2.cfg +++ /dev/null @@ -1,232 +0,0 @@ -[DCD Descriptor] - -// ============================================================================= -// Clock Init -// MT48LC16M16A2 SDRAM on MIMXRT1052CVJ5B -// -// Включаем только необходимые тактовые домены (fix 6): -// CCM_CCGR0: биты [1:0]=11 (aips_tz1), биты [3:2]=11 (aips_tz2) — доступ к периферии -// CCM_CCGR2: биты [29:28]=11 (iomuxc) — конфигурация пинов -// CCM_CCGR3: биты [5:4]=11 (semc) — контроллер SDRAM -// CCM_CCGR4: биты [3:2]=11 (iomuxc_gpr) — GPR регистры -// CCM_CCGR5: биты [1:0]=11 (rom) — BootROM -// -// ВАЖНО: если после изменения плата не стартует — проверь по RM Table 18-5 -// (CCM Clock Gating Register) и вернись к 0xFFFFFFFF для отладки. -// ============================================================================= - -*(uint32_t*)0x400FC068 = 0x0000000F; // CCM_CCGR0: aips_tz1 + aips_tz2 -*(uint32_t*)0x400FC06C = 0x00000000; // CCM_CCGR1: не нужен для DCD -*(uint32_t*)0x400FC070 = 0x30000000; // CCM_CCGR2: iomuxc (CG14, bits[29:28]) -*(uint32_t*)0x400FC074 = 0x00000030; // CCM_CCGR3: semc (CG2, bits[5:4]) -*(uint32_t*)0x400FC078 = 0x0000000C; // CCM_CCGR4: iomuxc_gpr (CG1, bits[3:2]) -*(uint32_t*)0x400FC07C = 0x00000003; // CCM_CCGR5: rom (CG0, bits[1:0]) -*(uint32_t*)0x400FC080 = 0x00000000; // CCM_CCGR6: не нужен для DCD - -// PLL_SYS: 528 MHz (24 MHz * 22), DIV_SELECT=1 → Fvco=528MHz -*(uint32_t*)0x400D8030 = 0x00002001; - -// Ждём lock PLL_SYS (bit 31 = LOCK) перед переключением источника тактирования (fix 3) -(*(uint32_t*)0x400D8030 & 0x80000000) != 0; - -// PFD2 = 528 * 18 / 0x23(35) = ~271 MHz... нет. -// PFD528[PFD2_FRAC] = 0x23 = 35 → Fout = 528 * 18 / 35 = ~271? -// Фактически 0x00230000 → PFD2_FRAC = 0x23 = 35 → F = 528*18/35 ≈ 271 МГц -// Но для SEMC @ 133 МГц нужен делитель CCM_CBCDR[SEMC_PODF]. -// Проверь соответствие с clock_config.c! -*(uint32_t*)0x400D8100 = 0x00230000; // CCM_ANALOG_PFD_528: PFD2 = 133 MHz - -// CCM_CBCDR: SEMC_CLK_SEL=1 (PLL2_PFD2), SEMC_ALT_CLK_SEL=0, SEMC_PODF=1 (делитель /2) -// → SEMC clock = 133 / 2 = 66.5 МГц -// Если нужно 133 МГц — SEMC_PODF=0 (делитель /1), но убедись что SDRAM выдержит -*(uint32_t*)0x400FC014 = 0x00010D40; // CCM_CBCDR - -// ============================================================================= -// SDRAM Init — Configure IOMUXC for SEMC pins -// MT48LC16M16A2: 16Mx16bit, 4 Banks, LVTTL -// ============================================================================= - -// IOMUXC — MUX mode: все пины SEMC в режиме ALT0 (SEMC функция) -*(uint32_t*)0x401F8014 = 0x00000000; -*(uint32_t*)0x401F8018 = 0x00000000; -*(uint32_t*)0x401F801C = 0x00000000; -*(uint32_t*)0x401F8020 = 0x00000000; -*(uint32_t*)0x401F8024 = 0x00000000; -*(uint32_t*)0x401F8028 = 0x00000000; -*(uint32_t*)0x401F802C = 0x00000000; -*(uint32_t*)0x401F8030 = 0x00000000; -*(uint32_t*)0x401F8034 = 0x00000000; -*(uint32_t*)0x401F8038 = 0x00000000; -*(uint32_t*)0x401F803C = 0x00000000; -*(uint32_t*)0x401F8040 = 0x00000000; -*(uint32_t*)0x401F8044 = 0x00000000; -*(uint32_t*)0x401F8048 = 0x00000000; -*(uint32_t*)0x401F804C = 0x00000000; -*(uint32_t*)0x401F8050 = 0x00000000; -*(uint32_t*)0x401F8054 = 0x00000000; -*(uint32_t*)0x401F8058 = 0x00000000; -*(uint32_t*)0x401F805C = 0x00000000; -*(uint32_t*)0x401F8060 = 0x00000000; -*(uint32_t*)0x401F8064 = 0x00000000; -*(uint32_t*)0x401F8068 = 0x00000000; -*(uint32_t*)0x401F806C = 0x00000000; -*(uint32_t*)0x401F8070 = 0x00000000; -*(uint32_t*)0x401F8074 = 0x00000000; -*(uint32_t*)0x401F8078 = 0x00000000; -*(uint32_t*)0x401F807C = 0x00000000; -*(uint32_t*)0x401F8080 = 0x00000000; -*(uint32_t*)0x401F8084 = 0x00000000; -*(uint32_t*)0x401F8088 = 0x00000000; -*(uint32_t*)0x401F808C = 0x00000000; -*(uint32_t*)0x401F8090 = 0x00000000; -*(uint32_t*)0x401F8094 = 0x00000000; -*(uint32_t*)0x401F8098 = 0x00000000; -*(uint32_t*)0x401F809C = 0x00000000; -*(uint32_t*)0x401F80A0 = 0x00000000; -*(uint32_t*)0x401F80A4 = 0x00000000; -*(uint32_t*)0x401F80A8 = 0x00000000; -*(uint32_t*)0x401F80AC = 0x00000000; -*(uint32_t*)0x401F80B0 = 0x00000010; // SEMC_DATA15: SION=1 (software input on) -*(uint32_t*)0x401F80B4 = 0x00000000; -*(uint32_t*)0x401F80B8 = 0x00000000; - -// IOMUXC — PAD ctrl: 0x000110F9 -// SRE=1 (Fast Slew Rate) -// DSE=7 (Drive Strength: R0/7 — максимальный) -// SPEED=3 (200 MHz) -// ODE=0 (Open Drain disabled) -// PKE=1 (Pull/Keeper enabled) -// PUE=1 (Pull — не Keeper) -// PUS=0 (100K pull-down) -// HYS=0 (Hysteresis disabled) -*(uint32_t*)0x401F8204 = 0x000110F9; -*(uint32_t*)0x401F8208 = 0x000110F9; -*(uint32_t*)0x401F820C = 0x000110F9; -*(uint32_t*)0x401F8210 = 0x000110F9; -*(uint32_t*)0x401F8214 = 0x000110F9; -*(uint32_t*)0x401F8218 = 0x000110F9; -*(uint32_t*)0x401F821C = 0x000110F9; -*(uint32_t*)0x401F8220 = 0x000110F9; -*(uint32_t*)0x401F8224 = 0x000110F9; -*(uint32_t*)0x401F8228 = 0x000110F9; -*(uint32_t*)0x401F822C = 0x000110F9; -*(uint32_t*)0x401F8230 = 0x000110F9; -*(uint32_t*)0x401F8234 = 0x000110F9; -*(uint32_t*)0x401F8238 = 0x000110F9; -*(uint32_t*)0x401F823C = 0x000110F9; -*(uint32_t*)0x401F8240 = 0x000110F9; -*(uint32_t*)0x401F8244 = 0x000110F9; -*(uint32_t*)0x401F8248 = 0x000110F9; -*(uint32_t*)0x401F824C = 0x000110F9; -*(uint32_t*)0x401F8250 = 0x000110F9; -*(uint32_t*)0x401F8254 = 0x000110F9; -*(uint32_t*)0x401F8258 = 0x000110F9; -*(uint32_t*)0x401F825C = 0x000110F9; -*(uint32_t*)0x401F8260 = 0x000110F9; -*(uint32_t*)0x401F8264 = 0x000110F9; -*(uint32_t*)0x401F8268 = 0x000110F9; -*(uint32_t*)0x401F826C = 0x000110F9; -*(uint32_t*)0x401F8270 = 0x000110F9; -*(uint32_t*)0x401F8274 = 0x000110F9; -*(uint32_t*)0x401F8278 = 0x000110F9; -*(uint32_t*)0x401F827C = 0x000110F9; -*(uint32_t*)0x401F8280 = 0x000110F9; -*(uint32_t*)0x401F8284 = 0x000110F9; -*(uint32_t*)0x401F8288 = 0x000110F9; -*(uint32_t*)0x401F828C = 0x000110F9; -*(uint32_t*)0x401F8290 = 0x000110F9; -*(uint32_t*)0x401F8294 = 0x000110F9; -*(uint32_t*)0x401F8298 = 0x000110F9; -*(uint32_t*)0x401F829C = 0x000110F9; -*(uint32_t*)0x401F82A0 = 0x000110F9; -*(uint32_t*)0x401F82A4 = 0x000110F9; -*(uint32_t*)0x401F82A8 = 0x000110F9; - -// ============================================================================= -// SEMC Controller — конфигурация для MT48LC16M16A2 -// Базовый адрес SDRAM: 0x80000000 -// Размер: 32 MB (MT48LC16M16A2: 16M × 16bit = 32 MB) -// ============================================================================= - -// SEMC_MCR: MDIS=0, BTO=0x1F (timeout), DQSMD=1 (DQS internal loop) -*(uint32_t*)0x402F0000 = 0x10000004; - -// SEMC_BMCR0 & BMCR1: burst весовые коэффициенты -// 0x00000081: WQOS=1, RQOS=0, AGE=0, BSTLEN=0x10 (16 burst) -*(uint32_t*)0x402F0008 = 0x00000081; // SEMC_BMCR0 -*(uint32_t*)0x402F000C = 0x00000081; // SEMC_BMCR1 - -// SEMC_BR0..BR7 — Base Register для каждого region -// BR0: SDRAM @ 0x80000000, размер 32MB (MR=0x1B → 32MB), VLD=1 -*(uint32_t*)0x402F0010 = 0x8000001B; // BR0: SDRAM CS0, 0x80000000, 32MB -*(uint32_t*)0x402F0014 = 0x82000000; // BR1: SDRAM CS1 (если есть) -*(uint32_t*)0x402F0018 = 0x84000000; // BR2 -*(uint32_t*)0x402F001C = 0x86000000; // BR3 -*(uint32_t*)0x402F0020 = 0x90000021; // BR4: NAND -*(uint32_t*)0x402F0024 = 0xA0000019; // BR5: NOR/SRAM -*(uint32_t*)0x402F0028 = 0xA8000017; // BR6 -*(uint32_t*)0x402F002C = 0xA900001B; // BR7 -*(uint32_t*)0x402F0030 = 0x00000021; // BR8 - -// SEMC_INTEN: прерывания отключены -*(uint32_t*)0x402F0004 = 0x000079A8; - -// SEMC_SDRAMCR0: тайминги MT48LC16M16A2 @ 133MHz -// PS=1 (16-bit data bus), BL=3 (Burst Length 8), COL=2 (9-bit col addr), -// CL=3 (CAS Latency 3) -*(uint32_t*)0x402F0040 = 0x00000F31; - -// SEMC_SDRAMCR1 -// PRE2ACT=2, ACT2RW=2, RFRC=9 (tRFC), WRC=2, CKEOFF=2, ACT2PRE=6 -*(uint32_t*)0x402F0044 = 0x00652922; - -// SEMC_SDRAMCR2: Refresh rate -// MT48LC16M16A2: 4096 refresh cycles / 64ms → ~15.6 мкс @ 133MHz -// SRRC=0x02 (самообновление), REF2REF=0x02, ACT2ACT=0x01 -*(uint32_t*)0x402F0048 = 0x00020201; - -// SEMC_SDRAMCR3 -// REBL=1, PRESCALE=0x21, RT=0x3D, UT=0x0F -*(uint32_t*)0x402F004C = 0x08193D0F; - -// SEMC_IOCR -*(uint32_t*)0x402F0080 = 0x00000021; -*(uint32_t*)0x402F0084 = 0x00888888; - -// SEMC_IPTXDAT / IPRXDAT placeholder -*(uint32_t*)0x402F0094 = 0x00000002; -*(uint32_t*)0x402F0098 = 0x00000000; - -// ============================================================================= -// SDRAM Init Sequence (JEDEC: Precharge All → Auto-Refresh × 2 → Mode Register Set) -// ============================================================================= - -// SEMC_IPCR0: IP command target адрес = начало SDRAM -*(uint32_t*)0x402F0090 = 0x80000000; - -// IPCMD: Precharge All (команда 0xF) -*(uint32_t*)0x402F009C = 0xA55A000F; -// Ждём завершения: SEMC_INTR[IPCMDDONE] (bit 0) -(*(uint32_t*)0x402F003C & 0x01) != 0; - -// IPCMD: Auto-Refresh #1 (команда 0xC) -*(uint32_t*)0x402F0090 = 0x80000000; -*(uint32_t*)0x402F009C = 0xA55A000C; -(*(uint32_t*)0x402F003C & 0x01) != 0; - -// IPCMD: Auto-Refresh #2 -*(uint32_t*)0x402F0090 = 0x80000000; -*(uint32_t*)0x402F009C = 0xA55A000C; -(*(uint32_t*)0x402F003C & 0x01) != 0; - -// Mode Register Set: -// MRS = 0x33: Burst Length=8 (BL=3), Burst Type=Sequential, CAS Latency=3 -*(uint32_t*)0x402F00A0 = 0x00000033; -*(uint32_t*)0x402F0090 = 0x80000000; -// IPCMD: Mode Register Set (команда 0xA) -*(uint32_t*)0x402F009C = 0xA55A000A; -(*(uint32_t*)0x402F003C & 0x01) != 0; - -// SEMC_SDRAMCR3: финальное значение Refresh Rate после инит-последовательности -// Переключаемся с медленного (init) refresh на рабочий -*(uint32_t*)0x402F004C = 0x50210A09; \ No newline at end of file diff --git a/tools/host/dcd/ivt_flashloader.bin b/tools/host/dcd/ivt_flashloader.bin new file mode 100644 index 0000000..cab0330 Binary files /dev/null and b/tools/host/dcd/ivt_flashloader.bin differ diff --git a/tools/host/fdcb/fcb.bin b/tools/host/fdcb/fcb.bin deleted file mode 100644 index e7c87b6..0000000 Binary files a/tools/host/fdcb/fcb.bin and /dev/null differ diff --git a/tools/host/fdcb/fcb_w25q128_quad.yaml b/tools/host/fdcb/fcb_w25q128_quad.yaml deleted file mode 100644 index 53ac54f..0000000 --- a/tools/host/fdcb/fcb_w25q128_quad.yaml +++ /dev/null @@ -1,152 +0,0 @@ -# ============================================================================= -# FCB — Flash Configuration Block -# Чип: Winbond W25Q128FVSSIG (64 Mbit = 8 MB), Quad SPI -# Режим: Fast Read Quad I/O (0xEB), 133 MHz, 4-line -# Цель: MIMXRT1052CVJ5B (family: mimxrt1050 в SPSDK 3.7) -# -# LUT-последовательности: -# Seq 0: Fast Read Quad I/O (0xEB) — основное XIP-чтение -# Seq 1: Read Status Reg 1 (0x05) — опрос WIP бита -# Seq 2: Write Enable (0x06) — перед любой записью/стиранием -# Seq 3: Erase Sector 4KB (0x20) — стирание сектора -# Seq 4: Write SR2 (0x31) — установка QE бита (вызов при старте) -# Seq 5: Page Program Quad (0x32) — запись страницы в Quad режиме -# Seq 11: Chip Erase (0x60) — полное стирание чипа -# Seq 12: Read Status Reg 1 (0x05) — дублирует seq1, для blhost -# ============================================================================= - -family: mimxrt1050 -revision: latest -type: flexspi_nor - -fcb_settings: - tag: '0x42464346' # 'FCFB' — magic, фиксировано - version: '0x56010400' # Version 1.4 (актуально для SPSDK 3.7) - - readSampleClkSrc: '0x01' # loopback from DQS pad - csHoldTime: '0x03' - csSetupTime: '0x03' - columnAddressWidth: '0x03' - - # --------------------------------------------------------------------------- - # QE bit enable — W25Q128 Status Register 2, bit 1 - # BootROM выполнит Write Enable (seq 2) + Write SR2 (seq 4) при старте. - # deviceModeArg = 0x02 → SR2 = 0b00000010 (QE=1) - # waitTimeCfgCommands = 30 × 100us = 3ms (достаточно для записи SR) - # --------------------------------------------------------------------------- - deviceModeCfgEnable: '0x01' - deviceModeType: '0x01' - waitTimeCfgCommands: '0x001E' - deviceModeSeq: - seqNum: 1 - seqId: 4 # → Seq 4: Write SR2 (0x31) - deviceModeArg: '0x00000002' # SR2 = 0x02 → QE=1 - - deviceType: '0x01' # Serial NOR - sflashPadType: '0x04' # Quad — 4 линии данных (IO0..IO3) - serialClkFreq: '0x07' # 133 MHz - sflashA1Size: '0x01000000' # 16 MB — W25Q128FVSSIG (128 Mbit / 8) - - pageSize: '0x00000100' # 256 байт — стандарт для W25Q128 - sectorSize: '0x00001000' # 4 KB — минимальная единица стирания - - # --------------------------------------------------------------------------- - # LUT — Look-Up Table - # Каждая последовательность: 8 инструкций (instr0..instr7) - # Неиспользуемые инструкции = STOP (значение по умолчанию, можно не писать) - # --------------------------------------------------------------------------- - - # ── Seq 0: Fast Read Quad I/O (0xEB) ─────────────────────────────────────── - # CMD(×1) 0xEB → RADDR(×4) 24bit → DUMMY(×4) 6cycles → READ(×4) - lookupTable_seq0_instr0: - OPERAND: 0xEB - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq0_instr1: - OPERAND: 0x18 # 24-bit address - NUM_PADS: 4PAD - OPERATION_CODE: RADDR_SDR - lookupTable_seq0_instr2: - OPERAND: 0x06 # 6 dummy cycles @ 133MHz (4 mode + 2 dummy) - NUM_PADS: 4PAD - OPERATION_CODE: DUMMY_SDR - lookupTable_seq0_instr3: - OPERAND: 0x04 - NUM_PADS: 4PAD - OPERATION_CODE: READ_SDR - - # ── Seq 1: Read Status Register 1 (0x05) ─────────────────────────────────── - # CMD(×1) 0x05 → READ(×1) 1byte - lookupTable_seq1_instr0: - OPERAND: 0x05 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq1_instr1: - OPERAND: 0x04 - NUM_PADS: 1PAD - OPERATION_CODE: READ_SDR - - # ── Seq 2: Write Enable (0x06) ────────────────────────────────────────────── - # CMD(×1) 0x06 - lookupTable_seq2_instr0: - OPERAND: 0x06 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - - # ── Seq 3: Erase Sector 4KB (0x20) ───────────────────────────────────────── - # CMD(×1) 0x20 → RADDR(×4) 24bit - lookupTable_seq3_instr0: - OPERAND: 0x20 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq3_instr1: - OPERAND: 0x18 - NUM_PADS: 4PAD - OPERATION_CODE: RADDR_SDR - - # ── Seq 4: Write Status Register 2 (0x31) — установка QE бита ────────────── - # CMD(×1) 0x31 → WRITE(×1) 1byte - # Вызывается через deviceModeSeq при инициализации BootROM. - # deviceModeArg (0x02) записывается как аргумент. - lookupTable_seq4_instr0: - OPERAND: 0x31 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq4_instr1: - OPERAND: 0x01 # записать 1 байт - NUM_PADS: 1PAD - OPERATION_CODE: WRITE_SDR - - # ── Seq 5: Page Program Quad Input (0x32) ────────────────────────────────── - # CMD(×1) 0x32 → RADDR(×1) 24bit → WRITE(×4) - lookupTable_seq5_instr0: - OPERAND: 0x32 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq5_instr1: - OPERAND: 0x18 - NUM_PADS: 1PAD - OPERATION_CODE: RADDR_SDR - lookupTable_seq5_instr2: - OPERAND: 0x04 - NUM_PADS: 4PAD - OPERATION_CODE: WRITE_SDR - - # Seq 6..10: не используются (STOP по умолчанию) - - # ── Seq 11: Chip Erase (0x60) ─────────────────────────────────────────────── - # CMD(×1) 0x60 - lookupTable_seq11_instr0: - OPERAND: 0x60 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - - # ── Seq 12: Read Status Register 1 (дубль для blhost) ────────────────────── - lookupTable_seq12_instr0: - OPERAND: 0x05 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq12_instr1: - OPERAND: 0x04 - NUM_PADS: 1PAD - OPERATION_CODE: READ_SDR \ No newline at end of file diff --git a/tools/host/fdcb/fcb_w25q64_quad.yaml b/tools/host/fdcb/fcb_w25q64_quad.yaml deleted file mode 100644 index f34731e..0000000 --- a/tools/host/fdcb/fcb_w25q64_quad.yaml +++ /dev/null @@ -1,152 +0,0 @@ -# ============================================================================= -# FCB — Flash Configuration Block -# Чип: Winbond W25Q64FVSSIG (64 Mbit = 8 MB), Quad SPI -# Режим: Fast Read Quad I/O (0xEB), 133 MHz, 4-line -# Цель: MIMXRT1052CVJ5B (family: mimxrt1050 в SPSDK 3.7) -# -# LUT-последовательности: -# Seq 0: Fast Read Quad I/O (0xEB) — основное XIP-чтение -# Seq 1: Read Status Reg 1 (0x05) — опрос WIP бита -# Seq 2: Write Enable (0x06) — перед любой записью/стиранием -# Seq 3: Erase Sector 4KB (0x20) — стирание сектора -# Seq 4: Write SR2 (0x31) — установка QE бита (вызов при старте) -# Seq 5: Page Program Quad (0x32) — запись страницы в Quad режиме -# Seq 11: Chip Erase (0x60) — полное стирание чипа -# Seq 12: Read Status Reg 1 (0x05) — дублирует seq1, для blhost -# ============================================================================= - -family: mimxrt1050 -revision: latest -type: flexspi_nor - -fcb_settings: - tag: '0x42464346' # 'FCFB' — magic, фиксировано - version: '0x56010400' # Version 1.4 (актуально для SPSDK 3.7) - - readSampleClkSrc: '0x01' # loopback from DQS pad - csHoldTime: '0x03' - csSetupTime: '0x03' - columnAddressWidth: '0x03' - - # --------------------------------------------------------------------------- - # QE bit enable — W25Q64 Status Register 2, bit 1 - # BootROM выполнит Write Enable (seq 2) + Write SR2 (seq 4) при старте. - # deviceModeArg = 0x02 → SR2 = 0b00000010 (QE=1) - # waitTimeCfgCommands = 30 × 100us = 3ms (достаточно для записи SR) - # --------------------------------------------------------------------------- - deviceModeCfgEnable: '0x01' - deviceModeType: '0x01' - waitTimeCfgCommands: '0x001E' - deviceModeSeq: - seqNum: 1 - seqId: 4 # → Seq 4: Write SR2 (0x31) - deviceModeArg: '0x00000002' # SR2 = 0x02 → QE=1 - - deviceType: '0x01' # Serial NOR - sflashPadType: '0x04' # Quad — 4 линии данных (IO0..IO3) - serialClkFreq: '0x07' # 133 MHz - sflashA1Size: '0x00800000' # 8 MB — W25Q64FVSSIG (64 Mbit / 8) - - pageSize: '0x00000100' # 256 байт — стандарт для W25Q64 - sectorSize: '0x00001000' # 4 KB — минимальная единица стирания - - # --------------------------------------------------------------------------- - # LUT — Look-Up Table - # Каждая последовательность: 8 инструкций (instr0..instr7) - # Неиспользуемые инструкции = STOP (значение по умолчанию, можно не писать) - # --------------------------------------------------------------------------- - - # ── Seq 0: Fast Read Quad I/O (0xEB) ─────────────────────────────────────── - # CMD(×1) 0xEB → RADDR(×4) 24bit → DUMMY(×4) 6cycles → READ(×4) - lookupTable_seq0_instr0: - OPERAND: 0xEB - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq0_instr1: - OPERAND: 0x18 # 24-bit address - NUM_PADS: 4PAD - OPERATION_CODE: RADDR_SDR - lookupTable_seq0_instr2: - OPERAND: 0x06 # 6 dummy cycles @ 133MHz (4 mode + 2 dummy) - NUM_PADS: 4PAD - OPERATION_CODE: DUMMY_SDR - lookupTable_seq0_instr3: - OPERAND: 0x04 - NUM_PADS: 4PAD - OPERATION_CODE: READ_SDR - - # ── Seq 1: Read Status Register 1 (0x05) ─────────────────────────────────── - # CMD(×1) 0x05 → READ(×1) 1byte - lookupTable_seq1_instr0: - OPERAND: 0x05 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq1_instr1: - OPERAND: 0x04 - NUM_PADS: 1PAD - OPERATION_CODE: READ_SDR - - # ── Seq 2: Write Enable (0x06) ────────────────────────────────────────────── - # CMD(×1) 0x06 - lookupTable_seq2_instr0: - OPERAND: 0x06 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - - # ── Seq 3: Erase Sector 4KB (0x20) ───────────────────────────────────────── - # CMD(×1) 0x20 → RADDR(×4) 24bit - lookupTable_seq3_instr0: - OPERAND: 0x20 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq3_instr1: - OPERAND: 0x18 - NUM_PADS: 4PAD - OPERATION_CODE: RADDR_SDR - - # ── Seq 4: Write Status Register 2 (0x31) — установка QE бита ────────────── - # CMD(×1) 0x31 → WRITE(×1) 1byte - # Вызывается через deviceModeSeq при инициализации BootROM. - # deviceModeArg (0x02) записывается как аргумент. - lookupTable_seq4_instr0: - OPERAND: 0x31 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq4_instr1: - OPERAND: 0x01 # записать 1 байт - NUM_PADS: 1PAD - OPERATION_CODE: WRITE_SDR - - # ── Seq 5: Page Program Quad Input (0x32) ────────────────────────────────── - # CMD(×1) 0x32 → RADDR(×1) 24bit → WRITE(×4) - lookupTable_seq5_instr0: - OPERAND: 0x32 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq5_instr1: - OPERAND: 0x18 - NUM_PADS: 1PAD - OPERATION_CODE: RADDR_SDR - lookupTable_seq5_instr2: - OPERAND: 0x04 - NUM_PADS: 4PAD - OPERATION_CODE: WRITE_SDR - - # Seq 6..10: не используются (STOP по умолчанию) - - # ── Seq 11: Chip Erase (0x60) ─────────────────────────────────────────────── - # CMD(×1) 0x60 - lookupTable_seq11_instr0: - OPERAND: 0x60 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - - # ── Seq 12: Read Status Register 1 (дубль для blhost) ────────────────────── - lookupTable_seq12_instr0: - OPERAND: 0x05 - NUM_PADS: 1PAD - OPERATION_CODE: CMD_SDR - lookupTable_seq12_instr1: - OPERAND: 0x04 - NUM_PADS: 1PAD - OPERATION_CODE: READ_SDR \ No newline at end of file diff --git a/tools/host/flash_usb.py b/tools/host/flash_usb.py new file mode 100644 index 0000000..8564e95 --- /dev/null +++ b/tools/host/flash_usb.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +""" +flash_usb.py — прошивка MIMXRT1052 через USB (BootROM SDP → Flashloader → blhost) + +Использование: + python3 flash_usb.py --firmware firmware_test --build-type Debug + python3 flash_usb.py --firmware app --build-type Release + python3 flash_usb.py --firmware bootloader --build-type Release + python3 flash_usb.py --firmware firmware_test --build-type Debug --ram-only + +Шаги: + 1. Устройство в SDP режиме (VID:PID 1FC9:0130) + → sdphost загружает ivt_flashloader.bin в RAM + → sdphost прыгает на flashloader + 2. Flashloader запущен (VID:PID 15A2:0073) + → blhost конфигурирует FlexSPI NOR (пишет FCB) + → blhost стирает нужный регион Flash + → blhost пишет HAB образ начиная с 0x60002000 + → blhost reset +""" + +import argparse +import subprocess +import sys +import time +from pathlib import Path + +# ─── Константы ──────────────────────────────────────────────────────────────── +SCRIPT_DIR = Path(__file__).parent.resolve() +REPO_ROOT = SCRIPT_DIR.parent.parent +BUILD_DIR = REPO_ROOT / "build" +FLASHLOADER = SCRIPT_DIR / "dcd" / "ivt_flashloader.bin" + +# USB VID:PID +SDP_USB = "0x1FC9,0x0130" # BootROM Serial Download Protocol +BLHOST_USB = "0x15A2,0x0073" # Flashloader запущен + +# FlexSPI NOR config option word: 0xC0000007 +# bits[31:28]=0xC — tag (QuadSPI NOR) +# bits[3:0]=0x7 — option size +FLEXSPI_OPTION_ADDR = "0x2000" +FLEXSPI_OPTION_VALUE = "0xC0000007" +FLEXSPI_MEMORY_ID = "9" # FlexSPI NOR memory interface ID + +# Flash layout +FLASH_BASE = 0x60000000 +HAB_OFFSET = 0x1000 # IVT offset: HAB binary starts with IVT at byte 0 + # write address = FLASH_BASE + ivtOffset = 0x60001000 + + +def run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess: + print(f" $ {' '.join(cmd)}") + result = subprocess.run(cmd, capture_output=False) + if check and result.returncode != 0: + print(f"\n[ERROR] Команда завершилась с кодом {result.returncode}") + sys.exit(1) + return result + + +def step(msg: str) -> None: + print(f"\n{'─'*60}") + print(f" {msg}") + print(f"{'─'*60}") + + +def wait_for_flashloader(timeout: int = 10) -> bool: + """Ждём пока Flashloader поднимется (VID:PID 15A2:0073)""" + print(f"\n Ожидание Flashloader (до {timeout}с)...", end="", flush=True) + for i in range(timeout): + time.sleep(1) + result = subprocess.run( + ["blhost", "-u", BLHOST_USB, "-j", "--", "get-property", "1", "0"], + capture_output=True + ) + if result.returncode == 0: + print(f" OK ({i+1}с)") + return True + print(".", end="", flush=True) + print(" TIMEOUT") + return False + + +def load_flashloader() -> None: + """Загружает Flashloader через SDP если ещё не запущен""" + # Проверяем — вдруг уже запущен + result = subprocess.run( + ["blhost", "-u", BLHOST_USB, "-j", "--", "get-property", "1", "0"], + capture_output=True + ) + if result.returncode == 0: + print(" Flashloader уже запущен — пропускаем загрузку") + return + + if not FLASHLOADER.exists(): + print(f"[ERROR] Не найден: {FLASHLOADER}") + print(" Скачай ivt_flashloader.bin из MCUXpresso Secure Provisioning Tool") + print(" и положи в tools/host/dcd/ivt_flashloader.bin") + sys.exit(1) + + step("Загрузка Flashloader через SDP (1FC9:0130)") + run(["sdphost", "-u", SDP_USB, "-j", "--", + "write-file", "0x20001C00", str(FLASHLOADER)]) + run(["sdphost", "-u", SDP_USB, "-j", "--", + "jump-address", "0x20001C00"]) + + if not wait_for_flashloader(): + print("[ERROR] Flashloader не ответил. Проверь BOOT_MOD пины и подключение.") + sys.exit(1) + + +# Option word для записи FCB в Flash[0x60000000] +# 0xF000000F: tag=0xF → Write FCB command (Flashloader пишет готовый FCB в начало Flash) +FLEXSPI_FCB_VALUE = "0xF000000F" + + +def configure_flexspi() -> None: + """Инициализирует FlexSPI NOR контроллер через Flashloader""" + step("Конфигурация FlexSPI NOR (инициализация контроллера)") + run(["blhost", "-u", BLHOST_USB, "--", + "fill-memory", FLEXSPI_OPTION_ADDR, "4", FLEXSPI_OPTION_VALUE, "word"]) + run(["blhost", "-u", BLHOST_USB, "--", + "configure-memory", FLEXSPI_MEMORY_ID, FLEXSPI_OPTION_ADDR]) + + +def write_fcb() -> None: + """Записывает Flash Configuration Block в 0x60000000 + + Отдельный шаг после erase! Flashloader генерирует FCB из параметров FlexSPI + и пишет его по адресу 0x60000000. Без FCB BootROM не знает как читать Flash. + Option word 0xF000000F: tag=0xF → Write FCB command. + """ + step("Запись FCB в Flash[0x60000000]") + run(["blhost", "-u", BLHOST_USB, "--", + "fill-memory", FLEXSPI_OPTION_ADDR, "4", FLEXSPI_FCB_VALUE, "word"]) + run(["blhost", "-u", BLHOST_USB, "--", + "configure-memory", FLEXSPI_MEMORY_ID, FLEXSPI_OPTION_ADDR]) + + +def flash(hab_bin: Path, ram_only: bool = False) -> None: + if not hab_bin.exists(): + print(f"[ERROR] Файл не найден: {hab_bin}") + print(" Сначала собери образ: uv run nxpimage hab export -c ...") + sys.exit(1) + + if ram_only: + step(f"Загрузка в RAM (без записи во Flash): {hab_bin.name}") + # RAM-only: грузим в RAM прямо через SDP без flashloader + run(["sdphost", "-u", SDP_USB, "-j", "--", + "write-file", f"0x{FLASH_BASE + HAB_OFFSET:08X}", str(hab_bin)]) + run(["sdphost", "-u", SDP_USB, "-j", "--", + "jump-address", f"0x{FLASH_BASE + HAB_OFFSET:08X}"]) + return + + load_flashloader() + configure_flexspi() # 0xC0000007 — инициализация FlexSPI контроллера + + write_addr = f"0x{FLASH_BASE + HAB_OFFSET:08X}" + # Размер стирания: HAB_OFFSET (0x1000) + размер образа, выровнено вверх до 4KB + erase_size = ((HAB_OFFSET + hab_bin.stat().st_size + 0xFFF) // 0x1000) * 0x1000 + + step(f"Прошивка Flash: {hab_bin.name}") + print(f" Образ: {hab_bin}") + print(f" Размер: {hab_bin.stat().st_size} байт") + print(f" Адрес: {write_addr}") + print(f" Стирание: 0x{FLASH_BASE:08X} .. +{erase_size} байт") + + # memoryId=0 — mapped (XIP) адресное пространство + run(["blhost", "-u", BLHOST_USB, "--", + "flash-erase-region", f"0x{FLASH_BASE:08X}", + str(erase_size), "0"]) + + write_fcb() # 0xF000000F — запись FCB в 0x60000000 (после erase!) + + # memoryId=0 — mapped (XIP) адресное пространство + run(["blhost", "-u", BLHOST_USB, "--", + "write-memory", write_addr, str(hab_bin), "0"]) + + step("Reset") + run(["blhost", "-u", BLHOST_USB, "--", "reset"]) + print("\n ✓ Прошивка завершена успешно") + + +def main() -> None: + parser = argparse.ArgumentParser(description="Прошивка MIMXRT1052 через USB") + parser.add_argument("--firmware", required=True, + choices=["firmware_test", "bootloader", "app"], + help="Имя прошивки") + parser.add_argument("--build-type", required=True, + choices=["Debug", "Release"], + help="Тип сборки") + parser.add_argument("--ram-only", action="store_true", + help="Загрузить в RAM без записи во Flash") + args = parser.parse_args() + + # HAB образ собирается командой: nxpimage hab export -c hab_.yaml + # Выходной файл: build//_hab.bin + hab_bin = BUILD_DIR / args.build_type / f"{args.firmware}_hab.bin" + + print(f"\n{'═'*60}") + print(f" MIMXRT1052 Flash Tool") + print(f" Прошивка: {args.firmware} [{args.build_type}]") + print(f" Образ: {hab_bin}") + print(f"{'═'*60}") + + flash(hab_bin, ram_only=args.ram_only) + + +if __name__ == "__main__": + main() diff --git a/tools/host/hab/hab_app.yaml b/tools/host/hab/hab_app.yaml index 438fccf..a07f7d6 100644 --- a/tools/host/hab/hab_app.yaml +++ b/tools/host/hab/hab_app.yaml @@ -1,18 +1,20 @@ # ============================================================================= # HAB Container — firmware/app (боевая прошивка) +# Расположение: tools/host/hab/hab_app.yaml # -# flags: 0x0 — образ НЕ подписан -# DCD: обязателен — линкер размещает FreeRTOS heap и буферы LCDIF -# в SDRAM (0x80000000), которая должна быть инициализирована -# до первой инструкции прошивки. +# Сборка: +# cd tools/host/hab +# uv run nxpimage hab export --force -c hab_app.yaml \ +# -o ../../../build/Release/app_hab.bin # ============================================================================= options: - flags: 0x0 + flags: 0x00 + startAddress: 0x60000000 + ivtOffset: 0x1000 + initialLoadSize: 0x2000 family: mimxrt1050 - bootDevice: flexspi_nor - startAddress: 0x60000000 # FlexSPI NOR base address (XIP) - DCDFilePath: ../dcd/dcd.bin + DCDFilePath: ../dcd/dcd.bin # обязателен — heap FreeRTOS и LCDIF в SDRAM inputImageFile: "../../../build/Release/app.bin" diff --git a/tools/host/hab/hab_bootloader.yaml b/tools/host/hab/hab_bootloader.yaml index 971576a..f5e0786 100644 --- a/tools/host/hab/hab_bootloader.yaml +++ b/tools/host/hab/hab_bootloader.yaml @@ -1,18 +1,21 @@ # ============================================================================= # HAB Container — firmware/bootloader +# Расположение: tools/host/hab/hab_bootloader.yaml # -# flags: 0x0 — образ НЕ подписан -# DCD: отсутствует намеренно — загрузчик не использует SDRAM, -# минимальная зависимость от железа = максимальная надёжность. -# SDRAM инициализируется позже, уже внутри app через её DCD. +# Сборка: +# cd tools/host/hab +# uv run nxpimage hab export --force -c hab_bootloader.yaml \ +# -o ../../../build/Release/bootloader_hab.bin # ============================================================================= options: - flags: 0x0 + flags: 0x00 + startAddress: 0x60000000 + ivtOffset: 0x1000 + initialLoadSize: 0x2000 family: mimxrt1050 - bootDevice: flexspi_nor - startAddress: 0x60000000 # FlexSPI NOR base address (XIP) - + # DCD намеренно отсутствует — загрузчик не использует SDRAM + inputImageFile: "../../../build/Release/bootloader.bin" sections: [] \ No newline at end of file diff --git a/tools/host/hab/hab_firmware_test.yaml b/tools/host/hab/hab_firmware_test.yaml index 3ca10ec..e367f36 100644 --- a/tools/host/hab/hab_firmware_test.yaml +++ b/tools/host/hab/hab_firmware_test.yaml @@ -1,23 +1,22 @@ # ============================================================================= # HAB Container — firmware/test (входной контроль производства) +# Расположение: tools/host/hab/hab_firmware_test.yaml # -# flags: 0x0 — образ НЕ подписан (HAB в open/unsigned режиме) -# DCD: присутствует — инициализация SDRAM обязательна для тестов -# -# Важно: sections пустой — для unsigned образа CSF не нужен. -# BootROM примет образ без проверки подписи пока HAB не залочен (fuses). +# Сборка: +# cd tools/host/hab +# uv run nxpimage hab export --force -c hab_firmware_test.yaml \ +# -o ../../../build/Debug/firmware_test.bin # ============================================================================= options: - flags: 0x0 # unsigned — без подписи + flags: 0x00 # unsigned — без подписи + startAddress: 0x60000000 # FlexSPI NOR base (XIP) + ivtOffset: 0x1000 # IVT offset for FlexSPI NOR boot + initialLoadSize: 0x2000 # размер области IVT+BDT+DCD до кода family: mimxrt1050 - bootDevice: flexspi_nor # ivtOffset=0x1000, initialLoadSize=0x2000 — автоматически - startAddress: 0x60000000 # FlexSPI NOR base address (XIP) - - # DCD — инициализация SDRAM до передачи управления прошивке. - # Сгенерирован из dcd.cfg скриптом tools/dcd_cfg_to_bin.py - DCDFilePath: ../dcd/dcd.bin + DCDFilePath: ../dcd/dcd.bin # инициализация SDRAM +# .bin или .srec — оба принимаются inputImageFile: "../../../build/Debug/firmware_test.bin" sections: [] \ No newline at end of file diff --git a/tools/host/image/bootimg_app.yaml b/tools/host/image/bootimg_app.yaml deleted file mode 100644 index 8278d41..0000000 --- a/tools/host/image/bootimg_app.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# ============================================================================= -# Bootable Image — firmware/app (боевая прошивка) -# Расположение: tools/host/image/bootimg_app.yaml -# -# Пайплайн сборки: -# -# 1. FCB (один раз, из tools/host/fdcb/): -# nxpimage bootable-image fcb export -c fcb_w25q64_quad.yaml -o fcb.bin -# -# 2. Образ (из tools/host/image/): -# nxpimage bootable-image export -c bootimg_app.yaml -# -# 3. Проверка: -# nxpimage bootable-image parse -b ../../../../build/Release/app_bootable.bin -f mimxrt1050 -# ============================================================================= - -family: mimxrt1050 -revision: latest -memory_type: flexspi_nor - -output: "../../../build/Release/app_bootable.bin" -output_format: bin - -fcb: ../fdcb/fcb.bin - -hab_container: ../hab/hab_app.yaml \ No newline at end of file diff --git a/tools/host/image/bootimg_bootloader.yaml b/tools/host/image/bootimg_bootloader.yaml deleted file mode 100644 index 8c6d41b..0000000 --- a/tools/host/image/bootimg_bootloader.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# ============================================================================= -# Bootable Image — firmware/bootloader -# Расположение: tools/host/image/bootimg_bootloader.yaml -# -# Пайплайн сборки: -# -# 1. FCB (один раз, из tools/host/fdcb/): -# nxpimage bootable-image fcb export -c fcb_w25q64_quad.yaml -o fcb.bin -# -# 2. Образ (из tools/host/image/): -# nxpimage bootable-image export -c bootimg_bootloader.yaml -# -# 3. Проверка: -# nxpimage bootable-image parse -b ../../../../build/Release/bootloader_bootable.bin -f mimxrt1050 -# ============================================================================= - -family: mimxrt1050 -revision: latest -memory_type: flexspi_nor - -output: "../../../build/Release/bootloader_bootable.bin" -output_format: bin - -fcb: ../fdcb/fcb.bin - -hab_container: ../hab/hab_bootloader.yaml \ No newline at end of file diff --git a/tools/host/image/bootimg_firmware_test.yaml b/tools/host/image/bootimg_firmware_test.yaml deleted file mode 100644 index 4307b27..0000000 --- a/tools/host/image/bootimg_firmware_test.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# ============================================================================= -# Bootable Image — firmware/test (входной контроль производства) -# Расположение: tools/host/image/bootimg_firmware_test.yaml -# -# Пайплайн сборки: -# -# 1. FCB (один раз, из tools/host/fdcb/): -# nxpimage bootable-image fcb export -c fcb_w25q64_quad.yaml -o fcb.bin -# -# 2. Образ (из tools/host/image/): -# nxpimage bootable-image export -c bootimg_firmware_test.yaml -# -# 3. Проверка: -# nxpimage bootable-image parse -b ../../../../build/Debug/firmware_test_bootable.bin -f mimxrt1050 -# -# Структура образа во Flash (0x60000000): -# 0x000 FCB (512 байт) -# 0x400 зарезервировано -# 0x1000 IVT ] -# 0x1020 BDT ] HAB container -# 0x1030 DCD ] -# 0x3000 код ] -# ============================================================================= - -family: mimxrt1050 -revision: latest -memory_type: flexspi_nor - -output: "../../../build/Debug/firmware_test_bootable.bin" -output_format: bin - -# FCB — собран из tools/host/fdcb/fcb_w25q64_quad.yaml -fcb: ../fdcb/fcb.bin - -# HAB container — YAML напрямую, export соберёт его сам -hab_container: ../hab/hab_firmware_test.yaml \ No newline at end of file