8.4 KiB
Портирование firmware-info
Назначение и границы
Это C-библиотека описания работающего образа: SemVer, дата/время компиляции, 8 символов build ID и сериализация контракта v1. Она не обращается к сети, не читает версию из сервера и не записывает Flash. HAL, RTOS, UART и CAN ядру не нужны. Отправку результата выполняет приложение.
Для размещения .hex/.bin в каталоге SETGUI уже существуют
setprotocol.firmware_publish
и tools/firmware-publish.
Связь компонентов и перенос публикации описаны в
tools/firmware-publish/PORTING.md.
1. Файлы и конфигурация
Пример ниже предполагает lib/templates внутри нового проекта:
project/
inc/firmware_info_config.h
generated/firmware_build_id.h # создаётся до сборки
lib/templates/c/firmware-info/
src/
Добавьте в сборку оба файла:
lib/templates/c/firmware-info/src/firmware_info.c
lib/templates/c/firmware-info/src/firmware_info_port.c
В include path добавьте inc, generated и
lib/templates/c/firmware-info/include. Встроенный CMakeLists.txt собирает
только ядро и host-тест; firmware_info_port.c и каталоги конфигурации нужно
добавлять к целевому firmware target самостоятельно.
Скопируйте ports/<mcu>/firmware_info_config.template.h как
inc/firmware_info_config.h. Есть варианты STM32F1/F4/G4 и К1921ВК028;
они не содержат регистров МК. Для другого МК с обычными 8-битными байтами
достаточно такого же config:
#ifndef FIRMWARE_INFO_CONFIG_H
#define FIRMWARE_INFO_CONFIG_H
#define FIRMWARE_VERSION_MAJOR 1U
#define FIRMWARE_VERSION_MINOR 2U
#define FIRMWARE_VERSION_PATCH 3U
#include "firmware_build_id.h"
#endif
Обязательный include в этом примере позволяет обнаружить пропущенный pre-build.
В готовых шаблонах include опциональный через __has_include; если заголовок
не подключён, порт использует LOCALDEV. Для компилятора без __has_include
используйте явный include. Можно связать три версии с существующими макросами
проекта, как это сделано в KONOR_ds18b20/inc/firmware_info_config.h.
2. Build ID
Из корня нового проекта перед компиляцией запустите:
powershell -NoProfile -ExecutionPolicy Bypass -File "lib/templates/c/firmware-info/tools/make_build_id.ps1" -Repository "." -Output "generated/firmware_build_id.h"
Указывайте -Repository и -Output явно: расположение сабмодуля и рабочий
каталог IDE различаются между проектами. -Repository должен указывать на
исходники прошивки, а не на репозиторий templates. Для Keil из каталога mdk
соответственно используйте ..\lib\templates\..., -Repository ".." и
-Output ".\Generated\firmware_build_id.h".
При доступном Git чистый checkout получает 8 знаков commit, изменения tracked
файлов — 7 знаков и +. Если commit определить нельзя, используется NOGIT000.
Новые untracked-файлы текущий генератор при определении dirty не учитывает.
Дата/время берутся из __DATE__/__TIME__ при компиляции firmware_info_port.c;
для выпуска выполняйте полный Rebuild, чтобы не оставить старый объектный файл.
3. Обработчик запроса версии
Пример функции подготовки полезной нагрузки, вызываемой вашим обработчиком:
#include "firmware_info_port.h"
firmware_info_status_t app_make_firmware_info(uint8_t *payload, size_t capacity)
{
firmware_info_t info;
firmware_info_status_t status = firmware_info_port_describe(&info);
if (status != FIRMWARE_INFO_OK) return status;
return firmware_info_to_le_bytes(&info, payload, capacity);
}
При успехе передайте ровно FIRMWARE_INFO_PAYLOAD_SIZE (24) байта в собственный
транспорт. При ошибке верните ошибку протокола, а не содержимое буфера.
Не отправляйте sizeof(firmware_info_t): структура не является wire format.
В KONOR обработчик app_send_firmware_info() отвечает на
PROTO_MSG_FIRMWARE_INFO = 0x03, сохраняя sequence запроса. Старый 32-байтовый
DEVICE_INFO остаётся отдельным сообщением. Для нового протокола сначала
согласуйте команду с клиентом: подключение библиотеки само по себе не добавит
декодер и отображение версии в GUI.
Для Modbus вызовите firmware_info_to_registers() с массивом из 12 uint16_t
и разместите его в выбранной карте регистров. Адреса и Modbus-порядок байтов
обеспечивает ваш Modbus-стек; LE-буфер в Modbus напрямую не копируйте.
4. Контракт v1
| Индекс слова | Содержимое |
|---|---|
| 0 | Версия контракта: 1 |
| 1, 2, 3 | major, minor, patch |
| 4 | Год |
| 5 | (month << 8) | day |
| 6 | (hour << 8) | minute |
| 7 | Секунды |
| 8–11 | По два ASCII-символа build ID: первый в старшем байте слова |
В LE-представлении младший байт каждого слова идёт первым. Например, build ID
ab в начале строки даёт слово 0x6162, но байты 62 61; декодируйте сначала
слово, затем символы из старшего/младшего байта. NUL-терминатор не передаётся.
Текущая проверка допускает major/minor до 255 и patch до 999. Если в каталоге
используется (major << 16) | (minor << 8) | patch, ограничьте все три части
до 255, иначе значения пересекутся. Версия каталога автоматически из C-config
не извлекается.
Для C2000 с 16-битным char нельзя считать готовым байтовый порт: отдельно
проверьте наличие uint8_t и представление октетов в транспорте. Публикация
TMS SCI8-файла с ПК поддерживается независимо от переноса этой C-библиотеки.
5. Проверка переноса
- Соберите host-тест из
tests/test_firmware_info.cвместе с ядром либо используйте CMake/CTest. Он проверяет дату, регистры и порядок байтов build ID. - Соберите целевую прошивку с обоими
.cи сгенерированным заголовком. - Запросите версию у устройства: сравните SemVer, build ID, время и 24-байтовый
ответ с конкретной сборкой. Проверьте, что прежний
DEVICE_INFOне изменился. - Подключите выпуск по инструкции публикатора; сравните версию в config и
firmware-release.cmdперед Rebuild и--preflight.