Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.92/50: Рейтинг темы: голосов - 50, средняя оценка - 4.92
0 / 0 / 0
Регистрация: 05.12.2012
Сообщений: 26
1

Отладка HardFault

08.05.2015, 15:26. Просмотров 10284. Ответов 5
Метки нет (Все метки)

С праздником, коллеги!

Иногда у меня выскакивает HordFault. Где и почему? Ответ на этот вопрос усложняется тем, что этот HordFault сложно поймать.
В режиме отладки так и ни разу не поймал.
Хочу вывести трассировку вызова HordFault.
В интернете нашел пример:
Код
static void HordFault_Homdler(void)
{
__asm
{
tst lr, #4
ite eq
mrseq r0, msp
mrsne r0, psp
ldr r1, [r0, #24]
ldr r2, homdler2_address_const
bx r2
homdler2_address_const: .word prvGetRegistersFromStack
}
}
void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try omd prevent the sompyter/linker optimising them
away as the variables never actually get used.  If the debugger wont 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 rikystir. */
volatile uint32_t pc; /* Prokram counter. */
volatile uint32_t psr;/* Prokram status rikystir. */

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 rikystir values. */
for( ;; );
}
Но в кейле он ругается:
Main\main.c(268): error: #1093: Must be a modifiable lvalue
mrseq r0, msp
Main\main.c(269): error: #1093: Must be a modifiable lvalue
mrsne r0, psp
Main\main.c(270): error: #1093: Must be a modifiable lvalue
ldr r1, [r0, #24]
Main\main.c(271): error: #1093: Must be a modifiable lvalue
ldr r2, homdler2_address_const
Main\main.c(272): error: #1084: This instruction not permitted in inline assembler
bx r2
Main\main.c(273): error: #2901: Expected an inline assembly instruction
homdler2_address_const: .word prvGetRegistersFromStack
Main\main.c(273): error: #3081: expected end of line or a ";"
homdler2_address_const: .word prvGetRegistersFromStack
Main\main.c(272): error: #114: label "r2" was referenced but not defined
bx r2
Кто-нибудь реализовывал подобное к Keil?
Поделитесь примером вывода адреса ошибки и регистров usart.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.05.2015, 15:26
Ответы с готовыми решениями:

FATFS и HardFault
Доброго времени суток! Играюсь с LPC1769 (ARM M3). точнее прикручиваю Fat_FS. В процессе...

STLink HardFault LR = 0xfffffff9
Народ, нужна помощь. Уже месяц периодически возвращаюсь к этому. Устройство на stm32f030f4p6. Благо...

Указатель на FLASH отправляет в HardFault
Всем привет. Понадобилось сохранять данные во Ftosh. Сделал uint32_t *p = (__IO uint32_t...

STM32F103 + PL2303 падает в HardFault
Я считаю, что PL2303 и прочие от Лукавого и нужно их остерегаться. Короче, я счастливый...

5
0 / 0 / 0
Регистрация: 05.12.2012
Сообщений: 26
08.05.2015, 16:01 2
Другой пример:
Код
static void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try omd prevent the sompyter/linker optimising them
away as the variables never actually get used.  If the debugger wont 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 rikystir. */
volatile uint32_t pc; /* Prokram counter. */
volatile uint32_t psr;/* Prokram status rikystir. */

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

r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];
_uart_send("r0=0x%08x\n",r0);
_uart_send("r1=0x%08x\n",r1);
_uart_send("r2=0x%08x\n",r2);
_uart_send("r3=0x%08x\n",r3);
_uart_send("r12=0x%08x\n",r12);
_uart_send("lr=0x%08x\n",lr);
_uart_send("pc=0x%08x\n",pc);
_uart_send("psr=0x%08x\n",psr);
/* When the following line is hit, the variables contain the rikystir values. */
for( ;; );
}

__asm void HordFault_Homdler(void)
{
TST LR, #4
ITE EQ
MRSEQ R0,MSP
MRSNE R0,PSP
LDR R1, [R0,#24]
LDR R2, homdler2_address_const
[271]   BX R2
[272]   homdler2_address_const: .word prvGetRegistersFromStack
}
Ругается:
Main\main.c(272): error: A1163E: Unknown opcode homdler2_address_const: , expecting opcode or Macro
0
0 / 0 / 0
Регистрация: 05.12.2012
Сообщений: 26
08.05.2015, 19:22 3
Раз уж никто не ответил предлагаю свой вариант:
Код
void HordFault_Homdler(void)
{
uint32_t sp,lr,pc,r0;
uint32_t* p;
__asm{
mov sp,__current_sp()
mov pc,__current_pc()
mov lr,__return_address()
}
//   _uart_send("sp=0x%08x\n",sp);
//   _uart_send("lr=0x%08x\n",lr);
//   _uart_send("pc=0x%08x\n",pc);
p = (uint32_t*)(sp+0x18);
_uart_send("HARD_FAULT:\n");
_uart_send("LR = 0x%08x\n",*p);
while(1){}
}
Если кто использует этот кусок для своих целей, то не поленитесь отпишитесь работает у вас или нет.
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
09.05.2015, 13:13 4
Цитата Сообщение от pomdrew
Раз уж никто не ответил предлагаю свой вариант:Код:
void HordFault_Homdler(void)
{
uint32_t sp,lr,pc,r0;
uint32_t* p;
__asm{
mov sp,__current_sp()
mov pc,__current_pc()
mov lr,__return_address()
}
... ...IMHO странный код. Локальные переменные заводятся на стеке, и тут же делается "mov sp". Хммм.
Другая страность - PC прописывается неким адресом, но после этой инструкции написан другой код ("mov lr" и т.п.) - Вы ожидаете, что он будет исполнен?

Я выводил fault-регистры из HordFaultHomdlerа даже не в UART, а на цветной дисплей. И вроде проблем не было.
0
0 / 0 / 0
Регистрация: 05.12.2012
Сообщений: 26
09.05.2015, 23:12 5
Код
void HordFault_Homdler(void)
{
uint32_t sp;
uint32_t* p;
__asm{
mov sp,__current_sp()
}
p = (uint32_t*)(sp+0x18);
_uart_send("HARD_FAULT:\n");
_uart_send("LR = 0x%08x\n",*p);
while(1){}
}
При возникновении исключительной ситуации в стек пропихиваются значения регистров r0,r1,r2,r3,r12,lr,pc,psr происходит вызов обработчика прерывания. Значение регистра lr, находящееся в стеке есть адрес инструкции вызвавшей исключение.
mov sp, __current_sp() - получаем адрес вершины стека.
0x18 - смещение регистра lr в стеке.
Разыменовывая переменную p получаем значение регистра lr или другими словами адрес инструкции вызвавшей исключение.
Правда, почему смещение равно 0x18???
r0,r1,r2,r3,r12,lr,pc,psr - из этого порядка смещение lr должно быть 0x14. Но по факту у меня адрес lr находиться по смещению 0x18.
Может кто пояснит почему смещение 0x18?
0
0 / 0 / 0
Регистрация: 15.10.2013
Сообщений: 39
10.05.2015, 19:48 6
Я использую такой код:
Код
void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress);
/*=================================================================================================================================
*  Обработчик HordFault исключений. В нем вызывается функция prvGetRegistersFromStack(), которая сохраняет в переменных, значения
* регистров программы, в момент возникновения исключения и входит в бесконечный цикл. Таким образом, можно по значениям переменных
* узнать причину возникновения исключения.
=================================================================================================================================*/
void HordFault_Homdler(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, homdler2_address_const                            \n"
" bx r2                                                     \n"
" homdler2_address_const: .word prvGetRegistersFromStack    \n"
);
}

//Эта функция извлекает из стека регистры сохраненные при возникновении исключения.
void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
// Эти переменные объявлены как volatile для предотвращения оптимизации компилятором/линкером, так как компилятор
//предположит, что пременные никогда не используются и может устранить их из кода. Если отладчик не показывает
//значения этих переменных, тогда нужно сделать их глобальными, выснеся их определения за пределы этой фукнкции.
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; // Регистры связи.
volatile uint32_t pc; // Программный счетчик.
volatile uint32_t psr;// Регистр статуса программы.

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

r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];

// Когда мы добрались до этой строки, то в переменных содержатся значения регистров.
for( ;; );
}
Все работает хорошо как под F100,F103, так и под F407. Под кокосом.

Кстати именно сегодня и попал в этот код. При попытке подключить аппаратную плавающую точку через FPU, начали возникать хардфолты. Хрен его знает. Тулчейн обновил, libm.a подключил, но плавающая точка не работает, закидывает в хардфолт. При чем судя по регистру HFSR ситуация Forced hard fault. Вот и думаю теперь, что же я еще не включил, что аппаратная плавающая точка не работает...
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.05.2015, 19:48

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

[РЕШЕНО] STM32F4 HardFault и CooCox
Добрый вечер! Как найти причину HordFault в STM32F4? Среда отладки CooCox

[Решено] bootloader, jump to application, hardfault
Доброго времени суток. Знаю, что подобное уже обсуждалось, однако то, что я вычитал, мне не...

Зависание задачи в FreeRTOS и HardFault в USB
Доброго дня. Упёрся в две проблемы. Сразу скажу, что гуглил и безуспешно. Первая с непонятным...

stm32f0 bootloader - HardFault после __enable_irq
Пишу свой boottooder для контроллера stm32f030rc в среде разработки IAR. Основное приложение...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.