8.2 KiB
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 прекращает текущую передачу,
не активируя частично записанный слот.
Надёжность и повторы
- Блоки передаются строго по возрастанию
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 за установленное число запусков,
загрузчик возвращается к предыдущему подтверждённому слоту.
Эталонный сценарий
- ПМ адресно отправляет
IDENTIFY. - ПМ открывает ненулевой
SessionIDкомандойENTER_BOOT. - ПМ отправляет
BEGIN_IMAGEиBEGIN_COMPAT. - Прибор сообщает выбранный неактивный слот.
- ПМ выполняет
ERASEи передаётBOOT_DATA_AлибоBOOT_DATA_B. - ПМ выполняет
VERIFY, затемCOMMITиREBOOT. - Новое приложение после самопроверки выполняет
CONFIRM.