1. Тема дня

Когда ошибка обнаружена, не всегда нужно перезагружать весь MCU. Строим recovery ladder:

text
fault
 -> local FSM recovery
 -> service restart
 -> peripheral reset
 -> hardware power cycle
 -> MCU reset
 -> SAFE MODE

Главная мысль: watchdog — последняя линия защиты, а не основная recovery-архитектура.

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

EC25 может зависнуть, но input/ADC/config остаются здоровыми. Перезагружать весь ESP32 при каждом LTE fault слишком грубо. MQTT можно перезапустить без modem reset. Storage error может перевести систему в DEGRADED, не ломая phase detection.

3. Теория

Fault domain

Граница восстановимости:

text
INPUT DOMAIN: GPIO/ADC/phase FSM
MODEM DOMAIN: UART/AT/EC25/PDP
MQTT DOMAIN: socket/MQTT client/commands
STORAGE DOMAIN: NVS/config
DIAGNOSTIC DOMAIN: logger/metrics

Health lease

Подсистема продлевает lease, когда делает полезный progress.

c
typedef struct {
    uint32_t service_id;
    health_state_t state;
    uint32_t generation;
    uint64_t last_progress_us;
    uint32_t progress_counter;
    uint32_t lease_timeout_ms;
    uint32_t restart_count;
} health_record_t;

Heartbeat в loop недостаточен. Нужно progress: AT transaction finished, ADC block processed, FSM meaningful transition.

Supervisor

Supervisor не знает внутренности AT/CEREG. Подсистема сообщает health, reason, suggested recovery. Supervisor решает budget/escalation.

Recovery ladder EC25

text
L0 retry AT transaction
L1 reset AT parser + transactions
L2 restart modem software service
L3 hardware EC25 reset
L4 power-cycle EC25
L5 restart ESP32
L6 SAFE MODE

Restart budget

Ограничить количество restart в окне времени:

text
modem software restart: max 3 / 5 min
hardware modem reset: max 2 / 15 min
MCU reboot: max 3 / 30 min

Service generation

После restart generation++ и старые события игнорируются. Restart transaction

text
RUNNING -> QUIESCING -> STOPPING -> RESETTING -> STARTING -> VERIFYING -> RUNNING

HEALTH_OK выставляется только после proof of health, не сразу после init.

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

  1. Supervisor просто кормит watchdog.
  2. Heartbeat обновляется в каждом loop без useful progress.
  3. Каждая подсистема сама вызывает esp_restart().
  4. Нет restart budget.
  5. Task restart считается service restart.
  6. Forced task deletion как стандартная recovery.
  7. Restart без generation increment.
  8. Events приходят до полной initialization новой service genera- tion.
  9. HEALTH_OK сразу после init().
  10. Optional modem fault вызывает reboot critical input logic.
  11. Dependent MQTT fault считается независимым от modem fail- ure.
  12. Supervisor знает внутренние AT/CEREG детали.
  13. Hardware watchdog feed вызывается из timer независимо от health.
  14. Safe mode использует те же зависимости, что normal mode.

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

Создай SERVICE_INPUT и SERVICE_MODEM health records:

c
typedef enum { SERVICE_INPUT = 0, SERVICE_MODEM, SERVICE_COUNT } service_id_t;
typedef struct {
    health_state_t state;
    uint32_t generation;
    uint32_t progress;
    uint64_t last_progress_us;
    uint32_t reason;
} service_health_t;

Добавь progress API:

c
void supervisor_report_progress(service_id_t service)
{
    service_health_t *h = &s_health[service];
    h->progress++;
    h->last_progress_us = platform_monotonic_us();
}

Политики:

text
INPUT: lease=1000ms, critical=true, max_local_restarts=1
MODEM: lease=10000ms, critical=false, max_local_restarts=3

Сломай modem progress fault injection’ом. Ожидание: supervisor detects expired lease -> modem restart -> generation++ -> ESP32 не reboot.

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

  • Связать critical input_progress с ESP-IDF TWDT user API.
  • Сделать CLI health.
  • HIL: Raspberry Pi перестаёт отвечать на AT, проверяет уровень escalation и budget.
Какой сигнал должен продлевать health lease подсистемы?

Задание

Modem lease истёк, но critical input processing исправен. Опишите ограниченное recovery, сохраняющее здоровую domain и исключающее старые modem events после restart.

Критерии самопроверки: Сохраните input processing, задайте budget, увеличьте generation, отклоните stale events и проверьте health.

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

Supervisor применяет modem policy в пределах restart budget, quiesce/restart modem service вместо немедленного reboot всего MCU, увеличивает generation и отклоняет старые events. HEALTH_OK возвращается после проверенного progress. Escalation выполняется при неудаче нижнего уровня или исчерпании budget.