Типичная ситуация. Компонент логирования и UART не проинициализировался корректно или устройство где-то зависло в инициализации после reset. Или устройство бесконечно перезагружается после подачи питания. Как же понять на какой строчке возникла run-time ошибка? Классическое решение это пошаговая отладка через JTAG или SWD.
Немного про железо. Работать буду вот с этой платой

Тут на board(e) как программатор U2 так и сам микроконтроллер U1 (Target). Оба 94pin(новые) nrf5340 в корпусе aQFN94. Соединены они интерфейсом SWD. Внутри каждого по 2 ядра Arm Cortex-M33 (Armv8-M). На улицу также выходит 2 UART(а) для интерфейса командной строки. Они же пробрасываются по USB (J2) на DeskTop.
Что понадобится из софта?
|
Утилита |
Назначение |
Path |
|
arm-none-eabi-gdb.exe |
GDB Client для ARM |
C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin |
|
JLinkGDBServer.exe |
GDB Server |
C:\Program Files (x86)\SEGGER\JLink\ |
|
nrfjprog.exe |
Прошивальщик микроконтроллера |
C:\Program Files (x86)\Nordic Semiconductor\nrf-command-line-tools\bin |
|
ttermpro.exe |
Терминал COM портов |
C:\Program Files (x86)\teraterm |
Этого должно быть достаточно.
Фаза 1 Залить прошивку в Target
Это можно проделать вот этим скриптом
echo off cls set com_port_num=10 set baudrate=115200 set project_name=headset_app set project_dir=%~dp0 set NRF_SDK_DIR=C:/ncs/v2.1.0 set SDK_PROJECT_DIR=%NRF_SDK_DIR%/nrf/applications/nrf5340_dk_audio_w IF "%1"=="" ( echo set dflt SDK ver set ARTEFACT_HEX=%SDK_PROJECT_DIR%\build\headset_app\zephyr\zephyr.hex ) ELSE ( echo set dflt SDK from argument set ARTEFACT_HEX=%1 ) echo Artefact hex: [%ARTEFACT_HEX%] set tools_dir=%cd%\..\..\..\tool echo Project Dir:%project_dir% set FlashTool="C:\Program Files (x86)\Nordic Semiconductor\nrf-command-line-tools\bin\nrfjprog.exe" set options=--iface USB --family NRF53 --coprocessor CP_APPLICATION --program %ARTEFACT_HEX% --log --chiperase --verify --reset call %FlashTool% %options% echo tools_dir=%tools_dir% call %tools_dir%\launch_terminal.bat 9 %baudrate% %project_name% call %tools_dir%\launch_terminal.bat 10 %baudrate% %project_name%
Отработав этот скрипт загрузит прошивку в микроконтроллер nrf5340.
Фаза 2 Запуск GDB сервера (Back-End)
GDB сервер это утилита, которая опрашивает программатор-отладчик. Именно она общается с устройством. Надо запустить GDB сервер. Вот скрипт запуска этой утилиты.
echo off cls set GDBServerOpt = -select USB -device nRF5340_xxAA_APP -endian little -if SWD -speed 400 -ir -LocalhostOnly -logtofile -log "C:\projects\code_base_workspace\code_base_firmware\tool\GdbServerLog.txt" set GDBServerDir="C:\Program Files (x86)\SEGGER\JLink\" set GDBServerPath=%GDBServerDir%JLinkGDBServer.exe" cd %GDBServerDir% call %GDBServerPath% %GDBServerOpt%
Надо установить интерфейс связи программатора и микроконтроллера который мы хотим отлаживать. В данном случае это интерфейс SWD.

J-link попросит выбрать микроконтроллер

список поддерживаесых чипов очень большой

В моем случае чип nrf5340

GDB сервер J-Link запущен локально. Программатор (S/N: 1050009032) подключен по USB. Target подключен к программатору по SWD.

вот полный лог ожидающего GDB сервера
Hidden text
SEGGER J-Link GDB Server V7.66a GUI Version
JLinkARM.dll V7.66a (DLL compiled May 19 2022 15:13:27)
——GDB Server start settings——
GDBInit file: none
GDB Server Listening port: 2331
SWO raw output listening port: 2332
Terminal I/O port: 2333
Accept remote connection: localhost only
Generate logfile: off
Verify download: off
Init regs on start: off
Silent mode: off
Single run mode: off
Target connection timeout: 5000 ms
——J-Link related settings——
J-Link Host interface: USB
J-Link script: none
J-Link settings file: none
——Target related settings——
Target device: Unspecified
Target interface: SWD
Target interface speed: 4000kHz
Target endian: little
Connecting to J-Link…
J-Link is connected.
Firmware: J-Link OB-nRF5340-NordicSemi compiled Dec 3 2021 15:46:49
Hardware: V1.00
S/N: 1050009032
Checking target voltage…
Target voltage: 3.30 V
Listening on TCP/IP port 2331
Connecting to target…
Connected to target
Waiting for GDB connection…
Сейчас GDB сервер просто ожидает подключения по TCP порту: 2331
На отладочной плате nRF5340-DK, есть встроенный программатор J-Link и там сейчас непрерывно светится зеленый LED, от отладчика.
Фаза 3 Запуск GDB клиента (Front-End )
Если GDB сервер можно метафорично считать Back-End(ом), то Front-End частью для пошаговой отладки выступает GDB клиент. Вот скрипт его запуска.
"C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe" --help "C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe" C:/ncs/v2.1.0/nrf/applications/nrf5340_dk_audio_w/build/headset_app/zephyr/zephyr.elf
GBD клиент смог подхватить *.elf файл с отладочными символами

Настало время подключиться к GBD серверу. Это делается командой.
target remote localhost:2331
Сработало

Подключился. Сейчас исполнение прошивки на паузе. HeartBeat LED не мигает, UART-Shell не отвечает.
Для запуска прошивки надо набрать команду continue

Теперь HeartBeat LED мигает CLI отвечает. LED на программаторе тоже мигает только как-то апериодично.
Для того чтобы снова остановить исполнение программы надо в терминале GDB клиента нажать Ctrl+C.
Теперь можно установить точку останова. Меня интересует функция bool hw_init(void)
(gdb) break hw_init
Посмотреть список установленных точек останова можно командой
(gdb) info b
Вот это сейчас отображается

Снова запускает программу на исполнение. Команда c
(gdb) c
Но вот незадача. Точка останова установлена внутри функции инициализации, которая уже давно отработала. Надо как-то перезагрузить trarget, чтобы инициализация снова отработала.
Вот тут то нам как раз поможет еще один терминал. Это терминал командной строки поверх UART реализованный прямо внутри прошивки на Target(е). Я просто попрошу устройство перезагрузиться командой в UART CLI
-> kernel reboot cold
и устройство в самом деле перезагружается

При этом я даже от клавиатуры рук не отводил. И вот отладчик зацепил функцию bool hw_init(void). Это называется синергия GDB и UART-CLI. Успех.

Выполнить одну строчку кода можно командой n. Посмотреть содержимое локальный переменный можно командой info locals

Зайти внутрь функции можно командой s.
Само собой, в консоли GBD клиента есть история команд и вы можете стрелками вверх и вниз на клавиатуре набирать уже используемые в прошлом команды.
Чтобы выйти из GDB клиента надо набрать в его консоли команду q. Target все еще suspended. Поэтому также надо закрыть GDB сервер. Только после этого Target станет resumed и продолжит исполнять свой код.
В последующем можно запустить GDB сервер и GDB клиент одним единственным скриптом.
echo off cls set FIRMWARE_FILE=C:/ncs/v2.1.0/nrf/applications/nrf5340_dk_audio_w/build/headset_app/zephyr/zephyr.elf set GDB_CLIENT="C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe" set tools_dir=%cd%\..\..\..\tool start %tools_dir%\0_LaunchGdbServerNrfAppCore.bat %GDB_CLIENT% --help %GDB_CLIENT% %FIRMWARE_FILE%
Суммируя вышесказанное, весь процесс можно объяснить вот этой простой схемой

Также небольшая шпаргалка по наиболее употребительным командам консольного GDB клиента
|
short |
full |
description |
|
— |
info args |
Show current function arguments |
|
i b |
info b |
List all breakpoints |
|
bt |
backtrace |
show function call stack |
|
n |
next |
Step over functions |
|
f |
finish |
Execute the rest of the current function. Step out of the current function. |
|
s |
step |
Step into functions |
|
p count |
|
Print the value of a variable count |
|
c |
continue |
Continue execution up to the next breakpoint or until termination if no breakpoints are encountered |
|
— |
delete n |
Delete breakpoint number n |
|
— |
info locals |
show local variables |
|
— |
target remote localhost:2331 |
Connect to J-Link |
|
q |
quit |
quit gdb |
|
b function |
|
Set a breakpoint at the beginning of function |
Буду также обновлять реестр команд GDB клиента вот тут
https://docs.google.com/spreadsheets/d/1AWD8GsDfaA9dtdsfqgbB1klagou1yrREc1AAK9CRUik/edit#gid=0
Вывод
Как видите в GDB отладке через консоль нет вообще ничего сложного. Поэтому всякие там циклопические и дорогущие IDE для пошаговой отладки не особо-то и нужны как бы. Консоль даже лучше в том смысле, что внимание концентрируется на сути (коде), а не на стразиках из оформления IDE. Можно вообще отлаживать без кода, просто получив по почте один лишь *.elf файл.
При этом накладные расходы на установку Toolchain(а) для пошаговой отладки минимальные и всё абсолютно бесплатно.
Links
https://condor.depaul.edu/glancast/373class/docs/gdb.html#Setting_Breakpoints
https://habr.com/ru/post/181738/
https://habr.com/ru/post/535960/
https://habr.com/ru/post/546216/
https://mcuoneclipse.com/2015/03/25/command-line-programming-and-debugging-with-gdb/
https://www.electricmonk.nl/docs/gdb_debugging/gdb_debugging.html
Вопрос *
Как работает механизм установки точек останова JTAG под капотом?
ссылка на оригинал статьи https://habr.com/ru/post/694708/
Добавить комментарий