Перейти к содержанию
    

Как отловить глюк, приводящий к HardFault

Добрый день, господа!

 

Я понимаю, что проблема не имеет прямого отношения к FreeRTOS, но всё же.

 

Я использую версию 8.2.3 на LPC1768. Компилятор IAR 7.5.

 

Что наблюдается. Периодически прога стала вылетать в HardFault. Причём, если код немного перекомпилировать, буквально добавить/убавить строку, то всё работает прекрасно.

 

Я смотрел на адреса в обработчике HardFault, но не могу понять, как возникает ошибка, т.к. эти адреса указывают то на файлы самой оси, то на мой код. Может быть есть какая-то проблема именно с Cortex-M3 и именно с этой версией, о которой все знают, а я не знаю?

 

Да, включен монитор стека, он не переполняется, либо монитор не ловит ошибку.

 

В общем я в лёгком отчаянии, не знаю, как ловить глюк. Код довольно объёмный на текущий момент времени, поэтому по частям уже прогу не проверишь...

 

Спасибо за любой совет!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я смотрел на адреса в обработчике HardFault, но не могу понять, как возникает ошибка, т.к. эти адреса указывают то на файлы самой оси, то на мой код.

Помимо адреса у fault'а есть еще и причина, что с ней?

 

Касательно FreeRTOS, проверьте приоритеты прерываний, в которых используются системные вызовы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void HardFault_Handler(void)
{
    volatile bool is_break = false;
    while(!is_break)
    {
    }
}

А вот этот трюк (насколько помню предложен Сергеем Борщ), не помогает найти место откуда вылетело?

Но вообще похоже на проблемы со стеком/хипом. Хип используется, если да, то проверяли?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Точно, Fault регистры посмотрите. В книжке Дж. Ю хорошо расписаны.

Простейший обработчик может быть таким:

__asm void HardFault_Handler(void)
{
  B .            ; бесконечный цикл
  BX LR            ; установить программный счетчик сюда и шагнуть
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Точно, Fault регистры посмотрите. В книжке Дж. Ю хорошо расписаны.

Простейший обработчик может быть таким:

 

Отладчик типа J-Link перехватывает сам все исключения и делает останов. Никаких обработчиков не надо делать.

Лучше смотреть таймлайн и анализировать как с моментом вылета коррелируют события прерываний.

Я бы поставил на то, что проблема скрывается в прерываниях.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Помимо адреса у fault'а есть еще и причина, что с ней?

Вот пример моего)

[HARD FAULT HANDLER]
R0 = 0x18400D4E
R1 = 0x2
R2 = 0x100046E0
R3 = 0x10000648
R12 = 0x21D8
LR [R14] = 0xA0BF  subroutine call return address
PC [R15] = 0xA0D4  program counter
PSR = 0x21000000
BFAR = 0x18400D56
CFSR = 0x8200
HFSR = 0x40000000
DFSR = 0x0
AFSR = 0x0

 

Касательно FreeRTOS, проверьте приоритеты прерываний, в которых используются системные вызовы.

В ней (фриртос) есть фича, которая не позволяет поставить неправильные приоритеты (выдаёт ассерт), или вы о другом?

 

 

void HardFault_Handler(void)
{
    volatile bool is_break = false;
    while(!is_break)
    {
    }
}

А вот этот трюк (насколько помню предложен Сергеем Борщ), не помогает найти место откуда вылетело?

Этот трюк вижу впервые.

Но вообще похоже на проблемы со стеком/хипом. Хип используется, если да, то проверяли?

Хип-менеджер используют от уважаемого zltigo, выложенный лет пять назад. Вроде в нём все баги выловили...

 

Лучше смотреть таймлайн и анализировать как с моментом вылета коррелируют события прерываний.

Я бы поставил на то, что проблема скрывается в прерываниях.

С этой техникой не знаком, можно подробнее (ссылочку, например?)

Кстати, под отладчиком оно не возникает (исключение).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно эта тема поможет.

Судя по всему при возникновении исключения выполнялся код в ОЗУ (0xA0D4). Посмотрите команду, которая находится перед 0xA0BF, возможно дело в ней.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно эта тема поможет.

Судя по всему при возникновении исключения выполнялся код в ОЗУ (0xA0D4). Посмотрите команду, которая находится перед 0xA0BF, возможно дело в ней.

Спасибо, погляжу! Но теперь, как на зло, не залетаю туда((( А ситуацию не сохранил, воспроизвести тоже не могу...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, погляжу! Но теперь, как на зло, не залетаю туда((( А ситуацию не сохранил, воспроизвести тоже не могу...

Как вариант. Проверьте наличие работы по "забытым" указателям.

Это легко приводит к порче стека и чемуугодно, в том числе завесу.

Для отлова аналогичного глюка (с вставкой строк и тд в вышеописанном стиле) помогло

перенос динамически выделеных массивов под static.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот пример моего)

У меня еще сохраняется и распечатывается кусочек из 8 значений стека, дабы можно было видеть, как дошли до жизни такой. То что у Вас творится это наверняка порушенный стек с возвратом неведомо куда :(.

Типа так:

Abort:[D] PC:0000BFD8 Op:E5315004 CPSR:00000092

LR:0000C564 SP:40001F88

SP[0]:00000000->00000000->00000000->0000C2E0->

SP[4]:00013413->00000000->E01FC0C4->0000BE58

R0:E59FF018 R1:259FF15C R2:E59FD1B8 R3:CB3FC1D0 R4:3967F46E R5:EFBFF1F0

R6:E0024000 R7:00000002 R8:4000006C R9:00000000 R10:00000001 R11:000007D7

R12:00002000

 

Может быть есть какая-то проблема именно с Cortex-M3 и именно с этой версией, о которой все знают, а я не знаю?

Относительно версий и проблем что-то может быть только в части порта. сравните, что там в 9 версии относительно Вашей поменяли, хотя думаю, что ничего.

Могу свой вариант порта на M3 выложить, то там ничего, насколько я помню, уникального нет.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Abort:[D] PC:0000BFD8 Op:E5315004 CPSR:00000092

LR:0000C564 SP:40001F88

SP[0]:00000000->00000000->00000000->0000C2E0->

SP[4]:00013413->00000000->E01FC0C4->0000BE58

R0:E59FF018 R1:259FF15C R2:E59FD1B8 R3:CB3FC1D0 R4:3967F46E R5:EFBFF1F0

R6:E0024000 R7:00000002 R8:4000006C R9:00000000 R10:00000001 R11:000007D7

R12:00002000

Давно в эту ветку не заглядывал, а оказывается здесь появились ответы :rolleyes: Вам не сложно выложить свой обработчик hard_fault'a?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Касательно FreeRTOS, проверьте приоритеты прерываний, в которых используются системные вызовы.

С FreeRTOS пока не знаком, но например в uCOS функции ОС из ISR-ов просто так вызывать нельзя. Надо такие вызовы обрамлять IsrEnter()/IsrExit().

Возможно в FreeRTOS сделано аналогично.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давно в эту ветку не заглядывал, а оказывается здесь появились ответы :rolleyes: Вам не сложно выложить свой обработчик hard_fault'a?

Собственно обработчик примитивен - он копирует в нециализируемую область памяти все, что считает нужным, выставляет сигнатуру записанной информации и перезагружает контроллер.

Ну и при запуске уже все это распечатывается, как удебно, в любом виде.

 

 

Возможно в FreeRTOS сделано аналогично.

Естественно, что некоторые функции нельзя вызывать из обработчиков, посему есть отдельная группа функций "FromISR". Но это не "универсальное обрамление", а именно специальные функции.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Естественно, что некоторые функции нельзя вызывать из обработчиков, посему есть отдельная группа функций "FromISR". Но это не "универсальное обрамление", а именно специальные функции.

Речь не о функциях, которые нельзя вызывать из ISR (их вызывать по-любому нельзя хоть с обрамлением хоть без, так как это например функции ожидания какого-то объекта синхронизации), а о функциях которые можно вызывать из ISR.

Но всё равно вызовы таких функций ОС должны быть обрамлены парой вызовов OSIntEnter()/OSIntExit(). Первая просто инкрементирует флаг, говорящий что находимся внутри как минимум одного ISR. Вторая - декрементирует этот флаг и если он стал ==0 вызывает функцию OS_SchedNew() - это решедулер просматривающий список задач, выбирающий из них наиболее приоритетную готовую к выполнению и подготавливает её к активации по PendSV.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Речь не о функциях, которые нельзя вызывать из ISR....

Да, конечно. Я о том функционале, использование которого принципиально возможно. Тогда это ДРУГИЕ функции ОПТИМАЛЬНО делающие свое дело, а не обернутые универсальные, как в uCOS.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...