|
Hard Fault Exception на кортексе м3, как узнать откуда прилезло |
|
|
|
 |
Ответов
(45 - 59)
|
Mar 31 2017, 09:32
|

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

|
Цитата(jcxz @ Mar 31 2017, 12:13)  У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте. Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код. А не надо думать про стек. При шаге - возврате из обработчика - попадете туда, откуда упали. Цитата(jcxz @ Mar 31 2017, 12:13)  Но на практике почему-то случаются такие ошибки (в том числе и HF), которые проявляются почему-то только у заказчика  Летом было. На скорую руку поправил одну функцию, типа, улучшил, по требованию. Проверил - работает, да и забыл про нее. Отправили 10 приборов в Нижний Новгород. Там они все "зависли намертво". Вернулись назад. Причину нашел быстро. Если бы там были лучшие умельцы, могли бы обновить программу сами. Но таковых не оказалось. Я уже заподозрил в попытке взлома...
|
|
|
|
|
Mar 31 2017, 09:38
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(jcxz @ Mar 31 2017, 12:13)  У Cortex есть неточные ошибки с памятью (Imprecise Bus Fault). Так Вы их место не найдёте. А через регистры - найдёте. Я не противопоставлял такой вариант обработчика просмотру содержимого регистров - скорее одно дополняет другое. Вывалились в обработчик посмотрели регистры, вернулись обратно (так сказать с комфортом) и посмотрели как содержимое регистров использовалось в момент вылета. Вот собственно и все. Цитата Да и очень неудобно каждый раз вспоминать где какой стек, лучше иметь готовый код. ViKo уже ответил, все произойдет само - вернетесь туда откуда выпали, вне зависимости от используемого стека.
|
|
|
|
|
Mar 31 2017, 09:46
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ViKo @ Mar 31 2017, 11:32)  А не надо думать про стек. При шаге - возврате из обработчика - попадете туда, откуда упали. Не обязательно. Прочитайте про неточные ошибки с памятью. Fault может произойти через несколько команд после места ошибки. Когда уже может выполняться другая функция или даже другая задача ОС или ISR. Возвращаетесь так по LR, а в том месте даже команд обращения к памяти вообще нет.  Цитата(ViKo @ Mar 31 2017, 11:32)  Вернулись назад. Причину нашел быстро. Если бы там были лучшие умельцы, могли бы обновить программу сами. Но таковых не оказалось. Я уже заподозрил в попытке взлома...  Надо делать удалённое обновление. Цитата(Шаманъ @ Mar 31 2017, 11:38)  ViKo уже ответил, все произойдет само - вернетесь туда откуда выпали, вне зависимости от используемого стека. И Вам тоже - читать мануал на ядро Cortex-M. Плюс - набраться опыта в отладке и ловле fault-ов. Или тут все только с Cortex-M0 работают где нет кешей и буферов отложенной записи и т.п.? Ну так и это ненадолго.
|
|
|
|
|
Mar 31 2017, 10:17
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ViKo @ Mar 31 2017, 12:07)  Этот выход указывает, в какой функции глюк. А дальше я уже по исходнику смотрю, что там может быть не так. да ну?  Вот Вы видите что выход произошёл на: MOVS R0, #1 ADDS R1, #2 LSLS R1, R1, #1 ITT MI MOVSMI R2,#1 MOVSMI R3,#2 ... и ещё пару десятков подобных команд до этого. И где же глюк? Даже ни одного обращения к памяти нету. А глюк оказывается был вообще в другой задаче, из которой управление только, что было передано сюда (например - переполнение её стека, запись в несуществующую/запрещённую память как раз в момент сохранения контекста, которая из-за наличия отложенной записи выдала Imprecise Bus Fault). Или он вообще был в ISR, который только что завершился BX LR. Или наоборот - это код в ISR, который только что прервал задачу, в которой и произошёл данный сбой. И где точно - Вы не знаете так как неточная ошибка памяти она на то и неточная - что где-то за несколько команд или десяток команд ранее случилась до входа в fault.
|
|
|
|
|
Mar 31 2017, 10:31
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(jcxz @ Mar 31 2017, 12:46)  Не обязательно. Прочитайте про неточные ошибки с памятью. Fault может произойти через несколько команд после места ошибки. Когда уже может выполняться другая функция или даже другая задача ОС или ISR. Возвращаетесь так по LR, а в том месте даже команд обращения к памяти вообще нет.  И Вам тоже - читать мануал на ядро Cortex-M. Плюс - набраться опыта в отладке и ловле fault-ов. Или тут все только с Cortex-M0 работают где нет кешей и буферов отложенной записи и т.п.? Ну так и это ненадолго.  Вы претендуете на наличие у Вас универсального решения? Так сказали "а", говорите "б" - рассказывайте, чтобы и кэши учитывались и несколько комманд и т.д., или Вы чисто поговорить? Я на наличие универсального решения не претендовал. 99% разных fault отлавливаются приведенным выше алгоритмом. Если fault произошел не в той команде куда возвратились смотрим, что было до нее. Если совсем туго, то смотрим в регистр BFSR, оттуда можно почерпнуть полезной инфы в том числе произошла ли ошибка по адресу возврата или нет. Ну и если так ничего и не понятно через регистр ACTLR можно поотключать разные улучшатели и сделать из М7 почти что М0  Но, по моему опыту (М3/М7) обычно все отлавливается после возврата простым анализом 5..10 комманд до точки возврата.
|
|
|
|
|
Mar 31 2017, 13:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(Шаманъ @ Mar 31 2017, 13:31)  Но, по моему опыту (М3/М7) обычно все отлавливается после возврата простым анализом 5..10 комманд до точки возврата. В подавляющем большинстве подобных случаев в этой злополучной строке будет обращение по указателю, особенно с приведением к другому типу. Например, как тут: Код if(--(*(MyClass*)p) ) Такой набор символов сходу и прочитать-то правильно сложно, а уж ошибиться - подавно )) Короче, при HF первым делом нужно проверять (в порядке важности): отсутствие любых предупреждений при компиляции (иногда даже стоит ужесточить условия их формирования), должно быть "Warinigs: 0" объем стека/стеков и кучи, конкурентный доступ к переменным из кода и прерываний (особое внимание обратить на глобальные переменные, которые используются в прерываниях), все указатели, а особенно те, которые используются с приведением типа, доступ к не инициализированным локальным переменным, если есть RTOS и используются приоритеты прерываний, то убедится, что нет вызовов сервисов оси из обработчиков, приоритет прерываний которых выше значения, заданного в настройках оси (FreeRTOS), ну и может еще что, с ходу не вспомню ))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Mar 31 2017, 14:01
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(jcxz @ Mar 31 2017, 16:11)  Читайте выше. Из соответствующих регистров можно прочитать реальный адрес где произошёл fault. В смысле мне себя почитать? Цитата(Шаманъ @ Mar 31 2017, 12:38)  Вывалились в обработчик посмотрели регистры, вернулись обратно (так сказать с комфортом) и посмотрели как содержимое регистров использовалось в момент вылета. Цитата(Forger @ Mar 31 2017, 16:39)  В подавляющем большинстве подобных случаев в этой злополучной строке будет обращение по указателю, особенно с приведением к другому типу. Например, как тут: Код if(--(*(MyClass*)p) ) Я обычно в таких случаях смотрю ассемблерный код - это намного продуктивнее.
|
|
|
|
|
Mar 31 2017, 14:11
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(Шаманъ @ Mar 31 2017, 17:01)  Я обычно в таких случаях смотрю ассемблерный код - это намного продуктивнее. А я под словом "продуктивный" понимаю такой код, который вообще исключает всякую необходимость рыться в "белье" компилятора  Сложные выражения предпочитаю разбить на примитивные, так и отлаживать проще. Зачастую это в итоге вынуждает переписать код, отказавших от мудреных конструкций со "звездочками". В итоге это экономит кучу времени, которое в ином случае было бы потрачено на поиск причин трудноуловимых багов.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|