Files
templates/c/set-protocol/docs/legacy/GAS.md
T
Andrey 876b58517c feat(set-protocol): Раздели GAS и добавь пакетный сбор регистров
Сохрани адресацию отдельных регистров GAS 0x3 и выдели слотам тип 0x4 с маской Word0. Добавь единое C-ядро GAS_WATCH2, тонкие Python/JNI-порты и проверки общих эталонных байтов.

Совместимость: тип 0x4 больше не обслуживает Modbus Coil. Потребителям PCAN_MSG_MODBUS_COIL и ProtoCanMsgToModbusCoil нужно перейти на GAS_SLOT и отдельный API слотов; регистровый GAS остаётся на 0x3.
2026-10-23 14:14:48 +03:00

90 lines
5.2 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.
# Общее адресное пространство (GAS)
> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Спецификация: `doc/setcan/protocan/OAP.md`; адреса этого документа остаются регистровыми.
Плоское пространство 16-битных регистров с адресом `0x0000..0xFFFF`.
Пространство собирается из **регионов**; регионы не перекрываются и
хранятся отсортированными по адресу, поиск — двоичный.
## Регион
```c
typedef struct pcan_gas_region {
uint16_t base; /* адрес первого регистра */
uint16_t count; /* число регистров */
uint16_t *storage; /* массив либо NULL */
pcan_gas_read_fn read;
pcan_gas_write_fn write;
uint8_t flags; /* PCAN_GAS_RDONLY / PCAN_GAS_WRONLY */
void *user;
const char *name;
} pcan_gas_region_t;
```
Если `storage != NULL`, чтение и запись идут прямо в массив — это самый
дешёвый вариант для обычных уставок. Если нужен вычисляемый регистр
(счётчик, состояние периферии, время работы), задайте `read`/`write`:
колбэк получает смещение внутри региона и указатель `user`.
`pcan_gas_map_validate()` проверяет карту на этапе старта: нулевые регионы,
выход за `0xFFFF`, перекрытие, нарушение порядка и регион без источника
данных. Вызывайте её один раз при инициализации — ошибка в таблице ловится
сразу, а не через месяц в поле.
## Доступ
```c
uint16_t v;
pcan_gas_read(&map, 0x0002, &v);
pcan_gas_write(&map, 0x0002, 0x1234);
uint16_t block[4];
uint16_t n = pcan_gas_read_block(&map, 0x0000, block, 4);
```
Блочное чтение обрывается на первом адресе, которого нет в карте, поэтому
вызывающий всегда получает непрерывный кусок и знает его длину.
## Отображение на кадры ProtoCAN
Тип сообщения `PCAN_MSG_GAS` (`0b0011`). Адрес первого регистра лежит
в `MsgBody`, данные — до 4 регистров подряд, младшим байтом вперёд.
Это ровно то, что делает `PROTOCAN_SEND_GENERAL_ADDRESS_SPACE()`
в `ports/stm32-bxcan/protocan.c` (бывший SETCAN), поэтому обмен совместим с существующими
устройствами.
| Кадр | DLC | Смысл |
|---|---:|---|
| GAS, `MsgBody = addr` | 0 | **запрос на чтение** |
| GAS, `MsgBody = addr` | 2..8 | значения регистров начиная с `addr` |
Запрос на чтение с `DLC = 0` — **расширение**: в исходном коде SETCAN
такой кодировки нет, там ответы на GAS формировала заглушка `ProtoCanMsgToGeneralAddressSpace()`,
возвращавшая строку `GAS-XXXX`. Кодировка выбрана так, чтобы не занимать
новых типов сообщений и не конфликтовать с существующим форматом ответа.
```c
pcan_frame_t rsp;
if (pcan_gas_handle(&map, &incoming, &rsp)) {
pcan_link_send(&link, &rsp); /* был запрос на чтение */
}
```
`pcan_gas_handle()`:
- на запрос чтения кладёт в `rsp` до 4 регистров и переключает `Route`
на `FROM_DEVICE`, возвращает `true`;
- на запись пишет регистры в карту и возвращает `false` — ответа нет;
- если адреса нет в карте, возвращает `false`: отвечать нечем, а молчание
честнее, чем ответ с нулями.
## Ограничения
- В один кадр помещается не больше 4 регистров (`PCAN_GAS_REGS_PER_FRAME`).
Длинные блоки разбивайте на несколько кадров.
- Частичная запись: если в середине блока попался адрес вне карты или
регион только для чтения, запись обрывается на нём. `pcan_gas_write_block()`
возвращает число фактически записанных регистров.
- Атомарности между регистрами нет. Если два регистра обязаны меняться
вместе, заведите колбэк, который применяет их по записи второго.