diff --git a/.gitignore b/.gitignore index fd9c66b..4e99bfd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build/ cmake-build-*/ *.o +*.obj *.d *.a *.elf diff --git a/README.md b/README.md index 4516400..19550eb 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,9 @@ templates/ | [`c/eeprom-ft24c256`](c/eeprom-ft24c256) | EEPROM 24Cxx по I²C с нарезкой записи по страницам | `stdint.h` | две I²C-транзакции, задержка | | [`c/can-sensor`](c/can-sensor) | передача 64-битных ROM датчиков парой CAN-кадров | `stdint.h` | отправка и приём CAN-кадра | | [`c/ds18b20`](c/ds18b20) | термометры DS18B20 поверх программной 1-Wire | `stdint.h` | Init, DelayUs, Reset, WriteBit, ReadBit — **порты STM32F103, STM32G431 и STM32G474 в комплекте** | -| [`c/protocan-transport`](c/protocan-transport) | транспорт ProtoCAN: кадр, канал, CRC, общее адресное пространство, каталог GUI и стабильный host ABI | `stdint.h` | запись в поток и запрос свободного места — **порты STM32F4, Windows/Linux/macOS FFI и Android JNI в комплекте** | +| [`c/set-protocol`](c/set-protocol) | единое ядро SETProtocol: SET v2, совместимые ProtoCAN/GUI v1, GAS, телеметрия, firmware flow и стабильный host ABI | C99 | COM/SLCAN/SocketCAN/USB/Ethernet или callbacks — **Windows, Android и STM32F4-порты в комплекте** | | [`c/protocan-boot`](c/protocan-boot) | адресная прошивка по ProtoCAN: A/B-слоты, сессия, CRC32, verify и rollback-контракт | C99 | CAN TX, erase/write Flash, boot metadata, проверка образа и reboot | | [`c/rs485-boot`](c/rs485-boot) | прошивка по RS-485 в формате SETGUI v1: потоковый parser, CRC32 и resume | C99 | UART TX/RX, DE, Flash — **порты STM32F103 и STM32G474VET в комплекте** | -| [`c/set-protocol`](c/set-protocol) | единый SET protocol v2: управление, real-time телеметрия и обновление прошивки через UART/CAN/USB/Ethernet | C99 | доставка целого stream/datagram-кадра, часы, backend карты и загрузчика | | [`c/rtc-service`](c/rtc-service) | RTC с резервированным backup-томом | `stdint.h` | доступ к RTC и backup-памяти — **порт K1921VK028 в комплекте** | | [`c/firmware-info`](c/firmware-info) | SemVer, build stamp и git build ID работающего образа | C99 | config-порты STM32F1/F4/G4 и К1921ВК028; упаковка для Modbus/SETGUI | @@ -43,9 +42,13 @@ templates/ |---|---|---| | [`python/protocan`](python/protocan) | разбор ProtoCAN, транспортный кадр моста, кадр SETGUI, кодеки каталога | stdlib, Python 3.9+ | -Кодировщики `c/protocan-transport` и `python/protocan` дают побайтово +Кодировщики `c/set-protocol` и `python/protocan` дают побайтово одинаковый результат — это зафиксировано эталонами в тестах на C. +Интерактивная документация общего ядра: [`doc/setprotocol.html`](doc/setprotocol.html). +В ней отдельно описаны граница ядра, ABI, память, три wire format и состояние +портов Windows, Android, Linux и MCU. + ## Как подключить к проекту **Сабмодуль** — когда нужна одна конкретная версия и обновление по команде: @@ -78,10 +81,10 @@ git subtree pull --prefix lib/templates https://git.rd12.ru/Andrey/templates.git |---|---| | `KONOR_ds18b20` | st7789, keypad, menu, eeprom-ft24c256, can-sensor, ds18b20, firmware-info | | `OpticalTester` | st7789, keypad, menu, eeprom-ft24c256 | -| `CAN_to_RS485` | protocan-transport, python/protocan | +| `CAN_to_RS485` | set-protocol legacy transport, python/protocan | | `candleLight_fw` | эталон разделения общей логики и G431/G474 FDCAN-порта; общий ProtoCAN Boot переносится по контракту `protocan-boot` | | `SETGUI` | python/protocan | -| новые устройства SET и `SETGUI` v2 | set-protocol | +| `SETGUI`, Android GUI и новые устройства SET | set-protocol | | `k1921vk028` | rtc-service | ## Что сюда не попало и почему diff --git a/c/protocan-boot/README.md b/c/protocan-boot/README.md index 8eb00da..174756f 100644 --- a/c/protocan-boot/README.md +++ b/c/protocan-boot/README.md @@ -43,7 +43,7 @@ STM32 HAL / другой MCU / host-тест | `tests/test_pcan_boot.c` | хостовые тесты с RAM вместо Flash | стандартная библиотека C | | `CMakeLists.txt` | сборка библиотеки и теста | CMake 3.13+ | -Модуль не зависит от `protocan-transport`: разбор пяти полей 29-битного ID +Модуль не зависит от legacy-модулей `set-protocol`: разбор пяти полей 29-битного ID сделан переносимыми сдвигами, без непереносимых C-битовых полей. ## Карта `MsgType` diff --git a/c/protocan-transport/CMakeLists.txt b/c/protocan-transport/CMakeLists.txt deleted file mode 100644 index baa128c..0000000 --- a/c/protocan-transport/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(protocan_transport C) - -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) - -# Ядро библиотеки: платформенных зависимостей нет, собирается под что угодно. -set(PCAN_CORE_SOURCES - src/gui_frame.c - src/pcan_abi.c - src/pcan_crc.c - src/pcan_frame.c - src/pcan_id.c - src/pcan_link.c - src/pcan_ring.c - src/pcan_gas.c -) - -add_library(protocan_transport STATIC ${PCAN_CORE_SOURCES}) - -target_include_directories(protocan_transport PUBLIC include) - -option(PCAN_BUILD_SHARED "Build stable host ABI shared library" ON) -if(PCAN_BUILD_SHARED) - add_library(setcore SHARED ${PCAN_CORE_SOURCES}) - target_include_directories(setcore PUBLIC include) - target_compile_definitions(setcore PRIVATE PCAN_ABI_BUILD_DLL) - set_target_properties(setcore PROPERTIES - C_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN YES - OUTPUT_NAME setcore - ) -endif() - -if(MSVC) - target_compile_options(protocan_transport PRIVATE /W4) -else() - target_compile_options(protocan_transport PRIVATE -Wall -Wextra -Wpedantic) -endif() - -if(TARGET setcore) - if(MSVC) - target_compile_options(setcore PRIVATE /W4) - else() - target_compile_options(setcore PRIVATE -Wall -Wextra -Wpedantic) - endif() -endif() - -# Порт ports/stm32f4 сюда не входит: ему нужен CMSIS-заголовок stm32f4xx.h, -# он подключается напрямую в проект прошивки. - -option(PCAN_BUILD_TESTS "Собирать тесты" ON) - -if(PCAN_BUILD_TESTS) - enable_testing() - add_executable(test_transport tests/test_transport.c) - target_link_libraries(test_transport PRIVATE protocan_transport) - add_test(NAME transport COMMAND test_transport) - add_executable(test_abi tests/test_abi.c) - target_link_libraries(test_abi PRIVATE protocan_transport) - add_test(NAME abi COMMAND test_abi) -endif() diff --git a/c/protocan-transport/README.md b/c/protocan-transport/README.md deleted file mode 100644 index f674e11..0000000 --- a/c/protocan-transport/README.md +++ /dev/null @@ -1,149 +0,0 @@ -# protocan-transport - -Переносимая библиотека транспортного уровня для протокола **ProtoCAN**: -кадрирование поверх любого байтового потока (RS485, RS232, USB CDC), -разбор идентификатора и общее адресное пространство регистров. - -Написана на C99, без динамической памяти, без ОС, без зависимостей от HAL -и от конкретного микроконтроллера. Состояние живёт в структурах вызывающего, -поэтому в одной прошивке поднимается сколько угодно независимых каналов. - -``` - ваш код protocan-transport платформа - ┌────────┐ ┌────────────────────┐ ┌──────────────┐ - │ кадры │─────►│ pcan_link_send() │─────►│ io.write() │──► UART/DMA - │ │◄─────│ on_frame() │◄─────│ pcan_link_feed() - └────────┘ └────────────────────┘ └──────────────┘ - pcan_gas_* pcan_id_* -``` - -## Состав - -| Модуль | Назначение | -|---|---| -| `pcan_frame` | кадр `AA 55 … CRC16` и потоковый разборщик с ресинхронизацией | -| `pcan_crc` | CRC-16/CCITT-FALSE, побитовый или табличный | -| `pcan_link` | экземпляр канала: приём, передача, SEQ, счётчики | -| `pcan_ring` | кольцевой буфер, отдаёт непрерывный участок для DMA | -| `pcan_id` | упаковка и разбор 29-битного идентификатора ProtoCAN | -| `pcan_gas` | общее адресное пространство: карта регионов, чтение/запись, мост к кадрам | -| `pcan_abi` | стабильный C ABI для Python, JNI, Swift и других FFI | -| `ports/stm32f4` | готовый порт USART + DMA (пакетная передача, кольцевой приём) | -| `ports/android` | JNI и Kotlin-фасад; собирает `libsetcore.so` из этого же C99-кода | - -## Кадр - -``` -AA 55 | LEN | SEQ | FLAGS | ID0 ID1 ID2 ID3 | DATA[0..8] | CRC_L CRC_H -``` - -`LEN = 6 + DLC` (6..14), CRC-16/CCITT-FALSE по байтам `LEN..DATA`, -little-endian. Подробности — [docs/FRAME.md](docs/FRAME.md). - -Полное описание прикладного ProtoCAN и общего адресного пространства теперь -также хранится здесь: [docs/PROTOCOL.md](docs/PROTOCOL.md) и -[docs/OAP.md](docs/OAP.md). Эталонные данные находятся в -`tests/vectors/test-vectors.json`. Это канонические документы; копии в SETCAN -считаются историческим снимком legacy HAL-адаптера. - -## Общее адресное пространство - -Плоское пространство 16-битных регистров `0x0000..0xFFFF`, собранное из -регионов. Регион ссылается либо на массив в памяти, либо на пару колбэков — -так в карту попадают и переменные, и вычисляемые значения, и регистры -периферии. Подробности — [docs/GAS.md](docs/GAS.md). - -```c -static uint16_t holding[8]; - -static const pcan_gas_region_t regions[] = { - { 0x0000, 8, holding, NULL, NULL, 0, NULL, "holding" }, - { 0xFF00, 4, NULL, diag_read, NULL, PCAN_GAS_RDONLY, NULL, "diag" }, -}; -static const pcan_gas_map_t map = { regions, 2 }; -``` - -## Использование - -```c -#include "protocan_transport.h" - -static void on_frame(const pcan_frame_t *f, void *user) -{ - /* ... */ -} - -pcan_io_t io; -pcan_uart_io(&uart, &io); /* или свой io */ - -pcan_link_t link; -pcan_link_init(&link, &io, on_frame, NULL); - -pcan_frame_t f = { .flags = PCAN_FLAG_IDE, .id = 0x1234567, .dlc = 2 }; -f.data[0] = 0xAA; f.data[1] = 0xBB; -pcan_link_send(&link, &f); /* SEQ проставится сам */ -``` - -Для своей платформы достаточно реализовать две функции: - -```c -size_t my_write(void *ctx, const uint8_t *data, size_t len); /* всё-или-ничего */ -size_t my_space(void *ctx); -``` - -## Сборка - -Библиотека — шесть файлов в `src/` и заголовки в `include/`. Добавьте их -в проект и укажите `include/` в путях поиска. CMake для тестов и хостовых -сборок: - -```bash -cmake -B build && cmake --build build && ctest --test-dir build -``` - -Для desktop CMake дополнительно собирает shared library `setcore` -(`setcore.dll`, `libsetcore.so` или `libsetcore.dylib`). Публичная граница -для приложений описана в `include/pcan_abi.h`; внутренние структуры ядра через -FFI не экспортируются. Python-обёртка находится в `python/protocan/native.py`. - -Android-проект подключает `ports/android/Android.mk` и добавляет -`ports/android/kotlin` в `sourceSets`. JNI-код занимается только преобразованием -типов и временем жизни parser context, а правила кадра и CAN ID остаются в C. - -Если на Windows нет CMake, host-библиотеку тем же MSVC можно собрать так: - -```powershell -python tools/build_host.py --output native/setcore.dll -``` - -Либо напрямую: - -```bash -clang -std=c99 -Wall -Wextra -Iinclude tests/test_transport.c src/pcan_*.c -o test && ./test -``` - -Порт `ports/stm32f4` в тесты не входит: ему нужен CMSIS-заголовок -`stm32f4xx.h`, подключайте его в проект прошивки отдельно. - -## Настройки - -Переопределяются через `-D` либо через свой `pcan_config_user.h` -(с `-DPCAN_USE_USER_CONFIG`): - -| Макрос | По умолчанию | Смысл | -|---|---|---| -| `PCAN_DATA_MAX` | 8 | длина поля данных CAN | -| `PCAN_CRC_TABLE` | 0 | 1 — таблица на 512 байт вместо побитового расчёта | -| `PCAN_GAS_MAX_REGIONS` | 16 | предел числа регионов в карте | -| `PCAN_BARRIER()` | барьер компилятора | для очередей, разделяемых с прерыванием | - -## Ограничения - -- Очереди рассчитаны на схему «один писатель + один читатель». Если - писателей несколько, оборачивайте вызовы своей блокировкой. -- Размер кольцевого буфера обязан быть степенью двойки; `pcan_ring_init()` - вернёт `false`, а не станет молча портить индексы. -- На STM32F407 DMA не видит CCM RAM (`0x10000000`) — буферы держите - в основном SRAM. -- Порядок байт на линии фиксирован (little-endian) и не зависит от порядка - байт хоста. diff --git a/c/set-protocol/CMakeLists.txt b/c/set-protocol/CMakeLists.txt index 52fc7f3..338f9f2 100644 --- a/c/set-protocol/CMakeLists.txt +++ b/c/set-protocol/CMakeLists.txt @@ -1,28 +1,84 @@ cmake_minimum_required(VERSION 3.13) -project(set_protocol C) +project(setprotocol C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) -add_library(set_protocol STATIC +# SET protocol v2: управление, телеметрия, CAN segmentation и firmware flow. +set(SETPROTOCOL_V2_SOURCES src/set_protocol.c src/set_can.c src/set_firmware.c src/set_telemetry.c ) -target_include_directories(set_protocol PUBLIC include) +# Совместимые ProtoCAN/SETGUI v1 форматы переходного периода. +set(SETPROTOCOL_LEGACY_SOURCES + src/gui_catalog.c + src/gui_frame.c + src/pcan_abi.c + src/pcan_crc.c + src/pcan_frame.c + src/pcan_gas.c + src/pcan_id.c + src/pcan_link.c + src/pcan_ring.c +) -if(MSVC) - target_compile_options(set_protocol PRIVATE /W4 /WX) -else() - target_compile_options(set_protocol PRIVATE -Wall -Wextra -Wpedantic -Werror) +set(SETPROTOCOL_SOURCES + ${SETPROTOCOL_V2_SOURCES} + ${SETPROTOCOL_LEGACY_SOURCES} +) + +add_library(setprotocol_static STATIC ${SETPROTOCOL_SOURCES}) +target_include_directories(setprotocol_static PUBLIC include) + +# Совместимое имя цели для проектов, уже использовавших SET protocol v2. +add_library(set_protocol ALIAS setprotocol_static) + +option(SETP_BUILD_SHARED "Build stable host ABI shared library" ON) +if(SETP_BUILD_SHARED) + add_library(setprotocol SHARED ${SETPROTOCOL_SOURCES}) + target_include_directories(setprotocol PUBLIC include) + target_compile_definitions(setprotocol PRIVATE PCAN_ABI_BUILD_DLL) + set_target_properties(setprotocol PROPERTIES + C_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN YES + OUTPUT_NAME setprotocol + ) endif() +function(setprotocol_warnings target) + if(MSVC) + target_compile_options(${target} PRIVATE /W4) + else() + target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic) + endif() +endfunction() + +setprotocol_warnings(setprotocol_static) +if(TARGET setprotocol) + setprotocol_warnings(setprotocol) +endif() + +# JNI/CMSIS-порты подключаются целевым проектом и в host CMake не входят. option(SETP_BUILD_TESTS "Build host tests" ON) if(SETP_BUILD_TESTS) enable_testing() + add_executable(test_set_protocol tests/test_set_protocol.c) - target_link_libraries(test_set_protocol PRIVATE set_protocol) - add_test(NAME set_protocol COMMAND test_set_protocol) + target_link_libraries(test_set_protocol PRIVATE setprotocol_static) + add_test(NAME set_protocol_v2 COMMAND test_set_protocol) + + add_executable(test_transport tests/test_transport.c) + target_link_libraries(test_transport PRIVATE setprotocol_static) + add_test(NAME legacy_transport COMMAND test_transport) + + add_executable(test_gui tests/test_gui.c) + target_link_libraries(test_gui PRIVATE setprotocol_static) + add_test(NAME legacy_gui COMMAND test_gui) + + add_executable(test_abi tests/test_abi.c) + target_link_libraries(test_abi PRIVATE setprotocol_static) + add_test(NAME stable_abi COMMAND test_abi) endif() diff --git a/c/set-protocol/README.md b/c/set-protocol/README.md index 8f21233..84ea25a 100644 --- a/c/set-protocol/README.md +++ b/c/set-protocol/README.md @@ -1,75 +1,81 @@ -# set-protocol +# SETProtocol -Единый переносимый протокол SET для новых устройств и SETGUI. Один и тот же -прикладной кадр используется для управления, чтения общей карты, потоковой -телеметрии и безопасной передачи прошивки через: +Единое переносимое протокольное ядро SET для `SETGUI`, Android GUI, устройств +и сервисных утилит. В одном C99-проекте собраны: -- RS-232 и RS-485; -- USB CDC; -- CAN с сегментацией; -- Ethernet TCP; -- Ethernet UDP, когда нужен обмен без соединения. +- SET protocol v2 для управления, карты данных, телеметрии и firmware flow; +- совместимый ProtoCAN transport для существующих CAN-мостов; +- SETGUI transport v1 для приборов переходного периода; +- стабильный host ABI для Python/JNI/других FFI; +- GAS, кольцевые буферы, CRC и потоковые parser. -Протокол не привязан к HAL, ОС или микроконтроллеру. Реализация на C99 не -использует динамическую память. Все многобайтные значения little-endian. +Ядро не зависит от HAL, ОС или конкретного адаптера, не использует +динамическую память и не открывает COM/CAN само. SLCAN, SocketCAN, USB CDC, +TCP, UART/DMA и аппаратный CAN подключаются портами. -## Что уже реализовано +## Структура -| Файл | Назначение | +| Каталог | Назначение | |---|---| -| `set_protocol.*` | кадр v2, CRC32, потоковый parser, статусы ответов | -| `set_can.*` | extended CAN ID, сегментация, flow-control и reassembly timeout | -| `set_firmware.*` | BEGIN/DATA/END/STATUS, resume, CRC блока, SHA-256 и подпись | -| `set_telemetry.*` | подписки и типизированные push-пакеты с timestamp | -| `PROTOCOL.md` | обязательный wire-контракт и привязки к носителям | -| `MIGRATION.md` | порядок перехода SETGUI и существующих прошивок с v1 | -| `PORTING.md` | подключение UART, CAN, USB и Ethernet | -| `tests/` | host-тесты и фиксированный эталонный кадр | - -Файл [`PROTOCOL.md`](PROTOCOL.md) является источником истины. Числа из него -нельзя менять без выпуска следующей версии протокола. - -## Минимальный stream-приёмник - -```c -#include "set_protocol.h" - -static setp_parser_t parser; - -static void on_frame(const setp_frame_t *frame, void *user) -{ - (void)user; - /* frame->payload действует только до возврата из callback. */ -} - -void protocol_init(void) -{ - setp_parser_init(&parser); -} - -void protocol_feed(const uint8_t *data, uint16_t length) -{ - (void)setp_parser_feed(&parser, data, length, on_frame, NULL); -} -``` - -Для RS-232, RS-485, USB CDC и TCP в parser передаются любые принятые chunks. -Для UDP один UDP payload должен содержать ровно один полный SETP-кадр. +| `include/set_*.h` | публичный SET protocol v2 | +| `include/pcan_*.h`, `gui_*.h` | совместимые ProtoCAN/GUI v1 модули | +| `include/setprotocol.h` | единая C99-точка включения | +| `include/setprotocol_abi.h` | стабильная FFI-точка включения ABI v1 | +| `src/` | общая реализация всех протокольных модулей | +| `ports/android` | JNI и Kotlin facade | +| `ports/stm32f4` | UART/DMA port для legacy byte stream | +| `docs/SETPROTOCOL.md` | архитектура, ABI, память и переносимость | +| `docs/legacy` | нормативные документы ProtoCAN/SETGUI v1 | +| `PROTOCOL.md` | нормативный wire contract SET protocol v2 | +| `MIGRATION.md` | переход с v1/ProtoCAN на v2 | +| `PORTING.md` | подключение новых транспортов и платформ | ## Сборка -```text -cmake -B build -cmake --build build -ctest --test-dir build +```bash +cmake -S c/set-protocol -B build/setprotocol -DSETP_BUILD_TESTS=ON +cmake --build build/setprotocol --config Release +ctest --test-dir build/setprotocol -C Release --output-on-failure ``` -Либо добавьте три файла из `src/` и каталог `include/` непосредственно в -проект прошивки. +CMake создаёт: -## Версии +- `setprotocol_static` — статическое C99-ядро; +- совместимую CMake-цель `set_protocol`; +- `setprotocol.dll`, `libsetprotocol.so` или `libsetprotocol.dylib`; +- тесты SET v2, ProtoCAN transport, GUI v1 и ABI. -- GUI protocol v1 остаётся только переходным форматом старых устройств. -- Все новые устройства используют SET protocol v2 (`SETP_VERSION = 2`). -- v1 и v2 имеют одинаковый SOF `A5 5A`, поэтому номер версии проверяется до - разбора остальных полей. +Упрощённая host-сборка: + +```powershell +python c/set-protocol/tools/build_host.py --output native/setprotocol.dll +``` + +```bash +python3 c/set-protocol/tools/build_host.py --output native/libsetprotocol.so +``` + +## Подключение в C + +Для всего ядра: + +```c +#include "setprotocol.h" +``` + +Для минимальной прошивки можно подключать только нужные заголовки и исходники. +Например, новый v2 stream parser использует `set_protocol.*`, а legacy +CAN-мост — `pcan_frame.*`, `pcan_crc.*` и `pcan_id.*`. + +FFI-клиенты подключают `setprotocol_abi.h`. Имена функций `pcan_abi_*` +сохраняются в ABI v1 для бинарной совместимости; переименование символов без +повышения версии ABI запрещено. + +## Версии wire format + +- SET protocol v2 — основной формат новых устройств. +- SETGUI v1 и ProtoCAN bridge остаются поддерживаемыми на время миграции. +- Одинаковый SOF `A5 5A` у GUI v1 и SET v2 различается полем версии. +- Изменение wire contract требует новой версии и тестовых векторов. + +Полная интерактивная документация: [`../../doc/setprotocol.html`](../../doc/setprotocol.html). diff --git a/c/set-protocol/docs/SETPROTOCOL.md b/c/set-protocol/docs/SETPROTOCOL.md new file mode 100644 index 0000000..b6da75c --- /dev/null +++ b/c/set-protocol/docs/SETPROTOCOL.md @@ -0,0 +1,342 @@ +# SETProtocol — переносимое протокольное ядро + +SETProtocol — общее C99-ядро для `SETGUI`, Android GUI, прошивок и утилит. +Оно объединяет основной SET protocol v2 и поддерживаемые форматы переходного +периода: ProtoCAN bridge и SETGUI transport v1. Windows, Linux, Android и +микроконтроллер используют одинаковые правила кадра, CRC, адресации, +телеметрии, обновления и потокового разбора. + +Ядро **не открывает COM-порт, CAN-адаптер или сокет**. COM, SLCAN, SocketCAN, +USB CDC, TCP и аппаратный CAN относятся к портам. Они доставляют байты или +CAN-кадры, а SETProtocol проверяет и интерпретирует их одинаково на всех +платформах. + +## 1. Граница ответственности + +```text +SETGUI / Android GUI / CLI / firmware + │ прикладные команды и события + ▼ +Python facade / JNI / прямой C API + │ стабильный ABI или C99 API + ▼ +┌──────────────────────── SETProtocol ────────────────────────┐ +│ SET v2 │ ProtoCAN ID │ v1 parsers │ CRC │ GAS │ telemetry │ +└─────────────────────────────────────────────────────────────┘ + │ байты или нормализованный CAN frame + ▼ +COM │ SLCAN │ SocketCAN │ USB CDC │ TCP │ STM32 UART/CAN +``` + +В ядре находятся: + +- форматы проводных кадров и порядок байт; +- SET protocol v2: команды, адресация, подписки и firmware state machines; +- проверка длины, версии, DLC и контрольной суммы; +- восстановление синхронизации после мусора или оборванного кадра; +- упаковка и разбор ProtoCAN Extended ID; +- счётчики качества входного потока; +- общее адресное пространство регистров (GAS); +- стабильная C ABI-граница для `ctypes`, JNI и будущего Swift/FFI. + +За пределами ядра остаются: + +- поиск устройств и выбор `COM6`, `can0` или Bluetooth/USB endpoint; +- скорость UART и CAN bitrate; +- драйверы SLCAN, SocketCAN, PCAN, CANable и vendor SDK; +- разрешения Android USB и жизненный цикл приложения; +- виджеты, вкладки, таблицы, графики и хранение настроек; +- HAL, IRQ, DMA, RTOS, Flash и распиновка платы. + +Отсюда следует важное правило: **500000 на экране COM — это baud rate +последовательного моста, а 500 kbit/s в CAN-настройках — bitrate самой CAN-шины. +Ядро не подменяет одно другим и не выбирает эти значения автоматически.** + +## 2. Состав исходников + +| Модуль | Роль | Платформенные зависимости | +|---|---|---| +| `set_protocol` | SET v2 frame, CRC32, stream/datagram parser | нет | +| `set_can` | CAN segmentation, flow control и reassembly | доставка CAN frame и время | +| `set_telemetry` | подписки и типизированные PUBLISH-пакеты | часы/callbacks приложения | +| `set_firmware` | BEGIN/DATA/END/STATUS и resume state machine | Flash/verify/reboot backend | +| `pcan_id` | Упаковка/разбор 29-битного ProtoCAN ID | нет | +| `pcan_crc` | CRC-16/CCITT-FALSE | нет | +| `pcan_frame` | Формат `AA 55`, encode и потоковый parser | нет | +| `gui_frame` | Формат `A5 5A`, CRC32, encode, parser и link | нет | +| `pcan_link` | Экземпляр канала, SEQ, RX/TX и статистика | два callback порта | +| `pcan_ring` | SPSC-кольцо и непрерывный участок для DMA | нет | +| `pcan_gas` | Карта 16-битных регистров и bridge к кадрам | callbacks региона | +| `gui_catalog` | C-каталог публикуемых GUI-полей | нет; входит в общий shared build | +| `pcan_abi` | Экспорт скалярного ABI для FFI | ABI компилятора C | + +Общая точка включения для C-кода — `include/setprotocol.h`. +Иностранные runtimes должны использовать `include/setprotocol_abi.h`, а не +повторять внутреннюю раскладку `pcan_parser_t` или `gui_parser_t`. +Shared-библиотека `setprotocol` содержит SET v2 и совместимые legacy-модули. +ABI v1 пока экспортирует функции `pcan_abi_*`: имена намеренно сохранены для +бинарной совместимости SETGUI/Android. Расширение ABI для прямого SET v2 FFI +должно быть совместимым добавлением или новой версией ABI. + +## 3. Три поддерживаемых wire format + +SETProtocol поддерживает основной v2 и два legacy-формата. После первого +корректного ответа формат соединения фиксируется до отключения. + +### 3.1. CAN bridge: `AA 55` + +```text +AA 55 | LEN | SEQ | FLAGS | CAN_ID[4] LE | DATA[0..8] | CRC16 LE +``` + +`LEN = 6 + DLC`, поэтому допустимый диапазон — `6..14`. CRC-16/CCITT-FALSE +считается по участку от `LEN` до последнего байта `DATA`. Максимальный размер +кадра — 19 байт. Формат переносит один classic CAN 2.0 кадр через COM, USB CDC, +RS-232, RS-485 или TCP byte stream. + +Флаги: + +| Бит | Имя | Значение | +|---:|---|---| +| 0 | `IDE` | расширенный 29-битный CAN ID | +| 1 | `RTR` | remote frame | +| 2 | `DIR` | `0` из CAN в host, `1` из host в CAN | +| 3 | `ERR` | служебный кадр диагностики моста | + +### 3.2. GUI transport: `A5 5A` + +```text +A5 5A | VER | TYPE | SEQ[2] BE | SIZE[2] BE | PAYLOAD[0..512] | CRC32 LE +``` + +Версия сейчас равна `1`. Заголовочные `SEQ` и `SIZE` идут big-endian, CRC32 +IEEE — little-endian. Payload до 512 байт нужен для каталога, чтения/записи +регистров, диагностики и потока значений. Это не CAN-кадр и у него нет DLC. + +Оба parser принимают произвольные chunks: один вызов может содержать половину +кадра, несколько кадров или мусор между ними. Границы `read()` не считаются +границами протокольных сообщений. + +### 3.3. SET protocol v2: `A5 5A 02` + +```text +A5 5A | VER=02 | FLAGS | TYPE u16 LE | SOURCE u16 LE | DEST u16 LE | +SEQ u16 LE | SIZE u16 LE | PAYLOAD[0..512] | CRC32 LE +``` + +Это основной формат новых устройств. Он одинаков поверх RS-232/485, USB CDC, +TCP и UDP; CAN переносит байты полного v2-кадра через сегментацию. В v2 +объединены запросы/ответы, события телеметрии и firmware flow. Нормативный +контракт находится в `PROTOCOL.md`. + +## 4. ProtoCAN Extended ID + +```text +28 27 26..24 23..20 19..16 15..0 +Priority | Route | DeviceType | DeviceID | MsgType | MsgBody +``` + +Для переносимости используются маски и сдвиги, а не C bit-fields. ABI-функции +`pcan_abi_id_pack()` и `pcan_abi_id_unpack()` дают одинаковую раскладку при +MSVC, GCC и Clang. + +## 5. Стабильный ABI v1 + +`pcan_abi.h` экспортирует простые числа, указатели и явно ограниченные буферы. +Текущая версия возвращается `pcan_abi_version()` и равна `1`. + +### CAN bridge API + +| Функция | Назначение | +|---|---| +| `pcan_abi_version` | Проверить совместимость загруженной библиотеки | +| `pcan_abi_id_pack/unpack` | Преобразовать поля ProtoCAN ID | +| `pcan_abi_crc16` | Рассчитать CRC-16/CCITT-FALSE | +| `pcan_abi_frame_encode` | Собрать целый `AA55` кадр | +| `pcan_abi_parser_size` | Узнать размер opaque parser context | +| `pcan_abi_parser_init` | Инициализировать память, принадлежащую вызывающему | +| `pcan_abi_parser_push` | Передать один байт; `1` означает готовый кадр | +| `pcan_abi_parser_stats` | Получить frames/CRC/bad length/stray bytes | + +### GUI API + +| Функция | Назначение | +|---|---| +| `pcan_abi_gui_crc32` | Рассчитать CRC32 IEEE | +| `pcan_abi_gui_frame_encode` | Собрать целый `A55A` кадр | +| `pcan_abi_gui_parser_size/init/push` | Управлять opaque GUI parser context | +| `pcan_abi_gui_parser_stats` | Получить frames/CRC/version/length/stray bytes | + +Возврат `0` из encode означает неверные аргументы или недостаточный output +buffer. Parser API возвращает отрицательное значение при неверном context, +`0` пока кадр не собран и `1` при готовом кадре. + +## 6. Память, состояние и многопоточность + +В переносимом C-слое нет `malloc`, singleton и скрытого глобального parser. +Каждый канал имеет собственное состояние. В ABI вызывающий сначала спрашивает +его размер, выделяет байтовый блок и передаёт его в `init`. + +```c +size_t size = pcan_abi_parser_size(); +void *storage = /* память вызывающей стороны размером size */; +pcan_abi_parser_init(storage, size); +``` + +Это позволяет: + +- держать память статически на MCU; +- использовать `ctypes.create_string_buffer()` в Python; +- выделять handle только в JNI-адаптере; +- одновременно разбирать несколько независимых линий. + +Один parser context нельзя одновременно изменять из нескольких потоков. +Правильная модель — один владелец на канал или внешняя блокировка. Кольцевой +буфер рассчитан на одного писателя и одного читателя (SPSC). Для нескольких +писателей синхронизацию обеспечивает порт/приложение. + +## 7. Порты и адаптеры + +| Среда | Артефакт | Состояние | +|---|---|---| +| Windows desktop | `setprotocol.dll` + Python `ctypes` | используется SETGUI, проверено тестами | +| Android | `libsetprotocol.so` + JNI + Kotlin facade | сборка ABI `arm64-v8a`, `armeabi-v7a`, `x86`, `x86_64` проверяется Android build | +| Linux desktop | `libsetprotocol.so` + тот же ABI | ядро и сборщик готовы; нужен Linux CI/smoke-test приложения | +| macOS | `libsetprotocol.dylib` + тот же ABI | исходники совместимы; отдельная упаковка не проверена | +| STM32F4 | прямой C99 + UART/DMA port | готовый порт в `ports/stm32f4` | +| Другой MCU | прямой C99 | реализуются только callbacks I/O/времени/памяти | +| iOS/Swift | C ABI | ABI подходит, Swift wrapper пока не добавлен | + +### Linux + +Само ядро не содержит WinAPI, поэтому собирается GCC или Clang. Для SETGUI под +Linux остаются две отдельные задачи: упаковать `libsetprotocol.so` с приложением и +подключить нужный физический backend (`pyserial` для USB-COM или SocketCAN для +`can0`). Правила кадра, CRC и ID менять не потребуется. + +SLCAN и SocketCAN — **порты снифера**, а не новая реализация протокола: + +```text +SLCAN text / struct can_frame + │ adapter + ▼ + can_id + flags + data + │ + ▼ + общий decoder/UI +``` + +## 8. Сборка + +### CMake: Windows, Linux, macOS + +```bash +cmake -S c/set-protocol -B build/setprotocol -DSETP_BUILD_TESTS=ON +cmake --build build/setprotocol --config Release +ctest --test-dir build/setprotocol -C Release --output-on-failure +``` + +Результат shared-сборки называется `setprotocol.dll`, `libsetprotocol.so` или +`libsetprotocol.dylib`. Статическая цель называется `setprotocol_static`; +совместимое имя CMake-цели SET v2 — `set_protocol`. + +### Упрощённая host-сборка + +```powershell +python c/set-protocol/tools/build_host.py --output native/setprotocol.dll +``` + +```bash +python3 c/set-protocol/tools/build_host.py --output native/libsetprotocol.so +``` + +На Windows tool использует MSVC, на Unix ищет `cc`, `clang` или `gcc`. + +### Python + +```python +from protocan.native import NativeProtocol + +core = NativeProtocol() +raw = core.encode(sequence=1, flags=1, can_id=0x1234567, data=b"\xAA\xBB") +frames = core.parser().feed(raw) +``` + +Если библиотека лежит вне стандартного дерева: + +```bash +export SETPROTOCOL_LIBRARY=/opt/set/lib/libsetprotocol.so +``` + +В PowerShell: + +```powershell +$env:SETPROTOCOL_LIBRARY = 'C:\set\native\setprotocol.dll' +``` + +### Android + +`ports/android/Android.mk` компилирует те же C-файлы. Kotlin-класс +`ru.setcorp.setprotocol.NativeSetProtocol` отвечает только за удобный API, а JNI — за +преобразование типов и время жизни parser handle. + +### Микроконтроллер + +Добавьте нужные `src/*.c` и каталог `include/` в проект. Порт STM32F4 не входит +автоматически в host CMake, потому что ему нужен CMSIS. Для другой платы +реализуйте `pcan_io_t.write` и `pcan_io_t.tx_space`; ISR/DMA лишь складывает +байты, а `pcan_link_feed()` вызывается в безопасном контексте приложения. + +## 9. Пример прямого ABI + +```c +#include "pcan_abi.h" + +uint8_t output[19]; +const uint8_t data[] = {0xAA, 0xBB}; +const uint8_t flags = 0x01U; /* IDE */ +uint32_t id = pcan_abi_id_pack(1, 0, 2, 3, 4, 0x1234); +size_t written = pcan_abi_frame_encode( + 7, flags, id, data, sizeof(data), output, sizeof(output)); +``` + +Для firmware удобнее полный C API из `protocan_transport.h`: он даёт link, +callbacks, ring и GAS без FFI-обёртки. + +## 10. Диагностика + +| Симптом | Что проверить | +|---|---| +| `crc_errors` растёт | bitrate/baud, ground, termination, порядок байт, потерю chunks | +| `bad_len`/`length_errors` | выбран ли правильный формат `AA55` или `A55A` | +| `version_errors` | версия GUI transport должна быть `1` | +| много `stray_bytes` | начало чтения посреди пакета допустимо; постоянный рост означает неверный порт | +| DLL/SO не найдена | путь, архитектуру процесса и `SETPROTOCOL_LIBRARY` | +| Android `UnsatisfiedLinkError` | имя `setprotocol`, ABI устройства и упаковку `jniLibs`/NDK | +| CAN пустой, но COM открыт | COM baud не равен CAN bitrate; проверьте настройку самого адаптера | + +## 11. Совместимость и ограничения + +- ABI v1 изменяется только совместимым добавлением функций. Ломающее изменение + требует нового значения `PCAN_ABI_VERSION`. +- Wire format нельзя менять без версии/миграционного документа и тестовых + векторов для C, Python и Android. +- CAN bridge сейчас рассчитан на classic CAN: `DLC <= 8`; CAN FD не включён. +- GUI payload ограничен 512 байтами; на MCU `GUI_RX_PAYLOAD_MAX` можно уменьшить. +- В ядре нет готового SocketCAN/SLCAN/vendor backend: это следующий слой портов. +- В ядро не входят виджеты GUI, настройки COM/CAN и обновление прошивки целиком. + Для firmware flow существует отдельная библиотека `protocan-boot`. + +## 12. Проверка изменений + +Минимальный quality gate: + +1. CMake build и `ctest` для `test_transport` и `test_abi`. +2. Сверка машинных векторов `tests/vectors/test-vectors.json`. +3. Python-тесты с обязательной загрузкой native core. +4. Android unit tests и `assembleDebug`, если менялись ABI/JNI/Kotlin. +5. Smoke-test целевого порта на реальной линии. + +Канонический код находится в `templates/c/set-protocol`. Проекты должны +получать его как Git submodule и фиксировать конкретный commit, а не хранить +разошедшиеся копии. diff --git a/c/protocan-transport/docs/CHANGELOG.md b/c/set-protocol/docs/legacy/CHANGELOG.md similarity index 100% rename from c/protocan-transport/docs/CHANGELOG.md rename to c/set-protocol/docs/legacy/CHANGELOG.md diff --git a/c/protocan-transport/docs/FRAME.md b/c/set-protocol/docs/legacy/FRAME.md similarity index 100% rename from c/protocan-transport/docs/FRAME.md rename to c/set-protocol/docs/legacy/FRAME.md diff --git a/c/protocan-transport/docs/GAS.md b/c/set-protocol/docs/legacy/GAS.md similarity index 100% rename from c/protocan-transport/docs/GAS.md rename to c/set-protocol/docs/legacy/GAS.md diff --git a/c/protocan-transport/docs/GUI_CATALOG.md b/c/set-protocol/docs/legacy/GUI_CATALOG.md similarity index 100% rename from c/protocan-transport/docs/GUI_CATALOG.md rename to c/set-protocol/docs/legacy/GUI_CATALOG.md diff --git a/c/protocan-transport/docs/OAP.md b/c/set-protocol/docs/legacy/OAP.md similarity index 100% rename from c/protocan-transport/docs/OAP.md rename to c/set-protocol/docs/legacy/OAP.md diff --git a/c/protocan-transport/docs/PROTOCOL.md b/c/set-protocol/docs/legacy/PROTOCOL.md similarity index 100% rename from c/protocan-transport/docs/PROTOCOL.md rename to c/set-protocol/docs/legacy/PROTOCOL.md diff --git a/c/protocan-transport/include/gui_catalog.h b/c/set-protocol/include/gui_catalog.h similarity index 98% rename from c/protocan-transport/include/gui_catalog.h rename to c/set-protocol/include/gui_catalog.h index ebd9fe0..0dd2f9b 100644 --- a/c/protocan-transport/include/gui_catalog.h +++ b/c/set-protocol/include/gui_catalog.h @@ -6,7 +6,7 @@ * оператор отмечает нужное, и прибор шлёт только отмеченное пакетами. * Схема повторяет реестр регистров ST Motor Control Workbench. * - * Двоичный контракт: docs/GUI_CATALOG.md. + * Двоичный контракт: docs/legacy/GUI_CATALOG.md. * Зеркало на Python: gui_desktop/core/gas_catalog.py. */ #ifndef GUI_CATALOG_H diff --git a/c/protocan-transport/include/gui_frame.h b/c/set-protocol/include/gui_frame.h similarity index 100% rename from c/protocan-transport/include/gui_frame.h rename to c/set-protocol/include/gui_frame.h diff --git a/c/protocan-transport/include/pcan_abi.h b/c/set-protocol/include/pcan_abi.h similarity index 100% rename from c/protocan-transport/include/pcan_abi.h rename to c/set-protocol/include/pcan_abi.h diff --git a/c/protocan-transport/include/pcan_config.h b/c/set-protocol/include/pcan_config.h similarity index 100% rename from c/protocan-transport/include/pcan_config.h rename to c/set-protocol/include/pcan_config.h diff --git a/c/protocan-transport/include/pcan_crc.h b/c/set-protocol/include/pcan_crc.h similarity index 100% rename from c/protocan-transport/include/pcan_crc.h rename to c/set-protocol/include/pcan_crc.h diff --git a/c/protocan-transport/include/pcan_frame.h b/c/set-protocol/include/pcan_frame.h similarity index 100% rename from c/protocan-transport/include/pcan_frame.h rename to c/set-protocol/include/pcan_frame.h diff --git a/c/protocan-transport/include/pcan_gas.h b/c/set-protocol/include/pcan_gas.h similarity index 99% rename from c/protocan-transport/include/pcan_gas.h rename to c/set-protocol/include/pcan_gas.h index 88b0097..aa59398 100644 --- a/c/protocan-transport/include/pcan_gas.h +++ b/c/set-protocol/include/pcan_gas.h @@ -14,7 +14,7 @@ * устройствами. * * Запрос на чтение кодируется кадром GAS с DLC = 0: в исходном коде - * SETCAN такой кодировки нет, это расширение - см. docs/GAS.md. + * SETCAN такой кодировки нет, это расширение - см. docs/legacy/GAS.md. */ #ifndef PCAN_GAS_H #define PCAN_GAS_H diff --git a/c/protocan-transport/include/pcan_id.h b/c/set-protocol/include/pcan_id.h similarity index 100% rename from c/protocan-transport/include/pcan_id.h rename to c/set-protocol/include/pcan_id.h diff --git a/c/protocan-transport/include/pcan_link.h b/c/set-protocol/include/pcan_link.h similarity index 100% rename from c/protocan-transport/include/pcan_link.h rename to c/set-protocol/include/pcan_link.h diff --git a/c/protocan-transport/include/pcan_ring.h b/c/set-protocol/include/pcan_ring.h similarity index 100% rename from c/protocan-transport/include/pcan_ring.h rename to c/set-protocol/include/pcan_ring.h diff --git a/c/protocan-transport/include/protocan_transport.h b/c/set-protocol/include/protocan_transport.h similarity index 100% rename from c/protocan-transport/include/protocan_transport.h rename to c/set-protocol/include/protocan_transport.h diff --git a/c/set-protocol/include/setprotocol.h b/c/set-protocol/include/setprotocol.h new file mode 100644 index 0000000..3cf2a3c --- /dev/null +++ b/c/set-protocol/include/setprotocol.h @@ -0,0 +1,19 @@ +/** + * @file setprotocol.h + * @brief Единственная C99-точка включения полного SETProtocol. + */ +#ifndef SETPROTOCOL_H +#define SETPROTOCOL_H + +/* Основной SET protocol v2. */ +#include "set_protocol.h" +#include "set_can.h" +#include "set_firmware.h" +#include "set_telemetry.h" + +/* Поддерживаемые форматы переходного периода. */ +#include "protocan_transport.h" +#include "gui_frame.h" +#include "gui_catalog.h" + +#endif /* SETPROTOCOL_H */ diff --git a/c/set-protocol/include/setprotocol_abi.h b/c/set-protocol/include/setprotocol_abi.h new file mode 100644 index 0000000..ce7b48a --- /dev/null +++ b/c/set-protocol/include/setprotocol_abi.h @@ -0,0 +1,15 @@ +/** + * @file setprotocol_abi.h + * @brief Стабильная FFI-граница SETProtocol ABI v1. + * + * Имена pcan_abi_* сохранены ради бинарной совместимости существующих + * SETGUI и Android-клиентов. Новые ABI-группы добавляются через этот facade. + */ +#ifndef SETPROTOCOL_ABI_H +#define SETPROTOCOL_ABI_H + +#include "pcan_abi.h" + +#define SETPROTOCOL_ABI_VERSION PCAN_ABI_VERSION + +#endif /* SETPROTOCOL_ABI_H */ diff --git a/c/protocan-transport/ports/android/Android.mk b/c/set-protocol/ports/android/Android.mk similarity index 69% rename from c/protocan-transport/ports/android/Android.mk rename to c/set-protocol/ports/android/Android.mk index 142285f..fb9c90c 100644 --- a/c/protocan-transport/ports/android/Android.mk +++ b/c/set-protocol/ports/android/Android.mk @@ -1,9 +1,14 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE := setcore +LOCAL_MODULE := setprotocol LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include LOCAL_SRC_FILES := \ + ../../src/set_protocol.c \ + ../../src/set_can.c \ + ../../src/set_firmware.c \ + ../../src/set_telemetry.c \ + ../../src/gui_catalog.c \ ../../src/gui_frame.c \ ../../src/pcan_abi.c \ ../../src/pcan_crc.c \ @@ -12,7 +17,7 @@ LOCAL_SRC_FILES := \ ../../src/pcan_link.c \ ../../src/pcan_ring.c \ ../../src/pcan_gas.c \ - setcore_jni.c + setprotocol_jni.c LOCAL_CFLAGS := -std=c99 -Wall -Wextra -Wpedantic -fvisibility=hidden LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) diff --git a/c/protocan-transport/ports/android/README.md b/c/set-protocol/ports/android/README.md similarity index 68% rename from c/protocan-transport/ports/android/README.md rename to c/set-protocol/ports/android/README.md index 8507da0..ee80107 100644 --- a/c/protocan-transport/ports/android/README.md +++ b/c/set-protocol/ports/android/README.md @@ -1,7 +1,7 @@ # Android port -`Android.mk` builds `libsetcore.so` from the same C99 sources used by MCU and -desktop builds. `setcore_jni.c` contains only JNI marshalling; protocol rules +`Android.mk` builds `libsetprotocol.so` from the same C99 sources used by MCU +and desktop builds. `setprotocol_jni.c` contains only JNI marshalling; protocol rules remain in the core. Add the Kotlin directory as an Android source directory and include this `Android.mk` from the application NDK build. diff --git a/c/protocan-transport/ports/android/kotlin/ru/setcorp/setcore/NativeProtoCan.kt b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt similarity index 87% rename from c/protocan-transport/ports/android/kotlin/ru/setcorp/setcore/NativeProtoCan.kt rename to c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt index 07cf39f..a4accc8 100644 --- a/c/protocan-transport/ports/android/kotlin/ru/setcorp/setcore/NativeProtoCan.kt +++ b/c/set-protocol/ports/android/kotlin/ru/setcorp/setprotocol/NativeSetProtocol.kt @@ -1,10 +1,10 @@ -package ru.setcorp.setcore +package ru.setcorp.setprotocol -/** Thin Kotlin facade over the shared C99 ProtoCAN core. */ -object NativeProtoCan { +/** Thin Kotlin facade over the shared C99 SETProtocol core. */ +object NativeSetProtocol { val available: Boolean by lazy { runCatching { - System.loadLibrary("setcore") + System.loadLibrary("setprotocol") nativeAbiVersion() == 1 }.getOrDefault(false) } diff --git a/c/protocan-transport/ports/android/setcore_jni.c b/c/set-protocol/ports/android/setprotocol_jni.c similarity index 90% rename from c/protocan-transport/ports/android/setcore_jni.c rename to c/set-protocol/ports/android/setprotocol_jni.c index dbcdff7..e48ac66 100644 --- a/c/protocan-transport/ports/android/setcore_jni.c +++ b/c/set-protocol/ports/android/setprotocol_jni.c @@ -3,7 +3,7 @@ #include #include -#include "pcan_abi.h" +#include "setprotocol_abi.h" typedef struct { uint8_t *storage; @@ -18,7 +18,7 @@ typedef struct { } android_gui_parser_t; JNIEXPORT jint JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeAbiVersion(JNIEnv *env, jobject self) +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeAbiVersion(JNIEnv *env, jobject self) { (void)env; (void)self; @@ -26,7 +26,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeAbiVersion(JNIEnv *env, jobject sel } JNIEXPORT jlong JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativePackId( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativePackId( JNIEnv *env, jobject self, jint priority, jint route, jint device_type, jint device_id, jint message_type, jint body) { @@ -38,7 +38,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativePackId( } JNIEXPORT jintArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeUnpackId( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeUnpackId( JNIEnv *env, jobject self, jlong raw) { (void)self; @@ -56,7 +56,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeUnpackId( } JNIEXPORT jint JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeCrc16( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeCrc16( JNIEnv *env, jobject self, jbyteArray input) { (void)self; @@ -71,7 +71,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeCrc16( } JNIEXPORT jbyteArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeEncodeFrame( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeEncodeFrame( JNIEnv *env, jobject self, jint sequence, jint flags, jlong can_id, jbyteArray input) { @@ -103,7 +103,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeEncodeFrame( } JNIEXPORT jlong JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeCreateParser(JNIEnv *env, jobject self) +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeCreateParser(JNIEnv *env, jobject self) { (void)env; (void)self; @@ -124,7 +124,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeCreateParser(JNIEnv *env, jobject s } JNIEXPORT void JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeDestroyParser( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeDestroyParser( JNIEnv *env, jobject self, jlong handle) { (void)env; @@ -138,7 +138,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeDestroyParser( /* Each returned record is 15 bytes: seq, flags, id LE, dlc, data[8]. */ JNIEXPORT jbyteArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeFeedParser( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeFeedParser( JNIEnv *env, jobject self, jlong handle, jbyteArray input) { (void)self; @@ -194,7 +194,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeFeedParser( } JNIEXPORT jintArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeParserStats( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeParserStats( JNIEnv *env, jobject self, jlong handle) { (void)self; @@ -214,7 +214,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeParserStats( } JNIEXPORT jbyteArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeGuiEncode( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeGuiEncode( JNIEnv *env, jobject self, jint message_type, jint sequence, jbyteArray input) { @@ -237,7 +237,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeGuiEncode( } JNIEXPORT jlong JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeCreateGuiParser(JNIEnv *env, jobject self) +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeCreateGuiParser(JNIEnv *env, jobject self) { (void)env; (void)self; android_gui_parser_t *parser = (android_gui_parser_t *)calloc(1U, sizeof *parser); @@ -252,7 +252,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeCreateGuiParser(JNIEnv *env, jobjec } JNIEXPORT void JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeDestroyGuiParser( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeDestroyGuiParser( JNIEnv *env, jobject self, jlong handle) { (void)env; (void)self; @@ -262,7 +262,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeDestroyGuiParser( /* Records: type[1], sequence LE[2], size LE[2], payload[size]. */ JNIEXPORT jbyteArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeFeedGuiParser( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeFeedGuiParser( JNIEnv *env, jobject self, jlong handle, jbyteArray input) { (void)self; @@ -300,7 +300,7 @@ Java_ru_setcorp_setcore_NativeProtoCan_nativeFeedGuiParser( } JNIEXPORT jintArray JNICALL -Java_ru_setcorp_setcore_NativeProtoCan_nativeGuiParserStats( +Java_ru_setcorp_setprotocol_NativeSetProtocol_nativeGuiParserStats( JNIEnv *env, jobject self, jlong handle) { (void)self; diff --git a/c/protocan-transport/ports/stm32f4/pcan_uart_stm32f4.c b/c/set-protocol/ports/stm32f4/pcan_uart_stm32f4.c similarity index 100% rename from c/protocan-transport/ports/stm32f4/pcan_uart_stm32f4.c rename to c/set-protocol/ports/stm32f4/pcan_uart_stm32f4.c diff --git a/c/protocan-transport/ports/stm32f4/pcan_uart_stm32f4.h b/c/set-protocol/ports/stm32f4/pcan_uart_stm32f4.h similarity index 100% rename from c/protocan-transport/ports/stm32f4/pcan_uart_stm32f4.h rename to c/set-protocol/ports/stm32f4/pcan_uart_stm32f4.h diff --git a/c/protocan-transport/src/gui_catalog.c b/c/set-protocol/src/gui_catalog.c similarity index 100% rename from c/protocan-transport/src/gui_catalog.c rename to c/set-protocol/src/gui_catalog.c diff --git a/c/protocan-transport/src/gui_frame.c b/c/set-protocol/src/gui_frame.c similarity index 100% rename from c/protocan-transport/src/gui_frame.c rename to c/set-protocol/src/gui_frame.c diff --git a/c/protocan-transport/src/pcan_abi.c b/c/set-protocol/src/pcan_abi.c similarity index 100% rename from c/protocan-transport/src/pcan_abi.c rename to c/set-protocol/src/pcan_abi.c diff --git a/c/protocan-transport/src/pcan_crc.c b/c/set-protocol/src/pcan_crc.c similarity index 100% rename from c/protocan-transport/src/pcan_crc.c rename to c/set-protocol/src/pcan_crc.c diff --git a/c/protocan-transport/src/pcan_frame.c b/c/set-protocol/src/pcan_frame.c similarity index 100% rename from c/protocan-transport/src/pcan_frame.c rename to c/set-protocol/src/pcan_frame.c diff --git a/c/protocan-transport/src/pcan_gas.c b/c/set-protocol/src/pcan_gas.c similarity index 100% rename from c/protocan-transport/src/pcan_gas.c rename to c/set-protocol/src/pcan_gas.c diff --git a/c/protocan-transport/src/pcan_id.c b/c/set-protocol/src/pcan_id.c similarity index 100% rename from c/protocan-transport/src/pcan_id.c rename to c/set-protocol/src/pcan_id.c diff --git a/c/protocan-transport/src/pcan_link.c b/c/set-protocol/src/pcan_link.c similarity index 100% rename from c/protocan-transport/src/pcan_link.c rename to c/set-protocol/src/pcan_link.c diff --git a/c/protocan-transport/src/pcan_ring.c b/c/set-protocol/src/pcan_ring.c similarity index 100% rename from c/protocan-transport/src/pcan_ring.c rename to c/set-protocol/src/pcan_ring.c diff --git a/c/protocan-transport/tests/test_abi.c b/c/set-protocol/tests/test_abi.c similarity index 100% rename from c/protocan-transport/tests/test_abi.c rename to c/set-protocol/tests/test_abi.c diff --git a/c/protocan-transport/tests/test_gui.c b/c/set-protocol/tests/test_gui.c similarity index 100% rename from c/protocan-transport/tests/test_gui.c rename to c/set-protocol/tests/test_gui.c diff --git a/c/protocan-transport/tests/test_transport.c b/c/set-protocol/tests/test_transport.c similarity index 100% rename from c/protocan-transport/tests/test_transport.c rename to c/set-protocol/tests/test_transport.c diff --git a/c/protocan-transport/tests/vectors/test-vectors.json b/c/set-protocol/tests/vectors/test-vectors.json similarity index 100% rename from c/protocan-transport/tests/vectors/test-vectors.json rename to c/set-protocol/tests/vectors/test-vectors.json diff --git a/c/protocan-transport/tools/build_host.py b/c/set-protocol/tools/build_host.py similarity index 87% rename from c/protocan-transport/tools/build_host.py rename to c/set-protocol/tools/build_host.py index 547b4d5..07efb18 100644 --- a/c/protocan-transport/tools/build_host.py +++ b/c/set-protocol/tools/build_host.py @@ -1,4 +1,4 @@ -"""Build the SETCore shared library without imposing one host toolchain. +"""Build the SETProtocol shared library without imposing one host toolchain. CMake remains the primary build. On a Windows workstation where CMake is absent, the script locates Visual Studio and invokes MSVC directly. Unix-like @@ -19,8 +19,10 @@ ROOT = Path(__file__).resolve().parent.parent INCLUDE = ROOT / "include" SOURCES = [ ROOT / "src" / name for name in ( - "gui_frame.c", "pcan_abi.c", "pcan_crc.c", "pcan_frame.c", "pcan_id.c", - "pcan_link.c", "pcan_ring.c", "pcan_gas.c", + "set_protocol.c", "set_can.c", "set_firmware.c", "set_telemetry.c", + "gui_catalog.c", "gui_frame.c", "pcan_abi.c", "pcan_crc.c", + "pcan_frame.c", "pcan_id.c", "pcan_link.c", "pcan_ring.c", + "pcan_gas.c", ) ] @@ -48,7 +50,7 @@ def _build_msvc(output: Path, build_dir: Path) -> None: if vcvars is None: raise SystemExit("Visual Studio C++ tools were not found") quoted_sources = " ".join(f'"{source}"' for source in SOURCES) - import_library = build_dir / "setcore.lib" + import_library = build_dir / "setprotocol.lib" command = ( f'call "{vcvars}" && cl /nologo /W4 /std:c11 ' f'/DPCAN_ABI_BUILD_DLL /I"{INCLUDE}" /LD {quoted_sources} ' @@ -75,7 +77,7 @@ def main() -> int: args = parser.parse_args() output = args.output.resolve() output.parent.mkdir(parents=True, exist_ok=True) - build_dir = output.parent / ".setcore-build" + build_dir = output.parent / ".setprotocol-build" build_dir.mkdir(parents=True, exist_ok=True) if platform.system() == "Windows": _build_msvc(output, build_dir) diff --git a/doc/build-setprotocol-html.ps1 b/doc/build-setprotocol-html.ps1 new file mode 100644 index 0000000..6183b25 --- /dev/null +++ b/doc/build-setprotocol-html.ps1 @@ -0,0 +1,32 @@ +[CmdletBinding()] +param() + +$ErrorActionPreference = 'Stop' +$outputPath = Join-Path $PSScriptRoot 'setprotocol.html' +$sourcePath = Join-Path $PSScriptRoot '..\c\set-protocol\docs\SETPROTOCOL.md' + +$markdown = Get-Content -Raw -LiteralPath $sourcePath -Encoding UTF8 +$html = (ConvertFrom-Markdown -InputObject $markdown).Html +$generatedBlock = @" + +
+$html +
+ +"@ + +$page = Get-Content -Raw -LiteralPath $outputPath -Encoding UTF8 +$pattern = '(?s).*?' +if ($page -notmatch $pattern) { + throw 'Не найдены маркеры SETPROTOCOL:START/END в doc/setprotocol.html.' +} + +$page = [regex]::Replace($page, $pattern, [System.Text.RegularExpressions.MatchEvaluator]{ + param($match) + $generatedBlock +}, 1) + +$page = $page.TrimEnd("`r", "`n") + [Environment]::NewLine +$utf8WithoutBom = [System.Text.UTF8Encoding]::new($false) +[System.IO.File]::WriteAllText($outputPath, $page, $utf8WithoutBom) +Write-Host "[DONE] SETProtocol HTML: $outputPath" diff --git a/doc/index.html b/doc/index.html index 140eba5..226c3ac 100644 --- a/doc/index.html +++ b/doc/index.html @@ -17,10 +17,9 @@ git subtree pull --prefix lib/templates https://git.rd12.ru/Andrey/templates.git

eeprom-ft24c256

EEPROM 24Cxx с нарезкой записи по страницам.

I²Cstorage

Порт: I²C write, write-read и delay.

can-sensor

Передача 64-битных ROM датчиков парой CAN-кадров.

CANsensor

Порт: CAN TX/RX.

ds18b20

1-Wire, CRC8, SEARCH ROM и несколько термометров.

1-Wireпорты F1/G4/F4

Порт: Init, DelayUs, Reset, WriteBit, ReadBit.

-

protocan-transport

ProtoCAN над байтовым потоком: CRC16, ring, GAS и каталог GUI.

UART/USBпорт STM32F4

Порт: stream write и доступный объём TX.

+

SETProtocol

Единое C99-ядро: SET v2, ProtoCAN/GUI v1, телеметрия, firmware flow, GAS и стабильный ABI.

UART/USB/CAN/EthernetWindows + Android + STM32F4

Порт: COM, SLCAN, SocketCAN, JNI или callbacks MCU.

protocan-boot

Прошивка по ProtoCAN: A/B-слоты, resume, CRC32, verify и rollback.

CANfirmware

Порт: CAN TX, Flash, metadata, verify, reboot.

rs485-boot

SETGUI v1 firmware update: stream parser, CRC32 и resume.

RS-485порты F103/G474

Порт: UART TX/RX, DE и Flash.

-

set-protocol

SET v2: управление, телеметрия и прошивка через UART/CAN/USB/Ethernet.

multi-transportv2

Порт: доставка кадров, часы, карта и firmware backend.

rtc-service

RTC с резервным backup-томом и единым API времени.

RTCпорт K1921VK028

Порт: RTC и backup storage.

Ничего не найдено.