17 KiB
Новый проект на переносимых библиотеках
Этот репозиторий содержит два разных типа кода:
c/<library>/includeиc/<library>/src— переносимое ядро;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.
Порядок создания проекта
- Создать проект в CubeMX/Keil либо добавить CMSIS, startup и linker script.
- Подключить
templatesсабмодулем. - Добавить только ядра нужных библиотек.
- Выбрать готовый 1-Wire порт по таблице выше.
- Создать
board/app_config.hс выводами и частотами. - Реализовать короткие адаптеры SPI/GPIO/I2C/CAN в
port/. - Сначала прогнать host-тесты библиотек, затем проверить аппаратные порты логическим анализатором или осциллографом.
Так новый проект не является копией старого: он использует общие ядра одной
версии, а аппаратные отличия видны в одном небольшом каталоге port/.
Слияние и обновление templates как Git submodule
Что именно хранит основной проект
Основной проект не хранит содержимое lib/templates в своей истории. Вместо
этого он хранит gitlink — ссылку на один конкретный commit репозитория
templates. Поэтому при работе есть два независимых уровня истории:
- изменения библиотек сливаются и публикуются в репозитории
templates; - основной проект отдельным коммитом переводит 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 не
смогут его получить.
Что происходит при слиянии веток основного проекта
Возможны три ситуации:
- Gitlink изменён только в одной ветке. Git обычно принимает эту ревизию
автоматически. После merge нужно выполнить
git submodule updateи тесты. - Обе ветки указывают на разные commits, но один commit
templatesявляется предком другого. Следует выбрать более новый проверенный commit, выполнитьgit add lib/templatesи продолжить merge. - Обе ветки указывают на расходящиеся 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 основного проекта
Перед отправкой результата следует проверить:
- итоговый commit
templatesдоступен в удалённом репозитории; git -C lib/templates statusне показывает локальных изменений;git submodule statusне начинается с+,-илиU;git diff --submodule=log <целевая-ветка>...HEADпоказывает ожидаемый набор commits библиотек;- тесты
templates, сборка основного проекта и проверки на целевой плате прошли; - в основном проекте закоммичены необходимые изменения адаптеров, конфигурации и сам новый gitlink.
После получения ветки другой разработчик восстанавливает ровно выбранное состояние одной командой:
git pull
git submodule update --init --recursive