refactor: merge protocol cores as SETProtocol
This commit is contained in:
@@ -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`
|
||||
|
||||
@@ -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()
|
||||
@@ -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) и не зависит от порядка
|
||||
байт хоста.
|
||||
@@ -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()
|
||||
|
||||
@@ -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).
|
||||
|
||||
342
c/set-protocol/docs/SETPROTOCOL.md
Normal file
342
c/set-protocol/docs/SETPROTOCOL.md
Normal file
@@ -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, а не хранить
|
||||
разошедшиеся копии.
|
||||
@@ -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
|
||||
@@ -14,7 +14,7 @@
|
||||
* устройствами.
|
||||
*
|
||||
* Запрос на чтение кодируется кадром GAS с DLC = 0: в исходном коде
|
||||
* SETCAN такой кодировки нет, это расширение - см. docs/GAS.md.
|
||||
* SETCAN такой кодировки нет, это расширение - см. docs/legacy/GAS.md.
|
||||
*/
|
||||
#ifndef PCAN_GAS_H
|
||||
#define PCAN_GAS_H
|
||||
19
c/set-protocol/include/setprotocol.h
Normal file
19
c/set-protocol/include/setprotocol.h
Normal file
@@ -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 */
|
||||
15
c/set-protocol/include/setprotocol_abi.h
Normal file
15
c/set-protocol/include/setprotocol_abi.h
Normal file
@@ -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 */
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user