Статьи

Отладка аппаратных ошибок ARM Cortex-M с помощью пользовательской команды GDB

В « Компоненте Processor Expert для помощи в сложных сбоях » я использую обработчик C с некоторым кодом сборки, созданным с помощью Processor Expert, чтобы помочь мне в отладке сложных ошибок в ARM Cortex-M. Вдохновленный здесь сценарием GNU GDB , у меня теперь есть альтернативный способ. Поскольку этот подход использует подход командной строки GDB, он работает как с Eclipse GUI, так и с использованием GDB только в режиме командной строки :-).

Название изображения

— скрипт GDB для отладки ARM Hard Faults

Идея заключается в следующем:

  1. Установите точку останова в обработчике исключений серьезных сбоев
  2. При возникновении серьезного сбоя ЦП вызовет обработчик исключений сбоя, а отладчик остановит цель.
  3. Выполните скрипт / команду armex (исключение ARM) в GDB, чтобы выгрузить составленные регистры, чтобы показать счетчик программ, где произошла проблема.

Скрипт .gdbinit

Есть несколько способов расширить GDB с помощью собственных команд. Один простой способ — добавить дополнительные функции в скрипт .gdbinit, который загружается GDB при запуске.

Я добавил следующее в мой файл .gdbinit, чтобы определить мою команду ‘armex’:


define armex
  printf "EXEC_RETURN (LR):\n",
  info registers $lr
    if $lr & 0x4 == 0x4
    printf "Uses MSP 0x%x return.\n", $MSP
    set $armex_base = $MSP
    else
    printf "Uses PSP 0x%x return.\n", $PSP
    set $armex_base = $PSP
    end
 
    printf "xPSR            0x%x\n", *($armex_base+28)
    printf "ReturnAddress   0x%x\n", *($armex_base+24)
    printf "LR (R14)        0x%x\n", *($armex_base+20)
    printf "R12             0x%x\n", *($armex_base+16)
    printf "R3              0x%x\n", *($armex_base+12)
    printf "R2              0x%x\n", *($armex_base+8)
    printf "R1              0x%x\n", *($armex_base+4)
    printf "R0              0x%x\n", *($armex_base)
    printf "Return instruction:\n"
    x/i *($armex_base+24)
    printf "LR instruction:\n"
    x/i *($armex_base+20)
end
 
document armex
ARMv7 Exception entry behavior.
xPSR, ReturnAddress, LR (R14), R12, R3, R2, R1, and R0
end

Вы можете разместить файл .gdbinit где угодно. Я разместил его там, где мой GDB находится внутри студии дизайна Freescale Kinetis (C: \ Freescale \ KDS_3.0.0 \ toolchain \ bin).

Чтобы убедиться, что GDB находит .gdbinit, я указываю путь к нему в настройках рабочей области Eclipse:

Название изображения

— Командный файл GDB в настройках Eclipse Workspace

Отладка Hard Fault

Чтобы отладить серьезную ошибку, я установил точку останова в моем обработчике прерывания жесткого сбоя, чтобы остановить отладчик при возникновении ошибки:

Название изображения

— остановился по грубой вине

Чтобы выяснить, где возникла проблема, я теперь использую команду ‘armex’ в консоли gdb:

    Используйте меню «треугольник» консоли, чтобы перейти к представлению arm-none-eabi-gdb

Название изображения

Команда armex в консоли GDB

Команда armex перечисляет составленные регистры (так же, как и мой обработчик, показанный в « Отладка аппаратных ошибок в ARM Cortex-M »). Важной информацией является либо инструкция возврата, либо информация инструкции LR. Я могу ввести этот адрес в окне разборки, чтобы узнать, где возникла проблема:

Разборка Вид на причину жесткой ошибки

В приведенном выше примере LR (регистр связи или адрес возврата) был 0xbd2 (0xbd3 с установленным битом большого пальца). В представлении разборки это адрес, по которому обработчик должен вернуться, поэтому проблема должна быть как раз перед этим. При проверке ассемблерного кода есть косвенный регистр ветки

blx r3

Сложенный регистр показывает

R3              0x0

Что вызывает серьезную ошибку. Если проблема не так ясна, просто установите точку останова вокруг этого местоположения и перезапустите приложение, чтобы отладить то, что происходит до того, как произойдет сбой. С этим должно быть легко надеяться найти и решить проблему.

Резюме

Теперь у меня есть еще один способ отладки моих серьезных сбоев: использование моей собственной команды gdb для сброса накопленных регистров. Преимущество этого подхода в том, что ему не нужны никакие дополнительные ресурсы для цели (без дополнительного обработчика в коде и без переменных) по сравнению с моим более ранним решением. И дополнительное преимущество теперь в том, что я знаю, как расширить GDB с помощью своих пользовательских команд :-).