Сохрани адресацию отдельных регистров GAS 0x3 и выдели слотам тип 0x4 с маской Word0. Добавь единое C-ядро GAS_WATCH2, тонкие Python/JNI-порты и проверки общих эталонных байтов. Совместимость: тип 0x4 больше не обслуживает Modbus Coil. Потребителям PCAN_MSG_MODBUS_COIL и ProtoCanMsgToModbusCoil нужно перейти на GAS_SLOT и отдельный API слотов; регистровый GAS остаётся на 0x3.
49 lines
8.0 KiB
C
49 lines
8.0 KiB
C
#ifndef PCAN_GAS_SLOT_H /* Отдельный интерфейс исключает смешение нового номера слота со старым адресом регистра. */
|
||
#define PCAN_GAS_SLOT_H /* Защита допускает включение из общего заголовка и непосредственно из порта MCU. */
|
||
#include <stdint.h> /* Фиксированные слова и uint_least8_t доступны также на C28x без восьмибитного char. */
|
||
#include <stddef.h> /* NULL используется без зависимости от ОС и динамической памяти. */
|
||
#include <limits.h> /* CHAR_BIT выбирает экспорт host ABI отдельно от 16-битного C28x. */
|
||
#if CHAR_BIT == 8 /* Host/ARM используют существующий экспорт DLL/SO. */
|
||
#include "pcan_abi.h" /* Переиспользуем публичный экспорт единого host-кодека. */
|
||
#elif !defined(PCAN_ABI_API) /* Встроенный C28x статически собирает функции без Windows-атрибутов. */
|
||
#define PCAN_ABI_API /* Не требуем отсутствующий на C28x uint8_t из host ABI. */
|
||
#endif /* Все последующие объявления одинаковы по смыслу на ARM, host и C28x. */
|
||
#ifdef __cplusplus /* C++ и JNI связываются с C99-ядром через стандартные C-имена. */
|
||
extern "C" { /* Начинаем область совместимого C ABI. */
|
||
#endif /* Дальнейшие объявления пригодны также для чистого C. */
|
||
#define PCAN_GAS_SLOT_WORDS 4U /* Восемь октетов кадра содержат четыре wire-слова: маску Word0 и три значения Word1…Word3. */
|
||
#define PCAN_GAS_SLOT_DATA_WORDS 3U /* Два октета маски оставляют шесть октетов для трёх независимых 16-битных значений. */
|
||
#define PCAN_GAS_SLOT_MASK 0x000EU /* Биты 1…3 выбирают одноимённые значения; бит 0 и биты 4…15 зарезервированы. */
|
||
#define PCAN_GAS_SLOT_MODE_COUNT 32U /* Два типа PERIPH по шестнадцать DeviceID дают mode 0…31. */
|
||
#define PCAN_GAS_SLOT_MODE_SLOTS 67U /* Округление 200/3 вверх сохраняет все регистры PERIPH; в последнем слоте действуют два значения. */
|
||
#define PCAN_GAS_SLOT_MODE_WORDS 200U /* Значение измеряется в 16-битных словах, не в байтах MCU. */
|
||
#define PCAN_GAS_SLOT_FLAG_IDE 1U /* Флаг Extended ID совпадает с транспортом pcan_frame; отдельно объявлен для C28x-порта. */
|
||
#define PCAN_GAS_SLOT_FLAG_RTR 2U /* RTR запрещён слотным профилем; запрос чтения использует data frame с DLC=0. */
|
||
#define PCAN_GAS_SLOT_FLAG_ERR 8U /* Ошибочный кадр моста не должен читаться как запрос к данным. */
|
||
typedef int (*pcan_gas_slot_read_fn)(void *, uint16_t, uint16_t[4]); /* Provider возвращает маску достоверных значений в Word0 и три значения; ноль означает успех. */
|
||
typedef int (*pcan_gas_slot_write_fn)(void *, uint16_t, const uint16_t[4]); /* Provider сначала проверяет все выбранные слова, затем меняет только биты 1…3 маски Word0 под общей блокировкой. */
|
||
typedef struct { /* Независимый MCU-кадр не меняет legacy ABI и не требует uint8_t на C28x. */
|
||
uint32_t id; /* Расширенный CAN ID содержит адрес узла и 16-битный номер слота. */
|
||
unsigned flags; /* IDE/RTR/ERR используют документированные значения транспортных флагов. */
|
||
unsigned dlc; /* Длина измеряется в октетах линии, а не в sizeof элементов C28x. */
|
||
uint_least8_t data[8]; /* На C28x октет хранится в 16-битной ячейке; значения строго 0…255. */
|
||
} pcan_gas_slot_frame_t; /* Порт переводит структуру в регистры CAN, не копируя wire-структуру через ABI. */
|
||
typedef struct { /* Один порт соединяет общий обработчик с данными конкретного узла без глобальной памяти. */
|
||
void *context; /* Контекст принадлежит проекту и должен жить дольше обработчика. */
|
||
pcan_gas_slot_read_fn read; /* NULL запрещает чтение; callback получает полный 16-битный адрес слота. */
|
||
pcan_gas_slot_write_fn write; /* NULL запрещает запись; callback не должен менять соседние слоты. */
|
||
} pcan_gas_slot_port_t; /* Размер существующих структур pcan_gas не изменяется. */
|
||
PCAN_ABI_API int32_t pcan_gas_slot_address(unsigned mode, unsigned local); /* Возвращает (mode<<8)|local либо -1 для mode>31 или local>66. */
|
||
PCAN_ABI_API uint32_t pcan_gas_slot_id(unsigned device_type, unsigned device_id, unsigned address, unsigned route); /* Формирует MsgType=0x4 для любого узла и адреса 0…65535 без сужения неверных входов. */
|
||
PCAN_ABI_API uint32_t pcan_gas_slot_request_id(unsigned mode, unsigned local, unsigned route); /* Формирует Extended ID PERIPH с Priority=1 и MsgType=0x4; ноль означает ошибку. */
|
||
PCAN_ABI_API int pcan_gas_slot_encode(const uint16_t *words, unsigned count, uint_least8_t *data); /* Допускает count=0 либо четыре wire-слова с непустой маской в Word0; длина измеряется октетами. */
|
||
PCAN_ABI_API int pcan_gas_slot_decode_words(uint32_t id, unsigned flags, const uint_least8_t *data, unsigned dlc, uint16_t *words); /* Проверяет общий слотный кадр любого узла; возвращает 0/4 либо -1 без изменения выхода при отказе. */
|
||
PCAN_ABI_API int pcan_gas_slot_decode(uint32_t id, unsigned flags, const uint_least8_t *data, unsigned dlc, unsigned *mode, unsigned *local, uint16_t *words); /* Проверяет узел, слот и октеты; возвращает 0/4 либо -1 без изменения выходов. */
|
||
PCAN_ABI_API int pcan_gas_slot_native(unsigned local, unsigned word, unsigned write, uint16_t *address); /* Переводит Word1…Word3 в родной адрес PERIPH; Word0 является маской и не адресует регистр. */
|
||
PCAN_ABI_API int pcan_gas_slot_handle_address(unsigned device_type, unsigned device_id, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response); /* Обслуживает масочную запись и чтение 0x4 для любого узла; не вызывает Modbus или GAS 0x3. */
|
||
PCAN_ABI_API int pcan_gas_slot_handle(unsigned mode, const pcan_gas_slot_port_t *port, const pcan_gas_slot_frame_t *request, pcan_gas_slot_frame_t *response); /* Возвращает 1 для ответа, 0 после записи, -1 при отказе; не вызывает legacy fallback. */
|
||
#ifdef __cplusplus /* Закрываем C ABI только при включении из C++. */
|
||
} /* Конец объявлений с C-соглашением о связывании. */
|
||
#endif /* Общие защитные символы не зависят от языка порта. */
|
||
#endif /* Завершаем защиту единственного интерфейса слотного профиля GAS. */
|