MiklPolikov 0 1 марта, 2016 Опубликовано 1 марта, 2016 · Жалоба Стабильно попадаю в 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 Вопрос: как искать причину такого глюка ? Что вообще может быть причиной ? Заранее спасибо ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 марта, 2016 Опубликовано 1 марта, 2016 (изменено) · Жалоба Искать так же, как в 500-х описанных ранее случаев. 1. Это не все регистры, отвечающие за ошибки. 2. Нужно из стека извлечь адрес команды, на которой произошел сбой. Изменено 1 марта, 2016 пользователем IgorKossak Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 1 марта, 2016 Опубликовано 1 марта, 2016 · Жалоба Искать так же, как в 500-х описанных ранее случаев. 1. Это не все регистры, отвечающие за ошибки. 2. Нужно из стека извлечь адрес команды, на которой произошел сбой. Есть ещё регистр адреса- но в нём нет значения, т.к. не выставлен соответствующий бит. Как из стека извлечь адрес ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 марта, 2016 Опубликовано 1 марта, 2016 · Жалоба Есть ещё регистр адреса- но в нём нет значения, т.к. не выставлен соответствующий бит. Как из стека извлечь адрес ? Насчет 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 . } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 1 марта, 2016 Опубликовано 1 марта, 2016 · Жалоба Я нашел для себя примитивное решение: void HardFault_Handler(void) { volatile int i = 0; while(!i) ; } Обнаружив прграмму в этом цикле переключаюсь в режим дизассемблера, изменяю значение i на 1 и выхожу из исключения. Попадаю на вызвавшую исключение команду. Дальше уже головой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 2 марта, 2016 Опубликовано 2 марта, 2016 · Жалоба Скажем так. Есть 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(); // Начать сначала } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
romas2010 1 2 марта, 2016 Опубликовано 2 марта, 2016 (изменено) · Жалоба Стабильно попадаю в 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 Изменено 2 марта, 2016 пользователем romas2010 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба Второй - непредсказуемый вылет в произвольном месте. Как правило, причина - неверный размер стека. Либо при работе с буферами неверно рассчитан его размер. То есть, в месте, где реально происходит ошибка, вылета нет, там просто портятся данные. А вылет происходит там где вы пытаетесь воспользоваться уже испорченными данными. Вот этого не понимаю. Почему место "произвольное" ? Оно ведь всё равно должно быть конкретное, при какой-то конкретной операции ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба Я нашел для себя примитивное решение: void HardFault_Handler(void) { volatile int i = 0; while(!i) ; } Обнаружив прграмму в этом цикле переключаюсь в режим дизассемблера, изменяю значение i на 1 и выхожу из исключения. Попадаю на вызвавшую исключение команду. Дальше уже головой. А без переменной, просто задать while (true)? (Т.е. команду B .) А потом, зайдя под отладчиком, передвинуть счетчик команд на следующую команду, return (BX). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба Вот этого не понимаю. Почему место "произвольное" ? Оно ведь всё равно должно быть конкретное, при какой-то конкретной операции ? Например в одной задаче вы заполняете буфер локальный. размер выбран неверно, либо просто ошибка. Вы вылазите за пределы локального стека и портите стек второй задачи. При переключении на задачу с запорченным стеком у вас будут непредсказуемые события. Может запустится неизвестно что неизвестно откуда. В конечном итоге произойдёт крах проги с вылетом по Hard Fault. Только смотреть там будет нечего. Так как ошибка произошла совершенно не в этом месте. Что тут не понятного? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба А без переменной, просто задать while (true)? (Т.е. команду B .) А потом, зайдя под отладчиком, передвинуть счетчик команд на следующую команду, return (BX).Я использую достаточно умные компиляторы, они не ставят BX после бесконечного цикла. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба Я использую достаточно умные компиляторы, они не ставят BX после бесконечного цикла. Я тоже так делаю, только делаю условный цикл и в отладчике меняю условие для выхода :) А еще трассировку делаю. Создаю массив структур. Массив размером 2^Х. В интересных точках записываю данные в поля структуры и передвигаю индекс. Индекс движется по кругу. Статическая переменная индекс показывает место начала и конца. Этот способ я сам придумал, но в одном проекте видел как делали трассировку при помощи логического анализатора. В интересных местах в свободные порты писали интересующие значения, а анализатором их захватывали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 3 марта, 2016 Опубликовано 3 марта, 2016 · Жалоба Вопрос: как искать причину такого глюка ? Что вообще может быть причиной ? Я бы начал с проверки корректности указания приоритетов прерываний. Помню давным давно тут обсуждали. В варианте FreeRTOS из коробки не хватало одной волшебной строчки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 7 марта, 2016 Опубликовано 7 марта, 2016 · Жалоба Например я во FreeRTOSConfig добавил следующую строку // для отладки. слежение за задачей #define traceTASK_SWITCHED_IN() *(uint32_t*)0x40002868 = pxCurrentTCB->uxTCBNumber (не обращайте внимание на прямой адрес. В программе у меня Вы этого больше нигде не увидите. Просто если добавляешь в исходники FreeRTOS заголовочные файлы, то там конфликты - я пытался этого избегать.) SasaVitebsk, спасибо ! Отслеживать последнюю задачу в vTaskSwitchContext отличный метод ! Только я не смог понять что такое "номер задачи" Поэтому в том же месте сохраняю её имя pxCurrentTCB->pcTaskName Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 10 марта, 2016 Опубликовано 10 марта, 2016 · Жалоба Только я не смог понять что такое "номер задачи" Я просто в IAR работаю. Там есть плагин для FreeRTOS. Номер задачи, это её номер запуска по сути. Я вижу список задач и их параметры, например, адреса стека задачи. Это даёт мне возможность просмотреть память в нужном месте. То есть увидеть насколько правильно я распределил память. Ну и вообще. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться