# 8 - IMPORTANT
- Переход на task-runner Just (Justfile - для хоста, build.just - для контейнера) - настройки clang-format - небольшие изменения в структуре проекта
This commit is contained in:
parent
6eaca0c183
commit
e8a9826944
37 changed files with 1957 additions and 286 deletions
55
.clang-format
Normal file
55
.clang-format
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
# --- Отступы ---
|
||||||
|
IndentWidth: 4 # 4 пробела — стандарт для embedded
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never # Только пробелы, чтобы не было войны в git
|
||||||
|
|
||||||
|
# --- Скобки ---
|
||||||
|
BreakBeforeBraces: Allman # Открывающая скобка на новой строке
|
||||||
|
# Альтернатива: Linux (скобка после if/for, но
|
||||||
|
# Allman нагляднее при отладке железа)
|
||||||
|
|
||||||
|
# --- Длина строки ---
|
||||||
|
ColumnLimit: 100 # 80 — слишком мало для современных мониторов
|
||||||
|
|
||||||
|
# --- Выравнивание ---
|
||||||
|
AlignConsecutiveAssignments:
|
||||||
|
Enabled: true # Выравнивает = в блоках присваиваний
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true # Очень удобно для регистровых масок
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false # Спорно — может ломать читаемость
|
||||||
|
|
||||||
|
# --- Пробелы ---
|
||||||
|
SpaceBeforeParens: ControlStatements # if (...) но func(...)
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpaceAfterCStyleCast: true # (uint8_t) value
|
||||||
|
|
||||||
|
# --- Указатели ---
|
||||||
|
PointerAlignment: Right # uint8_t *ptr (или Left — uint8_t* ptr)
|
||||||
|
# Right — традиционный C стиль
|
||||||
|
|
||||||
|
# --- Переносы ---
|
||||||
|
AllowShortFunctionsOnASingleLine: None # Запрет коротких функций в одну строку
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never # if всегда с телом на новой строке
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
|
||||||
|
# --- Include-сортировка ---
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
IncludeBlocks: Regroup # Группирует и сортирует #include блоки
|
||||||
|
|
||||||
|
# --- Комментарии ---
|
||||||
|
ReflowComments: false # НЕ переформатировать комментарии автоматически
|
||||||
|
# Важно для ASCII-art схем и таблиц регистров!
|
||||||
|
|
||||||
|
# --- Прочее ---
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
|
@ -58,12 +58,23 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
&& update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100 \
|
&& update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100 \
|
||||||
&& update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-17 100 \
|
&& update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-17 100 \
|
||||||
&& update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-17 100 \
|
&& update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-17 100 \
|
||||||
&& pip3 install --no-cache-dir spsdk cmake-format==0.6.13 \
|
&& pip3 install --no-cache-dir cmake-format==0.6.13 \
|
||||||
&& ln -s /usr/bin/clangd /usr/local/bin/clangd \
|
&& ln -s /usr/bin/clangd /usr/local/bin/clangd \
|
||||||
&& ln -s /usr/bin/clang /usr/local/bin/clang \
|
&& ln -s /usr/bin/clang /usr/local/bin/clang \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|
||||||
|
# uv — менеджер Python-окружений для spsdk и других host-инструментов.
|
||||||
|
# spsdk НЕ ставится через pip напрямую — версия фиксируется в tools/host/uv.lock.
|
||||||
|
# uv sync в postCreateCommand подтянет нужную версию автоматически.
|
||||||
|
ARG UV_VERSION=0.5.0
|
||||||
|
RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh
|
||||||
|
|
||||||
|
ARG JUST_VERSION=1.36.0
|
||||||
|
|
||||||
|
RUN curl -sSf https://just.systems/install.sh \
|
||||||
|
| bash -s -- --tag ${JUST_VERSION} --to /usr/local/bin
|
||||||
|
|
||||||
ARG USER_ID=1000
|
ARG USER_ID=1000
|
||||||
ARG GROUP_ID=1000
|
ARG GROUP_ID=1000
|
||||||
ARG WORKSPACE_PATH="/workspace"
|
ARG WORKSPACE_PATH="/workspace"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
},
|
},
|
||||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
"postCreateCommand": "cmake --preset host-debug && cmake --preset Debug",
|
"postCreateCommand": "cd tools/host && uv sync && cd ../.. && cmake --preset host-debug && cmake --preset Debug",
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
|
|
@ -43,7 +43,6 @@
|
||||||
"*.h": "c",
|
"*.h": "c",
|
||||||
"*.c": "c"
|
"*.c": "c"
|
||||||
},
|
},
|
||||||
// clangd
|
|
||||||
"clangd.path": "clangd",
|
"clangd.path": "clangd",
|
||||||
"clangd.arguments": [
|
"clangd.arguments": [
|
||||||
"--query-driver=/opt/arm-toolchain/bin/arm-none-eabi-*",
|
"--query-driver=/opt/arm-toolchain/bin/arm-none-eabi-*",
|
||||||
|
|
@ -52,20 +51,26 @@
|
||||||
"--header-insertion=iwyu",
|
"--header-insertion=iwyu",
|
||||||
"--log=error"
|
"--log=error"
|
||||||
],
|
],
|
||||||
// Отключаем встроенный IntelliSense от ms-vscode.cpptools, чтобы не конфликтовал с clangd
|
|
||||||
"C_Cpp.intelliSenseEngine": "disabled",
|
|
||||||
"C_Cpp.formatting": "disabled",
|
|
||||||
// clang-format
|
|
||||||
"clang-format.executable": "clang-format",
|
"clang-format.executable": "clang-format",
|
||||||
|
"clang-format.style": "file",
|
||||||
|
"clang-format.fallbackStyle": "LLVM",
|
||||||
"[c]": {
|
"[c]": {
|
||||||
"editor.defaultFormatter": "xaver.clang-format"
|
"editor.defaultFormatter": "xaver.clang-format",
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
},
|
||||||
|
"[h]": {
|
||||||
|
"editor.defaultFormatter": "xaver.clang-format",
|
||||||
|
"editor.formatOnSave": true
|
||||||
},
|
},
|
||||||
// cmake-format
|
|
||||||
"cmakeFormat.exePath": "cmake-format",
|
"cmakeFormat.exePath": "cmake-format",
|
||||||
"[cmake]": {
|
"[cmake]": {
|
||||||
"editor.defaultFormatter": "cheshirekow.cmake-format"
|
"editor.defaultFormatter": "cheshirekow.cmake-format"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"runArgs": [
|
||||||
|
"--name",
|
||||||
|
"tft-devcontainer"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -57,6 +57,7 @@ Debug/
|
||||||
Release/
|
Release/
|
||||||
build*
|
build*
|
||||||
Testing/
|
Testing/
|
||||||
|
!build.just
|
||||||
|
|
||||||
# Файлы настройки среды разработки
|
# Файлы настройки среды разработки
|
||||||
.project
|
.project
|
||||||
|
|
|
||||||
310
.vscode/tasks.json
vendored
310
.vscode/tasks.json
vendored
|
|
@ -1,213 +1,185 @@
|
||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
// Очистка директории с артефактами сборки
|
// =============================================================
|
||||||
|
// СБОРКА
|
||||||
|
// =============================================================
|
||||||
{
|
{
|
||||||
"label": "Clean",
|
"label": "🔨 Build",
|
||||||
"group": "build",
|
"group": {
|
||||||
"type": "shell",
|
"kind": "build",
|
||||||
"command": "rm -rf build*",
|
"isDefault": true
|
||||||
"windows": {
|
|
||||||
"command": "rm build* -Recurse -Force"
|
|
||||||
},
|
},
|
||||||
"options": {
|
|
||||||
"statusbar": {
|
|
||||||
"color": "#ff8b8b",
|
|
||||||
"label": "$(clear-all) CleanBuildDir",
|
|
||||||
"detail": "Clean ALL"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Сборка и запуск тестов на хосте в режиме Debug
|
|
||||||
{
|
|
||||||
"label": "Configure Host Debug tests",
|
|
||||||
"group": "build",
|
|
||||||
"hide": true,
|
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "cmake",
|
"command": "just",
|
||||||
"args": [
|
"args": [
|
||||||
"--preset",
|
"--justfile",
|
||||||
"host-debug"
|
"scripts/build.just",
|
||||||
],
|
"build-${input:project}-${input:buildType}"
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Build Host Debug tests",
|
|
||||||
"group": "build",
|
|
||||||
"hide": true,
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"--preset",
|
|
||||||
"host-debug-build"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
"dependsOn": "Configure Host Debug tests"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "🧪 Host Build & Test All",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "ctest",
|
|
||||||
"args": [
|
|
||||||
"--preset",
|
|
||||||
"host-debug-test"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
"statusbar": {
|
|
||||||
"color": "#c800ff",
|
|
||||||
"label": "$(test-view-icon) Host Test Debug",
|
|
||||||
"detail": "Perform all the host tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"group": "test",
|
|
||||||
"dependsOrder": "sequence",
|
|
||||||
"dependsOn": [
|
|
||||||
"Build Host Debug tests"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// Сборка и запуск тестов на хосте в режиме Release
|
|
||||||
{
|
|
||||||
"label": "Configure Host Release tests",
|
|
||||||
"group": "build",
|
|
||||||
"hide": true,
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--preset",
|
|
||||||
"host-release"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Build Host Release tests",
|
|
||||||
"group": "build",
|
|
||||||
"hide": true,
|
|
||||||
"type": "shell",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"--preset",
|
|
||||||
"host-release-build"
|
|
||||||
],
|
|
||||||
"dependsOn": "Configure Host Release tests"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "🧪 Host Release Tests",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "ctest",
|
|
||||||
"args": [
|
|
||||||
"--preset",
|
|
||||||
"host-release-test"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
"statusbar": {
|
|
||||||
"color": "#c800ff",
|
|
||||||
"label": "$(test-view-icon) Host Test Release",
|
|
||||||
"detail": "Perform all the host tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"group": "test",
|
|
||||||
"dependsOrder": "sequence",
|
|
||||||
"dependsOn": [
|
|
||||||
"Build Host Release tests"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Подготовка сборки в контейнере с пресетом Debug
|
|
||||||
{
|
|
||||||
"label": "Docker: Configure (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"hide": true,
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--preset",
|
|
||||||
"Debug"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
"group": "build",
|
|
||||||
"problemMatcher": []
|
|
||||||
},
|
|
||||||
// Сборка проекта в контейнере Debug
|
|
||||||
{
|
|
||||||
"label": "Docker: Build (Debug)",
|
|
||||||
"type": "shell",
|
|
||||||
"hide": false,
|
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
|
||||||
"--build",
|
|
||||||
"--preset",
|
|
||||||
"Debug"
|
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"statusbar": {
|
"statusbar": {
|
||||||
"color": "#ff8bd4",
|
"color": "#ff8bd4",
|
||||||
"label": "$(debug-console-view-icon) Target: Build (Debug)",
|
"label": "$(debug-console-view-icon) Build",
|
||||||
"detail": "do Debug build"
|
"detail": "Build selected firmware"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"group": "build",
|
"problemMatcher": [
|
||||||
"dependsOn": "Docker: Configure (Debug)",
|
"$gcc"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
// Подготовка сборки в контейнере с пресетом Release
|
// =============================================================
|
||||||
|
// HOST-ТЕСТЫ
|
||||||
|
// =============================================================
|
||||||
{
|
{
|
||||||
"label": "Docker: Configure (Release)",
|
"label": "🧪 Host Tests (Debug)",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"hide": true,
|
"command": "just",
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
"args": [
|
||||||
"--preset",
|
"--justfile",
|
||||||
"Release"
|
"scripts/build.just",
|
||||||
|
"test-host"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"statusbar": {
|
||||||
|
"color": "#c800ff",
|
||||||
|
"label": "$(test-view-icon) Host Tests",
|
||||||
|
"detail": "Run host unit tests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "🧪 Host Tests (Release)",
|
||||||
|
"group": "test",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "just",
|
||||||
|
"args": [
|
||||||
|
"--justfile",
|
||||||
|
"scripts/build.just",
|
||||||
|
"test-host-release"
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}"
|
"cwd": "${workspaceFolder}"
|
||||||
},
|
},
|
||||||
"group": "build",
|
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
// Сборка проекта в контейнере Release
|
// =============================================================
|
||||||
|
// HAB-ОБРАЗЫ
|
||||||
|
// =============================================================
|
||||||
{
|
{
|
||||||
"label": "Docker: Build (Release)",
|
"label": "📦 HAB Image",
|
||||||
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"hide": false,
|
"command": "just",
|
||||||
"command": "cmake",
|
|
||||||
"args": [
|
"args": [
|
||||||
"--build",
|
"--justfile",
|
||||||
"--preset",
|
"scripts/build.just",
|
||||||
"Release"
|
"hab-${input:habProject}-${input:buildType}"
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"statusbar": {
|
"statusbar": {
|
||||||
"color": "#03b3ff",
|
"color": "#03b3ff",
|
||||||
"label": "$(pass-filled) Target: Build (Release)",
|
"label": "$(package) HAB",
|
||||||
"detail": "do Release build"
|
"detail": "Build HAB image"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"group": "build",
|
"problemMatcher": []
|
||||||
"dependsOn": "Docker: Configure (Release)",
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "📦 HAB All (Debug)",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "just",
|
||||||
|
"args": [
|
||||||
|
"--justfile",
|
||||||
|
"scripts/build.just",
|
||||||
|
"hab-all-debug"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "📦 HAB All (Release)",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "just",
|
||||||
|
"args": [
|
||||||
|
"--justfile",
|
||||||
|
"scripts/build.just",
|
||||||
|
"hab-all-release"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
// =============================================================
|
||||||
|
// УТИЛИТЫ
|
||||||
|
// =============================================================
|
||||||
|
{
|
||||||
|
"label": "🗑️ Clean",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "just",
|
||||||
|
"args": [
|
||||||
|
"--justfile",
|
||||||
|
"scripts/build.just",
|
||||||
|
"clean"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"statusbar": {
|
||||||
|
"color": "#ff8b8b",
|
||||||
|
"label": "$(clear-all) Clean",
|
||||||
|
"detail": "Remove build artifacts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
{
|
||||||
|
"id": "project",
|
||||||
|
"type": "pickString",
|
||||||
|
"description": "Project",
|
||||||
|
"options": [
|
||||||
|
"firmware-test",
|
||||||
|
"bootloader",
|
||||||
|
"app",
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"default": "firmware-test"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "buildType",
|
"id": "buildType",
|
||||||
"type": "pickString",
|
"type": "pickString",
|
||||||
"description": "Тип сборки",
|
"description": "Build type",
|
||||||
"options": [
|
"options": [
|
||||||
"Debug",
|
"debug",
|
||||||
"Release",
|
"release"
|
||||||
],
|
],
|
||||||
"default": "Debug"
|
"default": "debug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "habProject",
|
||||||
|
"type": "pickString",
|
||||||
|
"description": "HAB project",
|
||||||
|
"options": [
|
||||||
|
"firmware-test",
|
||||||
|
"bootloader",
|
||||||
|
"app"
|
||||||
|
],
|
||||||
|
"default": "firmware-test"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -66,17 +66,67 @@
|
||||||
],
|
],
|
||||||
"buildPresets": [
|
"buildPresets": [
|
||||||
{
|
{
|
||||||
"name": "Debug",
|
"name": "all-debug",
|
||||||
|
"displayName": "All — Debug",
|
||||||
"configurePreset": "Debug"
|
"configurePreset": "Debug"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Release",
|
"name": "all-release",
|
||||||
|
"displayName": "All — Release",
|
||||||
"configurePreset": "Release"
|
"configurePreset": "Release"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "firmware-test-debug",
|
||||||
|
"displayName": "firmware_test — Debug",
|
||||||
|
"configurePreset": "Debug",
|
||||||
|
"targets": [
|
||||||
|
"firmware_test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "firmware-test-release",
|
||||||
|
"displayName": "firmware_test — Release",
|
||||||
|
"configurePreset": "Release",
|
||||||
|
"targets": [
|
||||||
|
"firmware_test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bootloader-debug",
|
||||||
|
"displayName": "bootloader — Debug",
|
||||||
|
"configurePreset": "Debug",
|
||||||
|
"targets": [
|
||||||
|
"bootloader"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bootloader-release",
|
||||||
|
"displayName": "bootloader — Release",
|
||||||
|
"configurePreset": "Release",
|
||||||
|
"targets": [
|
||||||
|
"bootloader"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "app-debug",
|
||||||
|
"displayName": "app — Debug",
|
||||||
|
"configurePreset": "Debug",
|
||||||
|
"targets": [
|
||||||
|
"app"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "app-release",
|
||||||
|
"displayName": "app — Release",
|
||||||
|
"configurePreset": "Release",
|
||||||
|
"targets": [
|
||||||
|
"app"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "host-debug-build",
|
"name": "host-debug-build",
|
||||||
|
"displayName": "Host Tests — Debug",
|
||||||
"configurePreset": "host-debug",
|
"configurePreset": "host-debug",
|
||||||
"displayName": "Build Host Debug Tests",
|
|
||||||
"targets": [
|
"targets": [
|
||||||
"test_host_simple",
|
"test_host_simple",
|
||||||
"test_host_second"
|
"test_host_second"
|
||||||
|
|
@ -84,8 +134,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "host-release-build",
|
"name": "host-release-build",
|
||||||
|
"displayName": "Host Tests — Release",
|
||||||
"configurePreset": "host-release",
|
"configurePreset": "host-release",
|
||||||
"displayName": "Build Host Release Tests",
|
|
||||||
"targets": [
|
"targets": [
|
||||||
"test_host_simple",
|
"test_host_simple",
|
||||||
"test_host_second"
|
"test_host_second"
|
||||||
|
|
|
||||||
22
HOW_TO_FLASH.md
Normal file
22
HOW_TO_FLASH.md
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Прошивка платы со стороны хоста
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
344
Justfile
Normal file
344
Justfile
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
# =============================================================================
|
||||||
|
# Justfile — корень репозитория
|
||||||
|
# Выполняется на ХОСТ-МАШИНЕ разработчика (вне devcontainer).
|
||||||
|
#
|
||||||
|
# Отвечает только за:
|
||||||
|
# - инициализацию окружения (setup)
|
||||||
|
# - прошивку платы через USB (flash)
|
||||||
|
# - сквозные сценарии (pipeline)
|
||||||
|
# - вспомогательные утилиты (util)
|
||||||
|
#
|
||||||
|
# Сборка, тесты и HAB-образы — в just/build.just (внутри devcontainer).
|
||||||
|
#
|
||||||
|
# Быстрый старт:
|
||||||
|
# ./scripts/bootstrap.sh # первый запуск после git clone
|
||||||
|
# just # показать все рецепты
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
JUST_MIN := "1.27.0"
|
||||||
|
UV_MIN := "0.4.0"
|
||||||
|
DOCKER_MIN := "24.0.0"
|
||||||
|
|
||||||
|
TOOLS_DIR := "tools/host"
|
||||||
|
CACHE_DIR := ".cache"
|
||||||
|
|
||||||
|
# По умолчанию — показать список рецептов
|
||||||
|
_default:
|
||||||
|
@just --list --unsorted
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: 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 ""
|
||||||
|
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"
|
||||||
148
README.md
148
README.md
|
|
@ -1,8 +1,8 @@
|
||||||
# tft_manufacture_test
|
# tft_manufacture_test
|
||||||
|
|
||||||
## Структура проекта
|
Монорепозиторий для **MIMXRT1052CVJ5B**. Содержит три независимых firmware-проекта с общей инфраструктурой сборки, тестирования и инструментарием.
|
||||||
|
|
||||||
Монорепозиторий для MIMXRT1052CVJ5B. Три независимых firmware-проекта с общей инфраструктурой сборки, тестирования и инструментарием.
|
> Архитектура рабочего окружения разработчика — [docs/DEV_ARCH.md](docs/DEV_ARCH.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -11,44 +11,55 @@
|
||||||
```bash
|
```bash
|
||||||
/
|
/
|
||||||
├── .devcontainer/ # VSCode Devcontainer — единое окружение для всех разработчиков
|
├── .devcontainer/ # VSCode Devcontainer — единое окружение для всех разработчиков
|
||||||
|
├── bsp/ # Board Support Package
|
||||||
|
│ └── generated/ # Сгенерировано NXP Config Tools (Pins + Clocks Tool)
|
||||||
|
│ ├── TFT_Board.mex # Источник истины конфигурации пинов и тактирования
|
||||||
|
│ ├── pin_mux.c/h # Сгенерировано из .mex (Pins Tool)
|
||||||
|
│ ├── clock_config.c/h # Сгенерировано из .mex (Clocks Tool)
|
||||||
|
│ ├── board.c/h # Ручная инициализация специфики платы
|
||||||
|
│ └── BOOT_FLAGS.md # Описание флагов загрузчика
|
||||||
├── cmake/ # Общие CMake модули и toolchain files
|
├── cmake/ # Общие CMake модули и toolchain files
|
||||||
|
│ ├── linker/ # Линкер-скрипты под разные схемы размещения
|
||||||
│ ├── toolchain_arm.cmake # ARM cross-compilation toolchain
|
│ ├── toolchain_arm.cmake # ARM cross-compilation toolchain
|
||||||
│ └── toolchain_host.cmake # Host GCC для unit-тестов
|
│ └── toolchain_host.cmake # Host GCC для unit-тестов
|
||||||
├── sdk/ # NXP MCUXpresso SDK — vendored, только нужные компоненты
|
├── sdk/ # NXP MCUXpresso SDK — vendored
|
||||||
│ ├── CMakeLists.txt # CMake-таргеты для каждого драйвера
|
│ ├── CMakeLists.txt
|
||||||
│ ├── CMSIS/
|
│ ├── CMSIS/
|
||||||
│ ├── devices/
|
│ ├── devices/MIMXRT1052/ # Драйверы, startup, утилиты
|
||||||
│ │ └── MIMXRT1052/
|
│ ├── components/ # fsl_button, fsl_led, serial_manager и др.
|
||||||
│ │ ├── drivers/ # fsl_flexcan, fsl_lpuart, fsl_usdhc и др.
|
│ ├── middleware/ # FatFS, FreeRTOS, LittleFS, USB, mcuboot и др.
|
||||||
│ │ ├── startup/
|
│ └── rtos/freertos/ # FreeRTOS (vendored через SDK)
|
||||||
│ │ └── utilities/
|
├── lib/ # Внешние библиотеки
|
||||||
│ └── components/
|
│ ├── Unity/ # Фреймворк для unit-тестов (vendored)
|
||||||
├── bsp/ # Board Support Package
|
│ ├── fff/ # Fake Function Framework для моков (vendored)
|
||||||
│ └── board/
|
│ └── SEGGER/ # SEGGER RTT — вывод логов через отладчик
|
||||||
│ ├── board.mex # Исходник конфигурации для NXP Config Tools
|
|
||||||
│ ├── pin_mux.c/h # Сгенерировано из board.mex (Pins Tool)
|
|
||||||
│ ├── clock_config.c/h # Сгенерировано из board.mex (Clocks Tool)
|
|
||||||
│ └── board.c/h # Ручная инициализация специфики платы
|
|
||||||
├── lib/ # Библиотеки и зависимости
|
|
||||||
│ ├── CMakeLists.txt # Агрегатор — подключает нужные модули через опции
|
|
||||||
│ ├── freertos/ # vendored
|
|
||||||
│ ├── fatfs/ # vendored
|
|
||||||
│ ├── mbedtls/ # vendored (если используется)
|
|
||||||
│ ├── unity/ # vendored (test framework)
|
|
||||||
│ ├── fff/ # vendored (fake functions для тестов)
|
|
||||||
│ └── hal/ # submodule — аппаратно-независимые библиотеки
|
|
||||||
│ # (второй разработчик, активно развивается)
|
|
||||||
├── firmware/
|
├── firmware/
|
||||||
│ ├── test/ # [Проект 1] Тестовая прошивка — входной контроль
|
│ ├── test/ # [Проект 1] Тестовая прошивка — входной контроль платы
|
||||||
│ ├── bootloader/ # [Проект 2] Загрузчик с поддержкой A/B обновления
|
│ ├── bootloader/ # [Проект 2] Загрузчик с поддержкой A/B обновления
|
||||||
│ └── app/ # [Проект 3] Основная боевая прошивка (FreeRTOS)
|
│ └── tft_app/ # [Проект 3] Основная боевая прошивка (FreeRTOS)
|
||||||
├── tests/ # Host-тесты (unit + integration)
|
├── tests/ # Тесты (host + target)
|
||||||
│ ├── host/
|
│ ├── host/ # Unit/интеграционные тесты, запускаемые на хосте
|
||||||
│ └── target/
|
│ ├── target/ # Тесты периферии, запускаемые на таргете
|
||||||
└── tools/ # Скрипты для прошивки, провизии, HIL-тестов
|
│ └── HostTestingGuide.md
|
||||||
├── flash_usb.py # Прошивка через USB ROM (blhost / nxp-spsdk)
|
├── tools/
|
||||||
├── flash_remote.sh # Прошивка на удалённый сервер через SSH
|
│ └── host/ # Инструменты для работы с таргетом
|
||||||
└── provision.py # Производственная провизия (SPT / nxpimage)
|
│ ├── flash_usb.py # Прошивка через USB ROM (nxp-spsdk / blhost)
|
||||||
|
│ ├── hab/ # Утилиты и гайд по HAB (Secure Boot)
|
||||||
|
│ ├── dcd/ # Device Configuration Data
|
||||||
|
│ └── HOW_TO_FLASH.md → см. также /HOW_TO_FLASH.md
|
||||||
|
├── scripts/
|
||||||
|
│ ├── bootstrap.sh # Первичная настройка окружения
|
||||||
|
│ └── build.just # Рецепты сборки (используется через Justfile)
|
||||||
|
├── docs/ # Документация проекта
|
||||||
|
│ ├── DEV_ARCH.md # Архитектура окружения разработки
|
||||||
|
│ ├── CMAKE_HINTS.md # Шпаргалка по CMake в проекте
|
||||||
|
│ ├── schematic.pdf # Схема платы
|
||||||
|
│ ├── mcu_rm.pdf # Reference Manual IMXRT1052
|
||||||
|
│ └── manufacturing_user's_guide.pdf
|
||||||
|
├── CMakeLists.txt # Корневой CMake
|
||||||
|
├── CMakePresets.json # Пресеты сборки (Release/Debug/Host)
|
||||||
|
├── Justfile # Точка входа для команд сборки/тестирования/прошивки
|
||||||
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -57,15 +68,32 @@
|
||||||
|
|
||||||
### 1. Тестовая прошивка (`firmware/test/`)
|
### 1. Тестовая прошивка (`firmware/test/`)
|
||||||
|
|
||||||
Bare-metal прошивка для входного контроля на производстве. Проверяет базовую работоспособность всех интерфейсов и периферии: CAN, UART, SDRAM, QSPI Flash, uSD, RGB-интерфейс, гальванически развязанные входы, светодиоды, кнопки. Загружается через USB ROM (Serial Download Mode). **Рекомендуется начать разработку с этого проекта** — он наиболее прост и позволяет полностью отладить окружение сборки.
|
Bare-metal прошивка для **входного контроля** платы. Проверяет базовую работоспособность всех интерфейсов: CAN, UART, SDRAM, QSPI Flash, uSD (SDIO), RGB-интерфейс, гальванически развязанные входы, светодиоды, кнопки, IR-приёмник, MQS.
|
||||||
|
|
||||||
|
Загружается через USB ROM (Serial Download Mode) — подробнее в [HOW_TO_FLASH.md](HOW_TO_FLASH.md).
|
||||||
|
|
||||||
|
> **Рекомендуется начать разработку с этого проекта** — он наиболее прост и позволяет полностью отладить окружение сборки и прошивки.
|
||||||
|
|
||||||
### 2. Загрузчик (`firmware/bootloader/`)
|
### 2. Загрузчик (`firmware/bootloader/`)
|
||||||
|
|
||||||
Отвечает за обновление боевой прошивки в полевых условиях. Поддерживает схему A/B с шифрованием (обновление через uSD). Обновление самого загрузчика — только через внешний инструмент (USB ROM + blhost), не через себя. Загружается на производстве вместе с первой версией боевой прошивки единым blob-ом.
|
Отвечает за обновление боевой прошивки в полевых условиях. Поддерживает схему **A/B** с обновлением через uSD. Обновление самого загрузчика — только через внешний инструмент (USB ROM + blhost), не через себя. На производстве загружается единым blob-ом вместе с первой версией боевой прошивки.
|
||||||
|
|
||||||
### 3. Боевая прошивка (`firmware/app/`)
|
### 3. Боевая прошивка (`firmware/tft_app/`)
|
||||||
|
|
||||||
Основная прошивка на базе FreeRTOS. Включает FatFS, бизнес-логику, модули. Обновляется через загрузчик по схеме A/B.
|
Основная прошивка на базе **FreeRTOS**. Включает FatFS, бизнес-логику, модули. Обновляется через загрузчик по схеме A/B.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Тестирование
|
||||||
|
|
||||||
|
Стратегия тестирования двухуровневая:
|
||||||
|
|
||||||
|
| Уровень | Расположение | Инструменты | Запуск |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **Host-тесты** (unit + интеграционные) | `tests/host/` | Unity + fff | `ctest` в devcontainer |
|
||||||
|
| **Target-тесты** (аппаратные) | `tests/target/` | Unity на железе | Удалённый ПК-сервер через SSH |
|
||||||
|
|
||||||
|
Подробнее — [tests/HostTestingGuide.md](tests/HostTestingGuide.md) и [tests/README.md](tests/README.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -73,44 +101,52 @@ Bare-metal прошивка для входного контроля на про
|
||||||
|
|
||||||
| Зависимость | Подход | Причина |
|
| Зависимость | Подход | Причина |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| NXP SDK | vendored | Стабильная версия, обновлений не планируется |
|
| NXP MCUXpresso SDK | vendored | Стабильная версия, обновлений не планируется |
|
||||||
| FreeRTOS | vendored | Стабильная версия |
|
| FreeRTOS, FatFS, LittleFS и др. | vendored (через SDK) | Стабильные версии |
|
||||||
| FatFS, mbedTLS и др. | vendored | Стабильные версии |
|
|
||||||
| Unity + fff | vendored | Маленькие, стабильные |
|
| Unity + fff | vendored | Маленькие, стабильные |
|
||||||
| lib/hal (второй разработчик) | **submodule** | Активно развивается параллельно |
|
| SEGGER RTT | vendored | Стабильный |
|
||||||
|
|
||||||
**Принцип:** всё что не меняется — vendored (скачано и закоммичено). Submodule только для активно развивающихся зависимостей. Это обеспечивает полностью автономную сборку после `git clone` без доступа к интернету.
|
**Принцип:** всё что не меняется — vendored (закоммичено в репозиторий). Это обеспечивает полностью автономную сборку после `git clone` без доступа к интернету.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Devcontainer — состав окружения
|
## Devcontainer — состав окружения
|
||||||
|
|
||||||
| Инструмент | Назначение |
|
| Инструмент | Назначение |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `arm-none-eabi-gcc` | Сборка firmware для таргета |
|
| `arm-none-eabi-gcc` | Сборка firmware для таргета |
|
||||||
| `arm-none-eabi-gdb` | Отладка через GDB server |
|
| `arm-none-eabi-gdb` | Отладка через GDB server (удалённая) |
|
||||||
| `host-gcc` | Сборка и запуск 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), производственная провизия |
|
| `Python 3 + nxp-spsdk` | Прошивка (blhost, nxpimage), HAB, провизия |
|
||||||
|
| `just` | Запуск рецептов сборки/тестирования/прошивки |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Конфигурация платы (NXP Config Tools)
|
## Конфигурация платы (NXP Config Tools)
|
||||||
|
|
||||||
Файл `bsp/board/board.mex` — источник истины для конфигурации пинов и тактирования. Открывается в NXP Config Tools (Pins Tool + Clocks Tool) для генерации `pin_mux.c/h` и `clock_config.c/h`. Используется **один раз** при старте проекта или при изменении аппаратной схемы. Коммитится в репозиторий вместе со сгенерированным кодом.
|
Файл `bsp/generated/TFT_Board.mex` — **источник истины** для конфигурации пинов и тактирования. Открывается в NXP Config Tools (Pins Tool + Clocks Tool) для регенерации `pin_mux.c/h` и `clock_config.c/h`. Используется при старте проекта или при изменении аппаратной схемы. Коммитится вместе со сгенерированным кодом.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Доставка прошивки
|
## Быстрый старт
|
||||||
|
|
||||||
| Сценарий | Способ |
|
```bash
|
||||||
|---|---|
|
git clone <repo-url>
|
||||||
| Разработка (с ПК разработчика) | `rsync` / `scp` → SSH на ПК-сервер → OpenOCD/blhost |
|
cd tft_manufacture_test
|
||||||
| Производство | `nxp-spsdk` (blhost + nxpimage) через USB ROM |
|
|
||||||
| Готовое ПО на сервер | GitLab CI/CD → GitLab Package Registry → сервер подтягивает |
|
# Открыть в VSCode → Reopen in Container
|
||||||
| Обновление загрузчика | USB ROM + blhost (только так, не через сам загрузчик) |
|
# Затем внутри devcontainer:
|
||||||
| Обновление боевой прошивки в поле | Через загрузчик, схема A/B, uSD |
|
|
||||||
|
just build-host # сборка host-тестов
|
||||||
|
just test # запуск host-тестов через CTest
|
||||||
|
just build-firmware # сборка firmware для таргета
|
||||||
|
just flash # прошивка через USB ROM
|
||||||
|
```
|
||||||
|
|
||||||
|
> Подробнее о прошивке — [HOW_TO_FLASH.md](HOW_TO_FLASH.md)
|
||||||
|
> Подробнее об окружении разработки — [docs/DEV_ARCH.md](docs/DEV_ARCH.md)
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,17 @@ endif()
|
||||||
# bsp_board — стартап, сгенерированные файлы Config Tools, инициализация платы
|
# bsp_board — стартап, сгенерированные файлы Config Tools, инициализация платы
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
add_library(bsp_board STATIC board/board.c board/pin_mux.c board/clock_config.c
|
add_library(
|
||||||
board/startup/startup_MIMXRT1052.S)
|
bsp_board STATIC
|
||||||
|
generated/board.c generated/pin_mux.c generated/clock_config.c
|
||||||
|
generated/startup/startup_MIMXRT1052.S)
|
||||||
|
|
||||||
target_include_directories(bsp_board PUBLIC board)
|
# Подавляем предупреждения при компиляции собственных .c файлов библиотеки
|
||||||
|
target_compile_options(bsp_board PRIVATE -w)
|
||||||
|
|
||||||
|
# SYSTEM подавляет предупреждения для всех внешних потребителей
|
||||||
|
target_include_directories(bsp_board SYSTEM PUBLIC generated)
|
||||||
|
|
||||||
# Подавляем предупреждения о macro redefined
|
|
||||||
set_source_files_properties(board/board.c board/pin_mux.c
|
|
||||||
PROPERTIES COMPILE_OPTIONS "-w")
|
|
||||||
# Дефайны PUBLIC — транзитивно подтянутся во все firmware таргеты TODO: для
|
# Дефайны PUBLIC — транзитивно подтянутся во все firmware таргеты TODO: для
|
||||||
# каждого приложения свои дефайны
|
# каждого приложения свои дефайны
|
||||||
target_compile_definitions(
|
target_compile_definitions(
|
||||||
|
|
|
||||||
219
docs/CMAKE_HINTS.md
Normal file
219
docs/CMAKE_HINTS.md
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
# PRIVATE, PUBLIC и INTERFACE в CMake
|
||||||
|
|
||||||
|
## Основная идея
|
||||||
|
|
||||||
|
Каждый таргет в CMake — это «чёрный ящик» с двумя границами:
|
||||||
|
|
||||||
|
- **внутренняя** — то, что нужно только для компиляции самого таргета
|
||||||
|
- **внешняя** — то, что таргет «экспортирует» своим потребителям
|
||||||
|
|
||||||
|
Ключевые слова `PRIVATE`, `PUBLIC` и `INTERFACE` управляют тем, в какую из этих границ попадает свойство.
|
||||||
|
|
||||||
|
``````bash
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ lib_a │
|
||||||
|
│ │
|
||||||
|
│ PRIVATE │ INTERFACE │
|
||||||
|
│ (только внутри) │ (только снаружи) │
|
||||||
|
│ │ │
|
||||||
|
│ PUBLIC = PRIVATE + INTERFACE │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
│ target_link_libraries(app PRIVATE lib_a)
|
||||||
|
▼
|
||||||
|
[ app ] ← получает только INTERFACE-свойства lib_a
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Определения
|
||||||
|
|
||||||
|
| Ключевое слово | Применяется к самому таргету | Передаётся потребителям |
|
||||||
|
|----------------|:----------------------------:|:-----------------------:|
|
||||||
|
| `PRIVATE` | ✅ | ❌ |
|
||||||
|
| `PUBLIC` | ✅ | ✅ |
|
||||||
|
| `INTERFACE` | ❌ | ✅ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Разбор на примерах
|
||||||
|
|
||||||
|
### Пример 1 — `target_include_directories`
|
||||||
|
|
||||||
|
``````bash
|
||||||
|
src/
|
||||||
|
├── lib_math/
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ ├── include/ ← публичные заголовки (нужны потребителям)
|
||||||
|
│ │ └── math.h
|
||||||
|
│ ├── internal/ ← внутренние заголовки (только для lib_math)
|
||||||
|
│ │ └── impl.h
|
||||||
|
│ └── math.c
|
||||||
|
└── app/
|
||||||
|
├── CMakeLists.txt
|
||||||
|
└── main.c ← #include "math.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# lib_math/CMakeLists.txt
|
||||||
|
add_library(lib_math STATIC math.c)
|
||||||
|
|
||||||
|
target_include_directories(lib_math
|
||||||
|
PRIVATE internal/ # impl.h нужен только при компиляции math.c
|
||||||
|
PUBLIC include/ # math.h нужен и lib_math, и всем её потребителям
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# app/CMakeLists.txt
|
||||||
|
add_library(app main.c)
|
||||||
|
target_link_libraries(app PRIVATE lib_math)
|
||||||
|
# app автоматически получает include/ через PUBLIC-свойство lib_math
|
||||||
|
# app НЕ получает internal/ — оно PRIVATE
|
||||||
|
```
|
||||||
|
|
||||||
|
**Итог:** `main.c` может писать `#include "math.h"`, но не видит `impl.h`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Пример 2 — `target_compile_definitions`
|
||||||
|
|
||||||
|
``````bash
|
||||||
|
lib_json ──→ lib_http ──→ app
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# lib_json
|
||||||
|
add_library(lib_json STATIC json.c)
|
||||||
|
target_compile_definitions(lib_json
|
||||||
|
PRIVATE JSON_INTERNAL_DEBUG # дефайн только для json.c
|
||||||
|
PUBLIC JSON_VERSION=2 # нужен и json.c, и потребителям
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# lib_http линкуется с lib_json
|
||||||
|
add_library(lib_http STATIC http.c)
|
||||||
|
target_link_libraries(lib_http PUBLIC lib_json)
|
||||||
|
# lib_http транзитивно передаёт JSON_VERSION=2 дальше в app
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# app
|
||||||
|
add_executable(app main.c)
|
||||||
|
target_link_libraries(app PRIVATE lib_http)
|
||||||
|
# app видит JSON_VERSION=2 (транзитивно через lib_http → lib_json)
|
||||||
|
# app НЕ видит JSON_INTERNAL_DEBUG (PRIVATE)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Пример 3 — `INTERFACE` (header-only библиотека)
|
||||||
|
|
||||||
|
`INTERFACE` используется тогда, когда таргет сам **не компилируется** — например, header-only библиотека или набор флагов.
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# Набор флагов для встроенных таргетов — сам не компилируется
|
||||||
|
add_library(flags_embedded INTERFACE)
|
||||||
|
|
||||||
|
target_compile_options(flags_embedded INTERFACE
|
||||||
|
-mcpu=cortex-m7
|
||||||
|
-mfpu=fpv5-d16
|
||||||
|
-mfloat-abi=hard
|
||||||
|
-mthumb
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(flags_embedded INTERFACE
|
||||||
|
ARM_MATH_CM7
|
||||||
|
__FPU_PRESENT=1
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# Любой firmware-таргет подключает флаги одной строкой
|
||||||
|
target_link_libraries(firmware_app PRIVATE flags_embedded)
|
||||||
|
# firmware_app получает все -mcpu, -mfpu и дефайны
|
||||||
|
```
|
||||||
|
|
||||||
|
Такой паттерн часто используется для:
|
||||||
|
|
||||||
|
- HAL/SDK флагов конкретного МК
|
||||||
|
- Флагов линкера (`-T linker.ld`)
|
||||||
|
- Опций оптимизации для конкретного сценария сборки
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Пример 4 — транзитивность
|
||||||
|
|
||||||
|
Понять транзитивность важно: свойства распространяются по цепочке зависимостей.
|
||||||
|
|
||||||
|
```
|
||||||
|
lib_base ──→ lib_mid ──→ app
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
add_library(lib_base STATIC base.c)
|
||||||
|
target_compile_definitions(lib_base
|
||||||
|
PUBLIC BASE_FEATURE_ENABLED # пойдёт вглубь цепочки
|
||||||
|
PRIVATE BASE_INTERNAL # остановится здесь
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(lib_mid STATIC mid.c)
|
||||||
|
target_link_libraries(lib_mid PUBLIC lib_base)
|
||||||
|
# ^^^^^^
|
||||||
|
# PUBLIC здесь означает: "lib_mid использует lib_base,
|
||||||
|
# и мои потребители тоже должны о ней знать"
|
||||||
|
|
||||||
|
add_executable(app main.c)
|
||||||
|
target_link_libraries(app PRIVATE lib_mid)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Что видит `app`:**
|
||||||
|
|
||||||
|
| Дефайн | Виден в app? | Причина |
|
||||||
|
|-----------------------|:------------:|--------------------------------------------------|
|
||||||
|
| `BASE_FEATURE_ENABLED`| ✅ | PUBLIC в lib_base → PUBLIC в lib_mid → app |
|
||||||
|
| `BASE_INTERNAL` | ❌ | PRIVATE в lib_base, цепочка обрывается |
|
||||||
|
|
||||||
|
Если бы `lib_mid` слинковался с `lib_base` через `PRIVATE`:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
target_link_libraries(lib_mid PRIVATE lib_base)
|
||||||
|
# тогда app НЕ увидел бы BASE_FEATURE_ENABLED — цепочка оборвалась бы на lib_mid
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Применимость к командам
|
||||||
|
|
||||||
|
Ключевые слова работают одинаково во всех `target_*` командах:
|
||||||
|
|
||||||
|
| Команда | Типичное использование |
|
||||||
|
|--------------------------------|----------------------------------------------------------|
|
||||||
|
| `target_include_directories` | PRIVATE — внутренние папки; PUBLIC — публичные заголовки |
|
||||||
|
| `target_compile_definitions` | PRIVATE — отладочные дефайны; PUBLIC — версии API |
|
||||||
|
| `target_compile_options` | PRIVATE — флаги оптимизации; INTERFACE — флаги МК |
|
||||||
|
| `target_link_libraries` | PRIVATE — внутр. зависимость; PUBLIC — транзитивная |
|
||||||
|
| `target_link_options` | INTERFACE — скрипт линкера для всей цепочки |
|
||||||
|
| `target_sources` | Всегда PRIVATE — исходники не передаются потребителям |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Правило выбора
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Нужно ли это свойство самому таргету?
|
||||||
|
│
|
||||||
|
ДА ──→ Нужно ли оно потребителям?
|
||||||
|
│ │
|
||||||
|
│ ДА ──→ PUBLIC
|
||||||
|
│ │
|
||||||
|
│ НЕТ ──→ PRIVATE
|
||||||
|
│
|
||||||
|
НЕТ ──→ Нужно ли оно потребителям?
|
||||||
|
│
|
||||||
|
ДА ──→ INTERFACE
|
||||||
|
│
|
||||||
|
НЕТ ──→ (не добавляйте это свойство вообще)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
566
docs/DEV_ARCH.md
Normal file
566
docs/DEV_ARCH.md
Normal file
|
|
@ -0,0 +1,566 @@
|
||||||
|
# Архитектура рабочего окружения разработчика
|
||||||
|
|
||||||
|
> Проект: TFT Firmware (MIMXRT1052CVJ5B)
|
||||||
|
> Документ описывает итоговый рабочий процесс разработчиков: от разворачивания
|
||||||
|
> окружения до сборки, тестирования, отладки и прошивки платы.
|
||||||
|
> Производственный сервер описан кратко — подробно в отдельном документе.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Концепция
|
||||||
|
|
||||||
|
Рабочее окружение разделено на два контекста с чёткой границей:
|
||||||
|
|
||||||
|
**Devcontainer** — всё что касается кода: сборка, статический анализ,
|
||||||
|
форматирование, host-тесты, подготовка HAB-образов. Разработчик проводит
|
||||||
|
здесь большую часть времени. Управляется через VSCode tasks и `scripts/build.just`.
|
||||||
|
|
||||||
|
**Хост** — всё что касается железа: прошивка платы через USB, отладка
|
||||||
|
через JLink/probe-rs. Управляется через корневой `Justfile`.
|
||||||
|
|
||||||
|
Такое разделение решает несколько проблем: USB-устройства не требуют
|
||||||
|
проброса в контейнер; оба разработчика работают в идентичных условиях;
|
||||||
|
CI использует те же команды что и локальная разработка.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Компоненты окружения
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ПК разработчика
|
||||||
|
│
|
||||||
|
├── Хост (Linux / macOS / Windows + Git Bash)
|
||||||
|
│ ├── just ← запуск задач хостового уровня
|
||||||
|
│ ├── docker ← управление devcontainer
|
||||||
|
│ ├── git ← работа с репозиторием
|
||||||
|
│ ├── uv + spsdk ← прошивка платы (flash_usb.py, sdphost, blhost)
|
||||||
|
│ ├── JLinkGDBServer / probe-rs ← сервер отладки (USB → TCP :2331)
|
||||||
|
│ └── VSCode ← IDE (Dev Containers extension)
|
||||||
|
│
|
||||||
|
├── Devcontainer (Docker)
|
||||||
|
│ ├── ARM GCC 13.3 ← кросс-компилятор
|
||||||
|
│ ├── cmake + ninja ← система сборки
|
||||||
|
│ ├── clang-17 ← компилятор для host-тестов
|
||||||
|
│ ├── clangd-17 ← LSP (автодополнение, диагностика)
|
||||||
|
│ ├── clang-tidy-17 ← статический анализ
|
||||||
|
│ ├── clang-format-17 ← форматирование кода
|
||||||
|
│ ├── cmake-format ← форматирование CMakeLists
|
||||||
|
│ ├── just ← запуск задач внутри контейнера
|
||||||
|
│ ├── uv + spsdk ← сборка HAB-образов (только nxpimage)
|
||||||
|
│ └── Unity + fff ← фреймворки host-тестов
|
||||||
|
│
|
||||||
|
└── Плата TFT (IMXRT1052) — на столе у разработчика
|
||||||
|
├── USB ──────────────▶ хост (SDP-режим, прошивка)
|
||||||
|
├── SWD ──────────────▶ JLink/probe-rs на хосте (отладка)
|
||||||
|
└── CAN / UART / IO ──▶ локальный стенд (target-тесты)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Что устанавливается и где
|
||||||
|
|
||||||
|
| Инструмент | Хост | Devcontainer | Сервер |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `just` | ✅ | ✅ Dockerfile | ✅ |
|
||||||
|
| `docker` | ✅ | — | — |
|
||||||
|
| `git` | ✅ | ✅ | ✅ |
|
||||||
|
| `uv` | ✅ | ✅ Dockerfile | ✅ |
|
||||||
|
| `spsdk` | ✅ uv sync | ✅ uv sync | ✅ uv sync |
|
||||||
|
| ARM GCC toolchain | — | ✅ | — |
|
||||||
|
| `cmake` / `ninja` | — | ✅ | — |
|
||||||
|
| `clang` / `clangd` | — | ✅ | — |
|
||||||
|
| Unity / fff | — | ✅ | — |
|
||||||
|
| JLink / probe-rs | ✅ | — | — |
|
||||||
|
|
||||||
|
`spsdk` присутствует везде, но с разными ролями:
|
||||||
|
|
||||||
|
- **devcontainer** — только `nxpimage` для сборки HAB-образов
|
||||||
|
- **хост** — полный стек: `nxpimage` + `sdphost` + `blhost` для прошивки
|
||||||
|
- **сервер** — то же что на хосте, но для производственного сценария
|
||||||
|
|
||||||
|
Версия `spsdk` зафиксирована в `tools/host/uv.lock` — все три места
|
||||||
|
используют одну и ту же версию.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Структура репозитория (automation-часть)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/
|
||||||
|
├── Justfile ← хост: прошивка, setup, pipeline
|
||||||
|
├── scripts/
|
||||||
|
│ └── bootstrap.sh ← уровень 0: just → just bootstrap
|
||||||
|
│ └── build.just ← devcontainer: сборка, тесты, HAB
|
||||||
|
├── .devcontainer/
|
||||||
|
│ ├── Dockerfile
|
||||||
|
│ └── devcontainer.json
|
||||||
|
├── tools/
|
||||||
|
│ └── host/
|
||||||
|
│ ├── hab/
|
||||||
|
│ │ ├── hab_firmware_test_debug.yaml
|
||||||
|
│ │ ├── hab_firmware_test_release.yaml
|
||||||
|
│ │ ├── hab_bootloader_debug.yaml
|
||||||
|
│ │ ├── hab_bootloader_release.yaml
|
||||||
|
│ │ ├── hab_app_debug.yaml
|
||||||
|
│ │ └── hab_app_release.yaml
|
||||||
|
│ ├── dcd/
|
||||||
|
│ │ ├── dcd.bin
|
||||||
|
│ │ └── ivt_flashloader.bin
|
||||||
|
│ ├── flash_usb.py
|
||||||
|
│ ├── pyproject.toml
|
||||||
|
│ └── uv.lock
|
||||||
|
├── .vscode/
|
||||||
|
│ └── tasks.json ← UI для build.just (внутри devcontainer)
|
||||||
|
├── CMakePresets.json
|
||||||
|
├── cmake/
|
||||||
|
├── sdk/
|
||||||
|
├── bsp/
|
||||||
|
├── lib/
|
||||||
|
├── firmware/
|
||||||
|
│ ├── test/
|
||||||
|
│ ├── bootloader/
|
||||||
|
│ └── app/
|
||||||
|
└── tests/ ← host-тесты (Unity + fff)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Первый запуск: разворачивание окружения
|
||||||
|
|
||||||
|
### 5.1 Предварительные требования
|
||||||
|
|
||||||
|
| Платформа | Что нужно до bootstrap |
|
||||||
|
|---|---|
|
||||||
|
| Linux | `docker`, `git`, `curl` |
|
||||||
|
| macOS | Docker Desktop, `git` (Xcode CLT) |
|
||||||
|
| Windows | Docker Desktop, Git for Windows → **использовать Git Bash** |
|
||||||
|
|
||||||
|
### 5.2 Единственная команда для нового разработчика
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repo-url> && cd <repo>
|
||||||
|
./scripts/bootstrap.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 Что делает bootstrap
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bootstrap.sh (уровень 0)
|
||||||
|
│
|
||||||
|
├── определить платформу (Linux / macOS / Windows Git Bash)
|
||||||
|
│ uname: MINGW64_NT-... → windows, Linux → linux, Darwin → macos
|
||||||
|
│
|
||||||
|
├── проверить just (semver без sort -V — работает в Git Bash)
|
||||||
|
│ < 1.27.0 или отсутствует:
|
||||||
|
│ Linux/macOS → curl | bash → ~/.local/bin/just
|
||||||
|
│ Windows → winget install --id Casey.Just
|
||||||
|
│ (перезапустить Git Bash после установки)
|
||||||
|
│
|
||||||
|
└── exec just bootstrap
|
||||||
|
│
|
||||||
|
├── [1/3] check-deps
|
||||||
|
│ just >= 1.27.0 · uv >= 0.4.0 · docker >= 24.0.0
|
||||||
|
│ платформо-зависимые подсказки при ошибках
|
||||||
|
│
|
||||||
|
├── [2/3] setup-udev (только Linux)
|
||||||
|
│ /etc/udev/rules.d/99-nxp-mimxrt.rules:
|
||||||
|
│ 1FC9:0130 ← NXP BootROM (SDP-режим)
|
||||||
|
│ 15A2:0073 ← NXP Flashloader
|
||||||
|
│ usermod -a -G plugdev $USER
|
||||||
|
│ требует re-login · на macOS/Windows пропускается
|
||||||
|
│
|
||||||
|
└── [3/3] setup-tools
|
||||||
|
uv sync в tools/host/
|
||||||
|
SHA-256 uv.lock кэшируется в .cache/
|
||||||
|
повторный вызов мгновенный если lockfile не изменился
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.4 После bootstrap
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Открыть VSCode → "Reopen in Container"
|
||||||
|
```
|
||||||
|
|
||||||
|
`postCreateCommand` выполняется автоматически при поднятии контейнера:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tools/host && uv sync &&
|
||||||
|
cd ../.. &&
|
||||||
|
cmake --preset host-debug &&
|
||||||
|
cmake --preset Debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Прогрев CMake-кэша нужен чтобы clangd и IntelliSense заработали сразу,
|
||||||
|
без первой ручной сборки.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Прошивки, boot-стратегии и матрица сборки
|
||||||
|
|
||||||
|
### 6.1 Три подпроекта
|
||||||
|
|
||||||
|
| Прошивка | Boot-стратегия | DCD | Назначение |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `firmware_test` | XIP из Flash | ✅ | Входной контроль, тестирование периферии |
|
||||||
|
| `bootloader` | Копирование в ITCM | ❌ | Загрузчик, не использует SDRAM |
|
||||||
|
| `app` | XIP + буферы в SDRAM | ✅ | Основное приложение (FreeRTOS, LCDIF) |
|
||||||
|
|
||||||
|
### 6.2 Матрица сборки
|
||||||
|
|
||||||
|
Каждый проект собирается в двух режимах:
|
||||||
|
|
||||||
|
| | Debug | Release |
|
||||||
|
|---|---|---|
|
||||||
|
| `firmware_test` | разработка, отладка | HAB для сервера |
|
||||||
|
| `bootloader` | отладка загрузчика | финальная прошивка |
|
||||||
|
| `app` | отладка приложения | финальная прошивка |
|
||||||
|
|
||||||
|
### 6.3 CMake пресеты
|
||||||
|
|
||||||
|
```bash
|
||||||
|
configurePresets: Debug · Release · host-debug · host-release
|
||||||
|
|
||||||
|
buildPresets (ARM):
|
||||||
|
all-debug / all-release ← все проекты (для CI)
|
||||||
|
firmware-test-debug / release
|
||||||
|
bootloader-debug / release
|
||||||
|
app-debug / release
|
||||||
|
|
||||||
|
buildPresets (host):
|
||||||
|
host-debug-build / host-release-build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 Карта Flash (W25Q128, 16 MB)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
0x60000000 FCB — Flash Config Block 512 байт (пишет Flashloader)
|
||||||
|
0x60001000 IVT + BDT ← начало HAB-образа
|
||||||
|
0x60001040 DCD — инициализация SDRAM ~1088 байт (firmware_test, app)
|
||||||
|
0x60003000 Код прошивки (.text, .data…)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Рабочий процесс разработчика
|
||||||
|
|
||||||
|
### 7.1 Карта задач по контекстам
|
||||||
|
|
||||||
|
| Задача | Где |
|
||||||
|
|---|---|
|
||||||
|
| Написание кода, clangd, форматирование | devcontainer |
|
||||||
|
| Статический анализ (clang-tidy) | devcontainer |
|
||||||
|
| Host-тесты (Unity + fff) | devcontainer |
|
||||||
|
| Сборка ARM firmware (ELF) | devcontainer |
|
||||||
|
| Подготовка HAB-образов (nxpimage) | devcontainer |
|
||||||
|
| Прошивка платы через USB | **хост** |
|
||||||
|
| Отладка — GDB-сервер (JLink/probe-rs) | **хост** |
|
||||||
|
| Отладка — GDB-клиент | devcontainer → хост по TCP |
|
||||||
|
| Target-тесты (управление стендом) | **хост** |
|
||||||
|
|
||||||
|
### 7.2 Типичная сессия разработки
|
||||||
|
|
||||||
|
```
|
||||||
|
Открыть VSCode → работать в devcontainer весь день
|
||||||
|
│
|
||||||
|
├── писать код
|
||||||
|
│
|
||||||
|
├── Ctrl+Shift+P → "Run Task" → 🧪 Host Tests (Debug)
|
||||||
|
│ или в терминале: just --justfile just/build.just test-host
|
||||||
|
│
|
||||||
|
├── Ctrl+Shift+P → "Run Task" → 🔨 Build → firmware-test · debug
|
||||||
|
│ → build/Debug/firmware/test/firmware_test.elf
|
||||||
|
│
|
||||||
|
├── Ctrl+Shift+P → "Run Task" → 📦 HAB Image → firmware-test · debug
|
||||||
|
│ → build/Debug/firmware_test_hab.bin
|
||||||
|
│
|
||||||
|
│ Переключиться в хостовый терминал
|
||||||
|
│
|
||||||
|
├── just flash firmware_test debug ← прошить отладочный образ
|
||||||
|
│ или
|
||||||
|
├── just flash-ram firmware_test debug ← загрузить в RAM (быстро, без износа Flash)
|
||||||
|
│
|
||||||
|
└── F5 в VSCode → отладка через JLink
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 VSCode Tasks (внутри devcontainer)
|
||||||
|
|
||||||
|
| Таск | Input 1 | Input 2 | Команда |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 🔨 Build | project | debug/release | `just build-<project>-<type>` |
|
||||||
|
| 🧪 Host Tests (Debug) | — | — | `just test-host` |
|
||||||
|
| 🧪 Host Tests (Release) | — | — | `just test-host-release` |
|
||||||
|
| 📦 HAB Image | project | debug/release | `just hab-<project>-<type>` |
|
||||||
|
| 📦 HAB All (Debug) | — | — | `just hab-all-debug` |
|
||||||
|
| 📦 HAB All (Release) | — | — | `just hab-all-release` |
|
||||||
|
| 🗑️ Clean | — | — | `just clean` |
|
||||||
|
|
||||||
|
Таски «Build» и «HAB Image» запрашивают два input последовательно:
|
||||||
|
сначала проект (`firmware-test / bootloader / app / all`),
|
||||||
|
затем тип (`debug / release`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Прошивка платы (хост)
|
||||||
|
|
||||||
|
### 8.1 Перевод платы в SDP-режим
|
||||||
|
|
||||||
|
```
|
||||||
|
1. BOOT_MOD_1 → 3V3
|
||||||
|
2. Reset
|
||||||
|
3. Подключить USB к хосту
|
||||||
|
→ плата определяется как VID:PID = 1FC9:0130
|
||||||
|
4. Выполнить нужный just flash-* рецепт
|
||||||
|
5. После прошивки: BOOT_MOD_1 → GND, Reset
|
||||||
|
→ плата стартует из Flash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 Команды прошивки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Основной рецепт (project × type)
|
||||||
|
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, мгновенный старт
|
||||||
|
# Удобно для частых итераций: не изнашивает Flash, не нужен BOOT_MOD переключатель
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 Что происходит внутри flash_usb.py
|
||||||
|
|
||||||
|
```
|
||||||
|
Плата в SDP-режиме (1FC9:0130)
|
||||||
|
│
|
||||||
|
├── sdphost: загрузить ivt_flashloader.bin в RAM (0x20001C00)
|
||||||
|
└── sdphost: jump-address 0x20001C00
|
||||||
|
│
|
||||||
|
│ ожидание до 10с — Flashloader поднимается как 15A2:0073
|
||||||
|
│
|
||||||
|
Flashloader (15A2:0073)
|
||||||
|
├── fill-memory + configure-memory (0xC0000007) — инициализация FlexSPI
|
||||||
|
├── flash-erase-region 0x60000000
|
||||||
|
├── fill-memory + configure-memory (0xF000000F) — запись FCB
|
||||||
|
├── write-memory 0x60001000 ← HAB-образ
|
||||||
|
└── reset
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Отладка
|
||||||
|
|
||||||
|
JLink/probe-rs работает на хосте напрямую через USB/SWD.
|
||||||
|
GDB-клиент в devcontainer подключается к серверу по TCP.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Хост
|
||||||
|
├── JLinkGDBServer -device MIMXRT1052 -if SWD -port 2331
|
||||||
|
│ USB/SWD → плата
|
||||||
|
└── host.docker.internal:2331 ← доступен из devcontainer
|
||||||
|
|
||||||
|
Devcontainer
|
||||||
|
└── arm-none-eabi-gdb / probe-rs
|
||||||
|
target remote host.docker.internal:2331
|
||||||
|
```
|
||||||
|
|
||||||
|
`.vscode/launch.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"servertype": "external",
|
||||||
|
"gdbTarget": "host.docker.internal:2331",
|
||||||
|
"executable": "${workspaceFolder}/build/Debug/firmware/test/firmware_test.elf"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`host.docker.internal` — стандартный DNS-алиас Docker для хоста.
|
||||||
|
Работает на macOS, Windows и Linux (Docker Desktop).
|
||||||
|
|
||||||
|
> USB-passthrough программатора в Docker на macOS невозможен, на других
|
||||||
|
> платформах нестабилен. TCP-мост — единственное надёжное решение для
|
||||||
|
> всех платформ.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Тесты
|
||||||
|
|
||||||
|
### 10.1 Host-тесты
|
||||||
|
|
||||||
|
Выполняются в devcontainer на хостовом компиляторе (x86/arm64). Железо не нужно.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Фреймворк: Unity + fff
|
||||||
|
Пресеты: host-debug / host-release
|
||||||
|
Компилятор: системный clang-17 (не ARM GCC)
|
||||||
|
Запуск: just --justfile just/build.just test-host
|
||||||
|
Результат: JUnit XML → VSCode CTest Lab + GitLab CI
|
||||||
|
```
|
||||||
|
|
||||||
|
`BUILD_TESTS_HOST=ON` отключает ARM-специфику (BSP, SDK) — компилируются
|
||||||
|
только тестируемые модули и fff-заглушки.
|
||||||
|
|
||||||
|
### 10.2 Target-тесты
|
||||||
|
|
||||||
|
Выполняются на физической плате. Прошивается `firmware_test`,
|
||||||
|
стенд подаёт сигналы и проверяет ответы.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Стенд (M5StampPLC или аналог) ←→ Плата TFT
|
||||||
|
|
||||||
|
Тестируемые подсистемы:
|
||||||
|
SDRAM 32 MB — чтение/запись паттернов
|
||||||
|
QSPI Flash — erase / write / verify
|
||||||
|
CAN — loopback + внешний фрейм от стенда
|
||||||
|
UART TTL — echo-тест
|
||||||
|
UART +24V изол. — echo-тест
|
||||||
|
Гальв. входы +24V — состояния при подаче напряжения от стенда
|
||||||
|
RTC BM8563 — установка / чтение времени
|
||||||
|
SD-карта (SDIO) — монтирование, R/W файл
|
||||||
|
MQS (аудио) — воспроизведение тестового сигнала
|
||||||
|
IR-приёмник — приём тестового кода от стенда
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Жизненный цикл изменений
|
||||||
|
|
||||||
|
```bash
|
||||||
|
feature-ветка
|
||||||
|
│
|
||||||
|
├── код в devcontainer
|
||||||
|
│ 🧪 Host Tests ← зелёные?
|
||||||
|
│ 🔨 Build firmware-test debug ← компилируется?
|
||||||
|
│
|
||||||
|
├── проверка на железе
|
||||||
|
│ 📦 HAB Image → firmware-test · debug
|
||||||
|
│ just flash-test-debug ← прошить
|
||||||
|
│ target-тесты со стендом ← периферия работает?
|
||||||
|
│
|
||||||
|
├── подготовка к MR
|
||||||
|
│ 📦 HAB All (Release) ← финальные образы
|
||||||
|
│ just flash firmware_test release ← убедиться что release работает
|
||||||
|
│
|
||||||
|
└── Merge Request → GitLab
|
||||||
|
[CI pipeline — отдельная тема]
|
||||||
|
host-тесты, сборка, публикация артефактов
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Производственный сервер
|
||||||
|
just incoming → firmware_test release → HIL
|
||||||
|
just production → bootloader + app release
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Обновление зависимостей
|
||||||
|
|
||||||
|
### spsdk (на хосте разработчика)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just upgrade-tools 3.8.0
|
||||||
|
git add tools/host/uv.lock tools/host/pyproject.toml
|
||||||
|
git commit -m "chore: upgrade spsdk to 3.8.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
После этого у всех разработчиков и в контейнере обновится автоматически
|
||||||
|
при следующем `just setup-tools` / `uv sync`.
|
||||||
|
|
||||||
|
### just в Dockerfile
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ARG JUST_VERSION=1.40.0 # .devcontainer/Dockerfile — единственное место
|
||||||
|
```
|
||||||
|
|
||||||
|
### ARM toolchain
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
ARG TOOLCHAIN_VERSION=14.2.rel1 # .devcontainer/Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
Пересборка инвалидирует только Stage 1 (toolchain). Stage 2
|
||||||
|
(clang, cmake и др.) берётся из кэша — пересборка быстрая.
|
||||||
|
|
||||||
|
### После git pull если изменился uv.lock
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just setup-tools # автоматически обнаружит изменение и выполнит uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Производственный сервер (к сведению)
|
||||||
|
|
||||||
|
Сервер работает **только с готовыми проверенными артефактами**.
|
||||||
|
Никакой сборки, никакого компилятора.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Источник: GitLab Releases или FTP
|
||||||
|
— только теггированные релизы, прошедшие CI
|
||||||
|
|
||||||
|
Сценарий входного контроля новой платы:
|
||||||
|
1. just incoming
|
||||||
|
└── flash firmware_test release → HIL-тесты периферии
|
||||||
|
2. Тесты пройдены:
|
||||||
|
just production
|
||||||
|
├── flash bootloader release
|
||||||
|
└── flash app release
|
||||||
|
|
||||||
|
Установлено: just · uv + spsdk · git
|
||||||
|
НЕ установлено: docker · cmake · компилятор · ARM toolchain
|
||||||
|
```
|
||||||
|
|
||||||
|
Детальный `server.just` и пайплайн сервера — отдельная задача.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Приложение А: минимальные версии
|
||||||
|
|
||||||
|
| Инструмент | Версия | Причина |
|
||||||
|
|---|---|---|
|
||||||
|
| `just` | 1.27.0 | поддержка `[group()]` |
|
||||||
|
| `uv` | 0.4.0 | стабильный lockfile формат |
|
||||||
|
| `docker` | 24.0.0 | Compose v2, `--build-arg` |
|
||||||
|
| `spsdk` | 3.7.x | совместимость с HAB yaml-форматом |
|
||||||
|
| ARM GCC | 13.3.rel1 | C11, LTO, текущий SDK |
|
||||||
|
| clang/clangd | 17 | поддержка `If:` в `.clangd` |
|
||||||
|
|
||||||
|
## Приложение Б: быстрая шпаргалка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ── Первый запуск ──────────────────────────────────────────────
|
||||||
|
./scripts/bootstrap.sh # инициализация хоста
|
||||||
|
# VSCode → Reopen in Container
|
||||||
|
|
||||||
|
# ── Внутри devcontainer (терминал VSCode) ──────────────────────
|
||||||
|
just --justfile just/build.just test-host
|
||||||
|
just --justfile just/build.just build-firmware-test-debug
|
||||||
|
just --justfile just/build.just build-app-release
|
||||||
|
just --justfile just/build.just hab-firmware-test-debug
|
||||||
|
just --justfile just/build.just hab-all-release
|
||||||
|
just --justfile just/build.just clean
|
||||||
|
|
||||||
|
# ── Хостовый терминал — прошивка ───────────────────────────────
|
||||||
|
just flash firmware_test debug # во Flash
|
||||||
|
just flash firmware_test release
|
||||||
|
just flash bootloader release
|
||||||
|
just flash app release
|
||||||
|
just flash-ram firmware_test # в RAM (быстро, без износа Flash)
|
||||||
|
just flash-production # bootloader + app release
|
||||||
|
|
||||||
|
# ── Хостовый терминал — обслуживание ───────────────────────────
|
||||||
|
just scan # найти NXP USB-устройства
|
||||||
|
just sdp-status # проверить BootROM
|
||||||
|
just setup-tools # обновить spsdk после git pull
|
||||||
|
just check-deps # проверить версии инструментов
|
||||||
|
```
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
# Программные компоненты ThirdParty
|
|
||||||
|
|
||||||
## Библиотеки сторонних разработчиков, загруженные в виде субмодулей
|
|
||||||
|
|
||||||
* [SEGGER_RTT](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/)
|
|
||||||
* [Unity](https://www.throwtheswitch.org/unity)
|
|
||||||
* [FFF](https://github.com/meekrosoft/fff)
|
|
||||||
|
|
||||||
## Работа с Git-Submodules
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Добавление субмодулей (например SEGGER_RTT)
|
|
||||||
git submodule add https://github.com/SEGGERMicro/RTT ThirdParty/RTT
|
|
||||||
# 2. Синхронизация состояния субмодулей, загруженных локально с remote
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
# Полная переинициализация субмодулей (На примере SEGGER_RTT)
|
|
||||||
# 1. Удалить submodule полностью
|
|
||||||
git submodule deinit -f ThirdParty/RTT
|
|
||||||
rm -rf .git/modules/ThirdParty/RTT
|
|
||||||
git rm -rf ThirdParty/RTT
|
|
||||||
|
|
||||||
# 2. Удалить .gitmodules запись
|
|
||||||
vim .gitmodules # удалить секцию [submodule "ThirdParty/RTT"]
|
|
||||||
|
|
||||||
# 3. Добавить заново
|
|
||||||
git submodule add https://github.com/SEGGERMicro/RTT ThirdParty/RTT
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
add_executable(firmware_test)
|
add_executable(firmware_test)
|
||||||
|
|
||||||
target_sources(firmware_test PRIVATE main.c
|
target_sources(firmware_test
|
||||||
${PROJECT_SOURCE_DIR}/bsp/board/syscalls.c)
|
PRIVATE main.c ${PROJECT_SOURCE_DIR}/bsp/generated/syscalls.c)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Зависимости — только то что нужно для входного контроля bsp_board транзитивно
|
# Зависимости — только то что нужно для входного контроля bsp_board транзитивно
|
||||||
|
|
@ -36,6 +36,7 @@ target_link_options(
|
||||||
-Wl,-Map=${CMAKE_BINARY_DIR}/firmware_test.map
|
-Wl,-Map=${CMAKE_BINARY_DIR}/firmware_test.map
|
||||||
-T${PROJECT_SOURCE_DIR}/cmake/linker/MIMXRT1052xxxxx_flexspi_nor.ld)
|
-T${PROJECT_SOURCE_DIR}/cmake/linker/MIMXRT1052xxxxx_flexspi_nor.ld)
|
||||||
|
|
||||||
|
# TODO: дефайны BOOT
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Post-build: генерация .bin для прошивки через blhost
|
# Post-build: генерация .bin для прошивки через blhost
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
|
||||||
#include "fsl_gpio.h"
|
#include "fsl_gpio.h"
|
||||||
#include "pin_mux.h"
|
#include "pin_mux.h"
|
||||||
|
|
||||||
|
|
@ -27,12 +26,12 @@
|
||||||
* Code
|
* Code
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
int main(void) {
|
int main(void)
|
||||||
const uint32_t USER_DELAY_US = 1000000;
|
{
|
||||||
BOARD_Init();
|
BOARD_Init();
|
||||||
// GPIO_PinWrite(BOARD_INITPINS_UserLed1_PORT, BOARD_INITPINS_UserLed1_PIN,
|
GPIO_PinWrite(BOARD_INITPINS_UserLed1_PORT, BOARD_INITPINS_UserLed1_PIN, 0);
|
||||||
// 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) {
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
157
scripts/bootstrap.sh
Executable file
157
scripts/bootstrap.sh
Executable file
|
|
@ -0,0 +1,157 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# scripts/bootstrap.sh
|
||||||
|
# Уровень 0: устанавливает just (если отсутствует), затем передаёт управление
|
||||||
|
# just bootstrap для полной инициализации окружения.
|
||||||
|
#
|
||||||
|
# Поддерживаемые платформы:
|
||||||
|
# Linux — bash (native)
|
||||||
|
# macOS — bash (native)
|
||||||
|
# Windows — Git Bash (поставляется вместе с git)
|
||||||
|
#
|
||||||
|
# Требования: bash >= 4, curl (Linux/macOS) или winget (Windows)
|
||||||
|
# Запуск: ./scripts/bootstrap.sh
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
JUST_VERSION="1.36.0"
|
||||||
|
LINUX_INSTALL_DIR="${HOME}/.local/bin"
|
||||||
|
|
||||||
|
BOLD="\033[1m"
|
||||||
|
RED="\033[0;31m"
|
||||||
|
YELLOW="\033[1;33m"
|
||||||
|
GREEN="\033[0;32m"
|
||||||
|
RESET="\033[0m"
|
||||||
|
|
||||||
|
info() { echo -e " ${BOLD}${*}${RESET}"; }
|
||||||
|
success() { echo -e " ${GREEN}✅ ${*}${RESET}"; }
|
||||||
|
warn() { echo -e " ${YELLOW}⚠️ ${*}${RESET}"; }
|
||||||
|
error() { echo -e " ${RED}❌ ${*}${RESET}"; }
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}=== TFT Firmware — Bootstrap ===${RESET}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 1. Определить платформу
|
||||||
|
# uname на Git Bash: MINGW64_NT-10.0-19045, MSYS_NT-..., CYGWIN_NT-...
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
_uname="$(uname -s)"
|
||||||
|
case "${_uname}" in
|
||||||
|
Linux*) PLATFORM="linux" ;;
|
||||||
|
Darwin*) PLATFORM="macos" ;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
|
||||||
|
*)
|
||||||
|
error "Unsupported platform: ${_uname}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
info "Platform detected: ${PLATFORM}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 2. Сравнение semver без sort -V (недоступен в Git Bash)
|
||||||
|
# Возвращает 0 если $1 >= $2
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
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}"
|
||||||
|
# Убрать нечисловые суффиксы (1.36.0-beta -> обнулить суффикс)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 3. Платформо-зависимая установка just
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
install_just_linux() {
|
||||||
|
info "Installing just ${JUST_VERSION} -> ${LINUX_INSTALL_DIR}"
|
||||||
|
mkdir -p "${LINUX_INSTALL_DIR}"
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh \
|
||||||
|
| bash -s -- --tag "${JUST_VERSION}" --to "${LINUX_INSTALL_DIR}"
|
||||||
|
|
||||||
|
if ! echo "${PATH}" | grep -q "${LINUX_INSTALL_DIR}"; then
|
||||||
|
warn "${LINUX_INSTALL_DIR} not in PATH -- adding for this session"
|
||||||
|
warn "Add to ~/.bashrc to make permanent:"
|
||||||
|
warn " export PATH=\"${LINUX_INSTALL_DIR}:\$PATH\""
|
||||||
|
export PATH="${LINUX_INSTALL_DIR}:${PATH}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_just_macos() {
|
||||||
|
if command -v brew &>/dev/null; then
|
||||||
|
info "Installing just via Homebrew..."
|
||||||
|
brew install just
|
||||||
|
else
|
||||||
|
install_just_linux
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_just_windows() {
|
||||||
|
# Предпочитаем winget -- кладёт just.exe в системный PATH автоматически
|
||||||
|
if command -v winget &>/dev/null; then
|
||||||
|
info "Installing just via winget..."
|
||||||
|
winget install --id Casey.Just \
|
||||||
|
--accept-package-agreements --accept-source-agreements || {
|
||||||
|
error "winget install failed."
|
||||||
|
echo " Run manually in PowerShell: winget install --id Casey.Just"
|
||||||
|
echo " Then restart Git Bash and re-run: ./scripts/bootstrap.sh"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
warn "Restart Git Bash so the new PATH from winget takes effect,"
|
||||||
|
warn "then re-run: ./scripts/bootstrap.sh"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
error "winget not found."
|
||||||
|
echo ""
|
||||||
|
echo " Options to install just on Windows:"
|
||||||
|
echo " 1. Install 'App Installer' from Microsoft Store (brings winget)"
|
||||||
|
echo " 2. Download just.exe manually: https://github.com/casey/just/releases"
|
||||||
|
echo " Place it in a directory that is in your Git Bash PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 4. Проверить / установить just
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
JUST_OK=false
|
||||||
|
|
||||||
|
if command -v just &>/dev/null; then
|
||||||
|
JUST_CURRENT="$(just --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
|
||||||
|
if semver_ge "${JUST_CURRENT}" "${JUST_VERSION}"; then
|
||||||
|
success "just ${JUST_CURRENT} (>= ${JUST_VERSION} required)"
|
||||||
|
JUST_OK=true
|
||||||
|
else
|
||||||
|
warn "just ${JUST_CURRENT} is outdated (need >= ${JUST_VERSION}), reinstalling..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${JUST_OK}" == "false" ]]; then
|
||||||
|
case "${PLATFORM}" in
|
||||||
|
linux) install_just_linux ;;
|
||||||
|
macos) install_just_macos ;;
|
||||||
|
windows) install_just_windows ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
JUST_CURRENT="$(just --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
|
||||||
|
success "just ${JUST_CURRENT} installed"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 5. Передать управление just bootstrap
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
info "Delegating to: just bootstrap"
|
||||||
|
echo ""
|
||||||
|
exec just bootstrap "$@"
|
||||||
208
scripts/build.just
Normal file
208
scripts/build.just
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
# =============================================================================
|
||||||
|
# scripts/build.just — сборка, тесты, HAB-образы
|
||||||
|
# Выполняется ТОЛЬКО внутри devcontainer (из терминала VSCode или tasks).
|
||||||
|
#
|
||||||
|
# Рабочая директория — корень репозитория (не scripts/).
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set working-directory := ".."
|
||||||
|
|
||||||
|
TOOLS_DIR := "tools/host"
|
||||||
|
BUILD_DIR := "build"
|
||||||
|
|
||||||
|
_default:
|
||||||
|
@just --list --justfile scripts/build.just --unsorted
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: build
|
||||||
|
#
|
||||||
|
# Матрица сборки:
|
||||||
|
# firmware-test × debug / release
|
||||||
|
# bootloader × debug / release
|
||||||
|
# app × debug / release
|
||||||
|
# all × debug / release (все проекты сразу, для CI)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
[private]
|
||||||
|
_configure-debug:
|
||||||
|
cmake --preset Debug
|
||||||
|
|
||||||
|
[private]
|
||||||
|
_configure-release:
|
||||||
|
cmake --preset Release
|
||||||
|
|
||||||
|
# ── firmware_test ─────────────────────────────────────────────────────────────
|
||||||
|
[group('build')]
|
||||||
|
build-firmware-test-debug: _configure-debug
|
||||||
|
cmake --build --preset firmware-test-debug
|
||||||
|
|
||||||
|
[group('build')]
|
||||||
|
build-firmware-test-release: _configure-release
|
||||||
|
cmake --build --preset firmware-test-release
|
||||||
|
|
||||||
|
# ── bootloader ───────────────────────────────────────────────────────────────
|
||||||
|
[group('build')]
|
||||||
|
build-bootloader-debug: _configure-debug
|
||||||
|
cmake --build --preset bootloader-debug
|
||||||
|
|
||||||
|
[group('build')]
|
||||||
|
build-bootloader-release: _configure-release
|
||||||
|
cmake --build --preset bootloader-release
|
||||||
|
|
||||||
|
# ── app ───────────────────────────────────────────────────────────────────────
|
||||||
|
[group('build')]
|
||||||
|
build-app-debug: _configure-debug
|
||||||
|
cmake --build --preset app-debug
|
||||||
|
|
||||||
|
[group('build')]
|
||||||
|
build-app-release: _configure-release
|
||||||
|
cmake --build --preset app-release
|
||||||
|
|
||||||
|
# ── все проекты сразу ─────────────────────────────────────────────────────────
|
||||||
|
[group('build')]
|
||||||
|
build-all-debug: _configure-debug
|
||||||
|
cmake --build --preset all-debug
|
||||||
|
|
||||||
|
[group('build')]
|
||||||
|
build-all-release: _configure-release
|
||||||
|
cmake --build --preset all-release
|
||||||
|
|
||||||
|
# ── утилиты ───────────────────────────────────────────────────────────────────
|
||||||
|
[group('build')]
|
||||||
|
clean:
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: test
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
[private]
|
||||||
|
_configure-host-debug:
|
||||||
|
cmake --preset host-debug
|
||||||
|
|
||||||
|
[private]
|
||||||
|
_configure-host-release:
|
||||||
|
cmake --preset host-release
|
||||||
|
|
||||||
|
[group('test')]
|
||||||
|
test-host: _configure-host-debug
|
||||||
|
cmake --build --preset host-debug-build
|
||||||
|
ctest --preset host-debug-test
|
||||||
|
|
||||||
|
[group('test')]
|
||||||
|
test-host-release: _configure-host-release
|
||||||
|
cmake --build --preset host-release-build
|
||||||
|
ctest --preset host-release-test
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ГРУППА: flash — подготовка HAB-образов
|
||||||
|
#
|
||||||
|
# Матрица HAB:
|
||||||
|
# firmware-test × debug / release
|
||||||
|
# bootloader × debug / release
|
||||||
|
# app × debug / release
|
||||||
|
# all × debug / release
|
||||||
|
#
|
||||||
|
# Debug HAB — для прошивки своей платы и отладки.
|
||||||
|
# Release HAB — для производственного сервера.
|
||||||
|
#
|
||||||
|
# HAB yaml конфиги:
|
||||||
|
# tools/host/hab/hab_<project>_debug.yaml — путь к Debug ELF
|
||||||
|
# tools/host/hab/hab_<project>_release.yaml — путь к Release ELF
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ── firmware_test ─────────────────────────────────────────────────────────────
|
||||||
|
[group('flash')]
|
||||||
|
hab-firmware-test-debug: build-firmware-test-debug
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_firmware_test_debug.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Debug/firmware_test_hab.bin"
|
||||||
|
echo " ✅ firmware_test_hab.bin (Debug)"
|
||||||
|
|
||||||
|
[group('flash')]
|
||||||
|
hab-firmware-test-release: build-firmware-test-release
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_firmware_test_release.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Release/firmware_test_hab.bin"
|
||||||
|
echo " ✅ firmware_test_hab.bin (Release)"
|
||||||
|
|
||||||
|
# ── bootloader ───────────────────────────────────────────────────────────────
|
||||||
|
[group('flash')]
|
||||||
|
hab-bootloader-debug: build-bootloader-debug
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_bootloader_debug.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Debug/bootloader_hab.bin"
|
||||||
|
echo " ✅ bootloader_hab.bin (Debug)"
|
||||||
|
|
||||||
|
[group('flash')]
|
||||||
|
hab-bootloader-release: build-bootloader-release
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_bootloader_release.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Release/bootloader_hab.bin"
|
||||||
|
echo " ✅ bootloader_hab.bin (Release)"
|
||||||
|
|
||||||
|
# ── app ───────────────────────────────────────────────────────────────────────
|
||||||
|
[group('flash')]
|
||||||
|
hab-app-debug: build-app-debug
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_app_debug.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Debug/app_hab.bin"
|
||||||
|
echo " ✅ app_hab.bin (Debug)"
|
||||||
|
|
||||||
|
[group('flash')]
|
||||||
|
hab-app-release: build-app-release
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "{{TOOLS_DIR}}/hab"
|
||||||
|
uv run nxpimage hab export --force \
|
||||||
|
-c hab_app_release.yaml \
|
||||||
|
-o "../../../{{BUILD_DIR}}/Release/app_hab.bin"
|
||||||
|
echo " ✅ app_hab.bin (Release)"
|
||||||
|
|
||||||
|
# ── все образы сразу ─────────────────────────────────────────────────────────
|
||||||
|
[group('flash')]
|
||||||
|
hab-all-debug: hab-firmware-test-debug hab-bootloader-debug hab-app-debug
|
||||||
|
@echo " ✅ All HAB images (Debug) ready"
|
||||||
|
|
||||||
|
[group('flash')]
|
||||||
|
hab-all-release: hab-firmware-test-release hab-bootloader-release hab-app-release
|
||||||
|
@echo " ✅ All HAB images (Release) ready"
|
||||||
|
|
||||||
|
# ── верификация образа (для отладки) ─────────────────────────────────────────
|
||||||
|
# Использование: just --justfile just/build.just hab-verify firmware_test debug
|
||||||
|
[group('flash')]
|
||||||
|
hab-verify project="firmware_test" type="release":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "{{project}}-{{type}}" in
|
||||||
|
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"
|
||||||
|
echo " Types: debug, release"
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
OUT="/tmp/hab_parse_{{project}}_{{type}}.yaml"
|
||||||
|
uv run nxpimage hab parse -b "${BIN}" -o "${OUT}"
|
||||||
|
echo " ✅ ${OUT}"
|
||||||
|
grep -E "(entry|csf|tag)" "${OUT}" || true
|
||||||
17
tools/host/hab/hab_app_debug.yaml
Normal file
17
tools/host/hab/hab_app_debug.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# =============================================================================
|
||||||
|
# HAB Container — firmware/app (боевая прошивка)
|
||||||
|
# Расположение: tools/host/hab/hab_app.yaml
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
options:
|
||||||
|
flags: 0x00
|
||||||
|
startAddress: 0x60000000
|
||||||
|
ivtOffset: 0x1000
|
||||||
|
initialLoadSize: 0x2000
|
||||||
|
family: mimxrt1050
|
||||||
|
DCDFilePath: ../dcd/dcd.bin # обязателен — heap FreeRTOS и LCDIF в SDRAM
|
||||||
|
|
||||||
|
inputImageFile: "../../../build/Debug/app.bin"
|
||||||
|
|
||||||
|
sections: []
|
||||||
17
tools/host/hab/hab_bootloader_debug.yaml
Normal file
17
tools/host/hab/hab_bootloader_debug.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# =============================================================================
|
||||||
|
# HAB Container — firmware/bootloader
|
||||||
|
# Расположение: tools/host/hab/hab_bootloader.yaml
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
options:
|
||||||
|
flags: 0x00
|
||||||
|
startAddress: 0x60000000
|
||||||
|
ivtOffset: 0x1000
|
||||||
|
initialLoadSize: 0x2000
|
||||||
|
family: mimxrt1050
|
||||||
|
# DCD намеренно отсутствует — загрузчик не использует SDRAM
|
||||||
|
|
||||||
|
inputImageFile: "../../../build/Debug/bootloader.bin"
|
||||||
|
|
||||||
|
sections: []
|
||||||
18
tools/host/hab/hab_firmware_test_release.yaml
Normal file
18
tools/host/hab/hab_firmware_test_release.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# =============================================================================
|
||||||
|
# HAB Container — firmware/test (входной контроль производства)
|
||||||
|
# Расположение: tools/host/hab/hab_firmware_test.yaml
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
options:
|
||||||
|
flags: 0x00 # unsigned — без подписи
|
||||||
|
startAddress: 0x60000000 # FlexSPI NOR base (XIP)
|
||||||
|
ivtOffset: 0x1000 # IVT offset for FlexSPI NOR boot
|
||||||
|
initialLoadSize: 0x2000 # размер области IVT+BDT+DCD до кода
|
||||||
|
family: mimxrt1050
|
||||||
|
DCDFilePath: ../dcd/dcd.bin # инициализация SDRAM
|
||||||
|
|
||||||
|
# .bin или .srec — оба принимаются
|
||||||
|
inputImageFile: "../../../build/Release/firmware_test.bin"
|
||||||
|
|
||||||
|
sections: []
|
||||||
Loading…
Reference in a new issue