HardFault_Handler на STM32F407ZET6 - PullRequest
0 голосов
/ 28 июня 2018

В настоящее время я сталкиваюсь с некоторыми проблемами с STM32F4, процесс "зависает", и я не могу понять, в какой момент он "заблокирован". Когда это произошло, я собрал следующие значения для следующих переменных (я создал переменную stepError для «перевода» переменной CFSR):

void prvGetRegistersFromStack (uint32_t * pulFaultStackAddress)
{
volatile uint32_t CFSRValue = SCB-> CFSR;
volatile uint32_t HFSRValue = SCB-> HFSR;
char stepError [1024] = "";
if ((HFSRValue & (1 << 30)) = 0) {
CFSRValue >> = 16;
if ((CFSRValue & (1 << 9)) = 0) strcpy (stepError, "Divide by zero");
if ((CFSRValue & (1 << 8))! = 0) strcpy (stepError, "Unaligned access");
if ((CFSRValue & (1 << 3)) = 0) strcpy (stepError, "No UsageFault coprocessor");
if ((CFSRValue & (1 << 2)) = 0) strcpy (stepError, "Invalid PC load UsageFault");
if ((CFSRValue & (1 << 1))! = 0) strcpy (stepError, "Invalid state");
if ((CFSRValue & (1 << 0))! = 0) strcpy (stepError, "Undefined instruction");
}

/ * These are volatile to try and prevent the compiler / linker optimizing them
away the variables never actually get used. If the debugger will not show the
values of the variables, make them global my moving their declaration outside
of this function. * /
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; / * Link register. * /
volatile uint32_t pc; / * Program counter. * /
volatile uint32_t psr; / * Program status register. * /

r0 = pulFaultStackAddress [0];
r1 = pulFaultStackAddress [1];
r2 = pulFaultStackAddress [2];
r3 = pulFaultStackAddress [3];

r12 = pulFaultStackAddress [4];
lr = pulFaultStackAddress [5]; // Bit (2 or 3) = 0 determines MSP (Main Stack Pointer); 1 = PSP (Process Stack Pointer)
pc = pulFaultStackAddress [6]; // Variable that contains the address where the error occurred. To check where it was, search the Disassembly on the screen Debug the address
psr = pulFaultStackAddress [7];

/ * When the following line is hit, the variables contain the register values. * /

// Joseph Yiu:
/ *
1) Look at LR value when the core enter hardfault, if bit 2 is 0, then read the value of MSP. Otherwise, read the value of PSP.
2) Based on the MSP / PSP value, you should be able to locate the start of stack frame, stacked PC is in address SP + 24.
3) Generate a disassembled listing of the program you run, and try to locate the stack PC address in the disassembled program list.
* /

GPIO_WriteLed (0,1);
for (int i = 0; i <= 10; i ++)
{
PWM_Change_DutyCycle (i, 0);
}
for (;;);
}

HFSRValue 1073741824 CFSRValue 0 StepError 0x2001fbb0 ""

r0 0 r1 0 r2 0 r3 11

r12 536890019 lr 134334773 шт. 0x0801bab0 psr 3221225472

Но я не могу знать из этих значений, где произошла ошибка, была ли она вызвана USB, последовательным интерфейсом, кодером или преобразователем АЦП и т. Д. Как реализовать void HardFault_Handler (void) чтобы я мог распознать, где происходит ошибка?

Редактировать: Из того, что я понимаю, разборка показывает неисправность, а не то, где код был до неисправности. enter image description here

1 Ответ

0 голосов
/ 28 июня 2018

Вы можете найти адрес инструкции / функции, вызвавшей ошибку, из фрейма стека исключений:

enter image description here

В приведенном вами примере это, похоже, уже передано функции 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 (вызывающий абонент).

...