ADR-012: Brownout detector отключён в wifiInit() как stand-only workaround¶
Дата: 2026-05-27 Статус: Accepted (workaround, требует пересмотра перед production-релизом на отдельных PSU) Связано: ADR-002 WiFi-стабильность
Контекст¶
При сборке f1d28c8 на стенде устройство стало падать в бесконечный
boot-loop с симптомом:
I (5554) wifi_manager: wifiInit started
Brownout detector was triggered
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
Через 2–3 итерации проходило само и стартовало с TX-power = 15 dBm (значение, ранее заданное оператором через Web UI и сохранённое в NVS).
Корневая причина: USB-питание ноутбука, через которое запитан
стендовый прототип, не тянет пиковый ток радиомодуля ESP32 в момент
первого WiFi.mode(WIFI_AP_STA). Просадка rail ниже 2.43В →
RTC_CNTL_BROWN_OUT_REG срабатывает → SW_CPU_RESET → новый boot →
повтор.
WiFi.setTxPower(), которым мы ограничиваем мощность, применяется
после WiFi.mode() — не успевает помочь самому первому пику.
Эталонный production-PSU (5В/2A, low-ESR кондёрами) должен тянуть
этот пик без проблем, но текущий стенд тянет не всегда.
После прохождения старта железо работает стабильно — детектор слишком чувствителен к коротким спайкам в стенд-конфигурации.
Решение¶
В src/wifi_manager.cpp::wifiInit(), до WiFi.mode(), добавлен:
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
ESP_LOGW(TAG, "brownout detector DISABLED (stand workaround)");
Это полностью отключает brownout detector чипа на всё время работы. Запись в лог уровня WARN, чтобы в любой диагностике видеть, что защита не активна.
Что мы понимаем про последствия¶
- Реального brownout-сценария защита больше не ловит. Если рейл действительно просядет (не короткий пик, а длительная просадка от плохого PSU / разряженного аккумулятора), CPU начнёт работать в неопределённой зоне; flash-write может оставить мусор.
- Стенд тянет ток — после прохождения boot устройство работает, без crashes и stack canary. Просто пиковый старт борцовый.
- Workaround временный — для production-PSU не нужен и должен быть пересмотрен. Не оставляем как «по умолчанию для всех».
Условия отката¶
Удалить запись в RTC_CNTL_BROWN_OUT_REG (или обернуть в
#ifdef AWDC_STAND_BUILD) когда выполнено хотя бы одно из:
- Production-PSU прошёл стенд-тест без boot-loop на 50 циклах power-cycle подряд на холодном устройстве — детектор можно вернуть, реальной просадки не происходит.
- Найдено и устранено корневое причина пика (например, добавлены bulk-кондёры на 3.3В рейле прямо у ESP32 — стандартный фикс для маржинального питания).
- Принято решение поставлять с собственным заведомо мощным PSU и явно положить ответственность за питание на нашу сторону.
В любом из этих случаев — снести WRITE_PERI_REG строку, перепрошить
стендовое устройство, проверить 50 циклов холодного boot, далее
выкатить как fix-релиз.
Альтернативы, которые отвергнуты¶
WiFi.setTxPower()доWiFi.mode()— невозможно,setTxPowerтребует уже инициализированный WiFi (esp_wifi_init). Любая попытка call'а доmode()— silently игнорируется.- Понижение TX-power через прямой
esp_wifi_set_max_tx_power()послеesp_wifi_initно доesp_wifi_start— теоретически возможно, но требует переписать всю WiFi-инициализацию мимо Arduino-обёртки. Высокая цена, риск регрессий по STA-стабильности. WIFI_PS_MIN_MODEM/WIFI_PS_MAX_MODEM(power-save) — снижают средний ток, но не пиковый при первом включении радио. Боевой пик отдельно.- Программная задержка между
mode()и реальной работой WiFi — не помогает, пик уже произошёл к моменту, когда задержка началась. - Аппаратный мост / external watchdog — выходит за рамки прошивки.
Что должно случиться, если кто-то будет дебажить странности¶
Если устройство ведёт себя странно (несанкционированные resets,
flash corruption), проверка №1 — питание. Прицепить осциллограф к 3.3В
рейлу прямо у ESP32, посмотреть просадку при mode(). Если ниже
~2.7В дольше 50мкс — питание маржинальное, brownout мог бы помочь;
без него — отсюда могут плыть баги. Это и есть момент возврата
детектора.
Связанное¶
- ADR-002 — общая стратегия WiFi.
- doc/admin/network/wifi-setup.md — секция «Тюнинг радио», упоминание риска brownout.
- changes-2026-05-27.md §2 — история диагностики boot-loop.