Как найти и преодолеть повреждение ОЗУ во время выполнения в микроконтроллерах? [закрыто]

Как я могу найти и устранить любое повреждение ОЗУ в микроконтроллере (ARM Cortex M0) во время выполнения? Например, что если два или три места повреждены, скажем, 0x2E 0x2F, 0x30. Как я могу все еще позволить системе работать, преодолевая или игнорируя это повреждение.

Вы имеете в виду в поле во время работы или на своем рабочем месте, потому что вы хотите сэкономить деньги и все равно использовать дефектный чип?
Исправление ошибки? Повреждения ОЗУ не так распространены в наземных приложениях. Каково ваше окружение?
@PlasmaHH В поле во время работы. В случае возникновения таких ошибок, как их найти и преодолеть?
Контрольная сумма и резервное копирование данных. Сохраните контрольную сумму критической области, а также вторую копию данных и контрольную сумму для нее. Если одна контрольная сумма оказывается неверной, скопируйте данные обратно из другой копии.
что делать, если регистры процессора повреждены?
@Jasen, этот вопрос идентичен «что, если что-то, что действительно критично для работы моего полупроводникового устройства, выйдет из строя», и ответ таков: тогда ваше устройство непоправимо сломано. Для некоторых регистров общего назначения вы можете достаточно модифицировать свой компилятор, чтобы просто не использовать этот регистр. Но: если, помимо всего прочего, происходит сбой регистра , то вы больше не можете доверять чему-либо, происходящему внутри ЦП. Выбросьте свой IC.
Глобальное повреждение данных в оперативной памяти обычно является признаком переполнения стека.
@filo нет, обычно нет. Особенно не на микроконтроллере, который вполне может быть запрограммирован на ассемблере вообще без использования кадров стека, хотя у вас обычно есть элегантные механизмы обработки стека при работе с прерываниями.
@filo, я вижу, что ты там сделал!
если это не сбой, а повреждение: например, космическими лучами, и адрес возврата в стеке поврежден, нет программного решения, кроме написания кода, который не доверяет всему содержимому оперативной памяти (поэтому не используйте стек для обратных адресов, если вы не можете работать избыточным способом) - но тогда насколько регистры ЦП отличаются от статического ОЗУ?
«ARM Cortex M0... местоположения 0x2E 0x2F, 0x30». - это зарезервированные места в таблице векторов прерываний, поэтому вы можете просто игнорировать любые «повреждения» в них, потому что они не должны содержать никакой полезной информации (если там вообще существует ОЗУ ).

Ответы (7)

Вам нужно выбрать правильный микроконтроллер с нужными вам функциями. Вот пример чипа Cortex M0, который имеет как EDAC (исправление однобитовых ошибок), так и Scrub (периодическое обновление содержимого памяти, предотвращающее накопление ошибок).

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

Как я могу все еще позволить системе работать, преодолевая или игнорируя это повреждение.

На общем Cortex M0: наверное, никак. Хотя это становится проще (не просто), если у вас есть MMU, который может отображать память вокруг, ваш микропроцессор ARM, скорее всего, не имеет этого. Таким образом, вам придется писать свое программное обеспечение и сценарии компоновщика таким образом, чтобы специально избегать этих адресов, а также компилировать его и запускать на микроконтроллере.

Как мне найти...

Как правило, это работа аппаратных механизмов проверки памяти. В мире вычислений в стиле ПК/сервера/рабочей станции/кластера вы бы выбрали память ECC и, возможно, даже избыточность памяти. В космических приложениях у вас, возможно, будут контроллеры памяти, которые имеют гораздо более сложную прямую коррекцию ошибок (FEC) в ОЗУ — тот же тип мышления, который используется твердотельным запоминающим устройством для предотвращения битовых ошибок, или ваш цифровой телевизионный приемник.

Проблема здесь в том, что у вас нет контроллера памяти, который может сделать это на Cortex M0. Конечно, вы можете сначала проверить каждую область ОЗУ по контрольной сумме, прежде чем обращаться к ней часто в программном обеспечении, но это будет огромная задача , а также не поможет, если повреждение памяти произойдет во время повторного чтения или записи.

Итак, если у Cortex M0 сломалась память, значит, она сломана и нуждается в замене.

Хорошо, что у этого типа чипов определенно не так много оперативной памяти, поэтому вероятность битовой ошибки из-за распределения Бернулли, вызванная «или» много «этот бит сломан?» вероятность не так высока. Что тем более означает, что вы должны заменить чип в полевых условиях, если он сломал оперативную память — с чипом что-то не так, и трудно предсказать, что выйдет из строя дальше.

Cortex M0 не имеет каких-либо специальных функций обнаружения ошибок или надежности, таких как ECC. Существуют микроконтроллеры (например, на базе Cortex-M7), которые имеют некоторые из этих функций, они могут помочь вам повысить надежность.

Оставляя в стороне причину ошибок (разумным случаем может быть рабочая среда с высоким уровнем радиации), вам необходимо добиться как минимум двух вещей. Обнаружение неисправности до того, как вашему сохраненному состоянию будет нанесен слишком большой ущерб, и восстановление системы. Это нетривиально, и лучший подход зависит от вашего приложения. Вещи, которые вы можете рассмотреть:

  • Сторожевая собака
  • Исполняемые контрольные суммы
  • Дублирование областей данных и контрольные суммы
  • Реплицированные потоки или ядра
  • Проверка данных (повторно)

Как только ошибка обнаружена, самое разумное, что можно сделать, это перезагрузить ядро ​​и начать заново. Иногда может помочь простой сброс ядра с помощью внешнего таймера.

Перезапись ОЗУ может быть признаком программной ошибки, а не аппаратного сбоя или неисправности. Две наиболее распространенные причины во встраиваемых программах на C связаны с указателями и выходом за границы массива. Часто инструменты отладки позволяют вам устанавливать точки останова при записи в память в определенные места, поэтому вы можете найти строку кода C, которая отвечает за перезапись, а затем определить, почему возникла эта ошибка.

Даже без такой поддержки вы могли бы сузить подозрительные строки, выяснив, какие переменные или массивы были выделены непосредственно перед этими адресами, поскольку это дает подсказку. Например, если есть массив из 8 элементов, и каждый элемент имеет размер 1 байт, и он начинается с 0x2E-0x08=0x26, то, если какой-то код записывает в этот массив, но индекс равен 9, он перезапишет 0x2E. (Возможно, у вас есть массив структур, каждая из которых занимает 3 байта, поэтому «плохие данные» могут дать вам представление о том, откуда они взялись).

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

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

В случае программной ошибки вы не хотите искать способ, чтобы система продолжала работать с таким повреждением; Вы должны найти и исправить ошибку. Если бы вы установили параметры компоновщика, чтобы избежать этой области памяти, ошибка, скорее всего, переместилась бы в другое место (при условии, что у вас нет неисправного оборудования).

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

Я никогда не видел избыточности на основе голосования в реализации ОЗУ MCU. У вас есть пример?
@DmitryGrigoryev: Вы бы не сделали избыточной только оперативную память; у вас будут избыточные вычислительные ядра, и вы будете голосовать на их соединениях ввода-вывода.

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

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

Многое из того, что вы слышите о стратегиях, особенно при работе с программными сбоями памяти, на самом деле только ухудшает ситуацию. Например, если ваш код занимает 1 КБ, а с проверкой ошибок — 2 КБ, вы только что удвоили вероятность появления случайной ошибки. Какую бы проверку вы ни делали сейчас, она должна преодолеть это просто для того, чтобы безубыточность. А как проверить чекер? Как я сказал в начале, вы просто не можете защитить себя от всех неудач.

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

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

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

Вы можете использовать кодирование с исправлением ошибок (ECC) для исправления или обнаружения ошибок памяти. Это значительно увеличит объем используемой оперативной памяти и приведет к дополнительным затратам на обработку.

ECC работает, используя только набор доступных слов. В качестве примера установите 000 и 111 в качестве допустимых слов. Если вы читаете 101, вы знаете, что это недопустимое слово. ECC — это широкая тема с множеством разных схем разной сложности. Приведенная выше схема, например, называется кодом повторения.

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

Что ж, проблема с этим на микроконтроллерах заключается в следующем: почему вы можете решить кодировать ECC все, что вы храните в ОЗУ, вы обычно не можете заставить свой контроллер DMA делать это, поэтому, хотя это, безусловно, помогает от ошибок в памяти, которую контролирует ваша программа , это не помогает в памяти, которая пишется аппаратно.
@MarcusMüller, вам, очевидно, нужно отключить DMA для периферийных устройств. Кроме того, вы можете получить контроллер DMA, который поддерживает ECC. Или, может быть, только один раздел ОЗУ имеет высокий BER. Вы можете направить периферийные устройства на более безопасную секцию. ОП не указал источник своего беспокойства, поэтому это невозможно узнать.