Ich verwende einen Microchip dsPIC30F6012a. Ich habe diesen Chip auf mehreren Leiterplatten, auf denen alle dieselbe Software ausführen, und beobachte auf allen das gleiche Problem. Dies impliziert ein systemisches Problem, kein einmaliges Produktionsproblem. Das Problem ist auch reproduzierbar, was bedeutet, dass ich es töten sollte, wenn ich weiß, wo ich suchen muss. Aber ich habe immer noch überraschende Schwierigkeiten beim Debuggen der Anwendung.
Die zu testende Karte akzeptiert 24 V, die über einen V7805 auf 5 V herabgesetzt werden. Der Chip läuft auf seinem internen Oszillator mit einer 16x PLL, was eine Betriebsgeschwindigkeit von ~ 29,5 MIPS ergibt. Der relevante Code auf dieser Karte ist im Wesentlichen sehr einfach: Aufwachen, Daten aus dem EEPROM lesen und dann in eine Endlosschleife eintreten. Unterbrechen Sie jede Millisekunde, beobachten Sie einige Umgebungsdaten und schreiben Sie einen aktualisierten Wert in das EEPROM. Es gibt noch andere Dinge, aber das Problem tritt immer noch auf, selbst wenn der nicht verwandte Code auskommentiert ist, sodass ich ziemlich sicher sein kann, dass er für das vorliegende Problem nicht relevant ist.
Im Allgemeinen wacht das Board in 95% der Fälle mit dem richtigen Wert im Speicher auf und geht seinem Geschäft nach. Die anderen 5% der Zeit wacht es jedoch mit einem falschen Wert auf. Insbesondere wird es mit einer etwas gespiegelten Version der Daten aktiviert, die es haben soll. Es ist ein 4-Byte-Long ohne Vorzeichen, den ich gerade beobachte, und entweder das obere oder das untere Wort des Long kann umgedreht werden. Zum Beispiel wird 10 zu 2 ^ 16-10, was später zu 2 ^ 32-10 wird. Ich kann den Fehler reproduzieren, indem ich die Stromversorgung mehrere Dutzend Mal manuell betätige, aber das ist nicht sehr konsistent, und mein Schaltfinger ist abgenutzt.
Um das Problem kontrolliert zu reproduzieren, habe ich eine zweite Karte gebaut, die die 24-V-Versorgung der zu testenden Karte steuert. (Ein weiterer dsPIC, der einen Darlington-Optokoppler antreibt.) Die Testplatine schaltet die 24 V für 1,5 Sekunden aus (lang genug, damit die 5-V-Schiene auf im Wesentlichen 0 abfällt und dort eine Sekunde bleibt) und schaltet dann die 24 V für eine konfigurierbare Zeitdauer ein . Mit einer Einschaltdauer von ca. 520 mS kann ich diesen EEPROM-Fehler jedes Mal innerhalb von fünf Stromzyklen reproduzieren.
Die 5V-Schiene verhält sich vernünftig. Es liegt bei 5 V innerhalb von 1 mS nach dem Einschalten, mit vielleicht 0,4 V Überschwingen, vorausgesetzt, ich kann meinem Zielfernrohr vertrauen. Beim Ausschalten fällt es exponentiell auf 0 V ab und erreicht 1 V innerhalb von 50 mS. Ich habe keine Build-Warnungen, die relevant erscheinen, nur nicht verwendete Variablen und fehlende Zeilenumbrüche am Ende der Dateien.
Ich habe verschiedene Dinge ausprobiert:
- Aktivieren / Deaktivieren der MCLR
- Aktivieren / Deaktivieren des WDT
- Aktivieren / Deaktivieren des Codeschutzes
- Aktivieren / Deaktivieren / Ändern der Brownout-Erkennungsspannung
- Aktivieren / Deaktivieren / Ändern des Einschalt-Timers
- Unterschiedliche PLL-Einstellungen am internen Hauptoszillator
- Anschließen / Trennen meines PICkit 3-Programmiergeräts
- Hinzufügen von 470 uF Kapazität zur 5-V-Schiene
- Hinzufügen / Entfernen von 0,1 uF über das 4,7-k-Pullup an meinem MCLR-Pin
- Deaktivieren Sie alle Interrupts im Code und lassen Sie nur EEPROM-Updates in der Hauptschleife
- Hinzufügen einer Verzögerung von 1,5 Sekunden zu meiner Startroutine, bevor ich mit dem Lesen des EEPROM beginne
Ich habe auch separaten Testcode geschrieben, der nichts anderes tut, als kontinuierlich Werte in das EEPROM zu schreiben und sie dann zurückzulesen, um sicherzustellen, dass sich der Wert nicht geändert hat. Zehntausende von Iterationen ergaben keine Fehler. Alles, was ich daraus schließen kann, ist, dass beim Lesen oder Schreiben des EEPROM etwas schief geht, insbesondere beim Ein- und Ausschalten.
Ich verwende seit 2007 dieselben EEPROM-Bibliotheken. Ich habe gelegentlich Störungen gesehen, aber nichts reproduzierbares. Den entsprechenden Code finden Sie hier:
http://srange.net/code/eeprom.c
http://srange.net/code/readEEByte.s
http://srange.net/code/eraseEEWord.s
http: / /srange.net/code/writeEEWord.s
Ich habe EEPROM-Fehler schon in anderen Anwendungen gesehen, aber immer als einmalige Störungen, nichts so reproduzierbares oder konsistentes.
Hat jemand eine Idee was los ist? Mir gehen die Dinge aus, um es zu versuchen.
quelle
Antworten:
Mir fallen zwei Dinge ein:
Erstens dauert laut Datenblatt ein Lösch-Schreib-Zyklus mindestens 0,8 ms und bis zu 2,6 ms. Sie sagen, dass Sie alle 1 ms einen Interrupt haben, der zu einem Schreibvorgang führen kann. Ich habe im Code gesehen, dass Sie Interrupts für Teile des Löschvorgangs und für Teile der Schreibfunktion deaktivieren. Aber es kann immer noch zu einer lustigen Verschachtelung der Funktionsaufrufe kommen. Vielleicht hilft es, wenn Sie Interrupts für die gesamte Sequenz von Löschen und Schreiben deaktivieren?
Zweitens: Möglicherweise möchten Sie schreiben, während die Stromversorgung ausfällt, und der EEPROM-Schreibvorgang erfolgt genau in dem Moment, in dem die Versorgungsspannung unter die Betriebsspannung fällt. Sie können versuchen, die Versorgungsspannung zu überwachen und einen Schreibvorgang abzulehnen, wenn sie unter 4,5 V liegt. Dies setzt voraus, dass es als minimale Betriebsspannung lange genug über 2,7 V bleibt und die Brown-Out-Erkennung so eingestellt ist, dass sie nur unter diesem Punkt ausgelöst wird.
quelle
Sie haben sich viele mögliche Hardwareprobleme angesehen. Das ist in Ordnung, aber dies ist höchstwahrscheinlich ein Firmware-Fehler.
Leider ist Ihr Quellcode schlecht dokumentiert und so formatiert, dass er visuell schwer zu verfolgen ist. Ihre erste Datei enthält oben die Deklaration externer Routinen:
Es ist nicht nur eine schlechte Idee, solche Deklarationen in Client-Modulen privat zu machen, es ist auch kein einziger Kommentar in Sicht! Wir können nur anhand ihres Namens erraten, was diese Routinen tun sollen, und die Aufrufargumente sind vollständig undokumentiert. Weiter in dieser Datei haben Sie verschiedene Zeilen, die mit "//" beginnen, und eine ganze Zeile mit Gleichheitszeichen. Diese sorgen für zusätzliche visuelle Unordnung, was es zu schwierig macht, dem Code zu folgen.
Sie können sagen, dass nichts davon für den Betrieb des Codes von Bedeutung ist. Solche schlechten Programmierpraktiken sind jedoch sehr wichtig. Sie führen dazu, dass Code schlecht geschrieben wird, und machen es schwierig, Fehler zu erkennen oder sogar, was der Code tun soll. All dies führt dazu, dass schwer zu findende Probleme lauern, wie Sie entdecken. Sie haben sogar selbst gesagt, dass Sie seit 2007 gelegentlich Störungen in diesem Code gesehen haben. Dies hätte ein starker Hinweis auf einen Fehler sein müssen, möglicherweise sogar auf ein schlechtes Gesamtdesign.
Beheben Sie das Problem, dokumentieren Sie alle Schnittstellen ordnungsgemäß und fügen Sie allgemeine Deklarationen in Include-Dateien ein, die Sie einmal schreiben, und verweisen Sie dann bei Bedarf darauf. Auch Ihre Aussage, dass ich keine Build-Warnungen habe, die relevant erscheinen, ist eine riesige rote Fahne. Beheben Sie das Chaos erneut. Gehen Sie beim Debuggen immer zuerst den leicht reproduzierbaren und behebbaren Problemen nach. Manchmal sind dies tatsächlich die Ursache für die schwierigen Probleme, oder manchmal entdecken Sie bei der Behebung der Probleme die Ursache für andere Probleme. Der Compiler warnt Sie vor Schlamperei auf einem Silbertablett. Was willst du noch? Sie sollten keine nicht verwendeten Variablen haben, da diese bei jedem, der versucht, Ihren Code zu verstehen, Verwirrung stiften, und es gibt überhaupt keine Entschuldigung dafür, dass neue Zeilen fehlen. Beheben Sie das offensichtliche Problem erneut, insbesondere bevor Sie andere Personen bitten, sich Ihren Code anzusehen.
Ordentlichkeit und Liebe zum Detail sind wichtig . Viel.
quelle
Ich hatte ein identisches Verhalten mit 4 Stück dsPIC30F6014A (von ungefähr 10, die in den letzten Monaten verwendet wurden ..). Die einzige Möglichkeit, die sporadische Datenbeschädigung beim Ausschalten zu vermeiden, besteht darin, die MCLR kurz vor dem Herunterfahren auf Null zu setzen.
Offensichtlich ist dies in der Praxis nicht machbar, also habe ich mich für den Ersatz des "schlechten" dsPIC entschieden, wenn jemand stattdessen eine andere Lösung hat ...
quelle