1. Тема дня

Архитектура безопасного OTA:

text
команда обновления
→ проверка условий
→ получение manifest
→ загрузка в неактивный OTA-slot
→ проверка образа
→ переключение boot partition
→ перезагрузка
→ быстрый self-test
→ подтверждение новой версии или rollback

Главная мысль: OTA заканчивается не тогда, когда файл записан во Flash, а когда новая прошивка загрузилась, прошла самодиагностику и сохранила возможность следующего обновления.

2. Зачем это нужно

LTE-соединение EC25 может оборваться в любой момент:

text
- пропало покрытие;
- EC25 перерегистрировался;
- PDP context закрылся;
- оператор оборвал TCP;
- просело питание при передаче.

Незаконченный образ не должен становиться загрузочным. После обновления должны продолжать работать безопасные выходы, input path, watchdog, fault manager и локальная диагностика. Потеря LTE/MQTT после перезагрузки - не всегда причина rollback: внешняя сеть может быть недоступна временно.

3. Теория

A/B OTA-разметка

Типовая структура:

text
bootloader
partition table
NVS
otadata
ota_0
ota_1
coredump
storage

Пока выполняется ota_0, новый образ пишется в ota_1. Текущая прошивка остаётся нетронутой. После проверки меняется otadata. Пример для Flash 4 MiB:

markdown
# Name,      Type, SubType,  Offset,   Size
nvs,         data, nvs,      0x9000,   0x6000
otadata,     data, ota,      0xF000,   0x2000
phy_init,    data, phy,      0x11000,  0x1000
coredump,    data, coredump, 0x12000,  0x10000
nvs_keys,    data, nvs_keys, 0x22000,  0x1000
ota_0,       app,  ota_0,    0x30000,  0x1D0000
ota_1,       app,  ota_1,    0x200000, 0x1D0000
storage,     data, fat,      0x3D0000, 0x20000

Образ должен уверенно помещаться в слот, лучше оставлять 10-15% запаса.

Rollback

Включи:

text
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y

Состояния:

text
ESP_OTA_IMG_NEW
→ первая загрузка
→ ESP_OTA_IMG_PENDING_VERIFY
→ self-test
   ├─ успешно → ESP_OTA_IMG_VALID
   └─ ошибка  → ESP_OTA_IMG_INVALID → предыдущая прошивка

Self-test после OTA

Проверяй быстро и локально:

text
- config load/migration/validation;
- safe outputs;
- input service;
- health supervisor;
- fault manager;
- watchdog;
- критичные задачи созданы.

Не надо ждать MQTT broker или регистрацию EC25 несколько минут. Внешняя сеть может быть недоступна, а прошивка всё равно рабочая. Каркас:

c
static bool ota_critical_self_test(void)
{
    if (!config_load_migrate_validate()) return false;
    if (!safe_outputs_apply()) return false;
    if (!input_service_start_and_self_test()) return false;
    if (!health_supervisor_start()) return false;
    if (!fault_manager_start()) return false;
    if (!modem_transport_init()) {
        system_enter_degraded_mode(DEGRADED_NO_MODEM);
    }
    return true;
}

Manifest

Один URL недостаточен. Нужен manifest:

c
{
  "schema": 1,
  "project": "traffic-controller",
  "version": "1.8.0",
  "build_number": 184,
  "chip": "esp32",
  "hw_rev_min": 2,
  "hw_rev_max": 4,
  "image_size": 1327104,
  "sha256": "8a7c...",
  "url": "https://fw.example.com/controller/1.8.0/app.bin"
}

Проверяй project, chip, hardware revision, размер, downgrade policy, SHA-256, TLS policy.

OTA через EC25

Вариант A - PPPoS: ESP32 поднимает PPP через UART EC25, затем использует обычный HTTPS OTA. Вариант B - EC25 HTTP AT: модем получает файл, ESP32 читает его порциями и пишет через esp_ota_write(). Здесь особенно опасны бинарные данные, URC, потеря байта, переполнение UART и повторная запись блока. MQTT лучше использовать как команду/триггер, а сам образ передавать по HTTPS.

4. Типичные ошибки

  • Подтвердить firmware в начале app_main().
  • Сделать MQTT обязательным self-test.
  • Использовать HTTPS без проверки сертификата.
  • Удалённо обновлять partition table без отдельной recovery-архитектуры.
  • Не проверять аппаратную ревизию.
  • Записывать progress в NVS после каждого блока.
  • Включить security anti-rollback слишком рано.

5. Практическое задание

  1. Создай partitions_ota_4mb.csv.
  2. Включи rollback.
  3. Реализуй ota_confirm_if_pending().
  4. Добавь ota status.
  5. Сделай HIL-тест rollback: firmware B один раз запускается, self-test возвращает false, после reboot загружается A.

CLI пример:

text
ota status:
state=DOWNLOAD
running=ota_0
target=ota_1
current_version=1.7.4
target_version=1.8.0
written=786432
total=1327104
progress=59%
transport=EC25_PPP
last_error=OK

6. Что попробовать дальше

  • Power-cut tests на 10%, 50%, 99% загрузки.
  • LTE разрыв во время скачивания.
  • Неверный manifest/hash/project/hw_rev.
  • Crash до подтверждения OTA.
  • Недоступный MQTT при исправной основной функции.

Задание

Новый образ загрузился правильно, но MQTT broker недоступен. Определите решение подтверждения, отделяющее локальную исправность прошивки от внешнего сетевого отказа.

Критерии самопроверки: Перечислить локальные проверки и объяснить отдельный fault domain внешней сети. Не подтверждать образ до локального self-test.

Показать ответ автора

Локальным self-test проверить конфигурацию, safe outputs, input service, supervisor, fault manager, watchdog и критичные задачи. Не требовать внешнего MQTT для подтверждения локально исправного образа; сетевой отказ сообщать отдельно.

Задание

Спроектируйте OTA-тест потери питания, доказывающий, что неполный образ не заменяет работающую прошивку.

Критерии самопроверки: Наблюдать полноту образа и выбор загрузки. Один download progress log не доказывает безопасное восстановление.

Показать ответ автора

Прервать загрузку в неактивный слот, перезагрузить и проверить запуск предыдущей валидной прошивки. Записать target slot, written size, результат verification и boot selection; затем проверить полный образ с неуспешным локальным self-test и rollback.