Files
templates/NEW_PROJECT.md

17 KiB
Raw Blame History

Новый проект на переносимых библиотеках

Этот репозиторий содержит два разных типа кода:

  1. c/<library>/include и c/<library>/src — переносимое ядро;
  2. c/<library>/ports/<family> — небольшой аппаратный порт конкретного семейства микроконтроллеров.

Привязка выводов, частоты шин и выбранной периферии принадлежит плате и всегда остаётся в проекте в app_config.h либо в узком конфигурационном заголовке библиотеки, например onewire_config.h.

Рекомендуемая структура прошивки

my-device/
  app/                    логика изделия
    include/
    src/
  board/                  одна конкретная плата
    app_config.h          выводы, частоты, адреса, возможности платы
  port/                   связь библиотек с SDK выбранного МК
    display_port.c
    keypad_port.c
    eeprom_port.c
    can_port.c
  vendor/                 CMSIS, startup, linker script или Cube-generated код
  lib/templates/          git submodule этого репозитория

Не следует помещать stm32xxxx.h, HAL_*, регистры, IRQ handlers и номера выводов в app/ или в ядро библиотеки. Тогда при переходе на другой МК заменяются только board/, port/, startup и linker script.

Выбор готового порта DS18B20

Целевой МК Файл порта Шаблон конфигурации
STM32F103 c/ds18b20/ports/stm32f1/onewire_stm32f1.c onewire_config.f103.template.h
STM32G431 c/ds18b20/ports/stm32g4/onewire_stm32g4.c onewire_config.g431.template.h
STM32G474 c/ds18b20/ports/stm32g4/onewire_stm32g4.c onewire_config.g474.template.h

В сборку добавляются ровно три файла:

c/ds18b20/src/onewire.c
c/ds18b20/src/ds18b20.c
c/ds18b20/ports/<family>/onewire_<family>.c

Пути включения:

c/ds18b20/include
board

Нужный шаблон копируется в board/onewire_config.h; после этого в нём меняются только порт, номер вывода и бит тактирования GPIO.

G431 и G474 намеренно используют один исходник порта: GPIO, RCC и DWT для этой задачи совместимы. Раздельными остаются конфигурация платы, startup, linker script и выбранный CMSIS device define.

Выбор готового порта parallel NAND

Целевой МК Реализация шины Каталог порта
TMS320F2812 XINTF Zone 6 c/parallel-nand/ports/tms320f2812
STM32F103RCT6 GPIO bit-bang, поскольку FSMC недоступен в LQFP64 c/parallel-nand/ports/stm32f103rc
STM32F103ZET6 FSMC NAND Bank 3 c/parallel-nand/ports/stm32f103ze
STM32F407VET6 FSMC NAND Bank 2 c/parallel-nand/ports/stm32f407ve
STM32G474CEU6 GPIO bit-bang для UFQFPN48 c/parallel-nand/ports/stm32g474ce

Ядро поддерживает профили Micron MT29F1G08ABADA и Hynix HY27UF084G2M. В сборку добавляются src/parallel_nand.c, при необходимости src/parallel_nand_gas.c или src/parallel_nand_pcan_gas.c, и ровно один аппаратный порт. Конкретная распиновка, требуемые модули HAL и пример инициализации приведены в README выбранного порта.

Для PROGRAM/ERASE линия WP# должна управляться портом. Готовые порты STM32F103RC, STM32F103ZE и STM32G474CE объявляют поддержку записи. Базовые схемы TMS320F2812 и STM32F407VE фиксируют WP# аппаратно и безопасно возвращают PNAND_ERROR_WRITE_PROTECTED, пока плата и порт не доработаны.

Рабочий пример полноценного G474-порта находится в соседнем проекте candleLight_fw: src/device/device_g4.c отвечает за clock/GPIO, src/can/m_can.c — за FDCAN, а include/config.h — за привязку платы STM32G474VET6. Эти файлы остаются в прошивке, поскольку зависят от STM32 HAL, USB gs_usb и конкретной разводки адаптера; переносимая логика протоколов остаётся в templates.

Какие части KONOR уже общие

Возможность Переносимое ядро Что остаётся в port/ проекта
DS18B20/1-Wire c/ds18b20 готовый порт выбранного семейства и вывод
дисплей ST7789 c/st7789 SPI, DC, CS, RESET, подсветка и задержка
кнопки c/keypad настройка GPIO и чтение уровней
меню c/menu только привязка painter к дисплею
индикация состояний c/led-indicator готовый STM32 HAL-порт или callbacks GPIO и выбранного таймера
EEPROM FT24C256 c/eeprom-ft24c256 I2C write/write-read и задержка
CAN SETTINGS c/can-sensor bxCAN для F103 либо FDCAN для G431/G474

Порт дисплея, EEPROM и CAN нельзя честно сделать только по названию МК: нужно знать экземпляр периферии, альтернативную функцию и выводы конкретной платы. Поэтому библиотеки принимают таблицы обратных вызовов, а короткие адаптеры лежат в проекте рядом с app_config.h.

Порядок создания проекта

  1. Создать проект в CubeMX/Keil либо добавить CMSIS, startup и linker script.
  2. Подключить templates сабмодулем.
  3. Добавить только ядра нужных библиотек.
  4. Выбрать готовый 1-Wire порт по таблице выше.
  5. Создать board/app_config.h с выводами и частотами.
  6. Реализовать короткие адаптеры SPI/GPIO/I2C/CAN в port/.
  7. Сначала прогнать host-тесты библиотек, затем проверить аппаратные порты логическим анализатором или осциллографом.

Так новый проект не является копией старого: он использует общие ядра одной версии, а аппаратные отличия видны в одном небольшом каталоге port/.

Слияние и обновление templates как Git submodule

Что именно хранит основной проект

Основной проект не хранит содержимое lib/templates в своей истории. Вместо этого он хранит gitlink — ссылку на один конкретный commit репозитория templates. Поэтому при работе есть два независимых уровня истории:

  1. изменения библиотек сливаются и публикуются в репозитории templates;
  2. основной проект отдельным коммитом переводит gitlink на проверенную ревизию templates.

Обычный git merge в основном проекте не переносит исходники между ветками templates и не создаёт merge-коммит внутри сабмодуля. Он может только выбрать одну из уже существующих ссылок на commit. Если ссылки разошлись, сначала нужно получить общий commit в самом templates, а затем зафиксировать его в основном проекте.

Текущую зафиксированную ревизию удобно смотреть из корня основного проекта:

git submodule status lib/templates
git diff --submodule=log

Символ - перед SHA в git submodule status означает, что сабмодуль ещё не инициализирован; + — что рабочая копия сабмодуля находится не на том commit, который записан в основном проекте; U — конфликт gitlink.

Клонирование проекта и переключение его веток

Новый клон лучше сразу создавать вместе с сабмодулями:

git clone --recurse-submodules <url-основного-проекта>
cd <основной-проект>

Если проект уже клонирован:

git submodule update --init --recursive

После git switch, git checkout, git pull или завершения слияния основной проект может начать ссылаться на другую ревизию templates. Рабочее дерево сабмодуля следует явно привести к записанному состоянию:

git submodule update --init --recursive

Это нормальный и воспроизводимый режим: внутри lib/templates обычно будет detached HEAD, потому что проект фиксирует commit, а не ветку. Не следует делать там git pull, пока не выбрана рабочая ветка и не понятно, какую ревизию должен получить основной проект.

Обычное обновление проекта на новую версию templates

Сначала изменение должно быть проверено, закоммичено, отправлено и слито в целевую ветку самого репозитория templates. После этого из корня основного проекта выполняется:

git -C lib/templates fetch origin
git -C lib/templates switch --detach origin/master
git add lib/templates
git diff --cached --submodule=log
git commit -m "build(templates): обновить общие библиотеки"

Перед коммитом нужно собрать основной проект и прогнать его тесты: успешные тесты в templates подтверждают работу библиотеки, но не проверяют конкретный порт, настройки платы и интеграцию приложения.

Коммит основного проекта содержит только переход со старого SHA сабмодуля на новый. Случайные незакоммиченные файлы внутри lib/templates в него не входят. Проверить оба уровня перед фиксацией можно так:

git status
git -C lib/templates status
git diff --submodule=log

Не нужно обновлять сабмодуль на последний master автоматически при каждой сборке. Зафиксированный SHA нужен именно для того, чтобы одна и та же версия проекта всегда собиралась с одной и той же версией библиотек.

Если библиотеку правят из рабочего дерева основного проекта

Нельзя коммитить изменение, оставаясь на detached HEAD: такой commit легко потерять при следующем git submodule update. Сначала внутри сабмодуля создаётся обычная ветка:

git -C lib/templates fetch origin
git -C lib/templates switch -c feat/<имя> origin/master

Затем изменения коммитятся и отправляются именно в репозиторий templates:

git -C lib/templates add <файлы>
git -C lib/templates commit -m "feat(<библиотека>): <описание>"
git -C lib/templates push -u origin feat/<имя>

После проверки ветка сливается в master репозитория templates. Только после публикации итогового commit основной проект обновляет свой gitlink по процедуре из предыдущего раздела. Не следует отправлять в общий основной проект ссылку на commit сабмодуля, которого ещё нет на сервере: остальные разработчики и CI не смогут его получить.

Что происходит при слиянии веток основного проекта

Возможны три ситуации:

  1. Gitlink изменён только в одной ветке. Git обычно принимает эту ревизию автоматически. После merge нужно выполнить git submodule update и тесты.
  2. Обе ветки указывают на разные commits, но один commit templates является предком другого. Следует выбрать более новый проверенный commit, выполнить git add lib/templates и продолжить merge.
  3. Обе ветки указывают на расходящиеся commits templates. Это настоящий конфликт истории сабмодуля: выбирать один SHA наугад нельзя, потому что так потеряются изменения второй ветки.

При конфликте сначала смотрят, какие ссылки пришли с обеих сторон:

git ls-files -u lib/templates
git -C lib/templates fetch origin
git -C lib/templates log --oneline --graph --decorate --all

Затем в отдельной ветке репозитория templates объединяют оба commit, устраняют конфликты исходников, запускают тесты и публикуют результат:

git -C lib/templates switch -c merge/<имя> <sha-одной-стороны>
git -C lib/templates merge <sha-другой-стороны>
# исправить конфликты и запустить тесты templates
git -C lib/templates add <исправленные-файлы>
git -C lib/templates commit
git -C lib/templates push -u origin merge/<имя>

Если общий merge-коммит уже существует в origin/master, создавать ещё один не нужно: достаточно выбрать существующий SHA. После получения итогового commit конфликт завершается на уровне основного проекта:

git -C lib/templates switch --detach <итоговый-sha>
git add lib/templates
git diff --cached --submodule=log
git merge --continue
git submodule update --init --recursive

git add lib/templates здесь отмечает разрешённым именно gitlink. Не нужно удалять каталог, копировать библиотеку поверх него или разрешать конфликт как обычный текстовый файл.

Что должно попасть в merge request основного проекта

Перед отправкой результата следует проверить:

  1. итоговый commit templates доступен в удалённом репозитории;
  2. git -C lib/templates status не показывает локальных изменений;
  3. git submodule status не начинается с +, - или U;
  4. git diff --submodule=log <целевая-ветка>...HEAD показывает ожидаемый набор commits библиотек;
  5. тесты templates, сборка основного проекта и проверки на целевой плате прошли;
  6. в основном проекте закоммичены необходимые изменения адаптеров, конфигурации и сам новый gitlink.

После получения ветки другой разработчик восстанавливает ровно выбранное состояние одной командой:

git pull
git submodule update --init --recursive