Документация ProtoCAN

Статус комплекта: Draft
Версия комплекта: 1.0
Дата редакции: 2026-08-29
Транспорт: Classic CAN 2.0B, Extended ID, DLC 0…8

Этот каталог разделяет нормативное описание протокола, загрузчик и реестр общего адресного пространства. Большой исходный документ Протокол CAN и ОАП.md сохранён как совместимое представление таблиц из Excel.

Документы

Документ Назначение Статус источника
PROTOCOL.md 29-битный CAN ID, адресация, реестр MsgType, порядок байтов нормативный
BOOTLOADER.md обновление прошивки, кадры, состояния, ошибки и A/B-слоты нормативный draft
OAP.md правила ведения общего адресного пространства нормативный индекс
../../Протокол CAN и ОАП.xlsx редактируемый реестр ОАП источник таблиц
examples/test-vectors.json машинные эталоны CAN ID и payload нормативные примеры
CHANGELOG.md история версий документа нормативный

Приоритет источников

При расхождении данных действует следующий порядок:

  1. PROTOCOL.md — структура ProtoCAN и реестр типов сообщений.
  2. BOOTLOADER.md — загрузочный сервис 0x9…0xD.
  3. XLSX — адреса и свойства регистров ОАП.
  4. Сгенерированный HTML — только представление, не самостоятельный источник.

Сборка HTML

В PowerShell 7:

./build-html.ps1

Результат создаётся в build/protocol.html. Скрипт не изменяет исходные Markdown/XLSX и пригоден для запуска в CI.


ProtoCAN — базовый протокол

Статус: Stable с зарезервированным загрузочным расширением
Версия: 1.0
Порядок байтов payload: little-endian, если явно не указано иное

Назначение

ProtoCAN — прикладной протокол поверх classic CAN 2.0B. Используются только расширенные 29-битные идентификаторы (IDE=1) и payload длиной 0…8 байт.

Термины

Термин Значение
ПМ управляющий модуль
прибор адресуемый узел на шине
DeviceType тип прибора, 0…7
DeviceID экземпляр прибора данного типа, 0…15
MsgType класс сообщения или сервис
MsgBody 16-битное поле, формат которого зависит от MsgType

Пара DeviceType/DeviceID задаёт до 8 × 16 = 128 уникальных адресов.

Расширенный CAN ID

28       27       26...24      23...20     19...16     15........0
Priority Route    DeviceType   DeviceID    MsgType     MsgBody
 1 бит    1 бит      3 бита      4 бита      4 бита      16 бит
can_id =
    ((uint32_t)priority    << 28) |
    ((uint32_t)route       << 27) |
    ((uint32_t)device_type << 24) |
    ((uint32_t)device_id   << 20) |
    ((uint32_t)msg_type    << 16) |
    msg_body;
Поле Значения Назначение
Priority 0 critical, 1 standard CAN-арбитраж
Route 0 от ПМ, 1 от прибора логическое направление
DeviceType 0…7 тип прибора
DeviceID 0…15 номер экземпляра
MsgType 0…15 тип сообщения
MsgBody 0…65535 команда, адрес или номер блока

Route не является направлением физического трансивера. Ответ прибора сохраняет адрес DeviceType/DeviceID и устанавливает Route=1.

Реестр MsgType

Код Имя Основное направление DLC Статус
0x0 BROADCAST ПМ → все зависит от команды stable
0x1 DISCRETE оба 0…8 stable
0x2 ANALOG оба 0…8 stable
0x3 GAS оба 0/2/4/6/8 stable
0x4 MODBUS_COIL оба 0…8 stable
0x5 MODBUS_DISCRETE оба 0…8 stable
0x6 MODBUS_HOLDING оба 0…8 stable
0x7 MODBUS_INPUT оба 0…8 stable
0x8 ERROR прибор → ПМ 0 stable
0x9 BOOT_CONTROL ПМ → прибор 0/8 draft
0xA BOOT_DATA_A ПМ → прибор 8 draft
0xB BOOT_DATA_B ПМ → прибор 8 draft
0xC BOOT_STATUS прибор → ПМ 8 draft
0xD BOOT_DISCOVERY прибор → ПМ 8 draft
0xE SETTINGS оба 0/1/8 stable
0xF PULSE прибор → сеть 1 stable

Подробный формат 0x9…0xD находится в BOOTLOADER.md.

Разметки MsgBody

MsgType Биты MsgBody
broadcast команда [15:4], параметр [3:0]
discrete/analog подтип [15:12], значение/адрес [11:0]
Modbus начальный адрес [15:4], количество [3:0]
GAS адрес первого 16-битного регистра [15:0]
error дополнительная информация [15:8], код [7:0]
settings номер сборки [15:8], позиция [7:0]
boot control/status SessionID[15:8], команда [7:0]
boot data BlockIndex[15:0]

Общие правила обмена

Эталон упаковки ID

Priority   = 1
Route      = 0
DeviceType = 3
DeviceID   = 5
MsgType    = 0x9
MsgBody    = 0x0702

CAN ID = 0x13590702

Этот пример соответствует ENTER_BOOT, SessionID=7. Машинные варианты находятся в examples/test-vectors.json.


ProtoCAN Boot Protocol

Статус: Draft
Версия протокола: 1.0
Совместимость: classic CAN 2.0B, Extended ID, DLC 0…8
Реализация: templates/c/protocan-boot

Назначение

Сервис обновляет адресованный прибор по CAN и поддерживает два логических слота A/B. Активный слот не стирается: новый образ записывается в неактивный, проверяется и атомарно назначается кандидатом на запуск.

Карта сообщений

MsgType Имя MsgBody Payload
0x9 BOOT_CONTROL SessionID[15:8] \| Command[7:0] параметры команды
0xA BOOT_DATA_A BlockIndex[15:0] 8 байт слота A
0xB BOOT_DATA_B BlockIndex[15:0] 8 байт слота B
0xC BOOT_STATUS SessionID[15:8] \| Command[7:0] статус и прогресс
0xD BOOT_DISCOVERY подтип ответа идентификация

Все команды записи адресуются конкретному DeviceType/DeviceID и имеют Route=0. Ответы сохраняют адрес прибора и имеют Route=1.

Адресация образа

MsgBody кадра данных — номер 8-байтового блока:

offset = (uint32_t)BlockIndex * 8U;
address = SLOT_X_BASE + offset;
512 КиБ = 524 288 байт
524 288 / 8 = 65 536 блоков
BlockIndex = 0x0000…0xFFFF
BlockIndex Смещение Диапазон байтов
0x0000 0x00000 0x00000…0x00007
0x0001 0x00008 0x00008…0x0000F
0xFFFF 0x7FFF8 0x7FFF8…0x7FFFF

0x80000 является первой позицией за границей слота. Последний кадр дополняется 0xFF, но CRC32 вычисляется только по ImageSize байтам.

Команды BOOT_CONTROL

Код Команда DLC Payload Допустимое состояние
0x01 IDENTIFY 0 отсутствует любое
0x02 ENTER_BOOT 0 отсутствует любое; SessionID != 0
0x03 BEGIN_IMAGE 8 размер и CRC32 metadata
0x04 BEGIN_COMPAT 8 совместимость и версия metadata
0x05 ERASE 0 отсутствует ready-to-erase
0x06 VERIFY 0 отсутствует образ получен
0x07 COMMIT 0 отсутствует verified
0x08 CONFIRM 0 отсутствует запущенное приложение
0x09 REBOOT 0 отсутствует активная сессия
0x0A ABORT 0 отсутствует активная сессия
0x0B QUERY_PROGRESS 0 отсутствует активная сессия

BEGIN_IMAGE

DATA[0..3] ImageSize, uint32 little-endian
DATA[4..7] ImageCRC32, uint32 little-endian

BEGIN_COMPAT

DATA[0..1] ProductType, uint16 little-endian
DATA[2]    HardwareRevisionMin
DATA[3]    HardwareRevisionMax
DATA[4..7] FirmwareVersion, uint32 little-endian

До ERASE прибор обязан получить обе части метаданных и проверить размер, тип изделия, аппаратную ревизию, версию и политику anti-rollback.

BOOT_STATUS

MsgBody[15..8] SessionID
MsgBody[7..0]  команда, на которую дан ответ

DATA[0]        Status
DATA[1]        TargetSlot: 0=A, 1=B, 0xFF=не выбран
DATA[2..3]     NextBlock, uint16 little-endian
DATA[4..7]     RunningCRC32, uint32 little-endian
Код Статус Повтор допустим
0x00 OK
0x01 BUSY да, после задержки
0x02 INVALID_COMMAND после исправления
0x03 WRONG_DEVICE нет для этого образа
0x04 WRONG_HARDWARE нет для этого образа
0x05 INVALID_SIZE нет для этого образа
0x06 CRC_ERROR новая передача
0x07 FLASH_ERROR зависит от платформы
0x08 SEQUENCE_ERROR да, с NextBlock
0x09 SIGNATURE_ERROR нет
0x0A SESSION_ERROR открыть новую сессию
0x0B VOLTAGE_ERROR да после нормализации питания
0x0C INVALID_STATE выполнить правильный переход

State machine

IDLE
  └─ ENTER_BOOT ─> METADATA
                     ├─ BEGIN_IMAGE
                     └─ BEGIN_COMPAT
                            │
                            v
                    READY_TO_ERASE
                            │ ERASE
                            v
                      RECEIVING
                            │ VERIFY
                            v
                       VERIFIED
                            │ COMMIT
                            v
                    PENDING + REBOOT
                            │ CONFIRM
                            v
                       CONFIRMED

Ошибка Flash, CRC, совместимости или подписи переводит сессию в FAILED. Новая ENTER_BOOT создаёт чистую сессию. ABORT прекращает текущую передачу, не активируя частично записанный слот.

Надёжность и повторы

Безопасность и A/B-обновление

active=A -> target=B -> verify -> pending=B
active=B -> target=A -> verify -> pending=A

CRC32 защищает только от случайного повреждения. Серийный загрузчик должен дополнительно проверить подпись контейнера, границы вектора, совместимость и anti-rollback. Bootloader не обновляется командами BOOT_DATA_A/B.

Boot metadata должна атомарно хранить:

Если приложение не выполняет CONFIRM за установленное число запусков, загрузчик возвращается к предыдущему подтверждённому слоту.

Эталонный сценарий

  1. ПМ адресно отправляет IDENTIFY.
  2. ПМ открывает ненулевой SessionID командой ENTER_BOOT.
  3. ПМ отправляет BEGIN_IMAGE и BEGIN_COMPAT.
  4. Прибор сообщает выбранный неактивный слот.
  5. ПМ выполняет ERASE и передаёт BOOT_DATA_A либо BOOT_DATA_B.
  6. ПМ выполняет VERIFY, затем COMMIT и REBOOT.
  7. Новое приложение после самопроверки выполняет CONFIRM.

Общее адресное пространство

Статус: Stable, данные ведутся в XLSX
Порядок значений: 16-битные регистры, little-endian в CAN payload

Редактируемый источник реестра: Протокол CAN и ОАП.xlsx.

Просматриваемая большая таблица находится в Протокол CAN и ОАП.html и Протокол CAN и ОАП.md.

Назначение

ОАП связывает 16-битный адрес регистра с его типом, назначением, доступом и масштабом. В ProtoCAN используется MsgType=0x3, а MsgBody содержит адрес первого регистра.

Обязательные поля реестра

Поле Требование
AddressHex 0x0000…0xFFFF, уникальное значение
AddressDec десятичный эквивалент AddressHex
Group функциональная группа
Name однозначное имя параметра
Type u16, i16, u32, i32, float32, bitmap или массив
Registers число занятых 16-битных регистров
Access R, W или RW
Unit физическая единица либо
Scale множитель/делитель представления
Default значение после сброса, если применимо
Description семантика, диапазон и особые значения

Правила ведения

Экспорт

Для программной генерации каталог следует экспортировать из XLSX в CSV с UTF-8 и фиксированными английскими именами колонок. CSV должен проверяться на:

До появления автоматического экспортёра нормативным источником адресов остаётся XLSX, а HTML/Markdown считаются представлением.


История изменений ProtoCAN

Формат основан на Keep a Changelog. Версия относится к спецификации, а не к версии прошивки отдельного прибора.

[Unreleased]

Added

[1.0] — 2026-08-29

Added