Wie kann man Laufzeit-RAM-Korruption in einem Mikrocontroller finden und überwinden? [geschlossen]

Wie kann ich eine RAM-Korruption in einem Mikrocontroller (ARM Cortex M0) während der Laufzeit finden und überwinden? Was ist zum Beispiel, wenn zwei oder drei Standorte beschädigt sind, sagen wir 0x2E 0x2F, 0x30. Wie kann ich das System trotzdem laufen lassen, indem ich diese Beschädigung überwinde oder ignoriere.

Meinen Sie im Feld während des Betriebs oder auf Ihrem Labortisch, weil Sie das Geld sparen und trotzdem einen defekten Chip verwenden möchten?
Fehler Korrektur? RAM-Korruptionen sind bei terrestrischen Anwendungen nicht so häufig. Was ist Ihre Umgebung?
@PlasmaHH Im Feld während des Betriebs. Wie kann man im Falle solcher Fehler diese finden und beheben?
Prüfsummenbildung und Datensicherung. Hinterlegen Sie eine Prüfsumme des kritischen Bereichs, sowie eine zweite Kopie der Daten und eine Prüfsumme dafür. Wenn eine Prüfsumme falsch ist, kopieren Sie die Daten von der anderen Kopie zurück.
Was ist, wenn die Prozessorregister beschädigt werden?
@Jasen diese Frage ist identisch mit "Was ist, wenn etwas, das für den Betrieb meines Halbleitergeräts wirklich entscheidend ist, ausfällt" und die Antwort lautet: Dann ist Ihr Gerät irreparabel kaputt. Bei einigen Allzweckregistern können Sie Ihren Compiler möglicherweise so modifizieren, dass er dieses Register einfach nicht verwendet. Aber: Wenn ausgerechnet ein Register ausfällt, dann kann man sich auf nichts mehr verlassen, was in der CPU passiert. Werfen Sie Ihren IC weg.
Globale Datenbeschädigung im RAM ist normalerweise ein Hinweis auf einen Stapelüberlauf.
@filo nein, nicht generell. Vor allem nicht auf einem Mikrocontroller, der ohne die Verwendung von Stack-Frames in Assembler programmiert werden könnte, obwohl Sie normalerweise elegante Stack-Handling-Mechanismen haben, wenn Sie mit Interrupts umgehen.
@filo, ich sehe, was du da gemacht hast!
Wenn es nicht fehlschlägt, sondern beschädigt ist: z. B. durch kosmische Strahlung und die Rücksendeadresse auf dem Stapel beschädigt ist, gibt es keine Softwarelösung, außer Code zu schreiben, der dem gesamten RAM-Inhalt misstraut (also keine Verwendung des Stapels für Rücksendeadressen, es sei denn, Sie können arbeiten redundant aus) - aber wie unterscheiden sich dann CPU-Register von statischem RAM?
"ARM Cortex M0... Standorte 0x2E 0x2F,0x30." - Dies sind reservierte Stellen in der Interrupt-Vektortabelle, sodass Sie jegliche "Korruption" in ihnen einfach ignorieren können, da sie keine nützlichen Informationen enthalten sollten (falls dort überhaupt RAM vorhanden ist ).

Antworten (7)

Sie müssen die richtige MCU auswählen, die über die Funktionen verfügt, die Sie benötigen. Hier ist ein Beispiel für einen Cortex M0-Chip, der sowohl über EDAC (Korrektur von Einzelbitfehlern) als auch über Scrub (regelmäßige Aktualisierung des Speicherinhalts, der eine Fehlerakkumulation verhindert) verfügt.

Wenn Sie keine Hardwarefunktionen zur Fehlerkorrektur haben, ist das Beste, was Sie tun können, eine regelmäßige Überprüfung des Speicherinhalts, dessen Änderung nicht erwartet wurde, und ein Neustart, wenn eine Änderung festgestellt wurde.

Wie kann ich das System trotzdem laufen lassen, indem ich diese Beschädigung überwinde oder ignoriere.

Auf einem allgemeinen Cortex M0: wahrscheinlich überhaupt nicht. Während dies einfacher (nicht einfach) wird, wenn Sie eine MMU haben, die Speicher zuordnen kann, hat Ihr ARM-Mikroprozessor dies sehr wahrscheinlich nicht. Sie müssten also Ihre Software und Linker-Skripte so schreiben, dass diese Adressen ausdrücklich vermieden werden, und das kompilieren und auf dem µC ausführen.

Wie kann ich finden ...

Typischerweise ist dies die Aufgabe von Hardwaremechanismen zur Speichervalidierung. In der Welt der Berechnungen im PC/Server/Workstation/Cluster-Stil würden Sie sich für ECC-Speicher und möglicherweise sogar für Speicherredundanz entscheiden. In weltraumgestützten Anwendungen hätten Sie möglicherweise Speichercontroller mit einer viel ausgefeilteren Vorwärtsfehlerkorrektur (FEC) im RAM – die gleiche Denkweise, die Solid-State-Massenspeicher verwenden, um Bitfehler zu vermeiden, oder Ihr digitaler Fernsehempfänger.

Das Problem hier ist: Sie haben keinen Speichercontroller, der das auf einem Cortex M0 tun kann. Man könnte natürlich zuerst jede RAM-Region gegen eine Prüfsumme prüfen, bevor man häufig in der Software darauf zugreift, aber das ist eine enorme Aufgabe und hilft auch nicht wirklich, wenn die Speicherbeschädigung beim wiederholten Lesen oder Schreiben auftritt.

Wenn also ein Cortex M0 einen kaputten Speicher hat, ist er kaputt und muss ersetzt werden.

Das Gute daran ist, dass diese Art von Chip definitiv nicht so viel RAM hat, sodass die Bitfehlerwahrscheinlichkeit aufgrund der Bernoulli-Verteilung, die durch "oder" verursacht wird, viel "ist dieses Bit kaputt?" Wahrscheinlichkeit ist nicht so hoch. Was umso mehr bedeutet, dass Sie den Chip vor Ort ersetzen sollten, wenn der RAM kaputt ist – irgendetwas stimmt nicht mit dem Chip, und es ist schwer vorherzusagen, was als nächstes ausfallen wird.

Cortex M0 hat keine spezifischen Fehlererkennungs- oder Zuverlässigkeitsfunktionen wie ECC. Es gibt Mikrocontroller (z. B. auf Cortex-M7-Basis), die über einige dieser Funktionen verfügen. Diese können Ihnen helfen, die Zuverlässigkeit zu verbessern.

Abgesehen von der Ursache der Fehler (eine Betriebsumgebung mit hoher Strahlung wäre ein vernünftiger Fall), müssen Sie mindestens zwei Dinge erreichen. Erkennung des Fehlers, bevor Ihr gespeicherter Zustand zu stark beschädigt wurde, und Wiederherstellung des Systems. Diese sind nicht trivial, und der beste Ansatz hängt von Ihrer Anwendung ab. Dinge, die Sie berücksichtigen können, sind:

  • Wachhund
  • Ausführbare Prüfsummen
  • Duplizierung von Datenregionen und Prüfsummen
  • Replizierte Threads oder Kerne
  • Datenvalidierung (wiederholt)

Sobald ein Fehler erkannt wird, ist es am sinnvollsten, den Kern zurückzusetzen und neu zu starten. Das einfache Zurücksetzen des Kerns mit einem externen Timer von Zeit zu Zeit kann helfen.

Das Überschreiben von RAM kann eher ein Symptom für einen Softwarefehler als für einen Hardwarefehler oder -fehler sein. Die beiden häufigsten Ursachen in eingebetteten C-Programmen sind auf Zeiger und Array-Zugriffe außerhalb der Grenzen zurückzuführen. Debugging-Tools ermöglichen es Ihnen häufig, Haltepunkte für Speicherschreibvorgänge an bestimmten Stellen festzulegen, sodass Sie möglicherweise die C-Codezeile finden können, die für das Überschreiben verantwortlich ist, und dann feststellen können, warum dieser Fehler aufgetreten ist.

Auch ohne eine solche Unterstützung können Sie möglicherweise die verdächtigen Zeilen eingrenzen, indem Sie herausfinden, welche Variablen oder Arrays direkt vor diesen Adressen zugewiesen wurden, da dies einen Hinweis liefert. Wenn es beispielsweise ein Array mit 8 Elementen gibt und jedes Element 1 Byte groß ist und bei 0x2E-0x08=0x26 beginnt, dann würde ein Code, der in dieses Array schreibt, aber der Index 9 ist, 0x2E überschreiben. (Vielleicht haben Sie ein Array von Strukturen mit jeweils 3 Bytes, sodass die "schlechten Daten" Ihnen einen Hinweis darauf geben könnten, woher dies kommt).

Wenn jedoch ein nicht initialisierter Zeiger verwendet wird, wird das Speicherlayout wahrscheinlich keine Hilfe sein. Sie können Ihren Code jedoch weiterhin nach Zeigerverwendung durchsuchen oder statische Codeprüfer oder Ihre Compiler-Warnstufen verwenden, um nach Zeigern zu suchen, die verwendet werden, bevor sie mit einer gültigen Adresse initialisiert werden.

Wenn Sie dieses Überschreiben wiederholt erzeugen können, aber nicht feststellen können, welche Codezeile die Ursache ist, besteht ein Brute-Force-Ansatz darin, Codeabschnitte zu entfernen, die Sie vermuten, bis Sie sie finden. Dies birgt jedoch die Gefahr, dass der Rest des Codes so sehr gestört wird, dass sich der Fehler bewegt.

Im Falle eines Softwarefehlers möchten Sie keinen Weg finden, das System mit einer solchen Beschädigung weiterhin laufen zu lassen. Sie sollten den Fehler finden und beheben. Wenn Sie Linker-Optionen festlegen würden, um diesen Bereich des Speichers zu vermeiden, würde sich der Fehler wahrscheinlich an eine andere Stelle verschieben (vorausgesetzt, Sie haben keine defekte Hardware).

Wo es auf hohe Zuverlässigkeit ankommt, laufen oft mehrere Systeme parallel und stimmen über die Entscheidungen ab.

Ich habe noch nie eine abstimmungsbasierte Redundanz in der MCU-RAM-Implementierung gesehen. Haben Sie ein Beispiel?
@DmitryGrigoryev: Sie würden den RAM allein nicht überflüssig machen; Sie hätten redundante Rechenkerne und würden die Abstimmung an ihren E / A-Verbindungen vornehmen.

Letztendlich kann man sich einfach nicht vor allen Speicherausfällen schützen. Glücklicherweise sind diese äußerst selten, es sei denn, Ihr Gerät geht in den Weltraum.

Sie können sich durch zusätzliche Zyklen vor Beschädigung in bestimmten Teilen des Speichers schützen. Beispielsweise könnten Sie mehrere Kopien einer kritischen Datenstruktur aufbewahren, jede mit ihrer eigenen Prüfsumme. Sie müssten auf die Daten in diesem Abschnitt über Subroutinen zugreifen, die die mehreren Kopien aktualisieren, die Prüfsummen berechnen und Diskrepanzen behandeln.

Viele der Dinge, die Sie da draußen als Strategien hören, insbesondere für den Umgang mit Programmspeicherausfällen, machen die Dinge tatsächlich noch schlimmer. Wenn Ihr Code beispielsweise 1 kB benötigt, die Fehlerprüfung jedoch 2 kB benötigt, haben Sie die Wahrscheinlichkeit, von einem zufälligen Fehler getroffen zu werden, gerade verdoppelt. Was auch immer Sie jetzt überprüfen, muss dies überwinden, um die Gewinnschwelle zu erreichen. Und wie überprüft man den Checker? Wie ich eingangs sagte, man kann sich einfach nicht gegen alle Ausfälle schützen.

Eine realistischere Strategie besteht darin, die Wahrscheinlichkeit eines Scheiterns von vornherein zu minimieren. Sie könnten einen alten Mikrocontroller mit einer größeren Funktionsgröße verwenden. Das macht es weniger wahrscheinlich, dass bestimmte Ereignisse ein wenig umkippen können. Externe Speichersubsysteme können eine Fehlerkorrektur und -erkennung bis zu einem gewissen Grad an Fehlern aufweisen.

Wenn etwas in der ALU oder einem der Schlüsselregister des Prozessors ein bisschen kippt, werden Sie geschraubt. In manchen Fällen kann ein Watchdog helfen. Wenn der Code den Watchdog-Timer nicht mehr regelmäßig löscht, wird der Prozessor zurückgesetzt und Sie können von vorne beginnen.

Grundsätzlich gilt: Wer extra hohe Zuverlässigkeit benötigt, wird diese mit mehrfach redundanten Systemen auf höherem Niveau besser erreichen als mit niedlichen Tricks in einem Mikrocontroller.

Sie können die Fehlerkorrekturcodierung (ECC) verwenden, um Speicherfehler zu korrigieren oder zu erkennen. Dies wird die Größe der RAM-Nutzung erheblich erhöhen und Verarbeitungs-Overheads einführen.

ECC funktioniert, indem es nur einen Satz der verfügbaren Wörter verwendet. Legen Sie beispielsweise 000 und 111 als gültige Wörter fest. Wenn Sie 101 lesen, wissen Sie, dass dies kein gültiges Wort ist. ECC ist ein breites Thema mit vielen verschiedenen Schemata unterschiedlicher Komplexität. Das obige Schema wird beispielsweise als Wiederholungscode bezeichnet.

Obwohl die Wahrscheinlichkeit, dass ein Fehler auftritt, zunimmt, erhöht sich aufgrund der erhöhten Speicherauslastung Ihre Fähigkeit, die Fehler zu korrigieren, schneller. Es stellt sich die Frage, welche Bitfehlerrate (BER) Sie tolerieren können, während Sie Ihre anderen Einschränkungen einhalten. Sie können das Codewort weiter erhöhen, um Ihre gewünschte BER zu erreichen, wobei die Speichereffizienz geopfert wird.

Nun, das Problem damit bei Mikrocontrollern ist: Warum Sie sich vielleicht entscheiden, alles, was Sie im RAM speichern, ECC-kodieren, können Sie Ihren DMA-Controller normalerweise nicht dazu zwingen, während dies sicherlich gegen Fehler im Speicher hilft, die Ihr Programm kontrolliert , es hilft nicht bei Speicher, der von Hardware geschrieben wird.
@MarcusMüller Sie müssten offensichtlich DMA für die Peripheriegeräte deaktivieren. Alternativ erhalten Sie einen DMA-Controller, der ECC unterstützt. Oder vielleicht hat nur ein Abschnitt des RAM eine hohe BER. Sie können die Peripheriegeräte auf den sichereren Bereich richten. Das OP hat die Quelle seiner Besorgnis nicht angegeben, daher ist es unmöglich zu wissen.