реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> STM32L151 Hardfault как найти причину ?
MiklPolikov
сообщение Mar 1 2016, 18:01
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Стабильно попадаю в Hardfault.
Используется FreeRTOS
При раскидывание по коду метки xxx_error=1 ; xxx_error=2 .... Hardfault исчезает, но конкретного места это не выдаёт.

При попадании в Hardfault под отладкой:
- в Call Stuck Window пусто, один Hardfault
Регистры ядра
SCB - > CFSR=0x00000400
SCB - > HFSR=0x40000000
т.е стоят биты:
Bit 10 IMPRECISERR: Imprecise data bus error
When the processor sets this bit to 1, it does not write a fault address to the BFAR.
This is an asynchronous fault.
Bit 30 FORCED: Forced hard fault
Indicates a forced hard fault, generated by escalation of a fault with configurable priority that
cannot be handles, either because of priority or because it is disabled:
When this bit is set to 1, the hard fault handler must read the other fault

Вопрос: как искать причину такого глюка ?
Что вообще может быть причиной ?

Заранее спасибо !


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 1 2016, 18:33
Сообщение #2


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Искать так же, как в 500-х описанных ранее случаев.
1. Это не все регистры, отвечающие за ошибки.
2. Нужно из стека извлечь адрес команды, на которой произошел сбой.


Сообщение отредактировал IgorKossak - Mar 1 2016, 19:11
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 1 2016, 18:37
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(ViKo @ Mar 1 2016, 21:33) *
Искать так же, как в 500-х описанных ранее случаев.
1. Это не все регистры, отвечающие за ошибки.
2. Нужно из стека извлечь адрес команды, на которой произошел сбой.


Есть ещё регистр адреса- но в нём нет значения, т.к. не выставлен соответствующий бит.
Как из стека извлечь адрес ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 1 2016, 19:25
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(MiklPolikov @ Mar 1 2016, 21:37) *
Есть ещё регистр адреса- но в нём нет значения, т.к. не выставлен соответствующий бит.
Как из стека извлечь адрес ?

Насчет L151 конкретно не знаю, но обычно регистров больше.
Из стека адрес - много раз показывали. Лучше в книжку Джозефа Ю заглянуть, там будет расписано и программа дана. И здесь поиском по форуму тоже. Есть два регистра стека, какой-то из них использован, к значению этого стека прибавить 24...
Код
__asm void HardFault_Handler(void)
{
  TST LR, #4
  ITE EQ
  MRSEQ R0, MSP        ; Main Stack was used, put MSP in R0
  MRSNE R0, PSP        ; Process Stack was used, put PSP in R0
  LDR R0, [R0, #24]    ; Get stacked PC from stack
  B .
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 1 2016, 22:46
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Я нашел для себя примитивное решение:
Код
void HardFault_Handler(void)
{
    volatile int i = 0;
    while(!i)
       ;
}
Обнаружив прграмму в этом цикле переключаюсь в режим дизассемблера, изменяю значение i на 1 и выхожу из исключения. Попадаю на вызвавшую исключение команду. Дальше уже головой.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 2 2016, 06:55
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Скажем так. Есть 2 вида вылета.
Первый происходит закономерно в одном и том же месте. Как правило это либо обращение по не выровненному адресу или обращение по несуществующему адресу. То есть неверный расчёт указателя при работе с указателями. Такой вылет найти просто. Вам надо найти место где он происходит (например способом предложенным Сергей Борщ). Потом поставить точку останова пораньше и пройти по шагам, анализируя работу.
Второй - непредсказуемый вылет в произвольном месте. Как правило, причина - неверный размер стека. Либо при работе с буферами неверно рассчитан его размер. То есть, в месте, где реально происходит ошибка, вылета нет, там просто портятся данные. А вылет происходит там где вы пытаетесь воспользоваться уже испорченными данными.
Тут рекомендуется:
1. Существенно увеличить размеры стека для разных задач. Пробовать останавливать и контролировать реальные размеры стеков.
2. Попытаться локализовать задачу где происходит вылет. Или место. Посмотреть какую-то статистику.
---
Например я во FreeRTOSConfig добавил следующую строку
// для отладки. слежение за задачей
#define traceTASK_SWITCHED_IN() *(uint32_t*)0x40002868 = pxCurrentTCB->uxTCBNumber
(не обращайте внимание на прямой адрес. В программе у меня Вы этого больше нигде не увидите. Просто если добавляешь в исходники FreeRTOS заголовочные файлы, то там конфликты - я пытался этого избегать.)
На самом деле это следующее
// Номер задачи, которая последней выполнялась перед вылетом по ошибке
#define NBRTASKFAULT RTC->BKP6R
Сама traceTASK_SWITCHED_IN вызывается во FreeRTOS в vTaskSwitchContext
Далее
Код
void HardFault_Handler(void)
{
  StatusTM3->nbrTskFlt = NBRTASKFAULT & 0x1f;    // записать номер вылетевшей программы
  StatusTM3->fHardFault = TRUE;                    // установить признак
  DelayMs(TIM_SMALLWAIT,100);                    // Задержка
  NVIC_SystemReset();                            // Начать сначала
}
Go to the top of the page
 
+Quote Post
romas2010
сообщение Mar 2 2016, 19:13
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515



Цитата(MiklPolikov @ Mar 1 2016, 21:01) *
Стабильно попадаю в Hardfault.
Используется FreeRTOS
При раскидывание по коду метки xxx_error=1 ; xxx_error=2 .... Hardfault исчезает, но конкретного места это не выдаёт.

При попадании в Hardfault под отладкой:
- в Call Stuck Window пусто, один Hardfault
......
Заранее спасибо !


Обычно такое происходит если
-невыровненые данные,когда команды ldm/stm
- pop{...,pc} где по смещению места регистра возврата в стеке почему-то левое значение,что-то гадит стек(особенно актуально для RTOS)..помогает увеличение зазмера стека задачи,но на самотек не пускать все равно..кстати,это самая гадкая ситуация-ведь регистр РС может находиться в диапазоне адресов вашей же программы и ваша же программа еще продолжает таки какое-то время работать и обеспечит вам напряженный день и бессонную ночь....
- смотрите также значение регистров r0-r3 они сохраняются при прерывании и иногда используются компилятором(keil) для хранения указателей,возможно обращение за гранью памяти..разберитесь,почему они вдруг указывают на левый адрес,что-то с алгоритмом вашим не так

да,весьма хорошую тему предложил Сергей Борщ...по крайней мере можно попытаться локализовать место возникновения..но и keil тоже продвинутая среда-окно CALL STACK->курсор мыши на функцию+правая кнопка->show caller code

Сообщение отредактировал romas2010 - Mar 2 2016, 19:29
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 3 2016, 07:46
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(SasaVitebsk @ Mar 2 2016, 09:55) *
Второй - непредсказуемый вылет в произвольном месте. Как правило, причина - неверный размер стека. Либо при работе с буферами неверно рассчитан его размер. То есть, в месте, где реально происходит ошибка, вылета нет, там просто портятся данные. А вылет происходит там где вы пытаетесь воспользоваться уже испорченными данными.


Вот этого не понимаю. Почему место "произвольное" ? Оно ведь всё равно должно быть конкретное, при какой-то конкретной операции ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 3 2016, 10:35
Сообщение #9


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Mar 2 2016, 01:46) *
Я нашел для себя примитивное решение:
Код
void HardFault_Handler(void)
{
    volatile int i = 0;
    while(!i)
      ;
}
Обнаружив прграмму в этом цикле переключаюсь в режим дизассемблера, изменяю значение i на 1 и выхожу из исключения. Попадаю на вызвавшую исключение команду. Дальше уже головой.

А без переменной, просто задать while (true)? (Т.е. команду B .) А потом, зайдя под отладчиком, передвинуть счетчик команд на следующую команду, return (BX).
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 3 2016, 10:40
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(MiklPolikov @ Mar 3 2016, 10:46) *
Вот этого не понимаю. Почему место "произвольное" ? Оно ведь всё равно должно быть конкретное, при какой-то конкретной операции ?

Например в одной задаче вы заполняете буфер локальный. размер выбран неверно, либо просто ошибка. Вы вылазите за пределы локального стека и портите стек второй задачи.
При переключении на задачу с запорченным стеком у вас будут непредсказуемые события. Может запустится неизвестно что неизвестно откуда. В конечном итоге произойдёт крах проги с вылетом по Hard Fault. Только смотреть там будет нечего. Так как ошибка произошла совершенно не в этом месте.
Что тут не понятного?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 3 2016, 12:12
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Mar 3 2016, 12:35) *
А без переменной, просто задать while (true)? (Т.е. команду B .) А потом, зайдя под отладчиком, передвинуть счетчик команд на следующую команду, return (BX).
Я использую достаточно умные компиляторы, они не ставят BX после бесконечного цикла.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Mar 3 2016, 13:25
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(Сергей Борщ @ Mar 3 2016, 15:12) *
Я использую достаточно умные компиляторы, они не ставят BX после бесконечного цикла.


Я тоже так делаю, только делаю условный цикл и в отладчике меняю условие для выхода sm.gif
А еще трассировку делаю. Создаю массив структур. Массив размером 2^Х. В интересных точках записываю данные в поля структуры и передвигаю индекс. Индекс движется по кругу. Статическая переменная индекс показывает место начала и конца.
Этот способ я сам придумал, но в одном проекте видел как делали трассировку при помощи логического анализатора. В интересных местах в свободные порты писали интересующие значения, а анализатором их захватывали.
Go to the top of the page
 
+Quote Post
adnega
сообщение Mar 3 2016, 20:44
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(MiklPolikov @ Mar 1 2016, 21:01) *
Вопрос: как искать причину такого глюка ?
Что вообще может быть причиной ?

Я бы начал с проверки корректности указания приоритетов прерываний.
Помню давным давно тут обсуждали. В варианте FreeRTOS из коробки не хватало одной волшебной строчки.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Mar 7 2016, 08:11
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(SasaVitebsk @ Mar 2 2016, 09:55) *
Например я во FreeRTOSConfig добавил следующую строку
// для отладки. слежение за задачей
#define traceTASK_SWITCHED_IN() *(uint32_t*)0x40002868 = pxCurrentTCB->uxTCBNumber
(не обращайте внимание на прямой адрес. В программе у меня Вы этого больше нигде не увидите. Просто если добавляешь в исходники FreeRTOS заголовочные файлы, то там конфликты - я пытался этого избегать.)


SasaVitebsk, спасибо ! Отслеживать последнюю задачу в vTaskSwitchContext отличный метод !
Только я не смог понять что такое "номер задачи"
Поэтому в том же месте сохраняю её имя pxCurrentTCB->pcTaskName


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Mar 10 2016, 05:57
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(MiklPolikov @ Mar 7 2016, 11:11) *
Только я не смог понять что такое "номер задачи"

Я просто в IAR работаю. Там есть плагин для FreeRTOS. Номер задачи, это её номер запуска по сути. Я вижу список задач и их параметры, например, адреса стека задачи.
Это даёт мне возможность просмотреть память в нужном месте. То есть увидеть насколько правильно я распределил память. Ну и вообще.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 05:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016