ПрошивкиГлава 18 / 51

Прошивка, которая переживает сеть

Как прошивка остаётся полезной без станции?

Язык снижает часть рисков памяти, но не отменяет аппаратные ограничения и проверку всего стека.

У прошивки несколько независимых обязанностей: измерять, обслуживать физический выход, поддерживать связь и обновляться. Если одна большая функция ждёт Wi-Fi, остальные не должны останавливаться вместе с ней.

Rust помогает описать границы и владение данными, но надёжность появляется из архитектуры задач, ограниченных буферов и понятных состояний. Кнопка, стартовый уровень реле и реакция на потерю связи проверяются раньше красивой телеметрии.

У ESP есть два принципиальных Rust-пути. Первый использует ESP-IDF через Rust-обвязки и получает сетевой стек, RTOS и сервисы SDK. Второй строится на esp-hal без стандартной библиотеки и даёт больше контроля над памятью и исполнением. Для Koobique важно не выбрать «самый чистый Rust», а получить проверяемое устройство с безопасной сетью, обновлением и локальным выходом.

ESP-IDF или no_std#

ПутьСильная сторонаИнженерная ценаГде начать
Rust + ESP-IDFБогатый SDK, provisioning, OTA, TLSC/FFI, несколько версий инструментов, сопровождение обвязокПервый Wi-Fi-узел
esp-hal / no_stdКонтроль ресурсов и аппаратурыПроверка зрелости конкретного радио, TLS и обновленияИсследовательская ветка или простой узел
Другой MCU + RustВыбор питания и периферии под задачуНовый toolchain и BSPБудущее батарейное устройство

Репозиторий Rust-обвязок ESP-IDF прямо описывает ограничения сопровождения сообщества и возможное отставание; официальный esp-hal имеет другую модель развития. The Rust on ESP Book предупреждает об изменениях нестабильных API. Это не причина отказаться от Rust, а причина фиксировать toolchain и испытывать выбранную комбинацию. [31][32][33]

Для первого Wi-Fi-профиля предлагаем Rust + ESP-IDF с проверенной версией SDK. Ветка no_std выполняет тот же контракт устройства, но не должна задерживать сборку основного стенда. Общие типы сообщений и тестовые векторы не зависят от конкретной RTOS.

Память — измерять в худший момент#

Пик может возникнуть не при обычной телеметрии, а во время BLE-сопряжения, TLS-handshake и OTA. Заранее освобождённая BLE-память после настройки полезна, если BLE больше не требуется. Внутренние лимиты сообщений должны быть значительно меньше всей доступной RAM; буфер «на всякий случай 64 КБ» в каждом слое быстро исчерпывает MCU.

Mbed TLS в актуальной ESP-IDF имеет профили конфигурации; минимальный preset может не включать TLS 1.3, хотя другая конфигурация его поддерживает. Поэтому профиль Koobique фиксирует разрешённую версию и проверяет реальный handshake с Rustls, а не полагается на название SDK. [34]

Нужны измерения свободной памяти, крупнейшего свободного блока, пиков стека и отказов выделения. Успешный запуск один раз не доказывает отсутствие фрагментации после тысячи переподключений.

Задачи и приоритеты#

Локальный владелец выхода обрабатывает короткие события кнопки и команды. Опрос датчика имеет ограничение времени. Сетевая задача занимается соединением и передачей. Обновление выполняется отдельным режимом с согласованным безопасным состоянием. Тяжёлое форматирование логов и запись flash не происходят в обработчике прерывания.

A23Предлагаемое разделение задач. Ограничения очередей и владение выходом важнее количества потоков.

ISR фиксирует минимальные данные и передаёт событие. volatile не заменяет атомарность и синхронизацию. Общий изменяемый доступ к периферии ограничивается одним владельцем или явно синхронизированным интерфейсом. Блокировка, удерживаемая во время сетевого ожидания, может остановить кнопку — это недопустимая граница ответственности.

Ошибки как часть интерфейса#

Драйвер возвращает различимые ошибки: нет ответа, неверный CRC, превышен диапазон, устаревшие данные, периферия не инициализирована. В зависимости от причины выполняется повтор, переинициализация шины или перевод канала в недоступный режим. Бесконечный retry без задержки способен перегрузить шину и журнал.

Watchdog должен проверять продвижение задач, а не просто обслуживаться из отдельного живого таймера. Если управление выходом зависло, но таймер продолжает «кормить собаку», защита не выполняет задачу. После reset сохраняется причина, насколько это поддерживается аппаратурой; она передаётся станции для диагностики.

Flash и обновление#

Разделы для конфигурации, двух образов и служебных данных определяются после измерения размера прошивки. Запись каждого измерения во flash не допускается по умолчанию. Частые счётчики хранятся в RAM или агрегируются; критичная идентичность и параметры имеют отдельную политику записи.

Secure Boot и защита flash исследуются на отладочных устройствах с пониманием необратимых настроек. Производственные eFuse нельзя прожигать до проверки восстановления и хранения ключей. Отладочный доступ удобен на стенде, но для постоянно используемого устройства является частью модели угроз. [35][36]

Gate прошивки#

Узел должен пережить многократные Wi-Fi-обрывы, отказ датчика, переполнение входного сообщения, повтор команды и перезапуск во время обмена. Физическая кнопка и безопасный выход проверяются не только при исправной сети. Версии Rust, ESP-IDF, зависимостей и sdkconfig сохраняются вместе с результатами.

Отладочная плата и защищённый прибор — два режима#

DEV / E0APPLIANCE / после проверки
Отладка доступна; тестовые секретыSecure Boot v2 и Flash Encryption с проверенным workflow
Нет обещания стойкости при физическом доступеNVS Encryption, контроль debug/download-интерфейсов
Рабочий ключ создаётся на узлеНеэкспортируемость/защита ключа подтверждены настройкой
Восстановление через кабель допустимоRecovery и OTA испытаны до необратимых eFuse

NVS-шифрование не следует считать автоматическим следствием Flash Encryption. Выбранная схема и ключи фиксируются отдельно. Конфиденциальность flash также не доказывает защиту от возврата старого корректно зашифрованного образа: если в модели угроз есть физический rollback, потребуется отдельная защита состояния владения. Для E0 этот класс атак не объявляется решённым. [150][151]

Ключ и boot_id генерируются на самом MCU при выполненных условиях аппаратной энтропии. В ESP-IDF качество RNG зависит от включённых источников; вызов esp_fill_random сразу после старта приложения сам по себе не доказывает достаточную случайность. Случайный boot_id — часть защиты от старой команды, поэтому тест генерации идентичности входит в обязательный опыт. [152]

Первый технологический опыт — одна зафиксированная связка#

До остальной прошивки проверяется один C6: выбранные Rust toolchain, esp-idf-sys/hal/svc, SDK и sdkconfig; BLE с уникальным provisioning-секретом; TLS 1.3 с Core; одна команда; кнопка под нагрузкой; прерванное OTA. Измеряют min-free heap, largest-free-block, стеки, размер подписанного образа, паузы flash и задержку кнопки. Эти версии пока не названы «проверенными» — карточка заполняется только выводами реальной сборки.

Одновременность режимов ограничена: provisioning и OTA не работают вместе; не более одного bulk-сеанса; после onboarding BLE освобождается, если профиль это позволяет. Неудача опыта сначала приводит к пересмотру конкурентности и SDK, а не к выводу, что любой Rust-путь слишком тяжёлый.

Найти в книге

Поиск по всем главам, схемам и техническим разделам.