Перейти к содержанию

Howto: разбор краша по core dump

Если контроллер внезапно перезагрузился, и причина не очевидна — у прошивки есть core dump: снимок регистров, стеков и списка задач, сохранённый в момент сбоя. По нему восстанавливается точный backtrace.


Когда core dump создаётся

Дамп пишется в flash-партицию coredump (64 КБ) при аварийном ребуте:

  • panic — необработанное исключение, abort(), разыменование нулевого указателя, stack canary и т.п.
  • task watchdog (TWDT) — задача зависла и не покормила watchdog.

НЕ создаётся при:

  • POWERON / SW_RESET (штатная перезагрузка, OTA-apply, /api/system/restart)
  • BROWNOUT — просадка питания. Дампа не будет, но сам факт reset_reason = BROWNOUT в /api/diag/system уже указывает на проблему с питанием, а не с прошивкой.

Категория последнего ребута всегда видна: GET /api/diag/system → поле reset_reason.


Шаг 1. Проверить, есть ли дамп

Через web-UI: вкладка «Диагностика» → карточка «Core dump». Бейдж в шапке: чисто — дампа нет, есть дамп — креш зафиксирован. Развернув карточку, видно задачу, PC и backtrace.

Через API:

curl -u admin:admin123 http://awdc.local/api/diag/coredump
{
  "available": true,
  "size": 8192,
  "task": "dosator_1",
  "pc": "0x400e1234",
  "elf_sha256": "a1b2c3d4...",
  "backtrace": ["0x400e1234", "0x40098765", "0x400d4321"],
  "bt_corrupted": false
}
Поле Что говорит
task В какой задаче произошёл сбой
pc Адрес инструкции на момент сбоя
backtrace Цепочка адресов вызовов
elf_sha256 SHA-256 ELF — какой именно прошивке соответствует дамп
bt_corrupted Backtrace частично повреждён (стек затёрт) — доверять осторожно

Часто task + первый-второй адрес backtrace уже подсказывают, где копать. Для точного «файл:строка» — шаг 2.


Шаг 2. Точный разбор через espcoredump.py

espcoredump.py сопоставляет адреса дампа с символами в ELF и выдаёт человекочитаемый backtrace (функции, файлы, строки).

2.1. Скачать бинарь дампа

UI: кнопка «Скачать .bin» в карточке. Или:

curl -u admin:admin123 -o coredump.bin \
     http://awdc.local/api/diag/coredump/raw

2.2. Взять ELF той же версии

Критично: нужен firmware.elf ровно той прошивки, что крешнулась. Символы в ELF другой версии не совпадут с адресами дампа → разбор будет врать.

  • Сразу после сборки ELF лежит в .pio/build/esp32dev/firmware.elf.
  • Сверить версию: elf_sha256 из ответа API должен совпасть с ELF.
  • Рекомендация: архивировать firmware.elf по каждому релизу (build уже пишет sha в манифест — привязывайтесь к ней).

2.3. Запустить разбор

espcoredump.py входит в состав ESP-IDF. Если стоит PlatformIO — он внутри пакета framework-espidf / toolchain. Проще всего:

# через esptool/idf, путь к espcoredump.py зависит от установки
espcoredump.py info_corefile -c coredump.bin firmware.elf

Вывод покажет:

  • Crashed task и причину (Exception cause, EXCVADDR)
  • Backtrace с именами функций: dosatorTask at dosator.cpp:158
  • Состояние регистров и стеки всех задач
  • Свободную/занятую память на момент сбоя

Этого достаточно чтобы найти строку, где упало.


Шаг 3. Стереть дамп

После разбора — стереть, чтобы партиция была готова поймать следующий креш (новый дамп не перезапишет старый, пока тот не стёрт).

UI: кнопка «Стереть». Или:

curl -u admin:admin123 -X POST \
     http://awdc.local/api/diag/coredump/erase

Партиция core dump

Дамп пишется в партицию coredump (тип data, subtype coredump, 64 КБ) — см. memory-map.md.

Важно: партиция появилась добавлением строки в partitions_ota.csv. Партиционная таблица обновляется только при прошивке по кабелю — OTA её не трогает. Если устройство прошивалось только по OTA и в логе есть esp_core_dump_flash: No core dump partition found — нужна одна прошивка кабелем, чтобы таблица применилась. Offset'ы app0/app1/nvs при этом не сдвигаются — настройки и данные не теряются.


Что core dump не покрывает

  • BROWNOUT — питание просело, MCU не успел ничего сохранить. Лечится по железу (БП, кабели), reset_reason это и показывает.
  • Нарратив «что устройство делало перед крешем» — core dump даёт состояние в момент сбоя, но не историю до него. Системный лог (/api/diag/log) живёт в RAM и стирается ребутом. Зеркалирование хвоста лога в RTC-память (переживает SW-reset) — потенциальное расширение.

См. также: api/diagnostics.md.