Цитата(Arlleex @ Jul 7 2018, 18:39)

А что делаете с тяжелыми отказами, отказами шины и прочими?
Определил для себя понятие "критическая ошибка". Это такая ошибка, возникновение которой не предусмотрено при создании программы, неизвестно "что делать?" при её возникновении и невозможно продолжать штатное функционирование устройства.
Такие ошибки у меня могут возбуждаться как аппаратными событиями (исключение от MPU при попытке недопустимого доступа к памяти, всяческие прочие HF (и Bus fault-ы и user fault-ы - для всех у меня делается эскалация до Hard Fault с общим обработчиком HF)); так могут вызываться и программно (набор функций trap(...)) если какая-то часть программы обнаружила недопустимое состояние (для каждого программного модуля/драйвера - свой класс возбуждаемых trap-ов). Обработчик trap() у меня висит на SVC.
При возникновении любого типа критической ошибки я делаю:
Защёлкиваю тип и ID критической ошибки состояние выполнения (регистры CPU, N слов от вершины стека), для программного trap() также защёлкиваю аргументы вызова. Для некоторых типов критических ошибок (например: неожиданное прерывание (которого не должно быть)) защёлкиваю состояние выполнения (регистры/стек) не текущего контекста, а прерванного. Далее - делаю базовый инит (выкл. всей периферии, останов DMA, инит базовой периферии - MPU и пр.) и дальше - в зависимости от состояния соответствующего ключа компиляции:
1) компиляция DEBUG: переход устройства в спец.режим "TRAP" - инит тактирования (PLL и пр.) для этого режима (минимальные частоты), инит отладочного UART, и циклический, раз в секунду, вывод "синего экрана смерти" - периодический дамп всех защёлкнутых данных в UART в текстовом виде; устройство находится в режиме TRAP до внешнего сброса/выкл. питания, обеспечивая фиксацию состояния ошибки.
2) компиляция RELEASE: аппаратный reset устройства.
И для того и для другого случая, копирую защёлкнутую инфу в спец. область памяти, которая не будет стёрта при reset-е, снабжаю её флагом и CRC. И, если устройство имеет non-volatile память, то после штатного рестарта, после начального инита периферии, эта инфа переписывается в журнал критических сбоев в этой non-volatile памяти.
Цитата(Arlleex @ Jul 7 2018, 18:39)

Но ведь может быть такое, что устройство уже стоит у заказчика и частично подлежит отладке на объектах. И оно должно продолжить функционирование. Как обрабатывать тогда ошибки?
Если ошибка может быть обработана и устройство может продолжать после этого нормально функционировать - это уже не критическая ошибка, а штатная работа. И механизм критической ошибки здесь не использую.
Цитата(Arlleex @ Jul 7 2018, 18:39)

Сейчас мне видится вариант с сохранением лога событий в памяти (допустим, SD карты) и перезагрузкой МК.
В момент ошибки у Вас устройство уже работает, куча разной периферии/DMA работают, и если при этом произошла ошибка, то в этом окружении уже опасно дальше что-то делать, иначе можно получить каскад таких сбоев. Лучше просто защёлкнуть как можно быстрее инфу об ошибке
в ОЗУ и сделать начальный инит периферии к минимальному функциональному состоянию - минимуму работающей периферии необходимой для записи события ошибки в какую-то энергонезависимую память, и записать эту инфу. А уж после рестартовать опять систему к полной функциональности.
Цитата(Arlleex @ Jul 7 2018, 18:39)

в боевой работе устройство ни коим образом не должно ловить такие Fault-ы?
Фиксация и отработка сбоев должна быть и в боевом режиме.
Цитата(Arlleex @ Jul 7 2018, 18:39)

2. Пункт 1 влечет за собой следующий вопрос: если в боевом коде обработчики должны быть предусмотрены (я подразумеваю, что все-таки это именно так) - как правильно строить архитектуру обработки ошибок?
У меня у обработчик общий, но имеет два входа: для программного возбуждения сбоя (trap()) и для аппаратного возбуждения сбоя (все типы fault-ов).
Цитата(Arlleex @ Jul 7 2018, 18:39)

3. Вопрос больше из разряда "как больше нравится" - код обработчика на ассемблере или на Си?
Защёлкивание всей инфы (регистры, стек, состояние CPU и пр.) у меня на асме, а "синий экран смерти" (режим работы TRAP) - на си.
Цитата(Arlleex @ Jul 7 2018, 18:39)

Вопрос не философский и хотелось бы узнать, как коллеги на реальной практике применяют обработчики исключений CPU для обеспечения надежности ПО и устройства в целом от сбоев.
Если есть инфа, что где-то на объекте что-то сбоит, смотрим журнал критических ошибок устройства на объекте - их частота, кол-во, периодичность, какие типы и в каких местах программы и пр. Дальше смотрим листинги этой версии ПО, пытаемся воспроизвести ситуацию у себя на столе. Если не получается - снимаем сбоящее устройство и везём к себе.
Как-то так.
Цитата(ViKo @ Jul 7 2018, 21:28)

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

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