ESC-протоколы: 4-way interface, EEPROM AM32 и BLHeli_S/Bluejay — факты для тулы (AD-856/AD-1066/AD-1070)
Статус: research / discovery + фактическая база, используемая кодом
(web/static/js/tools/esc_fourway.js+web/static/js/tools/esc_blheli.js,
AD-1066). Документ фиксирует, откуда взяты протокольные факты, где проходит
граница уверенности и что НЕ реализовано (честность важнее охвата).
Лицензионный анализ и решение — в ADRdocs/adr/ad-856-esc-clean-room.md.
1. Clean-room и источники
Код кодека написан с нуля по открытым описаниям (без копирования GPL/AGPL):
- 4-way interface — спецификация интерфейса BLHeliSuite (описание кадров,
команд, ACK-кодов; опубликована в дистрибутиве BLHeliSuite,
https://github.com/bitdump/BLHeli) и вики Betaflight «4 way interface». - MSP-вход в passthrough — открытые таблицы MSP INAV/Betaflight:
MSP_SET_4WAY_IF/MSP_SET_PASSTHROUGH= 245; без payload = переход в
4-way, ответ — 1 байт (число выходов ESC), после ответа порт полётника
говорит на протоколе 4-way до командыInterfaceExit. - BLHeli_S/Bluejay EEPROM — опубликованные исходники самих прошивок как
первоисточник формата данных; поимённый список файлов и что из каждого взято
— § 5.1 (AD-1070). - AM32 — открытая документация проекта (https://github.com/am32-firmware/AM32,
https://am32.ca): раскладка блока настроек, адреса блока по таргетам,
формулы производных величин.
2. Протокол 4-way interface (реализовано)
запрос : 0x2F cmd addr_hi addr_lo len params[len] crc_hi crc_lo
ответ : 0x2E cmd addr_hi addr_lo len params[len] ack crc_hi crc_lo
len == 0означает 256 байт параметров; «без параметров» не бывает —
кодируется один dummy-байт0x00(len=1);- CRC — CRC16/XMODEM (poly 0x1021, init 0), от стартового байта
включительно; в ответе ack входит в CRC; на проводе — big-endian; - device info (ответ
DeviceInitFlash) — 4 байта:
[sig_lo, sig_hi, метка bootloader-сообщения, режим интерфейса]; - режимы интерфейса: 0 SiLabs C2, 1 SiLabs BLB (BLHeli_S), 2 Atmel BLB,
3 Atmel SK, 4 ARM BLB (AM32).
Реализованное подмножество команд (v1 read-only): InterfaceTestAlive 0x30,
ProtocolGetVersion 0x31, InterfaceGetName 0x32, InterfaceGetVersion 0x33,
InterfaceExit 0x34, DeviceReset 0x35, DeviceInitFlash 0x37,
DeviceRead 0x3A. Команды записи/стирания (0x38, 0x39, 0x3B, 0x3E и др.)
сознательно не реализованы — инвариант v1, закреплён тестом.
3. EEPROM AM32 (реализовано, с границей уверенности)
- Блок настроек лежит во флеше по фиксированному смещению таргета:
0x7C00 (классические 32К-таргеты: STM32F051, AT32F421 и др.) или
0xF800 (таргеты с большим флешем, например G071). Оба адреса влезают в
16-битное поле адреса кадра. Тула пробует адреса по порядку и принимает блок
только после валидации формы (looksLikeAm32Eeprom: правдоподобная версия
прошивки + читаемое имя таргета; иначе — только сырой дамп). - Читается 48 байт — документированная зона настроек.
- Разбираемая раскладка (байты): 0 boot byte, 1 версия EEPROM-раскладки,
2 версия загрузчика, 3/4 версия прошивки (major/minor), 5–16 имя таргета
(12 ASCII), 17–45 — настройки (полный список с идентификаторами — в
AM32_SETTINGS_LAYOUT,web/static/js/tools/esc_fourway.js). - Производные величины показываются только там, где формула документирована:
timing advance = байт × 7.5°, KV = байт × 40 + 20, порог ячейки =
(байт + 250)/100 В, лимит тока = байт × 2 А, серво-пороги
(×2+750 / ×2+1750 / +1374 мкс). Сырой байт показывается всегда. - Байты 46+ и любые поля вне списка не разбираются — видны только в
HEX-дампе (принцип «не выдумываем»).
4. Телеметрия (реализовано частично)
- RPM через полётник: MSP2
INAV_ESC_RPM= 0x2040 (INAV с esc-sensor),
ответ — по u32 LE RPM на мотор. Прошивка без esc-sensor отвечает
MSP-ошибкой → тула честно показывает «недоступно». - KISS/AM32-телеметрия по сигнальному проводу (температура/напряжение/ток)
в режиме passthrough недоступна (регулятор в загрузчике, не в рабочей
прошивке) — кандидат на v2 через MSP-каналы полётника
(BetaflightMSP_ESC_SENSOR_DATA= 134, INAVMSP2_INAV_ESC_TELEM).
5. BLHeli_S/Bluejay — детект (AD-1066) и чтение настроек (AD-1070)
web/static/js/tools/esc_blheli.js классифицирует регулятор по ОТВЕТУ
DeviceInitFlash (те же факты, что в § 2 — режим интерфейса 0..4):
- режим интерфейса
1(SiLabs BLB) покрывает и BLHeli_S, и Bluejay —
обе прошивки используют один и тот же бутлоадер/интерфейс на SiLabs
EFM8-микроконтроллерах; - режимы
2/3(Atmel BLB/SK) — легаси 8-бит BLHeli на AVR; - режим
0(SiLabs C2) — отладочный интерфейс, не BLHeli-бутлоадер.
Легаси Atmel и SiLabs C2 по-прежнему только ОПОЗНАЮТСЯ: открытого описания их
блока настроек у нас нет. SiLabs BLB (BLHeli_S/Bluejay) с AD-1070 читается
полностью.
5.1. Источники раскладки (AD-1070)
Раскладка EEPROM — это ФОРМАТ ДАННЫХ, и первоисточник формата у BLHeli_S и
Bluejay один: их собственные опубликованные исходники прошивки. Решение
основателя по AD-1070 — брать факты формата оттуда и ссылаться на источник в
коде; clean-room-дисциплина ADR ad-856-esc-clean-room.md при этом не
меняется: КОД пишется с нуля, из GPL/AGPL-проектов не копируется ни строки, и
конфигураторы (esc-configurator.com — AGPL-3.0, BLHeliSuite) не используются
как источник вовсе. Точные места процитированы в шапке esc_blheli.js:
| Метка | Файл | Что взято |
|---|---|---|
[S1] |
BLHeli_S SiLabs/BLHeli_S.asm (github.com/bitdump/BLHeli) |
порядок меток Eep_* = смещения; комментарии к DEFAULT_PGM_* = перечисления и формулы; EEPROM_LAYOUT_REVISION EQU 33 |
[S2] |
src/Bluejay.asm (github.com/bird-sanctuary/bluejay) |
своя последовательность Eep_*; EEPROM_LAYOUT_REVISION EQU 208 |
[S3] |
src/Settings/BluejaySettings.asm (там же) |
комментарии к DEFAULT_PGM_* Bluejay: диапазоны и формулы |
[S4] |
src/Modules/Codespace.asm (там же) |
CSEG_EEPROM/CSEG_NAME по типам МК: 0x1A00 (EFM8BB1/BB21) и 0x3000 (EFM8BB51), имя — по +0x60 |
5.2. Что разбирается и что нет
- Адрес блока настроек подбирается перебором
[0x1A00, 0x3000]с
валидацией формы — тот же приём, что у AM32 (§ 3). Читается 0x70 байт: блок
настроек (0x00..0x2A) и зона имени (+0x60), однимDEVICE_READ. - Валидация формы — сигнатура «EEPROM инициализирован» (
0x55по 0x0D,
0xAAпо 0x0E, [S1]/[S2]) плюс известная ревизия раскладки в байте 0x02. - Ревизия раскладки — гейт разбора, а не подсказка. 33 → таблица
BLHeli_S, 208 → таблица Bluejay, любая другая → разбор НЕ выполняется, UI
показывает ревизию и сырой дамп. Раскладка отличается между версиями
прошивки, и «похоже подходит» здесь означает молча наврать; неверно
распарсенная настройка выглядит достовернее, чем её отсутствие. - Bluejay — отдельная таблица, не «BLHeli_S плюс поля». Он занял байты,
свободные в BLHeli_S (0x04 STARTUP_POWER_MIN, 0x05 STARTUP_BEEP,
0x07 STARTUP_POWER_MAX, 0x0A PWM_FREQUENCY, 0x10 BRAKING_STRENGTH), и
освободил занятые им (0x19/0x1A MIN/MAX_THROTTLE, 0x21 CENTER_THROTTLE,
0x24 LOW_RPM_POWER_PROTECTION). Инвариант держитtests/test_esc_blheli.js. - НЕ разбирается намеренно: байты, объявленные в первоисточниках
неиспользуемыми (_Eep_*=0FFh); зоны +0x40 (layout tag) и +0x50
(MCU tag) — адреса документированы [S4], но содержимое пишет инструмент
прошивки, открытого описания формата нет; точная формула Bluejay
STARTUP_POWER_MAX— [S3] задаёт только диапазон, поэтому поле показывается
сырым числом; назначение битLED_CONTROLиSAFETY_ARM— только HEX.
Значение, которого нет в документированном перечислении, показывается
ЧИСЛОМ, а не ближайшим по смыслу вариантом. - Запись по-прежнему невозможна (инвариант AD-856): парсер только читает,
функции обратной сериализации настроек в байты нет и заводить её нельзя —
ошибка парсера при записи выводит регулятор из строя.
6. Не реализовано / отложено (v2+)
- запись настроек AM32 и прошивка (write/erase/verify) — отдельное решение
основателя, новый класс риска; - запись настроек BLHeli_S/Bluejay — тот же класс риска, отдельное решение;
- легаси BLHeli на Atmel (BLB/SK) и SiLabs C2: блок настроек не разбирается —
открытого описания их раскладки у нас нет (детект есть, см. § 5); - BLHeli_32 — NO-GO навсегда (закрытый протокол, лицензионная программа
остановлена); - карта «сигнатура MCU → таргет/размер флеша»: в открытых источниках есть
таблицы соответствий, но мы их не проверяли на железе — v1 показывает
сигнатуру hex как есть и подбирает адрес EEPROM (для AM32) перебором с
валидацией; - прямое подключение USB-UART к сигнальному проводу (без полётника) —
осознанно вне v1 (дефолт основателя: только passthrough).
7. Проверка на железе
Кодек и разбор покрыты юнит-тестами (tests/test_esc_fourway.js — CRC-вектор,
кадры, синтетический EEPROM AM32; tests/test_esc_blheli.js — классификация
семейства прошивки по всем 5 режимам интерфейса (AD-1066) и разбор
синтетического блока настроек BLHeli_S/Bluejay: обе ревизии раскладки, отказы
too_short/not_initialized/unsupported_layout, формулы по трём точкам
каждая (AD-1070)), но на реальном AM32- или BLHeli_S-регуляторе ещё не
прогонялся — тула помечена «предальфа». Синтетический тест доказывает, что
код читает ТЕ байты, которые описаны в источнике, но не то, что источник
описывает конкретный экземпляр регулятора: первый прогон на железе остаётся
обязательным. С AD-1066 инструмент включён по умолчанию фича-флагом
esc_tools (решение основателя, /admin/flags может выключить конкретное
окружение). Первый прогон на реальном железе (обеих семейств) остаётся
обязательным шагом перед снятием пометки «предальфа».