Führen Sie den Code einmal im Leben eines eingebetteten C-Programms aus

8

Wie kann ich ein Code-Snippet nur einmal im Leben eines Programms ausführen lassen? Es kann viele Male aus- und wieder eingeschaltet werden. Die einzige Möglichkeit, das Code-Snippet erneut auszuführen, muss das erneute Flashen der Karte sein.

Der Code ist ein Kalibrierungsabschnitt, den ich nicht erneut ausführen möchte. Wenn ich EEPROM oder Flash verwende, setzen wir ein Flag auf true oder False. Also, wenn wir diesen Speicherort zum ersten Mal lesen, was wäre der Zufallswert in diesem Speicherbereich?

Was ist die beste Methode, um dies in Embedded C zu implementieren?

Ganeshredcobra
quelle
5
Verwenden Sie eine Flagge und speichern Sie diese Flagge in eeprom (oder dem Blitz). Lesen Sie in jedem Augenblick die Flagge von eeprom. Beim allerersten Moment des Augenblicks erzwingt der Wert des Flags die Ausführung der Funktion. Danach können Sie den Wert des Flags ändern und erneut in eeprom speichern. In allen anderen Fällen erzwingt der Flag-Wert keine Funktionsausführung.
Hoo2
2
unklar, was Sie fragen.
old_timer
2
Was ist Ihre Motivation, um zu verhindern, dass der Code ein zweites Mal ausgeführt wird? Ist es wichtig, dass der Code nicht rückentwickelt werden kann. In diesem Fall ist das Setzen eines Flags zur Umgehung möglicherweise nicht sicher genug? Würde das zweite Ausführen des Codes die Hardware beschädigen? Ist es eine UX-Sache, bei der ersten Verwendung des Systems eine Tutorial-Meldung anzuzeigen. In diesem Fall kann es wünschenswert sein, dass die Funktion "Werksreset" (falls vorhanden) den Code erneut ausführt?
Micheal Johnson
5
Im Allgemeinen ist es eine gute Idee, eine Neukalibrierung zuzulassen, falls beim ersten Mal etwas durcheinander kommt oder das System für ein anderes Setup neu kalibriert werden muss oder um die Alterung der Hardware usw. zu kompensieren. Ich neige zum Beispiel dazu, die Kalibrierung durcheinander zu bringen Zum ersten Mal, weil ich nicht weiß, was ich tun soll.
Micheal Johnson
3
Wie wäre es, wenn Sie den Code so einrichten, dass es eine Möglichkeit gibt, ihn zum Ausführen zu befehlen (dh etwas über eine serielle Schnittstelle einzusenden). Auf diese Weise müssen Sie sich nicht um nichtflüchtigen Speicher kümmern, und Sie können die Kalibrierung während der Produktion auf kontrollierte Weise auslösen.
Alex.forencich

Antworten:

18

Ihr Mikrocontroller verfügt möglicherweise über ein EEPROM, einen OTP-Speicher und Benutzersicherungsbits, in denen Sie ein Flag setzen können.

Es gibt keine "beste Methode in eingebettetem C". Das Schreiben von nichtflüchtigem Speicher ist in jedem Mikrocontroller unterschiedlich.

bearbeiten:

BLITZ

Flash-Speicherinhalte werden beim Programmieren des Geräts gelöscht. Nach dem Programmieren enthalten alle nicht geschriebenen Bytes 0xFF. Konsultieren Sie das Datenblatt, um einen Bereich zu finden, der sicher aus der laufenden Firmware heraus programmiert werden kann.

EEPROM

Obwohl dies in den Datenblättern nicht garantiert ist, enthielten alle EEPROMs, die ich bisher gesehen habe, 0xFF: s, wenn sie ab Werk geliefert wurden (mit Ausnahme derjenigen, die mit einer eindeutigen MAC-Adresse vorprogrammiert sind, dies ist jedoch ausdrücklich dokumentiert). Einige Programmiergeräte / Software können auch EEPROM-Inhalte löschen oder programmieren. Einige können dauerhaft oder reversibel schreibgeschützt sein.

OTP

Einmal programmierbarer Speicher enthält immer genau definierte Anfangswerte, die im Datenblatt dokumentiert sind.

Es ist immer eine gute Idee, den geschriebenen Daten eine gute Prüfsumme wie CRC32 beizufügen, um sie vor Datenkorruption zu schützen, die durch fehlerhafte Teile, Übertragungsfehler, kosmische Strahlung usw. verursacht wird.

berendi - protestieren
quelle
Wenn ich EEPROM oder Flash verwende, setzen wir ein Flag auf true oder False. Wenn wir diesen Speicherort zum ersten Mal lesen, was wäre der zufällige Wert in diesem Speicherbereich?
Ganeshredcobra
2
Setzen Sie das EEPROM während der Herstellung zurück (entweder mit einem Programmierer, wenn möglich, oder indem Sie ein dummes kleines Wischerprogramm erstellen, flashen Sie es, schalten Sie es einige Sekunden lang normal ein und laden Sie es dann in Ihr Produktionsprogramm).
Nick T
13

Du sagtest:

Die einzige Option, um diesen Code auszuführen, muss die Karte erneut flashen.

Andere haben gesagt, dass sie EEPROM verwenden, um ein Flag zu speichern, das angibt, wann die Funktion run_once () ausgeführt wurde. Dies hat jedoch den Nachteil, dass beim erneuten Flashen des Mikrocontrollers das Flag ran_it_once im EEPROM bereits gesetzt wurde und die Funktion run_once () nicht ausgeführt wird. Wenn Ihr Mikrocontroller ein eingebettetes EEPROM hat, kann das Flag ran_it_once möglicherweise gelöscht werden, wenn Sie den Mikrocontroller erneut flashen, sofern der Programmierer dies unterstützt.

Ein besserer Weg ist es, Versionsnummern sowohl im EEPROM als auch im Code zu haben. Wenn der Code beim Einschalten ausgeführt wird, sollte er die Versionsnummer aus dem EEPROM lesen und mit der im Code gespeicherten Versionsnummer vergleichen. Wenn sie nicht übereinstimmen, wird die Funktion run_once () aufgerufen, und der letzte Vorgang des Codes run_once () besteht darin, die Firmware-Versionsnummer in das EEPROM zu schreiben. Jedes Mal, wenn Sie den Quellcode der Firmware ändern, müssen Sie die darin eingebettete Versionsnummer erhöhen.

Steve G.
quelle
1
Dies hätte tatsächlich das gleiche Problem wie ein boolesches Flag, wenn der Benutzer lediglich den Mikrocontroller neu flashen würde und er erneut ausgeführt werden müsste (in diesem Szenario). Es würde das Problem definitiv beheben, wenn die Firmware aktualisiert würde und erneut ausgeführt werden müsste.
Taegost
8

Wählen Sie einen Mikrocontroller, der seinen eigenen Programmspeicher schreiben / löschen kann. Lassen Sie nach Ausführung des betreffenden Codes den letzten Teil des Codes den ersten Befehl durch einen Sprung ersetzen, der ihn umgeht. Optional können Sie auch den Rest löschen (möglicherweise durch nop ersetzen), sodass die Wahrscheinlichkeit, dass er jemals wieder ausgeführt wird, absolut gleich Null ist.

Diese Nachricht wird sich in 5..4 selbst zerstören ...

Apalopohapa
quelle
1
So klug diese Antwort auch sein mag, ich denke, sie ist unnötig komplex. Vielleicht könnte ein Hinweis verwendet werden, der angibt, dass er wahrscheinlich nur verwendet werden soll, wenn kein persistenter Speicher außerhalb des Codespeichers verfügbar ist?
skrrgwasme
Selbst wenn andere Lösungen möglich sind, denke ich, dass dies leichter zu verstehen ist als andere.
Joshua
1
Selbst wenn andere Lösungen möglich wären, wäre dies auf Quellcodeebene meiner Meinung nach sehr schwer zu verstehen.
Ein CVn
Die meisten PICs haben nur 35 Anweisungen ... was könnte schief gehen? ;)
rdtsc
5

Da Sie diesen Code für die Kalibrierung verwenden, würde ich vorschlagen, einen Explosionsprozess zu erstellen, bei dem der Kalibrierungscode als erste Stufe ausgeführt wird und nicht einmal auf der fertigen Produktionsversion der Platine vorhanden ist. Dies ähnelt der Antwort von Apalopohapa, unterscheidet sich jedoch in dem Sinne, dass Sie zwei separate Programmlasten haben würden: einen Explosionsprozess, der die erste Programmlast blinkt, die alle Kalibrierungen ausführt und die Daten daraus ausspuckt. Nehmen Sie dann diese Daten und integrieren Sie sie in die Daten des zweiten Programmladens.

Ein Vorteil dieses Ansatzes besteht darin, dass Sie den benötigten Speicherplatz absolut minimieren - Sie müssen nicht Ihren einmaligen Code speichern, sondern nur die Daten, die er generiert. Durch einen Explosionsprozess, bei dem zwei separate Programme geladen werden, isolieren Sie sich auch ein wenig vor Fehlern im Initialisierungscode, die sonst auftreten könnten. Sie haben auch zusätzliche Flexibilität, wenn Sie Ihren Kalibrierungscode erneut ausführen möchten: Anstatt zusätzlichen Code schreiben zu müssen, um das Bit zu löschen, das angibt, dass Ihr Code ausgeführt wurde (was versehentlich bereits gelöscht werden könnte), führen Sie Ihren Code einfach erneut aus Strahlprozess.

Michael
quelle