Расшифровка отладочной информации ESP32

Отладка программы на микроконтроллере — необходимый навык для любого инженера, занятого разработкой электронных устройств. Методов отладки множество. Это и просто мигание светодиодами, и вывод ошибок в UART, и отладка через специальные интерфейсы JTAG/SWD. В этой статье мы обратим внимание на отладку программы, написанной для микроконтроллера ESP32 (по факту SoC).

Данный микроконтроллер имеет встроенный механизм формирования отладочной информации и вывода её через UART интерфейс. Так выглядит кадр отладочной информация ESP32-S3, которая формируется при возникновении ошибки. Многие, кто программирует для ESP32 встречали такой лог и не знали, что с ним делать.

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core 1 register dump:

PC: 0x4200cd53 PS: 0x00060b30 A0: 0x8200d1cb A1: 0x3fca3730
A2: 0x3fc9ea6c A3: 0x000000b4 A4: 0x000000be A5: 0x00000000
A6: 0x00000014 A7: 0x3fca3820 A8: 0x00000078 A9: 0x00000000
A10: 0x00000001 A11: 0x00000000 A12: 0x00000000 A13: 0x00000000
A14: 0x00000000 A15: 0x000000b4 SAR: 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG: 0x4200bcb4 LEND: 0x4200bcbe LCOUNT: 0x00000000

Backtrace: 0x4200cd50:0x3fca3730 0x4200d1c8:0x3fca3880 0x42007078:0x3fca38b0 0x4200888c:0x3fca3900 0x4200560f:0x3fca3920 0x42005c47:0x3fca3940 0x42016e68:0x3fca3960 0x4037cff6:0x3fca3980

Если посмотреть на этот набор шестнадцатеричных чисел взглядом IT-обывателя, то это мало что прояснит. Сверху — непонятное сообщение об ошибке. Ниже (Core 1 register dump), состояние всех регистров. Ещё ниже (Backtrace) — вероятно, трассировка стека, но только без названий функций.

Трассировка стека — это отчет о цепочке вызовов функций, которая привела к ошибке. Это очень ценная информация для поиска ошибки. Именно её расшифровкой мы и займёмся.

Необходимая информация для расшифровки хранится в файле .elf, который генерируется во время компиляции программы. А для анализа этих .elf файлов в esp-idf существуют специальные утилиты — addr2line.

Итак, чтобы расшифровать трассировку стека в ESP32 понадобится:

  • утилита addr2line (для esp32-s3 это xtensa-esp32s3-elf-addr2line);
  • файл .elf.

Где взять утилиту addr2line?

Эта утилита устанавливается вместе с набором инструментов esp-idf. Соответственно, самый простой способ её получить — установить esp-idf. Ссылка на инструкцию по установке есть в конце статьи.

Утилиты для работы с конкретными ядрами микроконтроллеров живут в папке: ~/.espressif/tools. Зайдём в эту папку и выберем подходящий пакет. Для работы с ESP32, ESP32-S2 или ESP32-S3 откроем папку xtensa-esp-elf. А вот у ESP32-C6 ядро другое — RISC-V, так что и утилита будет совершенно другая, в папке riscv32-esp-elf.

Спускаемся вниз до папки bin и находим там: xtensa-esp32s3-elf-addr2line — это то, что нам нужно!

Также наличие нужной утилиты можно проверить так:

which xtensa-esp32s3-elf-addr2line

Примечание. Видно утилиту будет только после подключения окружения esp-idf командой source. Как это сделать, читай ниже.

Где взять .elf?

Этот файл формируется каждый раз при сборке проекта для целей отладки и анализа. В отличие от .hex файла, в .elf хранятся имена функций, что нам как раз и необходимо для расшифровки отладочной информации.

Например, в среде Arduino IDE файл лежит во временной папке проекта:

C:\Users\master\AppData\Local\arduino\sketches\26D11705A98E98C54B438CA83C79660E\test.ino.elf

Расшифровка отладочной информации (backtrace)

Итак, по шагам.

1. Подключаем окружение esp-idf командой:

source export.sh

2. Запускаем утилиту расшифровки, передавая в неё .elf и исходные коды отладочной информации:

xtensa-esp32s3-elf-addr2line -pfiaC -e test.ino.elf 0x4200cd50:0x3fca3730 0x4200d1c8:0x3fca3880 0x42007078:0x3fca38b0 0x4200888c:0x3fca3900 0x4200560f:0x3fca3920 0x42005c47:0x3fca3940 0x42016e68:0x3fca3960 0x4037cff6:0x3fca3980

Результат:

0x4200d1c8:0x3fca3880 0x42007078:0x3fca38b0 0x4200888c:0x3fca3900 0x4200560f:0x3fca3920 0x42005c47:0x3fca3940 0x42016e68:0x3fca3960 0x4037cff6:0x3fca3980
0x4200cd50: TFT_eSPI::pushImage(long, long, long, long, unsigned short*, unsigned short) at C:\Users\olege\AppData\Local\Programs\Arduino IDE/c:\Users\olege\Documents\Arduino\libraries\TFT_eSPI/TFT_eSPI.cpp:1504
0x4200d1c8: TFT_eSPI::frameEnd() at C:\Users\olege\AppData\Local\Programs\Arduino IDE/c:\Users\olege\Documents\Arduino\libraries\TFT_eSPI/TFT_eSPI.cpp:2469
0x42007078: SDGFX::drawItemBar(Item&, unsigned char) at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Devel\Projects\1. ROC\ROC.TFT-ESP-S3\src\RobotClass_Photon_S3/sdgfx.cpp:450
0x4200888c: SDGFX::drawItem(Item&, unsigned char) at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Devel\Projects\1. ROC\ROC.TFT-ESP-S3\src\RobotClass_Photon_S3/sdgfx.cpp:191
0x4200560f: handleGFX() at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Devel\Projects\1. ROC\ROC.TFT-ESP-S3\src\RobotClass_Photon_S3/RobotClass_Photon_S3.ino:440 (discriminator 2)
(inlined by) handleGFX() at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Devel\Projects\1. ROC\ROC.TFT-ESP-S3\src\RobotClass_Photon_S3/RobotClass_Photon_S3.ino:426 (discriminator 2)
0x42005c47: loop() at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Devel\Projects\1. ROC\ROC.TFT-ESP-S3\src\RobotClass_Photon_S3/RobotClass_Photon_S3.ino:619
0x42016e68: loopTask(void*) at C:\Users\olege\AppData\Local\Programs\Arduino IDE/C:\Users\olege\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.1\cores\esp32/main.cpp:74
0x4037cff6: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:139

Ну вот, теперь понятно, куда копать. В данном коде ошибка была в функции drawItemBar. Она была успешно изолирована и устранена!

Полезные ссылки

Инструкция по установке esp-idf на linux:

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html


Изменено:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Комментарий
Имя
E-mail

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.