Files
templates/c/protocan-transport/README.md

150 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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) и не зависит от порядка
байт хоста.