Вы можете найти адрес инструкции / функции, вызвавшей ошибку, из фрейма стека исключений:
В приведенном вами примере это, похоже, уже передано функции prvGetRegistersFromStack
, которую вы указали в качестве параметра pulFaultStackAddress
. Поскольку вам интересно узнать, какая часть вашего кода стала причиной HardFault, это можно найти в PC
и LR
, которые были сложены - в вашем примере они взяты из pulFaultStackAddress[6]
и pulFaultStackAddress[5]
соответственно .
PC
должен содержать счетчик программ, который является командой, которая выполнялась по мере возникновения ошибки. LR
должно содержать значение Link Link, которое является адресом возврата, или другими словами - адрес вызывающей подпрограммы / функции.
Вы опубликовали, что эти значения: pc 0x0801bab0
и lr 134334773
(0x801C935 в шестнадцатеричном формате). Оба значения являются действительными адресами во внутренней флэш-памяти для STM32F407ZE, поэтому мы можем предположить, что они действительны. Осталось только перевести адреса памяти обратно в строки исходного кода. Два примера того, как это сделать:
Использование вашей IDE
В настоящее время большинство IDE имеют вид «разборки». Обычно используемые в Eclipse (например, SW4STM32 или TrueSTUDIO для STM32) имеют его в Window-> Show View-> Other-> Debug-> Disassembly. У IAR тоже есть такой. После открытия вставьте адрес памяти (например, 0x0801bab0
, который был значением PC
) в поле во время отладки и нажмите Enter. Это должно показать вам соответствующую разборку с чередованием строк исходного кода. Это должно дать вам представление о том, где произошел HardFault.
Другой подход к ..
Использование набора инструментов
В инструментальных цепочках также есть инструменты командной строки, позволяющие вам сделать то же самое, что и выше. Чтобы привести пример, я предполагаю, что вы используете arm-none-eabi
. Там вы можете использовать addr2line
для перевода адреса памяти обратно в исходный код строки:
arm-none-eabi-addr2line.exe -e [your executable].elf -i 0x0801bab0
где [your executable]
- это путь к файлу ELF, который вы загрузили в MCU. Переключатель -i
пытается развернуть встроенные функции, что иногда помогает лучше понять, откуда произошел вызов.
Какой бы подход вы ни выбрали, вы можете сделать то же самое для значения PC
(адрес, где произошла ошибка) и LR
(вызывающий абонент).