Начальный этап по разработке рабочего окружения закончен
- проверена работоспособность окружения (host + в контейнере) на нескольких хостах (Win, Mac) - пока не затронуты моменты с ci, tests
This commit is contained in:
parent
412e8037b2
commit
310a8d6bc9
12 changed files with 302 additions and 76 deletions
29
.env.example
29
.env.example
|
|
@ -0,0 +1,29 @@
|
|||
# =============================================================================
|
||||
# .env — единый источник конфигурации проекта
|
||||
# Читается: just (set dotenv-load) → экспортируется в окружение (set export)
|
||||
# → наследуется uv run python3 автоматически
|
||||
# =============================================================================
|
||||
|
||||
# --- Hardware ---
|
||||
BOARD=MIMXRT1052
|
||||
|
||||
# --- USB VID:PID (NXP) ---
|
||||
# Используются: just host.just (check-deps, udev) + flash_usb.py
|
||||
BOOTROM_VID=1fc9
|
||||
BOOTROM_PID=0130
|
||||
FLASHLOADER_VID=15a2
|
||||
FLASHLOADER_PID=0073
|
||||
|
||||
# --- Paths ---
|
||||
# BUILD_DIR и TOOLS_DIR задаются абсолютно в корневом justfile
|
||||
# через justfile_directory(), здесь можно переопределить если нужно
|
||||
# BUILD_DIR=/custom/path/build
|
||||
|
||||
# --- Build ---
|
||||
CMAKE_GENERATOR=Ninja
|
||||
|
||||
# --- Debug / SWD ---
|
||||
OPENOCD_INTERFACE=cmsis-dap.cfg
|
||||
TARGET_CFG=target/imxrt.cfg
|
||||
GDB_PORT=3333
|
||||
GDB_EXECUTABLE=gdb-multiarch
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,2 +1,4 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
.env text eol=lf
|
||||
.env.example text eol=lf
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -68,5 +68,6 @@ compile_commands.json
|
|||
__pycache__/
|
||||
*.pyc
|
||||
.env
|
||||
|
||||
tools/host/.venv-host/
|
||||
tools/host/.venv-host-win/
|
||||
|
||||
|
|
|
|||
104
HOW_TO_FLASH.md
Normal file
104
HOW_TO_FLASH.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# HOW TO FLASH
|
||||
|
||||
Прошивка выполняется **на хосте** (вне devcontainer) через USB ROM (Serial Download Protocol).
|
||||
|
||||
---
|
||||
|
||||
## 1. Перевод платы в SDP-режим
|
||||
|
||||
```bash
|
||||
1. BOOT_MOD_1 → 3V3
|
||||
2. Reset
|
||||
3. Подключить USB к хосту
|
||||
→ плата определяется как VID:PID 1FC9:0130
|
||||
```
|
||||
|
||||
После прошивки — вернуть в нормальный режим:
|
||||
|
||||
```bash
|
||||
BOOT_MOD_1 → GND → Reset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Подготовить HAB-образ (внутри devcontainer)
|
||||
|
||||
HAB-образ собирается из ELF-файла командой `nxpimage`. Выполнять в терминале VSCode:
|
||||
|
||||
```bash
|
||||
just build::hab-firmware-test-debug # → build/Debug/firmware_test_hab.bin
|
||||
just build::hab-firmware-test-release # → build/Release/firmware_test_hab.bin
|
||||
just build::hab-bootloader-release # → build/Release/bootloader_hab.bin
|
||||
just build::hab-app-release # → build/Release/app_hab.bin
|
||||
just build::hab-all-release # все три Release за один раз
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Прошивка (хостовый терминал)
|
||||
|
||||
### Запись во Flash
|
||||
|
||||
```bash
|
||||
# Основной рецепт: just host::flash <project> <type>
|
||||
just host::flash firmware_test debug # разработка, итерации с отладчиком
|
||||
just host::flash firmware_test release # проверить как будет на сервере
|
||||
just host::flash bootloader release
|
||||
just host::flash app release
|
||||
```
|
||||
|
||||
### Загрузка в RAM (без записи во Flash)
|
||||
|
||||
Быстро, не изнашивает Flash. Плата стартует сразу после загрузки.
|
||||
|
||||
```bash
|
||||
just host::flash-ram firmware_test # default: debug
|
||||
just host::flash-ram firmware_test debug
|
||||
just host::flash-ram firmware_test release
|
||||
```
|
||||
|
||||
### Быстрые алиасы
|
||||
|
||||
```bash
|
||||
just flash # = just host::flash firmware_test debug
|
||||
just host::flash-test-debug # то же
|
||||
just host::flash-test-release
|
||||
just host::flash-production # bootloader release + app release (с подтверждением)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Диагностика
|
||||
|
||||
```bash
|
||||
just host::scan # найти подключённые NXP USB-устройства
|
||||
just host::sdp-status # проверить связь с BootROM (плата в SDP-режиме)
|
||||
just host::flashloader-status # проверить Flashloader (после jump-address)
|
||||
just host::check-deps # проверить версии just / uv / docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Что происходит при прошивке
|
||||
|
||||
```bash
|
||||
Плата в SDP-режиме (1FC9:0130)
|
||||
│
|
||||
├── sdphost: загрузить ivt_flashloader.bin в RAM (0x20001C00)
|
||||
└── sdphost: jump-address → Flashloader поднимается как 15A2:0073
|
||||
│
|
||||
├── configure-memory (0xC0000007) — инициализация FlexSPI NOR
|
||||
├── flash-erase-region 0x60000000
|
||||
├── configure-memory (0xF000000F) — запись FCB в 0x60000000
|
||||
├── write-memory 0x60001000 ← HAB-образ
|
||||
└── reset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Производственный сценарий (сервер)
|
||||
|
||||
```bash
|
||||
just host::incoming # firmware_test release → HIL-тесты периферии
|
||||
just host::production # bootloader release + app release
|
||||
```
|
||||
6
Justfile
6
Justfile
|
|
@ -20,9 +20,9 @@ set dotenv-load
|
|||
|
||||
# === Общие переменные (доступны во всех модулях через export) ===
|
||||
BOARD := env('BOARD', 'MIMXRT1052')
|
||||
BUILD_DIR := env('BUILD_DIR', 'build')
|
||||
TOOLS_DIR := env('TOOLS_DIR', 'tools/host')
|
||||
CACHE_DIR := ".cache"
|
||||
BUILD_DIR := env('BUILD_DIR', justfile_directory() / 'build')
|
||||
TOOLS_DIR := env('TOOLS_DIR', justfile_directory() / 'tools/host')
|
||||
CACHE_DIR := justfile_directory() / '.cache'
|
||||
|
||||
# === Модули ===
|
||||
# Каждый модуль — это namespace с изолированными рецептами
|
||||
|
|
|
|||
23
README.md
23
README.md
|
|
@ -11,6 +11,11 @@
|
|||
```bash
|
||||
/
|
||||
├── .devcontainer/ # VSCode Devcontainer — единое окружение для всех разработчиков
|
||||
│ ├── Dockerfile
|
||||
│ └── devcontainer.json
|
||||
├── .vscode/
|
||||
│ ├── launch.json
|
||||
│ └── tasks.json # UI для just build::* (внутри devcontainer)
|
||||
├── bsp/ # Board Support Package
|
||||
│ └── generated/ # Сгенерировано NXP Config Tools (Pins + Clocks Tool)
|
||||
│ ├── TFT_Board.mex # Источник истины конфигурации пинов и тактирования
|
||||
|
|
@ -40,27 +45,31 @@
|
|||
├── tests/ # Тесты (host + target)
|
||||
│ ├── host/ # Unit/интеграционные тесты, запускаемые на хосте
|
||||
│ ├── target/ # Тесты периферии, запускаемые на таргете
|
||||
│ └── HostTestingGuide.md
|
||||
│ ├── HostTestingGuide.md
|
||||
│ └── README.md
|
||||
├── tools/
|
||||
│ └── host/ # Инструменты для работы с таргетом
|
||||
│ ├── flash_usb.py # Прошивка через USB ROM (nxp-spsdk / blhost)
|
||||
│ ├── hab/ # Утилиты и гайд по HAB (Secure Boot)
|
||||
│ └── dcd/ # Device Configuration Data
|
||||
│ ├── dcd/ # Device Configuration Data
|
||||
│ ├── pyproject.toml
|
||||
│ └── uv.lock
|
||||
├── just/ # Just-модули (автоматизация)
|
||||
│ ├── build.just # Сборка, тесты, HAB-образы (devcontainer)
|
||||
│ ├── host.just # Прошивка, bootstrap, HIL (хост)
|
||||
│ └── ci.just # CI/CD пайплайны
|
||||
├── scripts/
|
||||
│ └── bootstrap.sh # Первичная настройка окружения (уровень 0)
|
||||
├── docs/ # Документация проекта
|
||||
│ ├── DEV_ARCH.md # Архитектура окружения разработки
|
||||
│ ├── CMAKE_HINTS.md # Шпаргалка по CMake в проекте
|
||||
│ ├── schematic.pdf # Схема платы
|
||||
│ ├── mcu_rm.pdf # Reference Manual IMXRT1052
|
||||
│ └── manufacturing_user's_guide.pdf
|
||||
├── .env # Конфигурация проекта (VID:PID, пути, GDB и др.)
|
||||
├── .env.example # Шаблон .env для новых разработчиков
|
||||
├── bootstrap.sh # Первичная настройка окружения (уровень 0)
|
||||
├── CMakeLists.txt # Корневой CMake
|
||||
├── CMakePresets.json # Пресеты сборки (Release/Debug/Host)
|
||||
├── Justfile # Точка входа для команд (модули: build, host, ci)
|
||||
├── justfile # Точка входа для команд (модули: build, host, ci)
|
||||
└── README.md
|
||||
```
|
||||
|
||||
|
|
@ -142,7 +151,7 @@ git clone <repo-url>
|
|||
cd tft_manufacture_test
|
||||
|
||||
# Инициализация хоста (один раз)
|
||||
sudo chmod +x bootstrap.sh
|
||||
# Устанавливает just и uv, затем настраивает окружение
|
||||
./bootstrap.sh
|
||||
|
||||
# Открыть в VSCode → Reopen in Container
|
||||
|
|
@ -158,3 +167,5 @@ just flash # прошивка через USB ROM
|
|||
|
||||
> Подробнее о прошивке — [HOW_TO_FLASH.md](HOW_TO_FLASH.md)
|
||||
> Подробнее об окружении разработки — [docs/DEV_ARCH.md](docs/DEV_ARCH.md)
|
||||
>
|
||||
>
|
||||
|
|
@ -34,7 +34,8 @@ CI использует те же команды что и локальная р
|
|||
│ ├── docker ← управление devcontainer
|
||||
│ ├── git ← работа с репозиторием
|
||||
│ ├── uv + spsdk ← прошивка платы (flash_usb.py, sdphost, blhost)
|
||||
│ │ venv: tools/host/.venv-host
|
||||
│ │ venv: tools/host/.venv-host (Linux/macOS)
|
||||
│ │ tools/host/.venv-host-win (Windows)
|
||||
│ ├── JLinkGDBServer / probe-rs ← сервер отладки (USB → TCP :2331)
|
||||
│ └── VSCode ← IDE (Dev Containers extension)
|
||||
│
|
||||
|
|
@ -48,7 +49,7 @@ CI использует те же команды что и локальная р
|
|||
│ ├── cmake-format ← форматирование CMakeLists
|
||||
│ ├── just ← запуск задач внутри контейнера (just build::*)
|
||||
│ ├── uv + spsdk ← сборка HAB-образов (только nxpimage)
|
||||
│ │ venv: tools/host/.venv-container
|
||||
│ │ venv: tools/host/.venv
|
||||
│ └── Unity + fff ← фреймворки host-тестов
|
||||
│
|
||||
└── Плата TFT (IMXRT1052) — на столе у разработчика
|
||||
|
|
@ -83,7 +84,45 @@ CI использует те же команды что и локальная р
|
|||
Версия `spsdk` зафиксирована в `tools/host/uv.lock` — все три места
|
||||
используют одну и ту же версию.
|
||||
|
||||
---
|
||||
|
||||
## 3.1 Конфигурация проекта — `.env`
|
||||
|
||||
`.env` в корне репозитория — единый источник конфигурации для всего стека.
|
||||
|
||||
```ini
|
||||
# USB VID:PID (NXP)
|
||||
BOOTROM_VID=1fc9 # используется: host.just (udev-правила) + flash_usb.py
|
||||
BOOTROM_PID=0130
|
||||
FLASHLOADER_VID=15a2
|
||||
FLASHLOADER_PID=0073
|
||||
|
||||
# GDB / отладка
|
||||
GDB_PORT=3333
|
||||
GDB_EXECUTABLE=gdb-multiarch
|
||||
OPENOCD_INTERFACE=cmsis-dap.cfg
|
||||
TARGET_CFG=target/imxrt.cfg
|
||||
```
|
||||
|
||||
**Как значения попадают в инструменты:**
|
||||
|
||||
```bash
|
||||
.env
|
||||
│
|
||||
├─▶ just (set dotenv-load + set export)
|
||||
│ └─▶ just-рецепты видят переменные напрямую: {{BOOTROM_VID}}
|
||||
│ └─▶ uv run flash_usb.py ← наследует окружение автоматически
|
||||
│ └─▶ os.environ.get("BOOTROM_VID") ← без python-dotenv
|
||||
│
|
||||
└─▶ .vscode/launch.json ← через ${env:GDB_PORT} если нужно
|
||||
```
|
||||
|
||||
Аппаратные константы (`FLASH_BASE`, `HAB_OFFSET`, `FLEXSPI_OPTION_VALUE` и т.д.)
|
||||
намеренно оставлены в коде `flash_usb.py` — это не конфигурация, а часть
|
||||
протокола прошивки IMXRT1052, менять их незачем.
|
||||
|
||||
`.env.example` — шаблон без значений, коммитится в репозиторий.
|
||||
`.env` — реальные значения, в `.gitignore` (если содержит секреты), иначе тоже коммитится.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -91,16 +130,19 @@ CI использует те же команды что и локальная р
|
|||
|
||||
```bash
|
||||
/
|
||||
├── Justfile ← корневой оркестратор; модули: build, host, ci
|
||||
├── justfile ← корневой оркестратор; модули: build, host, ci
|
||||
├── bootstrap.sh ← уровень 0: устанавливает just+uv → just host::bootstrap
|
||||
├── .env ← конфигурация проекта (VID:PID, пути, GDB)
|
||||
├── .env.example ← шаблон для новых разработчиков
|
||||
├── just/
|
||||
│ ├── build.just ← devcontainer: сборка, тесты, HAB
|
||||
│ ├── host.just ← хост: прошивка, bootstrap, HIL
|
||||
│ └── ci.just ← CI/CD пайплайны
|
||||
├── scripts/
|
||||
│ └── bootstrap.sh ← уровень 0: just → just host::bootstrap
|
||||
├── .devcontainer/
|
||||
│ ├── Dockerfile
|
||||
│ └── devcontainer.json
|
||||
├── .vscode/
|
||||
│ └── tasks.json ← UI для just build::* (внутри devcontainer)
|
||||
├── tools/
|
||||
│ └── host/
|
||||
│ ├── hab/
|
||||
|
|
@ -113,11 +155,9 @@ CI использует те же команды что и локальная р
|
|||
│ ├── dcd/
|
||||
│ │ ├── dcd.bin
|
||||
│ │ └── ivt_flashloader.bin
|
||||
│ ├── flash_usb.py
|
||||
│ ├── flash_usb.py ← читает конфиг из env (VID:PID, BUILD_DIR)
|
||||
│ ├── pyproject.toml
|
||||
│ └── uv.lock
|
||||
├── .vscode/
|
||||
│ └── tasks.json ← UI для just build::* (внутри devcontainer)
|
||||
├── CMakePresets.json
|
||||
├── cmake/
|
||||
├── sdk/
|
||||
|
|
@ -157,12 +197,19 @@ bootstrap.sh (уровень 0)
|
|||
├── определить платформу (Linux / macOS / Windows Git Bash)
|
||||
│ uname: MINGW64_NT-... → windows, Linux → linux, Darwin → macos
|
||||
│
|
||||
├── проверить just (semver без sort -V — работает в Git Bash)
|
||||
├── проверить/установить just (semver без sort -V — работает в Git Bash)
|
||||
│ < 1.36.0 или отсутствует:
|
||||
│ Linux/macOS → curl | bash → ~/.local/bin/just
|
||||
│ macOS → brew install just (если есть Homebrew)
|
||||
│ Windows → winget install --id Casey.Just
|
||||
│ (перезапустить Git Bash после установки)
|
||||
│
|
||||
├── проверить/установить uv
|
||||
│ < 0.4.0 или отсутствует:
|
||||
│ Linux/macOS → curl -LsSf https://astral.sh/uv/install.sh | sh → ~/.local/bin/uv
|
||||
│ macOS → brew install uv (если есть Homebrew)
|
||||
│ Windows → powershell.exe irm https://astral.sh/uv/install.ps1 | iex
|
||||
│
|
||||
└── exec just host::bootstrap
|
||||
│
|
||||
├── [1/3] check-deps
|
||||
|
|
@ -173,11 +220,15 @@ bootstrap.sh (уровень 0)
|
|||
│ /etc/udev/rules.d/99-nxp-mimxrt.rules:
|
||||
│ 1FC9:0130 ← NXP BootROM (SDP-режим)
|
||||
│ 15A2:0073 ← NXP Flashloader
|
||||
│ VID:PID берутся из .env (BOOTROM_VID/PID, FLASHLOADER_VID/PID)
|
||||
│ usermod -a -G plugdev $USER
|
||||
│ требует re-login · на macOS/Windows пропускается
|
||||
│
|
||||
└── [3/3] setup-tools
|
||||
uv sync в tools/host/ (venv: .venv-host на хосте)
|
||||
uv sync в tools/host/
|
||||
venv: .venv-host (Linux/macOS) · .venv-host-win (Windows)
|
||||
разделение нужно: devcontainer создаёт .venv с Linux-симлинками,
|
||||
Windows не может их удалить без прав администратора
|
||||
SHA-256 uv.lock кэшируется в .cache/
|
||||
повторный вызов мгновенный если lockfile не изменился
|
||||
```
|
||||
|
|
@ -191,7 +242,7 @@ bootstrap.sh (уровень 0)
|
|||
`postCreateCommand` выполняется автоматически при поднятии контейнера:
|
||||
|
||||
```bash
|
||||
cd tools/host && uv sync && # venv: .venv-container
|
||||
cd tools/host && uv sync && # venv: tools/host/.venv (Linux, внутри контейнера)
|
||||
cd ../.. &&
|
||||
cmake --preset host-debug &&
|
||||
cmake --preset Debug
|
||||
|
|
@ -266,7 +317,7 @@ buildPresets (host):
|
|||
|
||||
### 7.2 Типичная сессия разработки
|
||||
|
||||
```
|
||||
```bash
|
||||
Открыть VSCode → работать в devcontainer весь день
|
||||
│
|
||||
├── писать код
|
||||
|
|
@ -311,7 +362,7 @@ buildPresets (host):
|
|||
|
||||
### 8.1 Перевод платы в SDP-режим
|
||||
|
||||
```
|
||||
```bash
|
||||
1. BOOT_MOD_1 → 3V3
|
||||
2. Reset
|
||||
3. Подключить USB к хосту
|
||||
|
|
@ -347,7 +398,12 @@ just host::flash-production # bootloader release + tft_app release
|
|||
|
||||
### 8.3 Что происходит внутри flash_usb.py
|
||||
|
||||
```
|
||||
`flash_usb.py` читает конфигурацию из окружения (just экспортирует `.env`):
|
||||
|
||||
- `BOOTROM_VID/PID`, `FLASHLOADER_VID/PID` → USB-адреса устройств
|
||||
- `BUILD_DIR` → абсолютный путь к артефактам сборки
|
||||
|
||||
```bash
|
||||
Плата в SDP-режиме (1FC9:0130)
|
||||
│
|
||||
├── sdphost: загрузить ivt_flashloader.bin в RAM (0x20001C00)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ int main(void)
|
|||
{
|
||||
BOARD_Init();
|
||||
GPIO_PinWrite(BOARD_INITPINS_UserLed1_PORT, BOARD_INITPINS_UserLed1_PIN, 0);
|
||||
GPIO_PinWrite(BOARD_INITPINS_UserLed2_PORT, BOARD_INITPINS_UserLed2_PIN, 0);
|
||||
// GPIO_PinWrite(BOARD_INITPINS_UserLed2_PORT, BOARD_INITPINS_UserLed2_PIN, 0);
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,20 +117,22 @@ test-host-release: _configure-host-release
|
|||
hab-firmware-test-debug: build-firmware-test-debug
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Debug"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_firmware_test_debug.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Debug/firmware_test_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Debug/firmware_test_hab.bin"
|
||||
echo " ✅ firmware_test_hab.bin (Debug)"
|
||||
|
||||
[group('hab_image_gen')]
|
||||
hab-firmware-test-release: build-firmware-test-release
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Release"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_firmware_test_release.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Release/firmware_test_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Release/firmware_test_hab.bin"
|
||||
echo " ✅ firmware_test_hab.bin (Release)"
|
||||
|
||||
# ── bootloader ───────────────────────────────────────────────────────────────
|
||||
|
|
@ -138,20 +140,22 @@ hab-firmware-test-release: build-firmware-test-release
|
|||
hab-bootloader-debug: build-bootloader-debug
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Debug"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_bootloader_debug.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Debug/bootloader_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Debug/bootloader_hab.bin"
|
||||
echo " ✅ bootloader_hab.bin (Debug)"
|
||||
|
||||
[group('hab_image_gen')]
|
||||
hab-bootloader-release: build-bootloader-release
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Release"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_bootloader_release.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Release/bootloader_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Release/bootloader_hab.bin"
|
||||
echo " ✅ bootloader_hab.bin (Release)"
|
||||
|
||||
# ── app ───────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -159,20 +163,22 @@ hab-bootloader-release: build-bootloader-release
|
|||
hab-app-debug: build-app-debug
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Debug"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_app_debug.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Debug/app_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Debug/app_hab.bin"
|
||||
echo " ✅ app_hab.bin (Debug)"
|
||||
|
||||
[group('hab_image_gen')]
|
||||
hab-app-release: build-app-release
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
mkdir -p "{{BUILD_DIR}}/Release"
|
||||
cd "{{TOOLS_DIR}}/hab"
|
||||
uv run nxpimage hab export --force \
|
||||
-c hab_app_release.yaml \
|
||||
-o "../../../{{BUILD_DIR}}/Release/app_hab.bin"
|
||||
-o "{{BUILD_DIR}}/Release/app_hab.bin"
|
||||
echo " ✅ app_hab.bin (Release)"
|
||||
|
||||
# ── все образы сразу ─────────────────────────────────────────────────────────
|
||||
|
|
@ -190,14 +196,13 @@ hab-all-release: hab-firmware-test-release hab-bootloader-release hab-app-releas
|
|||
hab-verify project="firmware_test" type="release":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(pwd)"
|
||||
case "{{project}}-{{type}}" in
|
||||
firmware_test-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/firmware_test_hab.bin" ;;
|
||||
firmware_test-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/firmware_test_hab.bin" ;;
|
||||
bootloader-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/bootloader_hab.bin" ;;
|
||||
bootloader-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/bootloader_hab.bin" ;;
|
||||
app-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/app_hab.bin" ;;
|
||||
app-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/app_hab.bin" ;;
|
||||
firmware_test-debug) BIN="{{BUILD_DIR}}/Debug/firmware_test_hab.bin" ;;
|
||||
firmware_test-release) BIN="{{BUILD_DIR}}/Release/firmware_test_hab.bin" ;;
|
||||
bootloader-debug) BIN="{{BUILD_DIR}}/Debug/bootloader_hab.bin" ;;
|
||||
bootloader-release) BIN="{{BUILD_DIR}}/Release/bootloader_hab.bin" ;;
|
||||
app-debug) BIN="{{BUILD_DIR}}/Debug/app_hab.bin" ;;
|
||||
app-release) BIN="{{BUILD_DIR}}/Release/app_hab.bin" ;;
|
||||
*)
|
||||
echo " ❌ Unknown: {{project}}-{{type}}"
|
||||
echo " Projects: firmware_test, bootloader, app"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
TOOLS_DIR := env('TOOLS_DIR', justfile_directory() / 'tools/host')
|
||||
CACHE_DIR := env('CACHE_DIR', justfile_directory() / '.cache')
|
||||
|
||||
_uname := `uname -s`
|
||||
_venv := if _uname =~ "MINGW|MSYS|CYGWIN" { ".venv-host-win" } else { ".venv-host" }
|
||||
|
||||
# === Минимальные версии зависимостей ===
|
||||
JUST_MIN := "1.36.0"
|
||||
UV_MIN := "0.4.0"
|
||||
|
|
@ -114,7 +117,7 @@ check-deps:
|
|||
|
||||
check_tool "just" "just" "{{JUST_MIN}}"
|
||||
check_tool "uv" "uv" "{{UV_MIN}}"
|
||||
check_tool "docker" "docker" "{{DOCKER_MIN}}" version --format '{{{{.Client.Version}}}}'
|
||||
check_tool "docker" "docker" "{{DOCKER_MIN}}"
|
||||
|
||||
if [[ "${PLATFORM}" == "linux" ]]; then
|
||||
echo ""
|
||||
|
|
@ -253,7 +256,7 @@ flash project type="release":
|
|||
echo " Valid: debug, release"
|
||||
exit 1 ;;
|
||||
esac
|
||||
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
||||
cd "{{TOOLS_DIR}}" && UV_PROJECT_ENVIRONMENT={{_venv}} uv run python flash_usb.py \
|
||||
--firmware "{{project}}" --build-type "${BUILD_TYPE}"
|
||||
|
||||
# Загрузить образ в RAM без записи во Flash.
|
||||
|
|
@ -271,7 +274,7 @@ flash-ram project type="debug":
|
|||
echo " Valid: debug, release"
|
||||
exit 1 ;;
|
||||
esac
|
||||
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
||||
cd "{{TOOLS_DIR}}" && UV_PROJECT_ENVIRONMENT={{_venv}} uv run python flash_usb.py \
|
||||
--firmware "{{project}}" --build-type "${BUILD_TYPE}" --ram-only
|
||||
|
||||
# Псевдонимы для частых сценариев ────────────────────────────────────────────
|
||||
|
|
@ -302,7 +305,7 @@ incoming: flash-test-release
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
echo " ▶ Running HIL tests (CAN, UART, SDRAM, SPI Flash)..."
|
||||
# cd tools/hil && uv run python3 run_hil.py <- раскомментить когда готово
|
||||
# cd tools/hil && UV_PROJECT_ENVIRONMENT={{_venv}} uv run python run_hil.py <- раскомментить когда готово
|
||||
echo " ⚠️ HIL tests not yet implemented"
|
||||
|
||||
# Финальная прошивка: загрузчик + основная прошивка (Release)
|
||||
|
|
@ -317,17 +320,17 @@ production: flash-production
|
|||
# Найти подключённые NXP USB-устройства
|
||||
[group('util')]
|
||||
scan:
|
||||
cd "{{TOOLS_DIR}}" && uv run nxpdevscan
|
||||
cd "{{TOOLS_DIR}}" && UV_PROJECT_ENVIRONMENT={{_venv}} uv run nxpdevscan
|
||||
|
||||
# Проверить связь с BootROM через SDP (плата в SDP-режиме)
|
||||
[group('util'), no-cd]
|
||||
sdp-status:
|
||||
cd "{{TOOLS_DIR}}" && uv run sdphost -u 0x1FC9,0x0130 -- error-status
|
||||
cd "{{TOOLS_DIR}}" && UV_PROJECT_ENVIRONMENT={{_venv}} uv run sdphost -u 0x1FC9,0x0130 -- error-status
|
||||
|
||||
# Проверить что Flashloader отвечает (после jump-address)
|
||||
[group('util')]
|
||||
flashloader-status:
|
||||
cd "{{TOOLS_DIR}}" && uv run blhost -u 0x15A2,0x0073 -- get-property 1 0
|
||||
cd "{{TOOLS_DIR}}" && UV_PROJECT_ENVIRONMENT={{_venv}} uv run blhost -u 0x15A2,0x0073 -- get-property 1 0
|
||||
|
||||
# Обновить spsdk до новой версии
|
||||
# Использование: just upgrade-tools 3.8.0
|
||||
|
|
|
|||
|
|
@ -17,35 +17,56 @@ flash_usb.py — прошивка MIMXRT1052 через USB (BootROM SDP → Fla
|
|||
→ blhost стирает нужный регион Flash
|
||||
→ blhost пишет HAB образ начиная с 0x60002000
|
||||
→ blhost reset
|
||||
|
||||
Конфигурация:
|
||||
Переменные окружения (задаются в .env, экспортируются через just):
|
||||
BOOTROM_VID — VID BootROM SDP (default: 1fc9)
|
||||
BOOTROM_PID — PID BootROM SDP (default: 0130)
|
||||
FLASHLOADER_VID — VID Flashloader (default: 15a2)
|
||||
FLASHLOADER_PID — PID Flashloader (default: 0073)
|
||||
BUILD_DIR — путь к директории сборки (default: <repo_root>/build)
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
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"
|
||||
# ─── Пути ─────────────────────────────────────────────────────────────────────
|
||||
SCRIPT_DIR = Path(__file__).parent.resolve()
|
||||
REPO_ROOT = SCRIPT_DIR.parent.parent
|
||||
FLASHLOADER = SCRIPT_DIR / "dcd" / "ivt_flashloader.bin"
|
||||
|
||||
# USB VID:PID
|
||||
SDP_USB = "0x1FC9,0x0130" # BootROM Serial Download Protocol
|
||||
BLHOST_USB = "0x15A2,0x0073" # Flashloader запущен
|
||||
# BUILD_DIR: берём из окружения (just экспортирует из .env как абсолютный путь),
|
||||
# fallback — рассчитываем от расположения скрипта
|
||||
BUILD_DIR = Path(os.environ.get("BUILD_DIR", str(REPO_ROOT / "build")))
|
||||
|
||||
# ─── USB VID:PID — из окружения (.env → just set export → uv run) ─────────────
|
||||
def _usb(vid_key: str, vid_default: str, pid_key: str, pid_default: str) -> str:
|
||||
|
||||
vid = os.environ.get(vid_key, vid_default).strip().upper().lstrip("0X")
|
||||
pid = os.environ.get(pid_key, pid_default).strip().upper().lstrip("0X")
|
||||
return f"0x{vid},0x{pid}"
|
||||
|
||||
SDP_USB = _usb("BOOTROM_VID", "1fc9", "BOOTROM_PID", "0130") # BootROM SDP
|
||||
BLHOST_USB = _usb("FLASHLOADER_VID","15a2", "FLASHLOADER_PID","0073") # 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
|
||||
FLEXSPI_MEMORY_ID = "9" # FlexSPI NOR memory interface ID
|
||||
|
||||
# Option word для записи FCB: tag=0xF → Write FCB command
|
||||
FLEXSPI_FCB_VALUE = "0xF000000F"
|
||||
|
||||
# Flash layout
|
||||
FLASH_BASE = 0x60000000
|
||||
HAB_OFFSET = 0x1000 # IVT offset: HAB binary starts with IVT at byte 0
|
||||
# write address = FLASH_BASE + ivtOffset = 0x60001000
|
||||
FLASH_BASE = 0x60000000
|
||||
HAB_OFFSET = 0x1000 # IVT offset: write address = FLASH_BASE + HAB_OFFSET
|
||||
|
||||
|
||||
def run(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess:
|
||||
|
|
@ -64,7 +85,7 @@ def step(msg: str) -> None:
|
|||
|
||||
|
||||
def wait_for_flashloader(timeout: int = 10) -> bool:
|
||||
"""Ждём пока Flashloader поднимется (VID:PID 15A2:0073)"""
|
||||
"""Ждём пока Flashloader поднимется"""
|
||||
print(f"\n Ожидание Flashloader (до {timeout}с)...", end="", flush=True)
|
||||
for i in range(timeout):
|
||||
time.sleep(1)
|
||||
|
|
@ -82,7 +103,6 @@ def wait_for_flashloader(timeout: int = 10) -> bool:
|
|||
|
||||
def load_flashloader() -> None:
|
||||
"""Загружает Flashloader через SDP если ещё не запущен"""
|
||||
# Проверяем — вдруг уже запущен
|
||||
result = subprocess.run(
|
||||
["blhost", "-u", BLHOST_USB, "-j", "--", "get-property", "1", "0"],
|
||||
capture_output=True
|
||||
|
|
@ -108,11 +128,6 @@ def load_flashloader() -> None:
|
|||
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 (инициализация контроллера)")
|
||||
|
|
@ -124,7 +139,7 @@ def configure_flexspi() -> None:
|
|||
|
||||
def write_fcb() -> None:
|
||||
"""Записывает Flash Configuration Block в 0x60000000
|
||||
|
||||
|
||||
Отдельный шаг после erase! Flashloader генерирует FCB из параметров FlexSPI
|
||||
и пишет его по адресу 0x60000000. Без FCB BootROM не знает как читать Flash.
|
||||
Option word 0xF000000F: tag=0xF → Write FCB command.
|
||||
|
|
@ -144,7 +159,6 @@ def flash(hab_bin: Path, ram_only: bool = False) -> None:
|
|||
|
||||
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", "--",
|
||||
|
|
@ -152,10 +166,9 @@ def flash(hab_bin: Path, ram_only: bool = False) -> None:
|
|||
return
|
||||
|
||||
load_flashloader()
|
||||
configure_flexspi() # 0xC0000007 — инициализация FlexSPI контроллера
|
||||
configure_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}")
|
||||
|
|
@ -164,14 +177,12 @@ def flash(hab_bin: Path, ram_only: bool = False) -> None:
|
|||
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!)
|
||||
write_fcb()
|
||||
|
||||
# memoryId=0 — mapped (XIP) адресное пространство
|
||||
run(["blhost", "-u", BLHOST_USB, "--",
|
||||
"write-memory", write_addr, str(hab_bin), "0"])
|
||||
|
||||
|
|
@ -181,6 +192,9 @@ def flash(hab_bin: Path, ram_only: bool = False) -> None:
|
|||
|
||||
|
||||
def main() -> None:
|
||||
print(f"DEBUG SDP_USB = {repr(SDP_USB)}")
|
||||
print(f"DEBUG BLHOST_USB = {repr(BLHOST_USB)}")
|
||||
print(f"DEBUG BUILD_DIR = {repr(BUILD_DIR)}")
|
||||
parser = argparse.ArgumentParser(description="Прошивка MIMXRT1052 через USB")
|
||||
parser.add_argument("--firmware", required=True,
|
||||
choices=["firmware_test", "bootloader", "app"],
|
||||
|
|
@ -192,18 +206,18 @@ def main() -> None:
|
|||
help="Загрузить в RAM без записи во Flash")
|
||||
args = parser.parse_args()
|
||||
|
||||
# HAB образ собирается командой: nxpimage hab export -c hab_<firmware>.yaml
|
||||
# Выходной файл: build/<BuildType>/<firmware>_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" Прошивка: {args.firmware} [{args.build_type}]")
|
||||
print(f" Образ: {hab_bin}")
|
||||
print(f" SDP USB: {SDP_USB}")
|
||||
print(f" BL USB: {BLHOST_USB}")
|
||||
print(f"{'═'*60}")
|
||||
|
||||
flash(hab_bin, ram_only=args.ram_only)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
@ -7,3 +7,4 @@ requires-python = ">=3.10"
|
|||
dependencies = [
|
||||
"spsdk==3.7.0",
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue