# 9
Переход на модульную архитектуру just скриптов (см. docs/DEV_ARCH.md)
This commit is contained in:
parent
e8a9826944
commit
6930479fdb
12 changed files with 673 additions and 566 deletions
0
.env.example
Normal file
0
.env.example
Normal file
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -67,4 +67,6 @@ compile_commands.json
|
||||||
.venv/
|
.venv/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
.env
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
28
.vscode/tasks.json
vendored
28
.vscode/tasks.json
vendored
|
|
@ -13,9 +13,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::build-${input:project}-${input:buildType}"
|
||||||
"scripts/build.just",
|
|
||||||
"build-${input:project}-${input:buildType}"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
|
@ -41,9 +39,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::test-host"
|
||||||
"scripts/build.just",
|
|
||||||
"test-host"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
|
@ -61,9 +57,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::test-host-release"
|
||||||
"scripts/build.just",
|
|
||||||
"test-host-release"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
|
|
@ -79,9 +73,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::hab-${input:habProject}-${input:buildType}"
|
||||||
"scripts/build.just",
|
|
||||||
"hab-${input:habProject}-${input:buildType}"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
|
@ -99,9 +91,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::hab-all-debug"
|
||||||
"scripts/build.just",
|
|
||||||
"hab-all-debug"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
|
|
@ -114,9 +104,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::hab-all-release"
|
||||||
"scripts/build.just",
|
|
||||||
"hab-all-release"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
|
|
@ -132,9 +120,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "just",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--justfile",
|
"build::clean"
|
||||||
"scripts/build.just",
|
|
||||||
"clean"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
# Прошивка платы со стороны хоста
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Прошить во Flash
|
|
||||||
just flash firmware_test debug # разработка — итерации с отладчиком
|
|
||||||
just flash firmware_test release # проверить как будет на сервере
|
|
||||||
just flash bootloader debug
|
|
||||||
just flash bootloader release
|
|
||||||
just flash app debug
|
|
||||||
just flash app release
|
|
||||||
|
|
||||||
|
|
||||||
# TODO:Загрузить в RAM (без записи во Flash, плата стартует сразу)
|
|
||||||
just flash-ram firmware_test # default: debug
|
|
||||||
just flash-ram firmware_test debug
|
|
||||||
just flash-ram app release
|
|
||||||
|
|
||||||
# TODO:Псевдонимы
|
|
||||||
just flash-test-debug # = just flash firmware_test debug
|
|
||||||
just flash-test-release # = just flash firmware_test release
|
|
||||||
just flash-production # bootloader release + app release
|
|
||||||
```
|
|
||||||
370
Justfile
370
Justfile
|
|
@ -1,344 +1,64 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Justfile — корень репозитория
|
# Корневой justfile — точка входа для всех команд
|
||||||
# Выполняется на ХОСТ-МАШИНЕ разработчика (вне devcontainer).
|
# Может выполняться на хосте или внутри devcontainer
|
||||||
#
|
|
||||||
# Отвечает только за:
|
|
||||||
# - инициализацию окружения (setup)
|
|
||||||
# - прошивку платы через USB (flash)
|
|
||||||
# - сквозные сценарии (pipeline)
|
|
||||||
# - вспомогательные утилиты (util)
|
|
||||||
#
|
|
||||||
# Сборка, тесты и HAB-образы — в just/build.just (внутри devcontainer).
|
|
||||||
#
|
#
|
||||||
# Быстрый старт:
|
# Быстрый старт:
|
||||||
# ./scripts/bootstrap.sh # первый запуск после git clone
|
# just # показать все доступные команды
|
||||||
# just # показать все рецепты
|
# just bootstrap # первая настройка после git clone (на хосте)
|
||||||
|
# just build ... # сборка (внутри devcontainer)
|
||||||
|
# just host::flash # прошивка (на хосте)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
JUST_MIN := "1.27.0"
|
# === Глобальные настройки ===
|
||||||
UV_MIN := "0.4.0"
|
# Все модули наследуют эти настройки
|
||||||
DOCKER_MIN := "24.0.0"
|
|
||||||
|
|
||||||
TOOLS_DIR := "tools/host"
|
set shell := ["bash", "-euo", "pipefail", "-c"]
|
||||||
|
# экспортируем все just-переменные в окружение
|
||||||
|
set export
|
||||||
|
# автоматически загружать .env
|
||||||
|
set dotenv-load
|
||||||
|
|
||||||
|
# === Общие переменные (доступны во всех модулях через export) ===
|
||||||
|
BOARD := env('BOARD', 'MIMXRT1052')
|
||||||
|
BUILD_DIR := env('BUILD_DIR', 'build')
|
||||||
|
TOOLS_DIR := env('TOOLS_DIR', 'tools/host')
|
||||||
CACHE_DIR := ".cache"
|
CACHE_DIR := ".cache"
|
||||||
|
|
||||||
# По умолчанию — показать список рецептов
|
# === Модули ===
|
||||||
_default:
|
# Каждый модуль — это namespace с изолированными рецептами
|
||||||
@just --list --unsorted
|
# host.just — операции на хост-машине
|
||||||
|
mod host 'just/host.just'
|
||||||
|
# build.just — сборка в DevContainer
|
||||||
|
mod build 'just/build.just'
|
||||||
|
# ci.just — CI/CD сценарии (опционально)
|
||||||
|
mod ci 'just/ci.just'
|
||||||
|
|
||||||
# =============================================================================
|
# === Default рецепт ===
|
||||||
# ГРУППА: setup — инициализация рабочего окружения
|
# Вызывается при `just` без аргументов
|
||||||
# =============================================================================
|
# Показывает полное дерево команд из всех модулей
|
||||||
|
|
||||||
# [1/3] Проверить наличие и версии инструментов на хост-машине
|
default:
|
||||||
[group('setup')]
|
@just --list --list-submodules
|
||||||
check-deps:
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
BOLD="\033[1m"; GREEN="\033[0;32m"; RED="\033[0;31m"; YELLOW="\033[1;33m"; RESET="\033[0m"
|
# === Популярные алиасы (для удобства команды) ===
|
||||||
ERRORS=0; WARNINGS=0
|
# Сокращают длинные вызовы модулей
|
||||||
|
|
||||||
ok() { echo -e " ${GREEN}✅ ${1}${RESET}"; }
|
# Инициализация окружения (эквивалент host::bootstrap)
|
||||||
fail() { echo -e " ${RED}❌ ${1}${RESET}"; ERRORS=$((ERRORS+1)); }
|
init:
|
||||||
warn() { echo -e " ${YELLOW}⚠️ ${1}${RESET}"; WARNINGS=$((WARNINGS+1)); }
|
@just host::bootstrap
|
||||||
|
|
||||||
_uname="$(uname -s)"
|
# Быстрая прошивка тестового образа в Debug
|
||||||
case "${_uname}" in
|
flash:
|
||||||
Linux*) PLATFORM="linux" ;;
|
@just host::flash-test-debug
|
||||||
Darwin*) PLATFORM="macos" ;;
|
|
||||||
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
|
|
||||||
*) PLATFORM="unknown" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Сравнение semver без sort -V (недоступен в Git Bash)
|
# Полная сборка всех проектов в Release (в контейнере)
|
||||||
semver_ge() {
|
build-all:
|
||||||
local a="$1" b="$2"
|
@just build::hab-all-release
|
||||||
local a1 a2 a3 b1 b2 b3
|
|
||||||
IFS='.' read -r a1 a2 a3 <<< "${a}"
|
|
||||||
IFS='.' read -r b1 b2 b3 <<< "${b}"
|
|
||||||
a1="${a1//[^0-9]/}"; a2="${a2//[^0-9]/}"; a3="${a3//[^0-9]/}"
|
|
||||||
b1="${b1//[^0-9]/}"; b2="${b2//[^0-9]/}"; b3="${b3//[^0-9]/}"
|
|
||||||
[[ "${a1:-0}" -gt "${b1:-0}" ]] && return 0
|
|
||||||
[[ "${a1:-0}" -lt "${b1:-0}" ]] && return 1
|
|
||||||
[[ "${a2:-0}" -gt "${b2:-0}" ]] && return 0
|
|
||||||
[[ "${a2:-0}" -lt "${b2:-0}" ]] && return 1
|
|
||||||
[[ "${a3:-0}" -ge "${b3:-0}" ]] && return 0
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
install_hint() {
|
# CI пайплайн
|
||||||
local tool=$1
|
run-ci:
|
||||||
case "${PLATFORM}" in
|
@just ci::pipeline
|
||||||
linux)
|
|
||||||
case "$tool" in
|
|
||||||
just) echo "curl -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin" ;;
|
|
||||||
uv) echo "curl -LsSf https://astral.sh/uv/install.sh | sh" ;;
|
|
||||||
docker) echo "https://docs.docker.com/engine/install/ubuntu/" ;;
|
|
||||||
esac ;;
|
|
||||||
macos)
|
|
||||||
case "$tool" in
|
|
||||||
just) echo "brew install just" ;;
|
|
||||||
uv) echo "brew install uv" ;;
|
|
||||||
docker) echo "brew install --cask docker" ;;
|
|
||||||
esac ;;
|
|
||||||
windows)
|
|
||||||
case "$tool" in
|
|
||||||
just) echo "winget install --id Casey.Just (в PowerShell)" ;;
|
|
||||||
uv) echo 'powershell -c "irm https://astral.sh/uv/install.ps1 | iex"' ;;
|
|
||||||
docker) echo "winget install --id Docker.DockerDesktop (в PowerShell)" ;;
|
|
||||||
esac ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
check_tool() {
|
|
||||||
local name=$1 cmd=$2 min_ver=$3
|
|
||||||
shift 3
|
|
||||||
local ver_args=("${@:---version}")
|
|
||||||
if ! command -v "$cmd" &>/dev/null; then
|
|
||||||
fail "$name not found -- $(install_hint "$name")"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
local actual
|
|
||||||
actual=$("$cmd" "${ver_args[@]}" 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
|
||||||
if [[ -z "$actual" ]]; then
|
|
||||||
warn "$name found but version could not be detected"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if semver_ge "$actual" "$min_ver"; then
|
|
||||||
ok "$name $actual (>= $min_ver)"
|
|
||||||
else
|
|
||||||
fail "$name $actual -- need >= $min_ver -- $(install_hint "$name")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${BOLD} Platform: ${PLATFORM}${RESET}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${BOLD} Checking host dependencies...${RESET}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
check_tool "just" "just" "{{JUST_MIN}}"
|
|
||||||
check_tool "uv" "uv" "{{UV_MIN}}"
|
|
||||||
check_tool "docker" "docker" "{{DOCKER_MIN}}" version --format '{{{{.Client.Version}}}}'
|
|
||||||
|
|
||||||
if [[ "${PLATFORM}" == "linux" ]]; then
|
|
||||||
echo ""
|
|
||||||
echo -e "${BOLD} Checking udev rules (Linux only)...${RESET}"
|
|
||||||
echo ""
|
|
||||||
local rules_file="/etc/udev/rules.d/99-nxp-mimxrt.rules"
|
|
||||||
local udev_ok=true
|
|
||||||
grep -q "1fc9" "$rules_file" 2>/dev/null || { warn "udev: BootROM rule missing (VID 1fc9)"; udev_ok=false; }
|
|
||||||
grep -q "15a2" "$rules_file" 2>/dev/null || { warn "udev: Flashloader rule missing (VID 15a2)"; udev_ok=false; }
|
|
||||||
if ! groups 2>/dev/null | grep -q plugdev; then
|
|
||||||
warn "User '$(whoami)' not in 'plugdev' group"
|
|
||||||
udev_ok=false
|
|
||||||
fi
|
|
||||||
if [[ "$udev_ok" == "false" ]]; then
|
|
||||||
warn "USB flashing requires root without udev rules -- run: just setup-udev"
|
|
||||||
else
|
|
||||||
ok "udev rules (NXP USB) + plugdev group"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
if [[ $ERRORS -gt 0 ]]; then
|
|
||||||
echo -e " ${RED}${BOLD}$ERRORS error(s) found. Fix them before continuing.${RESET}"
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
elif [[ $WARNINGS -gt 0 ]]; then
|
|
||||||
echo -e " ${YELLOW}${BOLD}$WARNINGS warning(s). Some features may not work.${RESET}"
|
|
||||||
else
|
|
||||||
echo -e " ${GREEN}${BOLD}All dependencies satisfied.${RESET}"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# [2/3] Установить udev правила для USB-прошивки (только Linux, требует sudo)
|
|
||||||
[group('setup')]
|
|
||||||
setup-udev:
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
case "$(uname -s)" in
|
|
||||||
Linux*) ;;
|
|
||||||
*)
|
|
||||||
echo " ℹ️ udev rules are Linux-only, skipping on $(uname -s)."
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
echo " Installing udev rules for NXP USB devices..."
|
|
||||||
printf '%s\n%s\n%s\n%s\n' \
|
|
||||||
'# NXP BootROM -- SDP mode (BOOT_MOD_1 = 3V3)' \
|
|
||||||
'SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="0130", MODE="0666", GROUP="plugdev"' \
|
|
||||||
'# NXP Flashloader -- after jump-address' \
|
|
||||||
'SUBSYSTEM=="usb", ATTR{idVendor}=="15a2", ATTR{idProduct}=="0073", MODE="0666", GROUP="plugdev"' \
|
|
||||||
| sudo tee /etc/udev/rules.d/99-nxp-mimxrt.rules > /dev/null
|
|
||||||
sudo udevadm control --reload-rules
|
|
||||||
sudo udevadm trigger
|
|
||||||
sudo usermod -a -G plugdev "$USER"
|
|
||||||
echo " ✅ udev rules installed"
|
|
||||||
echo " ⚠️ Re-login required for 'plugdev' group to take effect"
|
|
||||||
|
|
||||||
# [3/3] Синхронизировать зависимости tools/host (spsdk и др.)
|
|
||||||
# Идемпотентен: пропускает sync если uv.lock не изменился
|
|
||||||
[group('setup')]
|
|
||||||
setup-tools:
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
LOCK="{{TOOLS_DIR}}/uv.lock"
|
|
||||||
STAMP="{{CACHE_DIR}}/uv_lock.sha256"
|
|
||||||
mkdir -p "{{CACHE_DIR}}"
|
|
||||||
current=$(sha256sum "$LOCK" 2>/dev/null | cut -d' ' -f1 || echo "missing")
|
|
||||||
previous=$(cat "$STAMP" 2>/dev/null || echo "none")
|
|
||||||
if [[ "$current" == "$previous" ]]; then
|
|
||||||
echo " ✅ tools/host deps up to date (lockfile unchanged)"
|
|
||||||
else
|
|
||||||
echo " 📦 Syncing tools/host deps..."
|
|
||||||
cd "{{TOOLS_DIR}}" && uv sync
|
|
||||||
echo "$current" > "../../$STAMP"
|
|
||||||
echo " ✅ tools/host deps installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Полная инициализация — запустить один раз после git clone
|
|
||||||
[group('setup')]
|
|
||||||
bootstrap:
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
_uname="$(uname -s)"
|
|
||||||
case "${_uname}" in
|
|
||||||
Linux*) PLATFORM="linux" ;;
|
|
||||||
Darwin*) PLATFORM="macos" ;;
|
|
||||||
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
|
|
||||||
*) PLATFORM="unknown" ;;
|
|
||||||
esac
|
|
||||||
echo ""
|
|
||||||
echo " === Bootstrap: step 1/3 -- check-deps ==="
|
|
||||||
just check-deps
|
|
||||||
if [[ "${PLATFORM}" == "linux" ]]; then
|
|
||||||
echo " === Bootstrap: step 2/3 -- setup-udev ==="
|
|
||||||
just setup-udev
|
|
||||||
else
|
|
||||||
echo " ℹ️ step 2/3 -- setup-udev skipped (${PLATFORM})"
|
|
||||||
fi
|
|
||||||
echo " === Bootstrap: step 3/3 -- setup-tools ==="
|
|
||||||
just setup-tools
|
|
||||||
echo ""
|
|
||||||
echo " ✅ Bootstrap complete."
|
|
||||||
echo " Next: open project in VSCode -> 'Reopen in Container'"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# ГРУППА: flash — прошивка платы через USB
|
|
||||||
# Требует: uv + spsdk (just setup-tools), плата в SDP-режиме
|
|
||||||
# HAB-образы должны быть собраны заранее (just hab-* внутри devcontainer)
|
|
||||||
#
|
|
||||||
# Матрица прошивки:
|
|
||||||
# just flash firmware_test debug
|
|
||||||
# just flash firmware_test release
|
|
||||||
# just flash bootloader debug
|
|
||||||
# just flash bootloader release
|
|
||||||
# just flash app debug
|
|
||||||
# just flash app release
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# Прошить выбранный HAB-образ.
|
|
||||||
# Использование: just flash <project> <type>
|
|
||||||
# project: firmware_test | bootloader | app
|
|
||||||
# type: debug | release (default: release)
|
|
||||||
#
|
|
||||||
# Образ должен быть собран заранее в devcontainer:
|
|
||||||
# just --justfile just/build.just hab-<project>-<type>
|
|
||||||
[group('flash')]
|
|
||||||
flash project type="release":
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
case "{{type}}" in
|
|
||||||
debug) BUILD_TYPE="Debug" ;;
|
|
||||||
release) BUILD_TYPE="Release" ;;
|
|
||||||
*)
|
|
||||||
echo " ❌ Unknown type: {{type}}"
|
|
||||||
echo " Valid: debug, release"
|
|
||||||
exit 1 ;;
|
|
||||||
esac
|
|
||||||
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
|
||||||
--firmware "{{project}}" --build-type "${BUILD_TYPE}"
|
|
||||||
|
|
||||||
# Загрузить образ в RAM без записи во Flash.
|
|
||||||
# Полезно для быстрой проверки — не изнашивает Flash, плата стартует сразу.
|
|
||||||
# Использование: just flash-ram <project> <type>
|
|
||||||
[group('flash')]
|
|
||||||
flash-ram project type="debug":
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
case "{{type}}" in
|
|
||||||
debug) BUILD_TYPE="Debug" ;;
|
|
||||||
release) BUILD_TYPE="Release" ;;
|
|
||||||
*)
|
|
||||||
echo " ❌ Unknown type: {{type}}"
|
|
||||||
echo " Valid: debug, release"
|
|
||||||
exit 1 ;;
|
|
||||||
esac
|
|
||||||
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
|
||||||
--firmware "{{project}}" --build-type "${BUILD_TYPE}" --ram-only
|
|
||||||
|
|
||||||
# Псевдонимы для частых сценариев ────────────────────────────────────────────
|
|
||||||
|
|
||||||
# firmware_test Debug — самый частый при разработке
|
|
||||||
[group('flash')]
|
|
||||||
flash-test-debug:
|
|
||||||
@just flash firmware_test debug
|
|
||||||
|
|
||||||
# firmware_test Release — как будет на производстве
|
|
||||||
[group('flash')]
|
|
||||||
flash-test-release:
|
|
||||||
@just flash firmware_test release
|
|
||||||
|
|
||||||
# bootloader + app Release — финальная прошивка
|
|
||||||
[group('flash')]
|
|
||||||
flash-production:
|
|
||||||
@just flash bootloader release
|
|
||||||
@just flash app release
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# ГРУППА: pipeline — производственные сценарии (для сервера)
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# Входной контроль платы: тестовая прошивка (Release) -> HIL-тесты
|
|
||||||
[group('pipeline')]
|
|
||||||
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 <- раскомментить когда готово
|
|
||||||
echo " ⚠️ HIL tests not yet implemented"
|
|
||||||
|
|
||||||
# Финальная прошивка: загрузчик + основная прошивка (Release)
|
|
||||||
[group('pipeline')]
|
|
||||||
production: flash-production
|
|
||||||
@echo " ✅ Production firmware flashed (bootloader + app)"
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# ГРУППА: util — вспомогательные инструменты
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# Найти подключённые NXP USB-устройства
|
|
||||||
[group('util')]
|
|
||||||
scan:
|
|
||||||
cd "{{TOOLS_DIR}}" && uv run nxpdevscan
|
|
||||||
|
|
||||||
# Проверить связь с BootROM через SDP (плата в SDP-режиме)
|
|
||||||
[group('util')]
|
|
||||||
sdp-status:
|
|
||||||
sdphost -u 0x1FC9,0x0130 -- error-status
|
|
||||||
|
|
||||||
# Проверить что Flashloader отвечает (после jump-address)
|
|
||||||
[group('util')]
|
|
||||||
flashloader-status:
|
|
||||||
blhost -u 0x15A2,0x0073 -- get-property 1 0
|
|
||||||
|
|
||||||
# Обновить spsdk до новой версии
|
|
||||||
# Использование: just upgrade-tools 3.8.0
|
|
||||||
[group('util')]
|
|
||||||
upgrade-tools version:
|
|
||||||
cd "{{TOOLS_DIR}}" && uv add "spsdk=={{version}}" && uv sync
|
|
||||||
@echo " ✅ spsdk upgraded to {{version}}"
|
|
||||||
@echo " Run: git add tools/host/uv.lock tools/host/pyproject.toml"
|
|
||||||
|
|
|
||||||
70
README.md
70
README.md
|
|
@ -45,11 +45,13 @@
|
||||||
│ └── host/ # Инструменты для работы с таргетом
|
│ └── host/ # Инструменты для работы с таргетом
|
||||||
│ ├── flash_usb.py # Прошивка через USB ROM (nxp-spsdk / blhost)
|
│ ├── flash_usb.py # Прошивка через USB ROM (nxp-spsdk / blhost)
|
||||||
│ ├── hab/ # Утилиты и гайд по HAB (Secure Boot)
|
│ ├── hab/ # Утилиты и гайд по HAB (Secure Boot)
|
||||||
│ ├── dcd/ # Device Configuration Data
|
│ └── dcd/ # Device Configuration Data
|
||||||
│ └── HOW_TO_FLASH.md → см. также /HOW_TO_FLASH.md
|
├── just/ # Just-модули (автоматизация)
|
||||||
|
│ ├── build.just # Сборка, тесты, HAB-образы (devcontainer)
|
||||||
|
│ ├── host.just # Прошивка, bootstrap, HIL (хост)
|
||||||
|
│ └── ci.just # CI/CD пайплайны
|
||||||
├── scripts/
|
├── scripts/
|
||||||
│ ├── bootstrap.sh # Первичная настройка окружения
|
│ └── bootstrap.sh # Первичная настройка окружения (уровень 0)
|
||||||
│ └── build.just # Рецепты сборки (используется через Justfile)
|
|
||||||
├── docs/ # Документация проекта
|
├── docs/ # Документация проекта
|
||||||
│ ├── DEV_ARCH.md # Архитектура окружения разработки
|
│ ├── DEV_ARCH.md # Архитектура окружения разработки
|
||||||
│ ├── CMAKE_HINTS.md # Шпаргалка по CMake в проекте
|
│ ├── CMAKE_HINTS.md # Шпаргалка по CMake в проекте
|
||||||
|
|
@ -58,7 +60,7 @@
|
||||||
│ └── manufacturing_user's_guide.pdf
|
│ └── manufacturing_user's_guide.pdf
|
||||||
├── CMakeLists.txt # Корневой CMake
|
├── CMakeLists.txt # Корневой CMake
|
||||||
├── CMakePresets.json # Пресеты сборки (Release/Debug/Host)
|
├── CMakePresets.json # Пресеты сборки (Release/Debug/Host)
|
||||||
├── Justfile # Точка входа для команд сборки/тестирования/прошивки
|
├── Justfile # Точка входа для команд (модули: build, host, ci)
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -88,10 +90,10 @@ Bare-metal прошивка для **входного контроля** пла
|
||||||
|
|
||||||
Стратегия тестирования двухуровневая:
|
Стратегия тестирования двухуровневая:
|
||||||
|
|
||||||
| Уровень | Расположение | Инструменты | Запуск |
|
| Уровень | Расположение | Инструменты | Запуск |
|
||||||
|---|---|---|---|
|
| -------------------------------------- | --------------- | --------------- | -------------------------------------- |
|
||||||
| **Host-тесты** (unit + интеграционные) | `tests/host/` | Unity + fff | `ctest` в devcontainer |
|
| **Host-тесты** (unit + интеграционные) | `tests/host/` | Unity + fff | `just build::test-host` в devcontainer |
|
||||||
| **Target-тесты** (аппаратные) | `tests/target/` | Unity на железе | Удалённый ПК-сервер через SSH |
|
| **Target-тесты** (аппаратные) | `tests/target/` | Unity на железе | Удалённый ПК-сервер через SSH |
|
||||||
|
|
||||||
Подробнее — [tests/HostTestingGuide.md](tests/HostTestingGuide.md) и [tests/README.md](tests/README.md).
|
Подробнее — [tests/HostTestingGuide.md](tests/HostTestingGuide.md) и [tests/README.md](tests/README.md).
|
||||||
|
|
||||||
|
|
@ -99,12 +101,12 @@ Bare-metal прошивка для **входного контроля** пла
|
||||||
|
|
||||||
## Управление зависимостями
|
## Управление зависимостями
|
||||||
|
|
||||||
| Зависимость | Подход | Причина |
|
| Зависимость | Подход | Причина |
|
||||||
|---|---|---|
|
| ------------------------------- | -------------------- | -------------------------------------------- |
|
||||||
| NXP MCUXpresso SDK | vendored | Стабильная версия, обновлений не планируется |
|
| NXP MCUXpresso SDK | vendored | Стабильная версия, обновлений не планируется |
|
||||||
| FreeRTOS, FatFS, LittleFS и др. | vendored (через SDK) | Стабильные версии |
|
| FreeRTOS, FatFS, LittleFS и др. | vendored (через SDK) | Стабильные версии |
|
||||||
| Unity + fff | vendored | Маленькие, стабильные |
|
| Unity + fff | vendored | Маленькие, стабильные |
|
||||||
| SEGGER RTT | vendored | Стабильный |
|
| SEGGER RTT | vendored | Стабильный |
|
||||||
|
|
||||||
**Принцип:** всё что не меняется — vendored (закоммичено в репозиторий). Это обеспечивает полностью автономную сборку после `git clone` без доступа к интернету.
|
**Принцип:** всё что не меняется — vendored (закоммичено в репозиторий). Это обеспечивает полностью автономную сборку после `git clone` без доступа к интернету.
|
||||||
|
|
||||||
|
|
@ -112,18 +114,18 @@ Bare-metal прошивка для **входного контроля** пла
|
||||||
|
|
||||||
## Devcontainer — состав окружения
|
## Devcontainer — состав окружения
|
||||||
|
|
||||||
| Инструмент | Назначение |
|
| Инструмент | Назначение |
|
||||||
|---|---|
|
| ---------------------- | -------------------------------------- |
|
||||||
| `arm-none-eabi-gcc` | Сборка firmware для таргета |
|
| `arm-none-eabi-gcc` | Сборка firmware для таргета |
|
||||||
| `arm-none-eabi-gdb` | Отладка через GDB server (удалённая) |
|
| `arm-none-eabi-gdb` | Отладка через GDB server (удалённая) |
|
||||||
| `gcc` (host) | Сборка и запуск host-тестов |
|
| `gcc` (host) | Сборка и запуск host-тестов |
|
||||||
| `CMake + Ninja` | Система сборки |
|
| `CMake + Ninja` | Система сборки |
|
||||||
| `CTest` | Запуск тестов (Unity + fff) |
|
| `CTest` | Запуск тестов (Unity + fff) |
|
||||||
| `clangd` | Language server для VSCode |
|
| `clangd` | Language server для VSCode |
|
||||||
| `clang-format` | Форматирование кода |
|
| `clang-format` | Форматирование кода |
|
||||||
| `clang-tidy` | Статический анализ |
|
| `clang-tidy` | Статический анализ |
|
||||||
| `Python 3 + nxp-spsdk` | Прошивка (blhost, nxpimage), HAB, провизия |
|
| `Python 3 + nxp-spsdk` | HAB-образы (nxpimage) |
|
||||||
| `just` | Запуск рецептов сборки/тестирования/прошивки |
|
| `just` | Запуск рецептов через модули `build::` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -139,13 +141,19 @@ Bare-metal прошивка для **входного контроля** пла
|
||||||
git clone <repo-url>
|
git clone <repo-url>
|
||||||
cd tft_manufacture_test
|
cd tft_manufacture_test
|
||||||
|
|
||||||
|
# Инициализация хоста (один раз)
|
||||||
|
sudo chmod +x bootstrap.sh
|
||||||
|
./bootstrap.sh
|
||||||
|
|
||||||
# Открыть в VSCode → Reopen in Container
|
# Открыть в VSCode → Reopen in Container
|
||||||
# Затем внутри devcontainer:
|
# Затем внутри devcontainer:
|
||||||
|
|
||||||
just build-host # сборка host-тестов
|
just build::test-host # сборка и запуск host-тестов
|
||||||
just test # запуск host-тестов через CTest
|
just build::build-firmware-test-debug # сборка firmware для таргета
|
||||||
just build-firmware # сборка firmware для таргета
|
just build::hab-firmware-test-debug # подготовка HAB-образа
|
||||||
just flash # прошивка через USB ROM
|
|
||||||
|
# На хосте (вне контейнера):
|
||||||
|
just flash # прошивка через USB ROM
|
||||||
```
|
```
|
||||||
|
|
||||||
> Подробнее о прошивке — [HOW_TO_FLASH.md](HOW_TO_FLASH.md)
|
> Подробнее о прошивке — [HOW_TO_FLASH.md](HOW_TO_FLASH.md)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# scripts/bootstrap.sh
|
# bootstrap.sh
|
||||||
# Уровень 0: устанавливает just (если отсутствует), затем передаёт управление
|
# Уровень 0: устанавливает just (если отсутствует), затем передаёт управление
|
||||||
# just bootstrap для полной инициализации окружения.
|
# just host::bootstrap для полной инициализации окружения.
|
||||||
#
|
#
|
||||||
# Поддерживаемые платформы:
|
# Поддерживаемые платформы:
|
||||||
# Linux — bash (native)
|
# Linux — bash (native)
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# Windows — Git Bash (поставляется вместе с git)
|
# Windows — Git Bash (поставляется вместе с git)
|
||||||
#
|
#
|
||||||
# Требования: bash >= 4, curl (Linux/macOS) или winget (Windows)
|
# Требования: bash >= 4, curl (Linux/macOS) или winget (Windows)
|
||||||
# Запуск: ./scripts/bootstrap.sh
|
# Запуск: ./bootstrap.sh
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
|
@ -23,18 +23,17 @@ YELLOW="\033[1;33m"
|
||||||
GREEN="\033[0;32m"
|
GREEN="\033[0;32m"
|
||||||
RESET="\033[0m"
|
RESET="\033[0m"
|
||||||
|
|
||||||
info() { echo -e " ${BOLD}${*}${RESET}"; }
|
info() { echo -e " ${BOLD}${*}${RESET}"; }
|
||||||
success() { echo -e " ${GREEN}✅ ${*}${RESET}"; }
|
success() { echo -e " ${GREEN}✅ ${*}${RESET}"; }
|
||||||
warn() { echo -e " ${YELLOW}⚠️ ${*}${RESET}"; }
|
warn() { echo -e " ${YELLOW}⚠️ ${*}${RESET}"; }
|
||||||
error() { echo -e " ${RED}❌ ${*}${RESET}"; }
|
error() { echo -e " ${RED}❌ ${*}${RESET}"; }
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}=== TFT Firmware — Bootstrap ===${RESET}"
|
echo -e "${BOLD}=== Project Bootstrap ===${RESET}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 1. Определить платформу
|
# 1. Определить платформу
|
||||||
# uname на Git Bash: MINGW64_NT-10.0-19045, MSYS_NT-..., CYGWIN_NT-...
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
_uname="$(uname -s)"
|
_uname="$(uname -s)"
|
||||||
case "${_uname}" in
|
case "${_uname}" in
|
||||||
|
|
@ -52,14 +51,12 @@ echo ""
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 2. Сравнение semver без sort -V (недоступен в Git Bash)
|
# 2. Сравнение semver без sort -V (недоступен в Git Bash)
|
||||||
# Возвращает 0 если $1 >= $2
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
semver_ge() {
|
semver_ge() {
|
||||||
local a="$1" b="$2"
|
local a="$1" b="$2"
|
||||||
local a1 a2 a3 b1 b2 b3
|
local a1 a2 a3 b1 b2 b3
|
||||||
IFS='.' read -r a1 a2 a3 <<< "${a}"
|
IFS='.' read -r a1 a2 a3 <<< "${a}"
|
||||||
IFS='.' read -r b1 b2 b3 <<< "${b}"
|
IFS='.' read -r b1 b2 b3 <<< "${b}"
|
||||||
# Убрать нечисловые суффиксы (1.36.0-beta -> обнулить суффикс)
|
|
||||||
a1="${a1//[^0-9]/}"; a2="${a2//[^0-9]/}"; a3="${a3//[^0-9]/}"
|
a1="${a1//[^0-9]/}"; a2="${a2//[^0-9]/}"; a3="${a3//[^0-9]/}"
|
||||||
b1="${b1//[^0-9]/}"; b2="${b2//[^0-9]/}"; b3="${b3//[^0-9]/}"
|
b1="${b1//[^0-9]/}"; b2="${b2//[^0-9]/}"; b3="${b3//[^0-9]/}"
|
||||||
|
|
||||||
|
|
@ -98,18 +95,18 @@ install_just_macos() {
|
||||||
}
|
}
|
||||||
|
|
||||||
install_just_windows() {
|
install_just_windows() {
|
||||||
# Предпочитаем winget -- кладёт just.exe в системный PATH автоматически
|
|
||||||
if command -v winget &>/dev/null; then
|
if command -v winget &>/dev/null; then
|
||||||
info "Installing just via winget..."
|
info "Installing just via winget..."
|
||||||
winget install --id Casey.Just \
|
winget install --id Casey.Just \
|
||||||
--accept-package-agreements --accept-source-agreements || {
|
--accept-package-agreements --accept-source-agreements || {
|
||||||
error "winget install failed."
|
error "winget install failed."
|
||||||
echo " Run manually in PowerShell: winget install --id Casey.Just"
|
echo " Run manually in PowerShell: winget install --id Casey.Just"
|
||||||
echo " Then restart Git Bash and re-run: ./scripts/bootstrap.sh"
|
echo " Then restart Git Bash and re-run: ./bootstrap.sh"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
warn "Restart Git Bash so the new PATH from winget takes effect,"
|
warn "Restart Git Bash so the new PATH from winget takes effect,"
|
||||||
warn "then re-run: ./scripts/bootstrap.sh"
|
warn "then re-run: ./bootstrap.sh"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
error "winget not found."
|
error "winget not found."
|
||||||
|
|
@ -150,8 +147,8 @@ if [[ "${JUST_OK}" == "false" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 5. Передать управление just bootstrap
|
# 5. Передать управление just host::bootstrap для дальнейшей настройки рабочего окружения
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
info "Delegating to: just bootstrap"
|
info "Delegating to: just host::bootstrap"
|
||||||
echo ""
|
echo ""
|
||||||
exec just bootstrap "$@"
|
exec just host::bootstrap "$@"
|
||||||
257
docs/DEV_ARCH.md
257
docs/DEV_ARCH.md
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
**Devcontainer** — всё что касается кода: сборка, статический анализ,
|
**Devcontainer** — всё что касается кода: сборка, статический анализ,
|
||||||
форматирование, host-тесты, подготовка HAB-образов. Разработчик проводит
|
форматирование, host-тесты, подготовка HAB-образов. Разработчик проводит
|
||||||
здесь большую часть времени. Управляется через VSCode tasks и `scripts/build.just`.
|
здесь большую часть времени. Управляется через VSCode tasks и модуль `just build::`.
|
||||||
|
|
||||||
**Хост** — всё что касается железа: прошивка платы через USB, отладка
|
**Хост** — всё что касается железа: прошивка платы через USB, отладка
|
||||||
через JLink/probe-rs. Управляется через корневой `Justfile`.
|
через JLink/probe-rs. Управляется через модуль `just host::`.
|
||||||
|
|
||||||
Такое разделение решает несколько проблем: USB-устройства не требуют
|
Такое разделение решает несколько проблем: USB-устройства не требуют
|
||||||
проброса в контейнер; оба разработчика работают в идентичных условиях;
|
проброса в контейнер; оба разработчика работают в идентичных условиях;
|
||||||
|
|
@ -30,10 +30,11 @@ CI использует те же команды что и локальная р
|
||||||
ПК разработчика
|
ПК разработчика
|
||||||
│
|
│
|
||||||
├── Хост (Linux / macOS / Windows + Git Bash)
|
├── Хост (Linux / macOS / Windows + Git Bash)
|
||||||
│ ├── just ← запуск задач хостового уровня
|
│ ├── just ← запуск задач хостового уровня (just host::*)
|
||||||
│ ├── docker ← управление devcontainer
|
│ ├── docker ← управление devcontainer
|
||||||
│ ├── git ← работа с репозиторием
|
│ ├── git ← работа с репозиторием
|
||||||
│ ├── uv + spsdk ← прошивка платы (flash_usb.py, sdphost, blhost)
|
│ ├── uv + spsdk ← прошивка платы (flash_usb.py, sdphost, blhost)
|
||||||
|
│ │ venv: tools/host/.venv-host
|
||||||
│ ├── JLinkGDBServer / probe-rs ← сервер отладки (USB → TCP :2331)
|
│ ├── JLinkGDBServer / probe-rs ← сервер отладки (USB → TCP :2331)
|
||||||
│ └── VSCode ← IDE (Dev Containers extension)
|
│ └── VSCode ← IDE (Dev Containers extension)
|
||||||
│
|
│
|
||||||
|
|
@ -45,8 +46,9 @@ CI использует те же команды что и локальная р
|
||||||
│ ├── clang-tidy-17 ← статический анализ
|
│ ├── clang-tidy-17 ← статический анализ
|
||||||
│ ├── clang-format-17 ← форматирование кода
|
│ ├── clang-format-17 ← форматирование кода
|
||||||
│ ├── cmake-format ← форматирование CMakeLists
|
│ ├── cmake-format ← форматирование CMakeLists
|
||||||
│ ├── just ← запуск задач внутри контейнера
|
│ ├── just ← запуск задач внутри контейнера (just build::*)
|
||||||
│ ├── uv + spsdk ← сборка HAB-образов (только nxpimage)
|
│ ├── uv + spsdk ← сборка HAB-образов (только nxpimage)
|
||||||
|
│ │ venv: tools/host/.venv-container
|
||||||
│ └── Unity + fff ← фреймворки host-тестов
|
│ └── Unity + fff ← фреймворки host-тестов
|
||||||
│
|
│
|
||||||
└── Плата TFT (IMXRT1052) — на столе у разработчика
|
└── Плата TFT (IMXRT1052) — на столе у разработчика
|
||||||
|
|
@ -59,18 +61,18 @@ CI использует те же команды что и локальная р
|
||||||
|
|
||||||
## 3. Что устанавливается и где
|
## 3. Что устанавливается и где
|
||||||
|
|
||||||
| Инструмент | Хост | Devcontainer | Сервер |
|
| Инструмент | Хост | Devcontainer | Сервер |
|
||||||
|---|---|---|---|
|
| ------------------ | --------- | ------------ | --------- |
|
||||||
| `just` | ✅ | ✅ Dockerfile | ✅ |
|
| `just` | ✅ | ✅ Dockerfile | ✅ |
|
||||||
| `docker` | ✅ | — | — |
|
| `docker` | ✅ | — | — |
|
||||||
| `git` | ✅ | ✅ | ✅ |
|
| `git` | ✅ | ✅ | ✅ |
|
||||||
| `uv` | ✅ | ✅ Dockerfile | ✅ |
|
| `uv` | ✅ | ✅ Dockerfile | ✅ |
|
||||||
| `spsdk` | ✅ uv sync | ✅ uv sync | ✅ uv sync |
|
| `spsdk` | ✅ uv sync | ✅ uv sync | ✅ uv sync |
|
||||||
| ARM GCC toolchain | — | ✅ | — |
|
| ARM GCC toolchain | — | ✅ | — |
|
||||||
| `cmake` / `ninja` | — | ✅ | — |
|
| `cmake` / `ninja` | — | ✅ | — |
|
||||||
| `clang` / `clangd` | — | ✅ | — |
|
| `clang` / `clangd` | — | ✅ | — |
|
||||||
| Unity / fff | — | ✅ | — |
|
| Unity / fff | — | ✅ | — |
|
||||||
| JLink / probe-rs | ✅ | — | — |
|
| JLink / probe-rs | ✅ | — | — |
|
||||||
|
|
||||||
`spsdk` присутствует везде, но с разными ролями:
|
`spsdk` присутствует везде, но с разными ролями:
|
||||||
|
|
||||||
|
|
@ -81,16 +83,21 @@ CI использует те же команды что и локальная р
|
||||||
Версия `spsdk` зафиксирована в `tools/host/uv.lock` — все три места
|
Версия `spsdk` зафиксирована в `tools/host/uv.lock` — все три места
|
||||||
используют одну и ту же версию.
|
используют одну и ту же версию.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Структура репозитория (automation-часть)
|
## 4. Структура репозитория (automation-часть)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/
|
/
|
||||||
├── Justfile ← хост: прошивка, setup, pipeline
|
├── Justfile ← корневой оркестратор; модули: build, host, ci
|
||||||
|
├── just/
|
||||||
|
│ ├── build.just ← devcontainer: сборка, тесты, HAB
|
||||||
|
│ ├── host.just ← хост: прошивка, bootstrap, HIL
|
||||||
|
│ └── ci.just ← CI/CD пайплайны
|
||||||
├── scripts/
|
├── scripts/
|
||||||
│ └── bootstrap.sh ← уровень 0: just → just bootstrap
|
│ └── bootstrap.sh ← уровень 0: just → just host::bootstrap
|
||||||
│ └── build.just ← devcontainer: сборка, тесты, HAB
|
|
||||||
├── .devcontainer/
|
├── .devcontainer/
|
||||||
│ ├── Dockerfile
|
│ ├── Dockerfile
|
||||||
│ └── devcontainer.json
|
│ └── devcontainer.json
|
||||||
|
|
@ -110,7 +117,7 @@ CI использует те же команды что и локальная р
|
||||||
│ ├── pyproject.toml
|
│ ├── pyproject.toml
|
||||||
│ └── uv.lock
|
│ └── uv.lock
|
||||||
├── .vscode/
|
├── .vscode/
|
||||||
│ └── tasks.json ← UI для build.just (внутри devcontainer)
|
│ └── tasks.json ← UI для just build::* (внутри devcontainer)
|
||||||
├── CMakePresets.json
|
├── CMakePresets.json
|
||||||
├── cmake/
|
├── cmake/
|
||||||
├── sdk/
|
├── sdk/
|
||||||
|
|
@ -119,7 +126,7 @@ CI использует те же команды что и локальная р
|
||||||
├── firmware/
|
├── firmware/
|
||||||
│ ├── test/
|
│ ├── test/
|
||||||
│ ├── bootloader/
|
│ ├── bootloader/
|
||||||
│ └── app/
|
│ └── tft_app/
|
||||||
└── tests/ ← host-тесты (Unity + fff)
|
└── tests/ ← host-тесты (Unity + fff)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -129,17 +136,17 @@ CI использует те же команды что и локальная р
|
||||||
|
|
||||||
### 5.1 Предварительные требования
|
### 5.1 Предварительные требования
|
||||||
|
|
||||||
| Платформа | Что нужно до bootstrap |
|
| Платформа | Что нужно до bootstrap |
|
||||||
|---|---|
|
| --------- | ----------------------------------------------------------- |
|
||||||
| Linux | `docker`, `git`, `curl` |
|
| Linux | `docker`, `git`, `curl` |
|
||||||
| macOS | Docker Desktop, `git` (Xcode CLT) |
|
| macOS | Docker Desktop, `git` (Xcode CLT) |
|
||||||
| Windows | Docker Desktop, Git for Windows → **использовать Git Bash** |
|
| Windows | Docker Desktop, Git for Windows → **использовать Git Bash** |
|
||||||
|
|
||||||
### 5.2 Единственная команда для нового разработчика
|
### 5.2 Единственная команда для нового разработчика
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <repo-url> && cd <repo>
|
git clone <repo-url> && cd <repo>
|
||||||
./scripts/bootstrap.sh
|
./bootstrap.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.3 Что делает bootstrap
|
### 5.3 Что делает bootstrap
|
||||||
|
|
@ -151,15 +158,15 @@ bootstrap.sh (уровень 0)
|
||||||
│ uname: MINGW64_NT-... → windows, Linux → linux, Darwin → macos
|
│ uname: MINGW64_NT-... → windows, Linux → linux, Darwin → macos
|
||||||
│
|
│
|
||||||
├── проверить just (semver без sort -V — работает в Git Bash)
|
├── проверить just (semver без sort -V — работает в Git Bash)
|
||||||
│ < 1.27.0 или отсутствует:
|
│ < 1.36.0 или отсутствует:
|
||||||
│ Linux/macOS → curl | bash → ~/.local/bin/just
|
│ Linux/macOS → curl | bash → ~/.local/bin/just
|
||||||
│ Windows → winget install --id Casey.Just
|
│ Windows → winget install --id Casey.Just
|
||||||
│ (перезапустить Git Bash после установки)
|
│ (перезапустить Git Bash после установки)
|
||||||
│
|
│
|
||||||
└── exec just bootstrap
|
└── exec just host::bootstrap
|
||||||
│
|
│
|
||||||
├── [1/3] check-deps
|
├── [1/3] check-deps
|
||||||
│ just >= 1.27.0 · uv >= 0.4.0 · docker >= 24.0.0
|
│ just >= 1.36.0 · uv >= 0.4.0 · docker >= 24.0.0
|
||||||
│ платформо-зависимые подсказки при ошибках
|
│ платформо-зависимые подсказки при ошибках
|
||||||
│
|
│
|
||||||
├── [2/3] setup-udev (только Linux)
|
├── [2/3] setup-udev (только Linux)
|
||||||
|
|
@ -170,7 +177,7 @@ bootstrap.sh (уровень 0)
|
||||||
│ требует re-login · на macOS/Windows пропускается
|
│ требует re-login · на macOS/Windows пропускается
|
||||||
│
|
│
|
||||||
└── [3/3] setup-tools
|
└── [3/3] setup-tools
|
||||||
uv sync в tools/host/
|
uv sync в tools/host/ (venv: .venv-host на хосте)
|
||||||
SHA-256 uv.lock кэшируется в .cache/
|
SHA-256 uv.lock кэшируется в .cache/
|
||||||
повторный вызов мгновенный если lockfile не изменился
|
повторный вызов мгновенный если lockfile не изменился
|
||||||
```
|
```
|
||||||
|
|
@ -184,7 +191,7 @@ bootstrap.sh (уровень 0)
|
||||||
`postCreateCommand` выполняется автоматически при поднятии контейнера:
|
`postCreateCommand` выполняется автоматически при поднятии контейнера:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd tools/host && uv sync &&
|
cd tools/host && uv sync && # venv: .venv-container
|
||||||
cd ../.. &&
|
cd ../.. &&
|
||||||
cmake --preset host-debug &&
|
cmake --preset host-debug &&
|
||||||
cmake --preset Debug
|
cmake --preset Debug
|
||||||
|
|
@ -199,21 +206,21 @@ cmake --preset Debug
|
||||||
|
|
||||||
### 6.1 Три подпроекта
|
### 6.1 Три подпроекта
|
||||||
|
|
||||||
| Прошивка | Boot-стратегия | DCD | Назначение |
|
| Прошивка | Boot-стратегия | DCD | Назначение |
|
||||||
|---|---|---|---|
|
| --------------- | -------------------- | ---- | ---------------------------------------- |
|
||||||
| `firmware_test` | XIP из Flash | ✅ | Входной контроль, тестирование периферии |
|
| `firmware_test` | XIP из Flash | ✅ | Входной контроль, тестирование периферии |
|
||||||
| `bootloader` | Копирование в ITCM | ❌ | Загрузчик, не использует SDRAM |
|
| `bootloader` | Копирование в ITCM | ❌ | Загрузчик, не использует SDRAM |
|
||||||
| `app` | XIP + буферы в SDRAM | ✅ | Основное приложение (FreeRTOS, LCDIF) |
|
| `tft_app` | XIP + буферы в SDRAM | ✅ | Основное приложение (FreeRTOS, LCDIF) |
|
||||||
|
|
||||||
### 6.2 Матрица сборки
|
### 6.2 Матрица сборки
|
||||||
|
|
||||||
Каждый проект собирается в двух режимах:
|
Каждый проект собирается в двух режимах:
|
||||||
|
|
||||||
| | Debug | Release |
|
| | Debug | Release |
|
||||||
|---|---|---|
|
| --------------- | ------------------- | ------------------ |
|
||||||
| `firmware_test` | разработка, отладка | HAB для сервера |
|
| `firmware_test` | разработка, отладка | HAB для сервера |
|
||||||
| `bootloader` | отладка загрузчика | финальная прошивка |
|
| `bootloader` | отладка загрузчика | финальная прошивка |
|
||||||
| `app` | отладка приложения | финальная прошивка |
|
| `tft_app` | отладка приложения | финальная прошивка |
|
||||||
|
|
||||||
### 6.3 CMake пресеты
|
### 6.3 CMake пресеты
|
||||||
|
|
||||||
|
|
@ -235,7 +242,7 @@ buildPresets (host):
|
||||||
```bash
|
```bash
|
||||||
0x60000000 FCB — Flash Config Block 512 байт (пишет Flashloader)
|
0x60000000 FCB — Flash Config Block 512 байт (пишет Flashloader)
|
||||||
0x60001000 IVT + BDT ← начало HAB-образа
|
0x60001000 IVT + BDT ← начало HAB-образа
|
||||||
0x60001040 DCD — инициализация SDRAM ~1088 байт (firmware_test, app)
|
0x60001040 DCD — инициализация SDRAM ~1088 байт (firmware_test, tft_app)
|
||||||
0x60003000 Код прошивки (.text, .data…)
|
0x60003000 Код прошивки (.text, .data…)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -245,17 +252,17 @@ buildPresets (host):
|
||||||
|
|
||||||
### 7.1 Карта задач по контекстам
|
### 7.1 Карта задач по контекстам
|
||||||
|
|
||||||
| Задача | Где |
|
| Задача | Где |
|
||||||
|---|---|
|
| -------------------------------------- | -------------------------- |
|
||||||
| Написание кода, clangd, форматирование | devcontainer |
|
| Написание кода, clangd, форматирование | devcontainer |
|
||||||
| Статический анализ (clang-tidy) | devcontainer |
|
| Статический анализ (clang-tidy) | devcontainer |
|
||||||
| Host-тесты (Unity + fff) | devcontainer |
|
| Host-тесты (Unity + fff) | devcontainer |
|
||||||
| Сборка ARM firmware (ELF) | devcontainer |
|
| Сборка ARM firmware (ELF) | devcontainer |
|
||||||
| Подготовка HAB-образов (nxpimage) | devcontainer |
|
| Подготовка HAB-образов (nxpimage) | devcontainer |
|
||||||
| Прошивка платы через USB | **хост** |
|
| Прошивка платы через USB | **хост** |
|
||||||
| Отладка — GDB-сервер (JLink/probe-rs) | **хост** |
|
| Отладка — GDB-сервер (JLink/probe-rs) | **хост** |
|
||||||
| Отладка — GDB-клиент | devcontainer → хост по TCP |
|
| Отладка — GDB-клиент | devcontainer → хост по TCP |
|
||||||
| Target-тесты (управление стендом) | **хост** |
|
| Target-тесты (управление стендом) | **хост** |
|
||||||
|
|
||||||
### 7.2 Типичная сессия разработки
|
### 7.2 Типичная сессия разработки
|
||||||
|
|
||||||
|
|
@ -265,7 +272,7 @@ buildPresets (host):
|
||||||
├── писать код
|
├── писать код
|
||||||
│
|
│
|
||||||
├── Ctrl+Shift+P → "Run Task" → 🧪 Host Tests (Debug)
|
├── Ctrl+Shift+P → "Run Task" → 🧪 Host Tests (Debug)
|
||||||
│ или в терминале: just --justfile just/build.just test-host
|
│ или в терминале: just build::test-host
|
||||||
│
|
│
|
||||||
├── Ctrl+Shift+P → "Run Task" → 🔨 Build → firmware-test · debug
|
├── Ctrl+Shift+P → "Run Task" → 🔨 Build → firmware-test · debug
|
||||||
│ → build/Debug/firmware/test/firmware_test.elf
|
│ → build/Debug/firmware/test/firmware_test.elf
|
||||||
|
|
@ -277,22 +284,22 @@ buildPresets (host):
|
||||||
│
|
│
|
||||||
├── just flash firmware_test debug ← прошить отладочный образ
|
├── just flash firmware_test debug ← прошить отладочный образ
|
||||||
│ или
|
│ или
|
||||||
├── just flash-ram firmware_test debug ← загрузить в RAM (быстро, без износа Flash)
|
├── just host::flash-ram firmware_test debug ← загрузить в RAM (быстро, без износа Flash)
|
||||||
│
|
│
|
||||||
└── F5 в VSCode → отладка через JLink
|
└── F5 в VSCode → отладка через JLink
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7.3 VSCode Tasks (внутри devcontainer)
|
### 7.3 VSCode Tasks (внутри devcontainer)
|
||||||
|
|
||||||
| Таск | Input 1 | Input 2 | Команда |
|
| Таск | Input 1 | Input 2 | Команда |
|
||||||
|---|---|---|---|
|
| ---------------------- | ------- | ------------- | ------------------------------------ |
|
||||||
| 🔨 Build | project | debug/release | `just build-<project>-<type>` |
|
| 🔨 Build | project | debug/release | `just build::build-<project>-<type>` |
|
||||||
| 🧪 Host Tests (Debug) | — | — | `just test-host` |
|
| 🧪 Host Tests (Debug) | — | — | `just build::test-host` |
|
||||||
| 🧪 Host Tests (Release) | — | — | `just test-host-release` |
|
| 🧪 Host Tests (Release) | — | — | `just build::test-host-release` |
|
||||||
| 📦 HAB Image | project | debug/release | `just hab-<project>-<type>` |
|
| 📦 HAB Image | project | debug/release | `just build::hab-<project>-<type>` |
|
||||||
| 📦 HAB All (Debug) | — | — | `just hab-all-debug` |
|
| 📦 HAB All (Debug) | — | — | `just build::hab-all-debug` |
|
||||||
| 📦 HAB All (Release) | — | — | `just hab-all-release` |
|
| 📦 HAB All (Release) | — | — | `just build::hab-all-release` |
|
||||||
| 🗑️ Clean | — | — | `just clean` |
|
| 🗑️ Clean | — | — | `just build::clean` |
|
||||||
|
|
||||||
Таски «Build» и «HAB Image» запрашивают два input последовательно:
|
Таски «Build» и «HAB Image» запрашивают два input последовательно:
|
||||||
сначала проект (`firmware-test / bootloader / app / all`),
|
сначала проект (`firmware-test / bootloader / app / all`),
|
||||||
|
|
@ -309,7 +316,7 @@ buildPresets (host):
|
||||||
2. Reset
|
2. Reset
|
||||||
3. Подключить USB к хосту
|
3. Подключить USB к хосту
|
||||||
→ плата определяется как VID:PID = 1FC9:0130
|
→ плата определяется как VID:PID = 1FC9:0130
|
||||||
4. Выполнить нужный just flash-* рецепт
|
4. Выполнить нужный just host::flash-* рецепт
|
||||||
5. После прошивки: BOOT_MOD_1 → GND, Reset
|
5. После прошивки: BOOT_MOD_1 → GND, Reset
|
||||||
→ плата стартует из Flash
|
→ плата стартует из Flash
|
||||||
```
|
```
|
||||||
|
|
@ -318,23 +325,24 @@ buildPresets (host):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Основной рецепт (project × type)
|
# Основной рецепт (project × type)
|
||||||
just flash firmware_test debug # разработка — итерации с отладчиком
|
just host::flash firmware_test debug # разработка — итерации с отладчиком
|
||||||
just flash firmware_test release # проверить как будет на сервере
|
just host::flash firmware_test release # проверить как будет на сервере
|
||||||
just flash bootloader debug
|
just host::flash bootloader debug
|
||||||
just flash bootloader release
|
just host::flash bootloader release
|
||||||
just flash app debug
|
just host::flash tft_app debug
|
||||||
just flash app release
|
just host::flash tft_app release
|
||||||
|
|
||||||
# TODO: Загрузка в RAM — без записи во Flash, мгновенный старт
|
# Загрузка в RAM — без записи во Flash, мгновенный старт
|
||||||
# Удобно для частых итераций: не изнашивает Flash, не нужен BOOT_MOD переключатель
|
# Удобно для частых итераций: не изнашивает Flash
|
||||||
just flash-ram firmware_test # default: debug
|
just host::flash-ram firmware_test # default: debug
|
||||||
just flash-ram firmware_test debug
|
just host::flash-ram firmware_test debug
|
||||||
just flash-ram app release
|
just host::flash-ram tft_app release
|
||||||
|
|
||||||
# TODO: Быстрые псевдонимы
|
# Быстрые псевдонимы (из корневого Justfile)
|
||||||
just flash-test-debug # = just flash firmware_test debug
|
just flash # = just host::flash-test-debug
|
||||||
just flash-test-release # = just flash firmware_test release
|
just host::flash-test-debug
|
||||||
just flash-production # bootloader release + app release
|
just host::flash-test-release
|
||||||
|
just host::flash-production # bootloader release + tft_app release
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.3 Что происходит внутри flash_usb.py
|
### 8.3 Что происходит внутри flash_usb.py
|
||||||
|
|
@ -403,7 +411,7 @@ Devcontainer
|
||||||
Фреймворк: Unity + fff
|
Фреймворк: Unity + fff
|
||||||
Пресеты: host-debug / host-release
|
Пресеты: host-debug / host-release
|
||||||
Компилятор: системный clang-17 (не ARM GCC)
|
Компилятор: системный clang-17 (не ARM GCC)
|
||||||
Запуск: just --justfile just/build.just test-host
|
Запуск: just build::test-host
|
||||||
Результат: JUnit XML → VSCode CTest Lab + GitLab CI
|
Результат: JUnit XML → VSCode CTest Lab + GitLab CI
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -439,17 +447,17 @@ Devcontainer
|
||||||
feature-ветка
|
feature-ветка
|
||||||
│
|
│
|
||||||
├── код в devcontainer
|
├── код в devcontainer
|
||||||
│ 🧪 Host Tests ← зелёные?
|
│ just build::test-host ← зелёные?
|
||||||
│ 🔨 Build firmware-test debug ← компилируется?
|
│ just build::build-firmware-test-debug ← компилируется?
|
||||||
│
|
│
|
||||||
├── проверка на железе
|
├── проверка на железе
|
||||||
│ 📦 HAB Image → firmware-test · debug
|
│ just build::hab-firmware-test-debug
|
||||||
│ just flash-test-debug ← прошить
|
│ just flash ← прошить (алиас flash-test-debug)
|
||||||
│ target-тесты со стендом ← периферия работает?
|
│ target-тесты со стендом ← периферия работает?
|
||||||
│
|
│
|
||||||
├── подготовка к MR
|
├── подготовка к MR
|
||||||
│ 📦 HAB All (Release) ← финальные образы
|
│ just build::hab-all-release ← финальные образы
|
||||||
│ just flash firmware_test release ← убедиться что release работает
|
│ just host::flash firmware_test release ← убедиться что release работает
|
||||||
│
|
│
|
||||||
└── Merge Request → GitLab
|
└── Merge Request → GitLab
|
||||||
[CI pipeline — отдельная тема]
|
[CI pipeline — отдельная тема]
|
||||||
|
|
@ -457,29 +465,29 @@ feature-ветка
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
Производственный сервер
|
Производственный сервер
|
||||||
just incoming → firmware_test release → HIL
|
just host::incoming → firmware_test release → HIL
|
||||||
just production → bootloader + app release
|
just host::production → bootloader + tft_app release
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Обновление зависимостей
|
## 12. Обновление зависимостей
|
||||||
|
|
||||||
### spsdk (на хосте разработчика)
|
### spsdk
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just upgrade-tools 3.8.0
|
just host::upgrade-tools 3.8.0
|
||||||
git add tools/host/uv.lock tools/host/pyproject.toml
|
git add tools/host/uv.lock tools/host/pyproject.toml
|
||||||
git commit -m "chore: upgrade spsdk to 3.8.0"
|
git commit -m "chore: upgrade spsdk to 3.8.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
После этого у всех разработчиков и в контейнере обновится автоматически
|
После этого у всех разработчиков и в контейнере обновится автоматически
|
||||||
при следующем `just setup-tools` / `uv sync`.
|
при следующем `just host::setup-tools` / `uv sync`.
|
||||||
|
|
||||||
### just в Dockerfile
|
### just в Dockerfile
|
||||||
|
|
||||||
```dockerfile
|
```dockerfile
|
||||||
ARG JUST_VERSION=1.40.0 # .devcontainer/Dockerfile — единственное место
|
ARG JUST_VERSION=1.36.0 # .devcontainer/Dockerfile — единственное место
|
||||||
```
|
```
|
||||||
|
|
||||||
### ARM toolchain
|
### ARM toolchain
|
||||||
|
|
@ -494,7 +502,7 @@ ARG TOOLCHAIN_VERSION=14.2.rel1 # .devcontainer/Dockerfile
|
||||||
### После git pull если изменился uv.lock
|
### После git pull если изменился uv.lock
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just setup-tools # автоматически обнаружит изменение и выполнит uv sync
|
just host::setup-tools # автоматически обнаружит изменение и выполнит uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -509,12 +517,12 @@ just setup-tools # автоматически обнаружит измене
|
||||||
— только теггированные релизы, прошедшие CI
|
— только теггированные релизы, прошедшие CI
|
||||||
|
|
||||||
Сценарий входного контроля новой платы:
|
Сценарий входного контроля новой платы:
|
||||||
1. just incoming
|
1. just host::incoming
|
||||||
└── flash firmware_test release → HIL-тесты периферии
|
└── flash firmware_test release → HIL-тесты периферии
|
||||||
2. Тесты пройдены:
|
2. Тесты пройдены:
|
||||||
just production
|
just host::production
|
||||||
├── flash bootloader release
|
├── flash bootloader release
|
||||||
└── flash app release
|
└── flash tft_app release
|
||||||
|
|
||||||
Установлено: just · uv + spsdk · git
|
Установлено: just · uv + spsdk · git
|
||||||
НЕ установлено: docker · cmake · компилятор · ARM toolchain
|
НЕ установлено: docker · cmake · компилятор · ARM toolchain
|
||||||
|
|
@ -526,41 +534,42 @@ just setup-tools # автоматически обнаружит измене
|
||||||
|
|
||||||
## Приложение А: минимальные версии
|
## Приложение А: минимальные версии
|
||||||
|
|
||||||
| Инструмент | Версия | Причина |
|
| Инструмент | Версия | Причина |
|
||||||
|---|---|---|
|
| ------------ | --------- | ------------------------------------------------------------ |
|
||||||
| `just` | 1.27.0 | поддержка `[group()]` |
|
| `just` | 1.36.0 | поддержка `mod` с кастомным путём (`mod host 'just/host.just'`) |
|
||||||
| `uv` | 0.4.0 | стабильный lockfile формат |
|
| `uv` | 0.4.0 | стабильный lockfile формат |
|
||||||
| `docker` | 24.0.0 | Compose v2, `--build-arg` |
|
| `docker` | 24.0.0 | Compose v2, `--build-arg` |
|
||||||
| `spsdk` | 3.7.x | совместимость с HAB yaml-форматом |
|
| `spsdk` | 3.7.x | совместимость с HAB yaml-форматом |
|
||||||
| ARM GCC | 13.3.rel1 | C11, LTO, текущий SDK |
|
| ARM GCC | 13.3.rel1 | C11, LTO, текущий SDK |
|
||||||
| clang/clangd | 17 | поддержка `If:` в `.clangd` |
|
| clang/clangd | 17 | поддержка `If:` в `.clangd` |
|
||||||
|
|
||||||
## Приложение Б: быстрая шпаргалка
|
## Приложение Б: быстрая шпаргалка
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# ── Первый запуск ──────────────────────────────────────────────
|
# ── Первый запуск ──────────────────────────────────────────────
|
||||||
./scripts/bootstrap.sh # инициализация хоста
|
./bootstrap.sh # инициализация хоста
|
||||||
# VSCode → Reopen in Container
|
# VSCode → Reopen in Container
|
||||||
|
|
||||||
# ── Внутри devcontainer (терминал VSCode) ──────────────────────
|
# ── Внутри devcontainer (терминал VSCode) ──────────────────────
|
||||||
just --justfile just/build.just test-host
|
just build::test-host
|
||||||
just --justfile just/build.just build-firmware-test-debug
|
just build::build-firmware-test-debug
|
||||||
just --justfile just/build.just build-app-release
|
just build::build-tft-app-release
|
||||||
just --justfile just/build.just hab-firmware-test-debug
|
just build::hab-firmware-test-debug
|
||||||
just --justfile just/build.just hab-all-release
|
just build::hab-all-release
|
||||||
just --justfile just/build.just clean
|
just build::clean
|
||||||
|
|
||||||
# ── Хостовый терминал — прошивка ───────────────────────────────
|
# ── Хостовый терминал — прошивка ───────────────────────────────
|
||||||
just flash firmware_test debug # во Flash
|
just flash # алиас: firmware_test debug
|
||||||
just flash firmware_test release
|
just host::flash firmware_test debug # во Flash
|
||||||
just flash bootloader release
|
just host::flash firmware_test release
|
||||||
just flash app release
|
just host::flash bootloader release
|
||||||
just flash-ram firmware_test # в RAM (быстро, без износа Flash)
|
just host::flash tft_app release
|
||||||
just flash-production # bootloader + app release
|
just host::flash-ram firmware_test # в RAM (быстро, без износа Flash)
|
||||||
|
just host::flash-production # bootloader + tft_app release
|
||||||
|
|
||||||
# ── Хостовый терминал — обслуживание ───────────────────────────
|
# ── Хостовый терминал — обслуживание ───────────────────────────
|
||||||
just scan # найти NXP USB-устройства
|
just host::scan # найти NXP USB-устройства
|
||||||
just sdp-status # проверить BootROM
|
just host::sdp-status # проверить BootROM
|
||||||
just setup-tools # обновить spsdk после git pull
|
just host::setup-tools # обновить spsdk после git pull
|
||||||
just check-deps # проверить версии инструментов
|
just host::check-deps # проверить версии инструментов
|
||||||
```
|
```
|
||||||
|
|
@ -30,7 +30,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
BOARD_Init();
|
BOARD_Init();
|
||||||
GPIO_PinWrite(BOARD_INITPINS_UserLed1_PORT, BOARD_INITPINS_UserLed1_PIN, 0);
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@
|
||||||
# Рабочая директория — корень репозитория (не scripts/).
|
# Рабочая директория — корень репозитория (не scripts/).
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
set working-directory := ".."
|
# === Импорт общих переменных ===
|
||||||
|
TOOLS_DIR := env('TOOLS_DIR', justfile_directory() / 'tools/host')
|
||||||
|
BUILD_DIR := env('BUILD_DIR', justfile_directory() / 'build')
|
||||||
|
|
||||||
TOOLS_DIR := "tools/host"
|
set working-directory := '..'
|
||||||
BUILD_DIR := "build"
|
|
||||||
|
|
||||||
_default:
|
_default:
|
||||||
@just --list --justfile scripts/build.just --unsorted
|
@just --list --justfile scripts/build.just --unsorted
|
||||||
|
|
@ -22,7 +23,7 @@ _default:
|
||||||
# app × debug / release
|
# app × debug / release
|
||||||
# all × debug / release (все проекты сразу, для CI)
|
# all × debug / release (все проекты сразу, для CI)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
# Приватные рецепты для configure (не показываются в --list)
|
||||||
[private]
|
[private]
|
||||||
_configure-debug:
|
_configure-debug:
|
||||||
cmake --preset Debug
|
cmake --preset Debug
|
||||||
|
|
@ -68,7 +69,7 @@ build-all-release: _configure-release
|
||||||
cmake --build --preset all-release
|
cmake --build --preset all-release
|
||||||
|
|
||||||
# ── утилиты ───────────────────────────────────────────────────────────────────
|
# ── утилиты ───────────────────────────────────────────────────────────────────
|
||||||
[group('build')]
|
[group('build'), confirm("Delete build/ directory?")]
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
||||||
|
|
@ -112,7 +113,7 @@ test-host-release: _configure-host-release
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# ── firmware_test ─────────────────────────────────────────────────────────────
|
# ── firmware_test ─────────────────────────────────────────────────────────────
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-firmware-test-debug: build-firmware-test-debug
|
hab-firmware-test-debug: build-firmware-test-debug
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -122,7 +123,7 @@ hab-firmware-test-debug: build-firmware-test-debug
|
||||||
-o "../../../{{BUILD_DIR}}/Debug/firmware_test_hab.bin"
|
-o "../../../{{BUILD_DIR}}/Debug/firmware_test_hab.bin"
|
||||||
echo " ✅ firmware_test_hab.bin (Debug)"
|
echo " ✅ firmware_test_hab.bin (Debug)"
|
||||||
|
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-firmware-test-release: build-firmware-test-release
|
hab-firmware-test-release: build-firmware-test-release
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -133,7 +134,7 @@ hab-firmware-test-release: build-firmware-test-release
|
||||||
echo " ✅ firmware_test_hab.bin (Release)"
|
echo " ✅ firmware_test_hab.bin (Release)"
|
||||||
|
|
||||||
# ── bootloader ───────────────────────────────────────────────────────────────
|
# ── bootloader ───────────────────────────────────────────────────────────────
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-bootloader-debug: build-bootloader-debug
|
hab-bootloader-debug: build-bootloader-debug
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -143,7 +144,7 @@ hab-bootloader-debug: build-bootloader-debug
|
||||||
-o "../../../{{BUILD_DIR}}/Debug/bootloader_hab.bin"
|
-o "../../../{{BUILD_DIR}}/Debug/bootloader_hab.bin"
|
||||||
echo " ✅ bootloader_hab.bin (Debug)"
|
echo " ✅ bootloader_hab.bin (Debug)"
|
||||||
|
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-bootloader-release: build-bootloader-release
|
hab-bootloader-release: build-bootloader-release
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -154,7 +155,7 @@ hab-bootloader-release: build-bootloader-release
|
||||||
echo " ✅ bootloader_hab.bin (Release)"
|
echo " ✅ bootloader_hab.bin (Release)"
|
||||||
|
|
||||||
# ── app ───────────────────────────────────────────────────────────────────────
|
# ── app ───────────────────────────────────────────────────────────────────────
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-app-debug: build-app-debug
|
hab-app-debug: build-app-debug
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -164,7 +165,7 @@ hab-app-debug: build-app-debug
|
||||||
-o "../../../{{BUILD_DIR}}/Debug/app_hab.bin"
|
-o "../../../{{BUILD_DIR}}/Debug/app_hab.bin"
|
||||||
echo " ✅ app_hab.bin (Debug)"
|
echo " ✅ app_hab.bin (Debug)"
|
||||||
|
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-app-release: build-app-release
|
hab-app-release: build-app-release
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
@ -175,27 +176,28 @@ hab-app-release: build-app-release
|
||||||
echo " ✅ app_hab.bin (Release)"
|
echo " ✅ app_hab.bin (Release)"
|
||||||
|
|
||||||
# ── все образы сразу ─────────────────────────────────────────────────────────
|
# ── все образы сразу ─────────────────────────────────────────────────────────
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-all-debug: hab-firmware-test-debug hab-bootloader-debug hab-app-debug
|
hab-all-debug: hab-firmware-test-debug hab-bootloader-debug hab-app-debug
|
||||||
@echo " ✅ All HAB images (Debug) ready"
|
@echo " ✅ All HAB images (Debug) ready"
|
||||||
|
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-all-release: hab-firmware-test-release hab-bootloader-release hab-app-release
|
hab-all-release: hab-firmware-test-release hab-bootloader-release hab-app-release
|
||||||
@echo " ✅ All HAB images (Release) ready"
|
@echo " ✅ All HAB images (Release) ready"
|
||||||
|
|
||||||
# ── верификация образа (для отладки) ─────────────────────────────────────────
|
# ── верификация образа (для отладки) ─────────────────────────────────────────
|
||||||
# Использование: just --justfile just/build.just hab-verify firmware_test debug
|
# Использование: just --justfile just/build.just hab-verify firmware_test debug
|
||||||
[group('flash')]
|
[group('hab_image_gen')]
|
||||||
hab-verify project="firmware_test" type="release":
|
hab-verify project="firmware_test" type="release":
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
ROOT="$(pwd)"
|
||||||
case "{{project}}-{{type}}" in
|
case "{{project}}-{{type}}" in
|
||||||
firmware_test-debug) BIN="{{BUILD_DIR}}/Debug/firmware_test_hab.bin" ;;
|
firmware_test-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/firmware_test_hab.bin" ;;
|
||||||
firmware_test-release) BIN="{{BUILD_DIR}}/Release/firmware_test_hab.bin" ;;
|
firmware_test-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/firmware_test_hab.bin" ;;
|
||||||
bootloader-debug) BIN="{{BUILD_DIR}}/Debug/bootloader_hab.bin" ;;
|
bootloader-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/bootloader_hab.bin" ;;
|
||||||
bootloader-release) BIN="{{BUILD_DIR}}/Release/bootloader_hab.bin" ;;
|
bootloader-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/bootloader_hab.bin" ;;
|
||||||
app-debug) BIN="{{BUILD_DIR}}/Debug/app_hab.bin" ;;
|
app-debug) BIN="${ROOT}/{{BUILD_DIR}}/Debug/app_hab.bin" ;;
|
||||||
app-release) BIN="{{BUILD_DIR}}/Release/app_hab.bin" ;;
|
app-release) BIN="${ROOT}/{{BUILD_DIR}}/Release/app_hab.bin" ;;
|
||||||
*)
|
*)
|
||||||
echo " ❌ Unknown: {{project}}-{{type}}"
|
echo " ❌ Unknown: {{project}}-{{type}}"
|
||||||
echo " Projects: firmware_test, bootloader, app"
|
echo " Projects: firmware_test, bootloader, app"
|
||||||
|
|
@ -203,6 +205,20 @@ hab-verify project="firmware_test" type="release":
|
||||||
exit 1 ;;
|
exit 1 ;;
|
||||||
esac
|
esac
|
||||||
OUT="/tmp/hab_parse_{{project}}_{{type}}.yaml"
|
OUT="/tmp/hab_parse_{{project}}_{{type}}.yaml"
|
||||||
uv run nxpimage hab parse -b "${BIN}" -o "${OUT}"
|
cd "{{TOOLS_DIR}}" && uv run nxpimage hab parse -b "${BIN}" -o "${OUT}"
|
||||||
echo " ✅ ${OUT}"
|
echo " ✅ ${OUT}"
|
||||||
grep -E "(entry|csf|tag)" "${OUT}" || true
|
grep -E "(entry|csf|tag)" "${OUT}" || true
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: quality — линтеры, форматтеры
|
||||||
|
# =============================================================================
|
||||||
|
# TODO: проверять bsp,firmware, modules
|
||||||
|
[group('quality')]
|
||||||
|
lint:
|
||||||
|
echo "TODO!"
|
||||||
|
# clang-tidy -p {{BUILD_DIR}}/Debug src/**/*.c
|
||||||
|
|
||||||
|
[group('quality')]
|
||||||
|
format:
|
||||||
|
echo "TODO!"
|
||||||
|
# clang-format -i src/**/*.{c,h}
|
||||||
53
just/ci.just
Normal file
53
just/ci.just
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
# =============================================================================
|
||||||
|
# ci.just — CI/CD пайплайны
|
||||||
|
# Выполняется в CI-окружении (GitHub Actions, GitLab CI, Jenkins)
|
||||||
|
#
|
||||||
|
# Предполагается что CI работает внутри devcontainer.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# === Импорт общих переменных ===
|
||||||
|
BUILD_DIR := env('BUILD_DIR', justfile_directory() / 'build')
|
||||||
|
set working-directory := '..'
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: ci — полные пайплайны
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Полный CI pipeline: сборка + тесты + линтеры
|
||||||
|
[group('ci')]
|
||||||
|
pipeline: build test lint
|
||||||
|
@echo " ✅ CI pipeline complete"
|
||||||
|
|
||||||
|
# Сборка всех проектов в Release
|
||||||
|
[group('ci')]
|
||||||
|
build:
|
||||||
|
just build::build-all-release
|
||||||
|
|
||||||
|
# Unit-тесты
|
||||||
|
[group('ci')]
|
||||||
|
test:
|
||||||
|
just build::test-host-release
|
||||||
|
|
||||||
|
# TODO: Линтеры + статический анализ
|
||||||
|
[group('ci')]
|
||||||
|
lint:
|
||||||
|
echo "TODO"
|
||||||
|
#just build::lint
|
||||||
|
#just build::check
|
||||||
|
|
||||||
|
# Генерация HAB-образов для релиза
|
||||||
|
[group('ci')]
|
||||||
|
release: build
|
||||||
|
just build::hab-all-release
|
||||||
|
@echo " ✅ Release artifacts ready in {{BUILD_DIR}}/Release/"
|
||||||
|
|
||||||
|
# Генерация coverage отчёта (если gcov настроен)
|
||||||
|
[group('ci'), private]
|
||||||
|
_coverage:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
if command -v gcovr &>/dev/null; then
|
||||||
|
echo " 📊 Generating coverage report..."
|
||||||
|
gcovr --xml -o {{BUILD_DIR}}/coverage.xml
|
||||||
|
else
|
||||||
|
echo " ⚠️ gcovr not found, skipping coverage"
|
||||||
|
fi
|
||||||
338
just/host.just
Normal file
338
just/host.just
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
# =============================================================================
|
||||||
|
# host.just — операции на хост-машине (вне devcontainer)
|
||||||
|
#
|
||||||
|
# Ответственность:
|
||||||
|
# - bootstrap окружения (just, uv, docker, udev)
|
||||||
|
# - USB-прошивка через spsdk
|
||||||
|
# - HIL-тесты на реальном железе
|
||||||
|
# - производственные сценарии (incoming, production)
|
||||||
|
#
|
||||||
|
# Все рецепты должны работать БЕЗ devcontainer.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# === Импорт общих переменных из корневого justfile ===
|
||||||
|
# Благодаря `set export` в корне, эти переменные доступны
|
||||||
|
TOOLS_DIR := env('TOOLS_DIR', justfile_directory() / 'tools/host')
|
||||||
|
CACHE_DIR := env('CACHE_DIR', justfile_directory() / '.cache')
|
||||||
|
|
||||||
|
# === Минимальные версии зависимостей ===
|
||||||
|
JUST_MIN := "1.36.0"
|
||||||
|
UV_MIN := "0.4.0"
|
||||||
|
DOCKER_MIN := "24.0.0"
|
||||||
|
set working-directory := '..'
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: setup — инициализация рабочего окружения
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# [1/3] Проверить наличие и версии инструментов на хост-машине
|
||||||
|
[group('setup')]
|
||||||
|
check-deps:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BOLD="\033[1m"; GREEN="\033[0;32m"; RED="\033[0;31m"; YELLOW="\033[1;33m"; RESET="\033[0m"
|
||||||
|
ERRORS=0; WARNINGS=0
|
||||||
|
|
||||||
|
ok() { echo -e " ${GREEN}✅ ${1}${RESET}"; }
|
||||||
|
fail() { echo -e " ${RED}❌ ${1}${RESET}"; ERRORS=$((ERRORS+1)); }
|
||||||
|
warn() { echo -e " ${YELLOW}⚠️ ${1}${RESET}"; WARNINGS=$((WARNINGS+1)); }
|
||||||
|
|
||||||
|
_uname="$(uname -s)"
|
||||||
|
case "${_uname}" in
|
||||||
|
Linux*) PLATFORM="linux" ;;
|
||||||
|
Darwin*) PLATFORM="macos" ;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
|
||||||
|
*) PLATFORM="unknown" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Сравнение semver без sort -V (недоступен в Git Bash)
|
||||||
|
semver_ge() {
|
||||||
|
local a="$1" b="$2"
|
||||||
|
local a1 a2 a3 b1 b2 b3
|
||||||
|
IFS='.' read -r a1 a2 a3 <<< "${a}"
|
||||||
|
IFS='.' read -r b1 b2 b3 <<< "${b}"
|
||||||
|
a1="${a1//[^0-9]/}"; a2="${a2//[^0-9]/}"; a3="${a3//[^0-9]/}"
|
||||||
|
b1="${b1//[^0-9]/}"; b2="${b2//[^0-9]/}"; b3="${b3//[^0-9]/}"
|
||||||
|
[[ "${a1:-0}" -gt "${b1:-0}" ]] && return 0
|
||||||
|
[[ "${a1:-0}" -lt "${b1:-0}" ]] && return 1
|
||||||
|
[[ "${a2:-0}" -gt "${b2:-0}" ]] && return 0
|
||||||
|
[[ "${a2:-0}" -lt "${b2:-0}" ]] && return 1
|
||||||
|
[[ "${a3:-0}" -ge "${b3:-0}" ]] && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install_hint() {
|
||||||
|
local tool=$1
|
||||||
|
case "${PLATFORM}" in
|
||||||
|
linux)
|
||||||
|
case "$tool" in
|
||||||
|
just) echo "curl -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin" ;;
|
||||||
|
uv) echo "curl -LsSf https://astral.sh/uv/install.sh | sh" ;;
|
||||||
|
docker) echo "https://docs.docker.com/engine/install/ubuntu/" ;;
|
||||||
|
esac ;;
|
||||||
|
macos)
|
||||||
|
case "$tool" in
|
||||||
|
just) echo "brew install just" ;;
|
||||||
|
uv) echo "brew install uv" ;;
|
||||||
|
docker) echo "brew install --cask docker" ;;
|
||||||
|
esac ;;
|
||||||
|
windows)
|
||||||
|
case "$tool" in
|
||||||
|
just) echo "winget install --id Casey.Just (в PowerShell)" ;;
|
||||||
|
uv) echo 'powershell -c "irm https://astral.sh/uv/install.ps1 | iex"' ;;
|
||||||
|
docker) echo "winget install --id Docker.DockerDesktop (в PowerShell)" ;;
|
||||||
|
esac ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
check_tool() {
|
||||||
|
local name=$1 cmd=$2 min_ver=$3
|
||||||
|
shift 3
|
||||||
|
local ver_args=("${@:---version}")
|
||||||
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
|
fail "$name not found -- $(install_hint "$name")"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local actual
|
||||||
|
actual=$("$cmd" "${ver_args[@]}" 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||||
|
if [[ -z "$actual" ]]; then
|
||||||
|
warn "$name found but version could not be detected"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if semver_ge "$actual" "$min_ver"; then
|
||||||
|
ok "$name $actual (>= $min_ver)"
|
||||||
|
else
|
||||||
|
fail "$name $actual -- need >= $min_ver -- $(install_hint "$name")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD} Platform: ${PLATFORM}${RESET}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD} Checking host dependencies...${RESET}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
check_tool "just" "just" "{{JUST_MIN}}"
|
||||||
|
check_tool "uv" "uv" "{{UV_MIN}}"
|
||||||
|
check_tool "docker" "docker" "{{DOCKER_MIN}}" version --format '{{{{.Client.Version}}}}'
|
||||||
|
|
||||||
|
if [[ "${PLATFORM}" == "linux" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD} Checking udev rules (Linux only)...${RESET}"
|
||||||
|
echo ""
|
||||||
|
rules_file="/etc/udev/rules.d/99-nxp-mimxrt.rules"
|
||||||
|
udev_ok=true
|
||||||
|
grep -q "1fc9" "$rules_file" 2>/dev/null || { warn "udev: BootROM rule missing (VID 1fc9)"; udev_ok=false; }
|
||||||
|
grep -q "15a2" "$rules_file" 2>/dev/null || { warn "udev: Flashloader rule missing (VID 15a2)"; udev_ok=false; }
|
||||||
|
if ! groups 2>/dev/null | grep -q plugdev; then
|
||||||
|
warn "User '$(whoami)' not in 'plugdev' group"
|
||||||
|
udev_ok=false
|
||||||
|
fi
|
||||||
|
if [[ "$udev_ok" == "false" ]]; then
|
||||||
|
warn "USB flashing requires root without udev rules -- run: just setup-udev"
|
||||||
|
else
|
||||||
|
ok "udev rules (NXP USB) + plugdev group"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ $ERRORS -gt 0 ]]; then
|
||||||
|
echo -e " ${RED}${BOLD}$ERRORS error(s) found. Fix them before continuing.${RESET}"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
elif [[ $WARNINGS -gt 0 ]]; then
|
||||||
|
echo -e " ${YELLOW}${BOLD}$WARNINGS warning(s). Some features may not work.${RESET}"
|
||||||
|
else
|
||||||
|
echo -e " ${GREEN}${BOLD}All dependencies satisfied.${RESET}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# [2/3] Установить udev правила для USB-прошивки (только Linux, требует sudo)
|
||||||
|
[group('setup')]
|
||||||
|
setup-udev:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Linux*) ;;
|
||||||
|
*)
|
||||||
|
echo " ℹ️ udev rules are Linux-only, skipping on $(uname -s)."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo " Installing udev rules for NXP USB devices..."
|
||||||
|
printf '%s\n%s\n%s\n%s\n' \
|
||||||
|
'# NXP BootROM -- SDP mode (BOOT_MOD_1 = 3V3)' \
|
||||||
|
'SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="0130", MODE="0666", GROUP="plugdev"' \
|
||||||
|
'# NXP Flashloader -- after jump-address' \
|
||||||
|
'SUBSYSTEM=="usb", ATTR{idVendor}=="15a2", ATTR{idProduct}=="0073", MODE="0666", GROUP="plugdev"' \
|
||||||
|
| sudo tee /etc/udev/rules.d/99-nxp-mimxrt.rules > /dev/null
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
sudo udevadm trigger
|
||||||
|
sudo usermod -a -G plugdev "$USER"
|
||||||
|
echo " ✅ udev rules installed"
|
||||||
|
echo " ⚠️ Re-login required for 'plugdev' group to take effect"
|
||||||
|
|
||||||
|
# [3/3] Синхронизировать зависимости tools/host (spsdk и др.)
|
||||||
|
# Идемпотентен: пропускает sync если uv.lock не изменился
|
||||||
|
[group('setup')]
|
||||||
|
setup-tools:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
LOCK="{{TOOLS_DIR}}/uv.lock"
|
||||||
|
STAMP="{{CACHE_DIR}}/uv_lock.sha256"
|
||||||
|
mkdir -p "{{CACHE_DIR}}"
|
||||||
|
current=$(sha256sum "$LOCK" 2>/dev/null | cut -d' ' -f1 || echo "missing")
|
||||||
|
previous=$(cat "$STAMP" 2>/dev/null || echo "none")
|
||||||
|
if [[ "$current" == "$previous" ]]; then
|
||||||
|
echo " ✅ tools/host deps up to date (lockfile unchanged)"
|
||||||
|
else
|
||||||
|
echo " 📦 Syncing tools/host deps..."
|
||||||
|
cd "{{TOOLS_DIR}}" && uv sync
|
||||||
|
echo "$current" > "$STAMP"
|
||||||
|
echo " ✅ tools/host deps installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Полная инициализация — запустить один раз после git clone
|
||||||
|
[group('setup')]
|
||||||
|
bootstrap:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
_uname="$(uname -s)"
|
||||||
|
case "${_uname}" in
|
||||||
|
Linux*) PLATFORM="linux" ;;
|
||||||
|
Darwin*) PLATFORM="macos" ;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
|
||||||
|
*) PLATFORM="unknown" ;;
|
||||||
|
esac
|
||||||
|
echo ""
|
||||||
|
echo " === Bootstrap: step 1/3 -- check-deps ==="
|
||||||
|
just host::check-deps
|
||||||
|
if [[ "${PLATFORM}" == "linux" ]]; then
|
||||||
|
echo " === Bootstrap: step 2/3 -- setup-udev ==="
|
||||||
|
just host::setup-udev
|
||||||
|
else
|
||||||
|
echo " ℹ️ step 2/3 -- setup-udev skipped (${PLATFORM})"
|
||||||
|
fi
|
||||||
|
echo " === Bootstrap: step 3/3 -- setup-tools ==="
|
||||||
|
just host::setup-tools
|
||||||
|
echo ""
|
||||||
|
echo " ✅ Bootstrap complete."
|
||||||
|
echo " Next: open project in VSCode -> 'Reopen in Container'"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: flash — прошивка платы через USB
|
||||||
|
# Требует: uv + spsdk (just setup-tools), плата в SDP-режиме
|
||||||
|
# HAB-образы должны быть собраны заранее (just hab-* внутри devcontainer)
|
||||||
|
#
|
||||||
|
# Матрица прошивки:
|
||||||
|
# just flash firmware_test debug
|
||||||
|
# just flash firmware_test release
|
||||||
|
# just flash bootloader debug
|
||||||
|
# just flash bootloader release
|
||||||
|
# just flash app debug
|
||||||
|
# just flash app release
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Прошить выбранный HAB-образ.
|
||||||
|
# Использование: just flash <project> <type>
|
||||||
|
# project: firmware_test | bootloader | app
|
||||||
|
# type: debug | release (default: release)
|
||||||
|
#
|
||||||
|
# Образ должен быть собран заранее в devcontainer:
|
||||||
|
# just --justfile just/build.just hab-<project>-<type>
|
||||||
|
[group('flash')]
|
||||||
|
flash project type="release":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "{{type}}" in
|
||||||
|
debug) BUILD_TYPE="Debug" ;;
|
||||||
|
release) BUILD_TYPE="Release" ;;
|
||||||
|
*)
|
||||||
|
echo " ❌ Unknown type: {{type}}"
|
||||||
|
echo " Valid: debug, release"
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
||||||
|
--firmware "{{project}}" --build-type "${BUILD_TYPE}"
|
||||||
|
|
||||||
|
# Загрузить образ в RAM без записи во Flash.
|
||||||
|
# Полезно для быстрой проверки — не изнашивает Flash, плата стартует сразу.
|
||||||
|
# Использование: just flash-ram <project> <type>
|
||||||
|
[group('flash')]
|
||||||
|
flash-ram project type="debug":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "{{type}}" in
|
||||||
|
debug) BUILD_TYPE="Debug" ;;
|
||||||
|
release) BUILD_TYPE="Release" ;;
|
||||||
|
*)
|
||||||
|
echo " ❌ Unknown type: {{type}}"
|
||||||
|
echo " Valid: debug, release"
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
cd "{{TOOLS_DIR}}" && uv run python3 flash_usb.py \
|
||||||
|
--firmware "{{project}}" --build-type "${BUILD_TYPE}" --ram-only
|
||||||
|
|
||||||
|
# Псевдонимы для частых сценариев ────────────────────────────────────────────
|
||||||
|
|
||||||
|
# firmware_test Debug — самый частый при разработке
|
||||||
|
[group('flash')]
|
||||||
|
flash-test-debug:
|
||||||
|
@just host::flash firmware_test debug
|
||||||
|
|
||||||
|
# firmware_test Release — как будет на производстве
|
||||||
|
[group('flash')]
|
||||||
|
flash-test-release:
|
||||||
|
@just host::flash firmware_test release
|
||||||
|
|
||||||
|
# TODO: bootloader + app Release — финальная прошивка
|
||||||
|
[group('flash'), confirm("Flash bootloader + app (Release)?")]
|
||||||
|
flash-production:
|
||||||
|
@just host::flash bootloader release
|
||||||
|
@just host::flash app release
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: pipeline — производственные сценарии (для сервера)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Входной контроль платы: тестовая прошивка (Release) -> HIL-тесты
|
||||||
|
[group('pipeline')]
|
||||||
|
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 <- раскомментить когда готово
|
||||||
|
echo " ⚠️ HIL tests not yet implemented"
|
||||||
|
|
||||||
|
# Финальная прошивка: загрузчик + основная прошивка (Release)
|
||||||
|
[group('pipeline')]
|
||||||
|
production: flash-production
|
||||||
|
@echo " ✅ Production firmware flashed (bootloader + app)"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: util — вспомогательные инструменты
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Найти подключённые NXP USB-устройства
|
||||||
|
[group('util')]
|
||||||
|
scan:
|
||||||
|
cd "{{TOOLS_DIR}}" && uv run nxpdevscan
|
||||||
|
|
||||||
|
# Проверить связь с BootROM через SDP (плата в SDP-режиме)
|
||||||
|
[group('util'), no-cd]
|
||||||
|
sdp-status:
|
||||||
|
cd "{{TOOLS_DIR}}" && 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
|
||||||
|
|
||||||
|
# Обновить spsdk до новой версии
|
||||||
|
# Использование: just upgrade-tools 3.8.0
|
||||||
|
[group('util')]
|
||||||
|
upgrade-tools version:
|
||||||
|
cd "{{TOOLS_DIR}}" && uv add "spsdk=={{version}}" && uv sync
|
||||||
|
@echo " ✅ spsdk upgraded to {{version}}"
|
||||||
|
@echo " Run: git add tools/host/uv.lock tools/host/pyproject.toml"
|
||||||
Loading…
Reference in a new issue