Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обработка Faults на Cortex-Mx
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
AlexandrY
Цитата(haker_fox @ Jul 11 2018, 16:19) *
И я вас уверяю, что если даже ваш контроллер протестирован ни на один раз, у вас небыло зависаний и выпадений в hf, никто в единственном экземпляре не поставит его на тормоза поезда, или в дозатор. Как минимум сдублируют. Хотя, может быть исключения и есть.

Только хочу уточнить, что тестирование делается перед каждым включением двигателя, актуатора или еще чего.
Тестируются все критичные области RAM-а и все объекты RTOS, включая сервисы как менеджер памяти, межпроцессорный обмен и т.д.
Тестирование всего этого также повторяется с заданной периодичностью, хоть и раз в 10 мс.
haker_fox
QUOTE (AlexandrY @ Jul 11 2018, 21:15) *
Лучше их выловить отладочным адаптером заранее.

Но как? Вот сегодня у меня. LPC4337. FreeRTOS. 12 задач. Снаружи 4 АЦП, память SDRAM, дисплей, ethernet, rs-485, реле и прочая дребедень, свойственная промышленному контроллеру. Периодически, один раз на 10 одинаковых событий вылетает hardfault, либо портится память в произвольной задаче (структуры данных в классе). Вот как искать? MPU? Но ему же закалебёшься объяснять, какая память какой задаче принадлежит. Ловушка переполнения стека в оси не срабатывает. Call Stack ничего полезного мне не даёт, либо я не умею читать между строк. В итоге я полдня сидели и комментировал задачи, пришёл к работоспособному варианту, и методом научного тыка разобрался, что вызывало ошибку. А это было у меня под носом. Но
пока пришёл к этому, затратил немало времени.


QUOTE (AlexandrY @ Jul 11 2018, 21:24) *
Только хочу уточнить, что тестирование делается перед каждым включением двигателя, актуатора или еще чего.
Тестируются все критичные области RAM-а и все объекты RTOS, включая сервисы как менеджер памяти, межпроцессорный обмен и т.д.
Тестирование всего этого также повторяется с заданной периодичностью, хоть и раз в 10 мс.

Сигнатуры в ОЗУ? Тестовые блоки с CRC? Не представляю, как можно тестировать менеджер памяти, межпроцессный обмен. Вы, как я понимаю, подобным занимаетесь. Может быть напишите нам подробнее эти тонкости, если они не затронут ноу-хау. Просто иногда хочется лбом об стенку биться, ибо не знаешь, где искать)))
AlexandrY
Цитата(haker_fox @ Jul 11 2018, 16:26) *
Периодически, один раз на 10 одинаковых событий вылетает hardfault, либо портится память в произвольной задаче (структуры данных в классе). Вот как искать?

Как правильно ловить hardfault-ы - https://www.iar.com/support/tech-notes/debu...lt-on-cortex-m/

Цитата(haker_fox @ Jul 11 2018, 16:28) *
Сигнатуры в ОЗУ? Тестовые блоки с CRC? Не представляю, как можно тестировать менеджер памяти, межпроцессный обмен. Вы, как я понимаю, подобным занимаетесь. Может быть напишите нам подробнее эти тонкости, если они не затронут ноу-хау. Просто иногда хочется лбом об стенку биться, ибо не знаешь, где искать)))

Не, к счастью мне такого не надо пока применять.
Обходимся так называемой ABC релейной схемой. Дивайсы с ней легко проходят сертификацию и на софт даже не глядят.
Просто в MQX таких фичей по самодиагностике много, я их аккуратно обхожу и как они работают особо не разбирался.
Pavia
Цитата(haker_fox @ Jul 11 2018, 16:28) *
Но как? Вот сегодня у меня. LPC4337. FreeRTOS. 12 задач. Снаружи 4 АЦП, память SDRAM, дисплей, ethernet, rs-485, реле и прочая дребедень, свойственная промышленному контроллеру. Периодически, один раз на 10 одинаковых событий вылетает hardfault, либо портится память в произвольной задаче (структуры данных в классе). Вот как искать? MPU? Но ему же закалебёшься объяснять, какая память какой задаче принадлежит.

Всё просто, но закалебёшься. Берём и пишем Unit-тесты на все случае жизни. Должны быть данные и проверочный-код который зайдёт во все ветки кода. Ошероув Рой.-Искусство автономного тестирования.
А по мимо автономной проверок ещё и внутренние делаются.
Проверка данных по входу обязательна для всех внешних систем.

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

Цитата(haker_fox @ Jul 11 2018, 16:28) *
и методом научного тыка разобрался, что вызывало ошибку.

Последний раз мне здорово помогло логирование. В лог для каждой функции пишем время имя функции/класса и параметры полученные по входу.
Плюс внутрь функции пишется дам-данных того, что получено через порты.

Я вот что думаю можно сделать так. Один раз пишется небольшая утилита которая внутрь каждой функции добавляет вывод в лог. И так же убирает.
Место вставки элементарно подсчетом скобок определяется. Только для каждого класса надо будет добавить GetDebugString
Kabdim
Цитата(Pavia @ Jul 11 2018, 19:21) *
Всё просто, но закалебёшься.

И всё сломается на первом же забежавшем быстрым нейтроном. biggrin.gif
AlexandrY
Цитата(Pavia @ Jul 11 2018, 19:21) *
Ошероув Рой.-Искусство автономного тестирования.

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

Замедление разработки в ответственных системах скорее всего даже полезно.
Но в большинстве проектов где я участвовал за такой саботаж уволили бы.
jcxz
Цитата(haker_fox @ Jul 11 2018, 12:53) *
А если только MPU? Или у нас Cortex-M0 без оного?

Расчудесная и многими любимая фирма STMicroelectronics даже некоторые МК на Cortex-M3 умудряется делать без MPU. Видимо заботится о юзерах - чтоб мозги не перенапрягли, разбираясь в нём. biggrin.gif

Цитата(ViKo @ Jul 11 2018, 13:22) *
Есть не один способ сбросить МК без собаки. Зачем ждать, пока собака проснется?

Да знаем мы уже Ваш способ! этот способ - юзер с большим рубильником biggrin.gif

Цитата(Arlleex @ Jul 11 2018, 14:52) *
А если этот ваш МК стоит на приводе управления тормозами поезда? А если в самолете?

...то их (девайсов) должно быть как минимум 4-ро. Если один вздумал вольнодумничать - 3 других дадут ему по шее, так чтоб перезагрузился. А если пойдут 2 на 2, то попросят помощи у машиниста/пилота. biggrin.gif

Цитата(AlexandrY @ Jul 11 2018, 16:15) *
Ловить HardFault-ы в релизе во время эксплуатации нет особого смысла.
Слишком много информации надо зафиксировать о контексте события, слишком обременительно хранить историю версий и парсить многомегабайтные логи.
Лучше их выловить отладочным адаптером заранее.

Ну никто-ж не спорит, что лучше быть богатым и здоровым чем бедным и больным писать код сразу и без багов. Но что-то ни у кого это не получается. И при компиляции в RELEASE ненайденные баги не исчезают волшебным образом. laughing.gif

Цитата(AlexandrY @ Jul 11 2018, 16:24) *
Тестирование всего этого также повторяется с заданной периодичностью, хоть и раз в 10 мс.

Сдаётся мне, что попытка вытворить такое не уменьшит, а наоборот - увеличит вероятность наличия багов.

Цитата(haker_fox @ Jul 11 2018, 16:28) *
MPU? Но ему же закалебёшься объяснять, какая память какой задаче принадлежит.

Вообще - это возможно. Если каждая задача работает только со своими переменными.
Собираем эти переменные в свои регионы памяти: для каждой задачи - отдельный регион, куда линкуются только её переменные; в хуке переключателя контекста (в uCOS такой уже есть, но если и нет - можно просто вставить в имеющийся переключатель) при переключении на какую-то задачу закрываем всю память от записи (или вообще любого доступа) кроме региона этой задачи.
Но так редко бывает, чтобы задача работала только со своими переменными без взаимодействия с другими задачами. Хотя тут тоже есть варианты.
А изначально Вам следовало определить причину HF. И от неё уже танцевать.
Конечно бывает, что HF вызывает вторичная причина (первичная просто разрушила чью-то память не вызвав HF, а когда пользователь этих данных полез к ним, то у него и случился HF). Тут уже сложнее. Но тоже есть варианты решений.

Цитата(Pavia @ Jul 11 2018, 19:21) *
Место вставки элементарно подсчетом скобок определяется. Только для каждого класса надо будет добавить GetDebugString

Набежали, блин, PC-теоретики.... 05.gif

Цитата(AlexandrY @ Jul 11 2018, 21:30) *
Замедление разработки в ответственных системах скорее всего даже полезно.

Да я тоже считаю что лучше 5 раз сходить на кофе-паузу чем 2!!! Ведь чем меньше времени программист проводит за клавиатурой, тем меньше у него времени плодить баги! biggrin.gif
На прошлой работе у меня был коллега, так он так начальству и говорил: "Вот я сейчас лишние полчаса просидел в кафе, так я же это с целью ускорить разработку - иначе бы за это время успел написать баг, но поиски которого пришлось бы потратить несколько дней. А так - выпил лишнюю чашку кофе - и ускорил проект на несколько дней!" biggrin.gif
Arlleex
Цитата(jcxz @ Jul 12 2018, 00:01) *
Конечно бывает, что HF вызывает вторичная причина (первичная просто разрушила чью-то память не вызвав HF, а когда пользователь этих данных полез к ним, то у него и случился HF). Тут уже сложнее. Но тоже есть варианты решений.

А вот тут, пожалуйста, поподробнее. Интересно как ловятся такие эскалационные баги smile3046.gif В терминологии ARM, нсколько я помню, это называется "не точный отказ" (not exact fault).
haker_fox
QUOTE (jcxz @ Jul 12 2018, 04:01) *
Расчудесная и многими любимая фирма STMicroelectronics даже некоторые МК на Cortex-M3 умудряется делать без MPU. Видимо заботится о юзерах - чтоб мозги не перенапрягли, разбираясь в нём. biggrin.gif

Не работал с их МК старше Cortex-M0. А STM32F051 и подобные мне очень нравятся из-за богатых аппаратных возможнстей (система триггеров и передачи сигналов на запуск периферии). На "ура" на них делал источники тока с обратными связями, с многофазной системой синхронизации и т.п. Один из источников полностью программный. Т.е. связка таймер-ПДП-АЦП рулит ШИМ и обеспечивает цифровой ПИД-регулятор.
QUOTE (jcxz @ Jul 12 2018, 04:01) *
...то их (девайсов) должно быть как минимум 4-ро. Если один вздумал вольнодумничать - 3 других дадут ему по шее, так чтоб перезагрузился. А если пойдут 2 на 2, то попросят помощи у машиниста/пилота. biggrin.gif

Угу. Смотрим на схемы Aribus A320, Boeing 7x7 как самые доступные в инете. Впечатляемся, и идём читать настоящие книжки)


QUOTE (Arlleex @ Jul 12 2018, 12:44) *
А вот тут, пожалуйста, поподробнее. Интересно как ловятся такие эскалационные баги smile3046.gif В терминологии ARM, нсколько я помню, это называется "не точный отказ" (not exact fault).

+1, тоже интересно. А ведь может быть и три таких ступени)
jcxz
Цитата(Arlleex @ Jul 12 2018, 07:44) *
А вот тут, пожалуйста, поподробнее. Интересно как ловятся такие эскалационные баги smile3046.gif В терминологии ARM, нсколько я помню, это называется "не точный отказ" (not exact fault).

Вы не поняли. Я тут вовсе не говорил про эскалацию fault-ов. Баг не обязательно приводит к fault-у. Ну затёрла одна функция данные другой - с чего это может вызвать fault? А вот когда уже вторая функция начнёт пользоваться этими разрушенными данными, то может получиться fault. А может и не получиться, а порушатся данные третьей функции. И так далее. И когда это может привести к fault-у (а может и нет).
И вот - в конце концов получили этот fault, определили что он возник из-за того что в какой-то функции какие-то данные приняли недопустимое значение. Начинаем разбираться, а судя по коду - ну не может быть таких значений у этой функции. А всё потому что - это не первичный сбой. А первичную причину в таком случае установить уже гораздо сложнее, чем если бы первичная причина сразу вызвала fault.

А эскалация - это когда к примеру у Вас запрещён BusFault, но происходит причина его вызывающая и, так как он запрещён, то происходит эскалация до HF. У меня обработка всех fault-ов построена на эскалации до HF - так проще, чем писать кучу обработчиков с одинаковыми действиями. В ISR HF по регистрам всегда можно определить первоначальный источник, до эскалации.

И "неточный отказ" не имеет никакого отношения к эскалации. Это просто один из видов отказов по вектору BusFault. Неточный - это значит, что регистр адреса отказа не содержит точного адреса отказа. Например - из-за кеширования. Выполнили Вы запись в память, но из-за наличия буфера записи, данные не сразу физически запишутся в ОЗУ, а через некоторое время. И если эта запись вызовет fault, то PC к этому времени уже убежит на несколько инструкций. Вот тут и получите "неточный отказ".
Arlleex
Цитата(jcxz @ Jul 12 2018, 16:29) *
А эскалация - это когда к примеру у Вас запрещён BusFault, но происходит причина его вызывающая и, так как он запрещён, то происходит эскалация до HF. У меня обработка всех fault-ов построена на эскалации до HF - так проще, чем писать кучу обработчиков с одинаковыми действиями. В ISR HF по регистрам всегда можно определить первоначальный источник, до эскалации.

Ну да. На самом деле-то вот что интересно: вообще возможно ли сделать так, чтобы "вычислить" начальное место, откуда пошло затирание памяти rolleyes.gif Вангую, что нет biggrin.gif
Разве что всегда при входе проверять аргументы на заданные диапазоны (указатели тем более) и в случае чего делать assert() с тем же вызовом SVC и записью в журнал. Да и не совсем очевидно, что делать, если в функцию пришли не ожидаемые параметры (к пример, слишком большой объем запрашиваемых данных на копирование) - совсем не отрабатывать (прямой return из функции), копировать по максимальному ожидаемому размеру, и т.д. Обычно такие ситуации я передаю наверх по стеку вызовов и там уже на уровне логики принимаю решение - делать ли перезапрос, например laughing.gif
А вот насчет порчи памяти третьим лицом (функцией в нашем случае) - вещь тоже довольно интересная, случалось сталкиваться с таким, причем даже с отладчиком порой можно просидеть день, ничего не надебаживши. Правда в таких случаях меня все-таки спасают assert-ы по входу функций. Сразу видно кому снесло голову.
jcxz
Цитата(haker_fox @ Jul 12 2018, 08:10) *
Один из источников полностью программный. Т.е. связка таймер-ПДП-АЦП рулит ШИМ и обеспечивает цифровой ПИД-регулятор.

В XMC4xxx можно периферию связывать между собой ещё более аппаратно - даже без использования DMA, который вносит непредсказуемую задержку.
Например в текущем проекте у меня передача блока данных по UART запускается сигналом от таймера (аппаратным сигналом без всяких DMA). Это позволяет устройству-приёмнику синхронизировать свои часы с передатчиком с точностью до такта CPU. С DMA такое не сделаешь.
Или например: АЦП по нескольким каналам измеряет и суммирует данные с большой скоростью, но пропускает окна из заданного числа тактов вокруг интервалов мёртвого времени от 3-фазного ШИМ (сигналы у переключении ключей на время замораживают АЦП), убирая таким образом из измерений помехи в моменты переключения мощной нагрузки.
Да ещё много что возможно. sm.gif

Цитата(Arlleex @ Jul 12 2018, 15:41) *
Ну да. На самом деле-то вот что интересно: вообще возможно ли сделать так, чтобы "вычислить" начальное место, откуда пошло затирание памяти rolleyes.gif Вангую, что нет biggrin.gif

В общем случае нет, но в части таких случаев - возможно. Нужны соответствующие инструменты.
Вот тут коллега haker_fox (вроде?) писал, что работает с LPC43xx. Так в нём есть ETB. Он позволяет сделать обратную отладку. И если со времени первопричины прошло не очень много времени, то так можно найти её.
Ну или эмулировать возможности ETB программно: у меня например для этого во многих проектах реализован "Монитор выполнения" - это высокочастотное периодическое прерывание, в котором в FIFO фиксируются регистры CPU и верхушка стека. Он не раз мне тоже помогал находить такие сложные ошибки с разрушением памяти.

Цитата(Arlleex @ Jul 12 2018, 15:41) *
А вот насчет порчи памяти третьим лицом (функцией в нашем случае) - вещь тоже довольно интересная, случалось сталкиваться с таким

А мне даже очень часто случалось сталкиваться. Потому что работаю обычно в команде, и это третье лицо очень часто - один из коллег. Вот это самая засада, когда у тебя начинает глючить совершенно на ровном месте когда ты ничего не менял даже. Просто накосячил один из коллег... crying.gif
Arlleex
Цитата(jcxz @ Jul 12 2018, 16:51) *
А мне даже очень часто случалось сталкиваться. Потому что работаю обычно в команде, и это третье лицо очень часто - один из коллег. Вот это самая засада, когда у тебя начинает глючить совершенно на ровном месте когда ты ничего не менял даже. Просто накосячил один из коллег...

Вот тут я Вас очень даже понимаю. Бывает над одним проектом работает несколько человек и у каждого "работает все".
Про ETB спасибо, кстати, надо бы до конца поразбираться со всякими CoreSight финтиклюшками - ITM, TPIU, ETB (Embedded Trace Bus который) и т.д. А то может уже все придумали давно а мы я не пользуемся(-юсь) sad.gif
jcxz
Цитата(Arlleex @ Jul 12 2018, 16:15) *
ETB (Embedded Trace Bus который)

Embedded Trace Buffer
Kabdim
Цитата(Arlleex @ Jul 12 2018, 15:41) *
"вычислить" начальное место, откуда пошло затирание памяти rolleyes.gif Вангую, что нет biggrin.gif

Вычислять нет, разрабатывать так что бы этого не происходило возможно. Использовать Ubsan, например, да и в целом поменьше указателей, побольше контейнеров. Вот только запас по памяти и быстродействию должен быть большим что бы включить и радоваться.
AlexandrY
Цитата(jcxz @ Jul 11 2018, 23:01) *
Ну никто-ж не спорит, что лучше быть богатым и здоровым чем бедным и больным писать код сразу и без багов. Но что-то ни у кого это не получается. И при компиляции в RELEASE ненайденные баги не исчезают волшебным образом. laughing.gif

Сдаётся мне, что попытка вытворить такое не уменьшит, а наоборот - увеличит вероятность наличия багов.

Вопрос не куда деваются баги, а где и когда их лучше искать.
Просто включить логику и осознать целесообразность. При полной неопределенности целесообразней искать там где удобно.
А напрягать юзеров и техподдержку логами не имеет смысла. Я на этом обжегся.
Во-первых юзеры устраивают истерику когда просишь логи, а тех.поддержка почитав логи начинает косо смотреть и требовать расшифровщик логов для их уровня интеллекта
и даже начинают требовать что писать и что не писать в логи.

Второе, искать надо там где бОльшая вероятность. И я согласен с ST, что самый чувствительный участок - это RAM. RAM занимает самую большую площадь на чипе.
А сбои в RAM-е имеют свойство накапливаться. Поэтому чем чаще тестируете RAM тем меньше накопленных ошибок будет.

Ну и последняя модная фишка от IAR 8.20 - стековые канарейки (stack canaries)
Такая фича компилера, когда он автоматом вставляет некую проверку стека на целостность в каждую подозрительную функцию.

Кста, если кто забыл. Есть еще такая фича у IAR как С-RUN Runtime Checking, тож проверяет кучу косяков в риалтайме как и Ubsan
haker_fox
QUOTE (AlexandrY @ Jul 13 2018, 03:40) *
Ну и последняя модная фишка от IAR 8.20 - стековые канарейки (stack canaries)
Такая фича компилера, когда он автоматом вставляет некую проверку стека на целостность в каждую подозрительную функцию.

Прямо сейчас внедрил в проект этот инструмент. Пусть будет. Вдруг поймает что-то.
AlexandrY, я, как понял, вы IAR только используете?
AlexandrY
Цитата(haker_fox @ Jul 13 2018, 04:27) *
Прямо сейчас внедрил в проект этот инструмент. Пусть будет. Вдруг поймает что-то.
AlexandrY, я, как понял, вы IAR только используете?

Нет не только. Сейчас в активной поддержке у меня проекты в Keil 4, Keil 5, IAR 7 , MPLAB
А вот как раз на 8-й IAR я еще не перешел. Жду плагина под MQX.
jcxz
Цитата(AlexandrY @ Jul 13 2018, 13:21) *
Нет не только. Сейчас в активной поддержке у меня проекты в Keil 4, Keil 5, IAR 7 , MPLAB
А вот как раз на 8-й IAR я еще не перешел. Жду плагина под MQX.

А что - с 7-го IAR на 8-й надо как-то переходить? wacko.gif
У меня довольно большой проект нормально компилится и работает как под IAR7.80 так и под IAR8.20. И разницы в работе не заметно. Разве что в размере кода небольшая.
haker_fox
QUOTE (AlexandrY @ Jul 13 2018, 18:21) *
Жду плагина под MQX.

Странно, что NXP купив Freescale не портировал MQX на LPC серию.
Kabdim
Зато они сменили лицензию на 5 версию. За деньги что-нибудь может и будет портировано.
Arlleex
Кстати, коллеги.
А нормальная ли практика фиксировать критические события во внутреннюю Program Flash МК? Обычно для внутрисистемных (внутри МК, в смысле) ошибок не требуется много памяти. Выделить два куска по N кБ и цикличный автомат журналирования организовать (чтобы при потере питания последние записи не потерлись). А то я, конечно, сам ставлю на все устройства внешнюю память, но интересует опыт (положительный/отрицательный) журналирования в набортную память МК. ИМХО, если не злоупотреблять printf() с прямым текстом в лог и только регистровые фреймы хранить, самое оно.
AlexandrY
Цитата(Arlleex @ Jul 17 2018, 12:03) *
Кстати, коллеги.
А нормальная ли практика фиксировать критические события во внутреннюю Program Flash МК? Обычно для внутрисистемных (внутри МК, в смысле) ошибок не требуется много памяти. Выделить два куска по N кБ и цикличный автомат журналирования организовать (чтобы при потере питания последние записи не потерлись). А то я, конечно, сам ставлю на все устройства внешнюю память, но интересует опыт (положительный/отрицательный) журналирования в набортную память МК. ИМХО, если не злоупотреблять printf() с прямым текстом в лог и только регистровые фреймы хранить, самое оно.

Расскажите лучше как вы по регистровым фреймам способны хоть что-то понять о причине сбоя. lol.gif
aaarrr
Цитата(Arlleex @ Jul 17 2018, 12:03) *
А нормальная ли практика фиксировать критические события во внутреннюю Program Flash МК?

Не лучший вариант, если принять во внимание сложность реализации и возникающую привязку к железу.
EEPROM стоит копейки, ни к чему экономить.

Цитата(AlexandrY @ Jul 17 2018, 12:09) *
Расскажите лучше как вы по регистровым фреймам способны хоть что-то понять о причине сбоя. lol.gif

Аншлаг прям.
jcxz
Цитата(Arlleex @ Jul 17 2018, 12:03) *
А то я, конечно, сам ставлю на все устройства внешнюю память, но интересует опыт (положительный/отрицательный) журналирования в набортную память МК.

Во всех устройствах, где надо было вести журналов сбоев, до сих пор располагал его только во FRAM/MRAM.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.