MyTetra Share
Делитесь знаниями!
Отлов причины ошибки HardFault в Миландр
Время создания: 21.08.2014 08:34
Текстовые метки: Миландр, Milandr, контроллер, ошибка, hardfault, поймать, отлов, проверка
Раздел: Linux, компиляция, C/C++ - ARM - Milandr
Запись: xintrea/mytetra_db_harpokrat/master/base/1408595670dcnub6ox6y/text.html на raw.githubusercontent.com

На основе документации:



http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html



Стек в момент HardFault содержит состояние регистров ядра ARM. Код ниже показывает, как считать эти регистры в переменные С. После этого можно посмотреть значения этих переменных в отладчике (так же как и других переменных).


Сначала, небольшая ассемблерная функция которая определяет, какой стек использовался в момент возникновения ошибки. Как только это будет сделано, ассемблерный код обработчика ошибок передает указатель на стек в функцию C, называемую prvGetRegistersFromStack().


Ниже показан обработчик ошибок, использующий синтаксис GCC. Обратите внимание, что функция объявлена как незашифрованная, поэтому она не содержит никакого кода, сгенерированного компилятором (например, нет кода пролога для ввода функции).



/* The prototype shows it is a naked function - in effect this is just an

assembly function. */

static void HardFault_Handler( void ) __attribute__( ( naked ) );


/* The fault handler implementation calls a function called

prvGetRegistersFromStack(). */

static void HardFault_Handler(void)

{

__asm volatile

(

" tst lr, #4 \n"

" ite eq \n"

" mrseq r0, msp \n"

" mrsne r0, psp \n"

" ldr r1, [r0, #24] \n"

" ldr r2, handler2_address_const \n"

" bx r2 \n"

" handler2_address_const: .word prvGetRegistersFromStack \n"

);

}



Ниже показана реализация функции prvGetRegistersFromStack(). Функция prvGetRegistersFromStack() копирует значения регистров из стека в переменные C, а затем выполняет цикл. Имена переменных указывают на значение регистра, которое они содержат. Другие регистры не изменились с момента возникновения ошибки, и их можно просмотреть непосредственно в окне регистра процессора отладчика.



void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )

{

/* These are volatile to try and prevent the compiler/linker optimising them

away as the variables never actually get used. If the debugger won't 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 ];

pc = pulFaultStackAddress[ 6 ];

psr = pulFaultStackAddress[ 7 ];


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

for( ;; );

}



Использование значений регистров


Первым интересующим нас регистром является программный счетчик pc. В приведенном выше коде переменная pc содержит значение программного счетчика. pc содержит адрес команды, которая выполнялась при возникновении ошибки в железе Hard Fault (или другой ошибки).


Для поиска инструкции по адресу, указанному в переменной pc...:


  • Откройте окно кода ассемблера в отладчике и вручную введите адрес, чтобы просмотреть инструкции по сборке по этому адресу, либо
  • Откройте окно точки останова в отладчике и вручную определите точку останова выполнения или доступа по этому адресу. После установки точки останова перезапустите приложение, чтобы увидеть, к какой строке кода относится команда.


Знание команды, которая выполнялась в момент возникновения ошибки, позволяет вам узнать, какие другие значения регистров также представляют интерес. Например, если команда использовала значение R7 в качестве адреса, то необходимо знать значение регистра R7. Далее, изучение ассемблерного кода в паре с кодом на C, который сгенерировал ассемблерный код, покажет, что на самом деле содержит R7 (например, это может быть значение переменной).


 
MyTetra Share v.0.64
Яндекс индекс цитирования