From ab60e58318517c727186917b9f84a4940d6b2f58 Mon Sep 17 00:00:00 2001 From: Andrey Kruchinkin Date: Sun, 30 Aug 2026 06:12:49 +0300 Subject: [PATCH] docs: consolidate documentation under doc --- README.md | 12 +- {docs/protocan => doc}/build-html.bat | 12 +- doc/build-html.ps1 | 87 ++ doc/index.html | 893 +++++++++++++++++- {docs => doc}/protocan/BOOTLOADER.md | 0 {docs => doc}/protocan/CHANGELOG.md | 2 +- {docs => doc}/protocan/OAP.md | 0 {docs => doc}/protocan/PROTOCOL.md | 0 {docs => doc}/protocan/README.md | 10 +- .../protocan/examples/test-vectors.json | 0 .../Протокол CAN и ОАП.html | 0 .../Протокол CAN и ОАП.md | 0 .../Протокол CAN и ОАП.xlsx | Bin .../ссылки на док.md | 0 docs/protocan/build-html.ps1 | 57 -- docs/protocan/build/protocol.html | 833 ---------------- docs/protocan/protocol.html | 833 ---------------- 17 files changed, 991 insertions(+), 1748 deletions(-) rename {docs/protocan => doc}/build-html.bat (51%) create mode 100644 doc/build-html.ps1 rename {docs => doc}/protocan/BOOTLOADER.md (100%) rename {docs => doc}/protocan/CHANGELOG.md (96%) rename {docs => doc}/protocan/OAP.md (100%) rename {docs => doc}/protocan/PROTOCOL.md (100%) rename {docs => doc}/protocan/README.md (82%) rename {docs => doc}/protocan/examples/test-vectors.json (100%) rename Протокол CAN и ОАП.html => doc/Протокол CAN и ОАП.html (100%) rename Протокол CAN и ОАП.md => doc/Протокол CAN и ОАП.md (100%) rename Протокол CAN и ОАП.xlsx => doc/Протокол CAN и ОАП.xlsx (100%) rename ссылки на док.md => doc/ссылки на док.md (100%) delete mode 100644 docs/protocan/build-html.ps1 delete mode 100644 docs/protocan/build/protocol.html delete mode 100644 docs/protocan/protocol.html diff --git a/README.md b/README.md index c8039ab..cd18a82 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ SETCAN/ Нормативное описание разделено по назначению: -- [`docs/protocan/PROTOCOL.md`](docs/protocan/PROTOCOL.md) — структура ProtoCAN; -- [`docs/protocan/BOOTLOADER.md`](docs/protocan/BOOTLOADER.md) — прошивка по CAN; -- [`docs/protocan/OAP.md`](docs/protocan/OAP.md) — правила ведения ОАП; -- [`docs/protocan/examples/test-vectors.json`](docs/protocan/examples/test-vectors.json) — машинные эталоны; -- [`docs/protocan/build/protocol.html`](docs/protocan/build/protocol.html) — собранная HTML-версия. +- [`doc/protocan/PROTOCOL.md`](doc/protocan/PROTOCOL.md) — структура ProtoCAN; +- [`doc/protocan/BOOTLOADER.md`](doc/protocan/BOOTLOADER.md) — прошивка по CAN; +- [`doc/protocan/OAP.md`](doc/protocan/OAP.md) — правила ведения ОАП; +- [`doc/protocan/examples/test-vectors.json`](doc/protocan/examples/test-vectors.json) — машинные эталоны; +- [`doc/index.html`](doc/index.html) — единая собранная HTML-версия всей документации. Большой файл `Протокол CAN и ОАП.md` и исходный XLSX сохранены как табличное представление реестра. Правила приоритета источников описаны в -[`docs/protocan/README.md`](docs/protocan/README.md). +[`doc/protocan/README.md`](doc/protocan/README.md). ## Формат расширенного CAN ID diff --git a/docs/protocan/build-html.bat b/doc/build-html.bat similarity index 51% rename from docs/protocan/build-html.bat rename to doc/build-html.bat index 52096a9..4891a17 100644 --- a/docs/protocan/build-html.bat +++ b/doc/build-html.bat @@ -5,15 +5,9 @@ set "SCRIPT_DIR=%~dp0" where pwsh.exe >nul 2>nul if %ERRORLEVEL% EQU 0 ( - pwsh.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build-html.ps1" %* + pwsh.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build-html.ps1" ) else ( - powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build-html.ps1" %* + powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build-html.ps1" ) -set "EXIT_CODE=%ERRORLEVEL%" -if not "%EXIT_CODE%"=="0" ( - echo. - echo Ошибка сборки HTML. Код: %EXIT_CODE% -) - -exit /b %EXIT_CODE% +exit /b %ERRORLEVEL% diff --git a/doc/build-html.ps1 b/doc/build-html.ps1 new file mode 100644 index 0000000..09f898a --- /dev/null +++ b/doc/build-html.ps1 @@ -0,0 +1,87 @@ +[CmdletBinding()] +param() + +$ErrorActionPreference = 'Stop' +$outputPath = Join-Path $PSScriptRoot 'index.html' +$sourceDirectory = Join-Path $PSScriptRoot 'protocan' +$documents = @( + 'README.md', + 'PROTOCOL.md', + 'BOOTLOADER.md', + 'OAP.md', + 'CHANGELOG.md' +) + +function Convert-LocalLinks { + param( + [string]$Html, + [string]$SourcePath + ) + + $sourceParent = Split-Path -Parent $SourcePath + $outputParent = Split-Path -Parent $outputPath + $pattern = '(?href|src)="(?(?![a-z]+:|/|#)[^"]+)"' + + return [regex]::Replace($Html, $pattern, { + param($match) + + $target = $match.Groups['target'].Value + $parts = $target -split '#', 2 + $targetPath = [Uri]::UnescapeDataString($parts[0]) + $absoluteTarget = [System.IO.Path]::GetFullPath((Join-Path $sourceParent $targetPath)) + $relativeTarget = [System.IO.Path]::GetRelativePath($outputParent, $absoluteTarget).Replace('\', '/') + if ($parts.Count -eq 2) { + $relativeTarget += '#' + $parts[1] + } + + return $match.Groups['attribute'].Value + '="' + $relativeTarget + '"' + }) +} + +$sections = foreach ($document in $documents) { + $path = Join-Path $sourceDirectory $document + $markdown = Get-Content -Raw -LiteralPath $path -Encoding UTF8 + $html = (ConvertFrom-Markdown -InputObject $markdown).Html + $html = Convert-LocalLinks -Html $html -SourcePath $path + "
$html
" +} + +$vectorsPath = Join-Path $sourceDirectory 'examples\test-vectors.json' +$vectors = [System.Net.WebUtility]::HtmlEncode( + (Get-Content -Raw -LiteralPath $vectorsPath -Encoding UTF8) +) +$sections += @" +
+

Тестовые векторы

+

Машинные эталоны из examples/test-vectors.json.

+
$vectors
+
+"@ + +$generatedBlock = @" + +
+

Полная документация ProtoCAN

+

Нормативные документы и тестовые векторы собраны в эту страницу из исходников doc/protocan.

+
+$($sections -join "`n") +
+
+ +"@ + +$page = Get-Content -Raw -LiteralPath $outputPath -Encoding UTF8 +$pattern = '(?s).*?' +if ($page -notmatch $pattern) { + throw 'Не найдены маркеры PROTOCAN:START/END в doc/index.html.' +} + +$page = [regex]::Replace($page, $pattern, [System.Text.RegularExpressions.MatchEvaluator]{ + param($match) + $generatedBlock +}, 1) + +$page = $page.TrimEnd("`r", "`n") + [Environment]::NewLine +$utf8WithoutBom = [System.Text.UTF8Encoding]::new($false) +[System.IO.File]::WriteAllText($outputPath, $page, $utf8WithoutBom) +Write-Host "[DONE] Создан единый HTML: $outputPath" diff --git a/doc/index.html b/doc/index.html index e827ec3..319163a 100644 --- a/doc/index.html +++ b/doc/index.html @@ -72,9 +72,28 @@ .docs { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; } .doclink { display: inline-flex; align-items: center; gap: 8px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel); } .doclink:hover { border-color: var(--cyan); text-decoration: none; } + #protocan-full { margin-top: 64px; scroll-margin-top: 82px; } + #protocan-full > .lead { margin-bottom: 24px; } + .protocan-grid { display: block; } + .protocan-document { width: 100%; margin-top: 16px; padding: clamp(20px, 4vw, 42px); overflow: hidden; } + .protocan-document:first-child { margin-top: 0; } + .protocan-document h1 { max-width: none; margin: 0 0 20px; font-size: clamp(30px, 4vw, 44px); line-height: 1.08; letter-spacing: -.035em; } + .protocan-document h2 { margin: 36px 0 12px; font-size: clamp(24px, 3vw, 32px); line-height: 1.15; } + .protocan-document h3 { margin: 26px 0 10px; font-size: 20px; } + .protocan-document h1 + p, + .protocan-document h2 + p, + .protocan-document h3 + p { margin-top: 0; } + .protocan-document p { max-width: 88ch; } + .protocan-document table { display: block; width: 100%; min-width: 0; margin: 16px 0 26px; overflow-x: auto; } + .protocan-document thead, + .protocan-document tbody { min-width: 720px; } + .protocan-document th, + .protocan-document td { min-width: 130px; } + .protocan-document pre { max-width: 100%; padding-top: 18px; } + .protocan-document hr { margin: 34px 0; border: 0; border-top: 1px solid var(--line); } footer { margin-top: 42px; padding-top: 20px; border-top: 1px solid var(--line); color: var(--muted); font-size: 13px; } @media (max-width: 850px) { .card, .card.wide { grid-column: 1 / -1; } .flow { grid-template-columns: 1fr 1fr; } } - @media (max-width: 520px) { .shell { width: min(100% - 20px, 1180px); padding-top: 20px; } .hero { padding-top: 22px; } .flow { grid-template-columns: 1fr; } .tabs-wrap { margin-bottom: 18px; } } + @media (max-width: 520px) { .shell { width: min(100% - 20px, 1180px); padding-top: 20px; } .hero { padding-top: 22px; } .flow { grid-template-columns: 1fr; } .tabs-wrap { margin-bottom: 18px; } .protocan-document { padding: 18px 14px; } } @media (prefers-reduced-motion: reduce) { * { scroll-behavior: auto !important; animation: none !important; } } @@ -106,7 +125,7 @@
Структура

Минимальное ядро + нормативные документы

SETCAN/ ├── Inc/protocan.h публичные типы, настройки и API ├── Src/protocan.c фильтры, RX-очередь, разбор и отправка -├── docs/protocan/ спецификация протокола +├── doc/protocan/ спецификация протокола │ ├── PROTOCOL.md 29-битный ID и типы сообщений │ ├── OAP.md общее адресное пространство │ ├── BOOTLOADER.md обновление прошивки по CAN (draft) @@ -270,11 +289,877 @@ if (PROTOCAN_SEND(id, tx) != PROTOCAN_OK) { }
-
Сформировано по исходникам и документации SETCAN. Нормативный приоритет сохраняют PROTOCOL.md, BOOTLOADER.md и реестр ОАП.
+ +
+

Полная документация ProtoCAN

+

Нормативные документы и тестовые векторы собраны в эту страницу из исходников doc/protocan.

+
+

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

+

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

+

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

+

Документы

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ДокументНазначениеСтатус источника
PROTOCOL.md29-битный 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. +
  3. BOOTLOADER.md — загрузочный сервис 0x9…0xD.
  4. +
  5. XLSX — адреса и свойства регистров ОАП.
  6. +
  7. Сгенерированный ../index.html — только представление, не самостоятельный источник.
  8. +
+

Сборка HTML

+

Из корня проекта:

+
./doc/build-html.bat
+
+

Все документы и тестовые векторы включаются в единый файл doc/index.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класс сообщения или сервис
MsgBody16-битное поле, формат которого зависит от 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;
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ПолеЗначенияНазначение
Priority0 critical, 1 standardCAN-арбитраж
Route0 от ПМ, 1 от приборалогическое направление
DeviceType0…7тип прибора
DeviceID0…15номер экземпляра
MsgType0…15тип сообщения
MsgBody0…65535команда, адрес или номер блока
+

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

+

Реестр MsgType

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КодИмяОсновное направлениеDLCСтатус
0x0BROADCASTПМ → всезависит от командыstable
0x1DISCRETEоба0…8stable
0x2ANALOGоба0…8stable
0x3GASоба0/2/4/6/8stable
0x4MODBUS_COILоба0…8stable
0x5MODBUS_DISCRETEоба0…8stable
0x6MODBUS_HOLDINGоба0…8stable
0x7MODBUS_INPUTоба0…8stable
0x8ERRORприбор → ПМ0stable
0x9BOOT_CONTROLПМ → прибор0/8draft
0xABOOT_DATA_AПМ → прибор8draft
0xBBOOT_DATA_BПМ → прибор8draft
0xCBOOT_STATUSприбор → ПМ8draft
0xDBOOT_DISCOVERYприбор → ПМ8draft
0xESETTINGSоба0/1/8stable
0xFPULSEприбор → сеть1stable
+

Подробный формат 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/statusSessionID[15:8], команда [7:0]
boot dataBlockIndex[15:0]
+

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

+
    +
  • Многобайтовые значения в DATA передаются little-endian.
  • +
  • Узел игнорирует адресованные кадры с чужим DeviceType/DeviceID.
  • +
  • Прибор принимает команды ПМ с Route=0; ПМ принимает ответы с Route=1.
  • +
  • Стандартные 11-битные CAN ID не являются кадрами ProtoCAN.
  • +
  • RTR для загрузочного сервиса запрещён.
  • +
  • Неописанные комбинации MsgType/MsgBody/DLC должны отвергаться.
  • +
+

Эталон упаковки 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ИмяMsgBodyPayload
0x9BOOT_CONTROLSessionID[15:8] \| Command[7:0]параметры команды
0xABOOT_DATA_ABlockIndex[15:0]8 байт слота A
0xBBOOT_DATA_BBlockIndex[15:0]8 байт слота B
0xCBOOT_STATUSSessionID[15:8] \| Command[7:0]статус и прогресс
0xDBOOT_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СмещениеДиапазон байтов
0x00000x000000x00000…0x00007
0x00010x000080x00008…0x0000F
0xFFFF0x7FFF80x7FFF8…0x7FFFF
+

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

+

Команды BOOT_CONTROL

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КодКомандаDLCPayloadДопустимое состояние
0x01IDENTIFY0отсутствуетлюбое
0x02ENTER_BOOT0отсутствуетлюбое; SessionID != 0
0x03BEGIN_IMAGE8размер и CRC32metadata
0x04BEGIN_COMPAT8совместимость и версияmetadata
0x05ERASE0отсутствуетready-to-erase
0x06VERIFY0отсутствуетобраз получен
0x07COMMIT0отсутствуетverified
0x08CONFIRM0отсутствуетзапущенное приложение
0x09REBOOT0отсутствуетактивная сессия
0x0AABORT0отсутствуетактивная сессия
0x0BQUERY_PROGRESS0отсутствуетактивная сессия
+

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
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КодСтатусПовтор допустим
0x00OK
0x01BUSYда, после задержки
0x02INVALID_COMMANDпосле исправления
0x03WRONG_DEVICEнет для этого образа
0x04WRONG_HARDWAREнет для этого образа
0x05INVALID_SIZEнет для этого образа
0x06CRC_ERRORновая передача
0x07FLASH_ERRORзависит от платформы
0x08SEQUENCE_ERRORда, с NextBlock
0x09SIGNATURE_ERRORнет
0x0ASESSION_ERRORоткрыть новую сессию
0x0BVOLTAGE_ERRORда после нормализации питания
0x0CINVALID_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 прекращает текущую передачу, +не активируя частично записанный слот.

+

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

+
    +
  • Блоки передаются строго по возрастанию BlockIndex.
  • +
  • Дубликат или пропуск возвращает SEQUENCE_ERROR и ожидаемый NextBlock.
  • +
  • Базовый режим подтверждает каждый блок.
  • +
  • Рабочий режим может подтверждать окно из 16 блоков.
  • +
  • После потери связи QUERY_PROGRESS возвращает следующий ожидаемый блок, +пока состояние загрузчика сохранено.
  • +
  • Для продолжения после перезагрузки порт должен сохранять session metadata +и восстановить её при инициализации; ядро версии 1.0 само это не делает.
  • +
+

Безопасность и 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 должна атомарно хранить:

+
    +
  • активный слот;
  • +
  • pending-слот;
  • +
  • подтверждение запуска;
  • +
  • число неудачных попыток;
  • +
  • версию и CRC32 образа.
  • +
+

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

+

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

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

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

+

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

+

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

+

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

+

Назначение

+

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

+

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

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

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

+
    +
  • Адрес не переиспользуется с другим смыслом после выпуска стабильной версии.
  • +
  • Многорегистровое значение занимает непрерывный диапазон.
  • +
  • Порядок 16-битных слов для 32-битного значения фиксируется в строке типа.
  • +
  • Резервные диапазоны явно отмечаются и не используются без изменения версии.
  • +
  • Удалённый параметр помечается deprecated, а не исчезает молча.
  • +
  • Изменение адреса, типа или масштаба отражается в CHANGELOG.md.
  • +
+

Экспорт

+

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

+
    +
  • уникальность адресов;
  • +
  • пересечение многорегистровых значений;
  • +
  • допустимые типы и права доступа;
  • +
  • равенство шестнадцатеричного и десятичного адреса;
  • +
  • попадание адреса в диапазон 0x0000…0xFFFF.
  • +
+

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

+
+

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

+

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

+

[Unreleased]

+

Added

+
    +
  • Структурированный комплект документации doc/protocan.
  • +
  • Загрузочный сервис MsgType=0x9…0xD.
  • +
  • Два логических слота по 512 КиБ, 65 536 блоков по 8 байт каждый.
  • +
  • Машинные эталоны CAN ID в examples/test-vectors.json.
  • +
+

[1.0] — 2026-08-29

+

Added

+
    +
  • Зафиксирована 29-битная структура ProtoCAN ID.
  • +
  • Зафиксирована адресация 8 типов по 16 экземпляров.
  • +
  • Существующие сообщения 0x0…0x8, 0xE, 0xF сохранены.
  • +
+
+
+

Тестовые векторы

+

Машинные эталоны из examples/test-vectors.json.

+
{
+  "schema_version": 1,
+  "byte_order": "little-endian",
+  "frames": [
+    {
+      "name": "enter_boot_session_7",
+      "direction": "pm_to_device",
+      "priority": 1,
+      "route": 0,
+      "device_type": 3,
+      "device_id": 5,
+      "msg_type": 9,
+      "msg_body": 1794,
+      "can_id_hex": "0x13590702",
+      "dlc": 0,
+      "data_hex": ""
+    },
+    {
+      "name": "slot_b_block_1",
+      "direction": "pm_to_device",
+      "priority": 1,
+      "route": 0,
+      "device_type": 3,
+      "device_id": 5,
+      "msg_type": 11,
+      "msg_body": 1,
+      "can_id_hex": "0x135B0001",
+      "dlc": 8,
+      "data_hex": "1011121314151617"
+    },
+    {
+      "name": "enter_boot_ok",
+      "direction": "device_to_pm",
+      "priority": 1,
+      "route": 1,
+      "device_type": 3,
+      "device_id": 5,
+      "msg_type": 12,
+      "msg_body": 1794,
+      "can_id_hex": "0x1B5C0702",
+      "dlc": 8,
+      "data_hex": "00FF000000000000"
+    }
+  ]
+}
+
+
+
+
+ + +
Сформировано по исходникам и документации SETCAN. Для пересборки запустите doc/build-html.bat. Нормативный приоритет сохраняют PROTOCOL.md, BOOTLOADER.md и реестр ОАП.