Hallo,
wir haben eine Anwendung mit PIC18 mit internen EEPROM.
Hier sind Kalibrierdaten und ein 32 Bit Zähler gespeichert.
Wenn die Maschine einen Zyklus beendet hat, was ca. 3 Sekunden dauert,
wird im RAM ein Zähler erhöht.
Wenn der RAM Zähler einen glatten Hunderter Stand erreicht, dann wird
dieser Zählerstand ins EEPROM kopiert.
Wenn die Spannung mal ausfällt, dann fehlen u.U bis zu 100
Maschinenzyklen, das ist aber egal.
Nach dem Einschalten wird der EEPROM Zähler geladen und ins RAM kopiert.
Problem:
Zeitweise kommt es vor, dass die Inhalte im EEPROM falsch sind. Sowohl
Kalibrierwerte als auch der Zähler.
Ich vermute, dass es daher kommt, dass während einem Schreibvorgang die
Spannung ausfällt.
Leider ist in der Hardware keine Schaltung verbaut, die erkennt wenn die
Netzspannung ausfällt.
Was könnte man machen ?
3-fach im EEPROM abspeichern und dann beim Laden eine Prüfung
durchführen ?
LG Dirk
Dirk F schrieb:> Was könnte man machen ?
Ich würde erstmal den Brownout Reset aktivieren, damit der Chip bei
Unterspannung ruhig ist und nicht mehr probiert, am EEPROM rumzufummeln.
Dirk F schrieb:> Ich vermute, dass es daher kommt, dass während einem Schreibvorgang die> Spannung ausfällt.
Kannst du ja testen indem du z.B. einen Zählerwert vor und nach den
Daten wegschreibst.
Dirk F schrieb:> 3-fach im EEPROM abspeichern und dann beim Laden eine Prüfung> durchführen ?
damit verdreifachst du Speicherbedarf und auch das Risiko. Würde eher
die Daten prüfen und noch ein "Daten geprüft und Ok" Flag danach ins
EEprom schreiben.
HyperMario schrieb:> Würde eher> die Daten prüfen und noch ein "Daten geprüft und Ok" Flag danach ins> EEprom schreiben.
... Allerdings natürlich nicht nur ein einzelnes Bit, das ist ja dann
wieder in 50% der Fälle falsch.
Dirk F schrieb:> Was könnte man machen ?
Erstmal dafür sorgen, dass der letzte gute Wert im EEPROM nicht
überschrieben wird: den Daten eine laufende Nummer und eine Prüfsumme
anfügen und mindestens in 2 Speicherbereiche abwechselnd schreiben. Wird
beim Schreiben ein Datensatz durch Absturz oder Stromausfall
zerknatscht, kann man noch den anderen nehmen.
Sind mal beide kaputt hast du ein anderes und viel ernsteres Problem.
Georg
Matthias S. schrieb:> Ich würde erstmal den Brownout Reset aktivieren, damit der Chip bei> Unterspannung ruhig ist und nicht mehr probiert, am EEPROM rumzufummeln.
Habe den Brownout aktiviert.
Der PIC wird normal mit 3,3 V versorgt.
BOR steht auf 1,8 V. Andere Einstellmöglichkeiten sind 2.2V, 2.7V und
3.0V.
Sollte ich hier den Wert erhöhen ?
Den Tip mit Prüfsumme und auf 2 Stellen speichern finde ich gut.
Dirk F schrieb:> BOR steht auf 1,8 V. Andere Einstellmöglichkeiten sind 2.2V, 2.7V und> 3.0V.> Sollte ich hier den Wert erhöhen ?
steht im DB unter EEPROM schreiben
Dirk F schrieb:> Der PIC wird normal mit 3,3 V versorgt.> BOR steht auf 1,8 V.
1,8V ist ja nicht garantiert, wenns nicht klappt also erhöhen
min 1,8V kann man so & so verstehen und
Using EECON to read/write
beachten, was immer das heissen mag, kenne PIC nicht.
Joachim B. schrieb:> 1,8V ist ja nicht garantiert,
Wieso, wenns im Datenblatt steht, dann ist es garantiert.
> Using EECON to read/write
Das ist die normale Art, das interne EEPROM währen dem Betrieb
anzusprechhen, also nicht übers Programmiergerät.
Dirk F schrieb:> Wieso, wenns im Datenblatt steht, dann ist es garantiert.
na denn....... :)))
(ich hatte zwar schon öfter falsche Datenblattangaben, aber glauben darf
man alles hier im Lande, es gibt ja Religionsfreiheit)
Schreibst du auch die Kalibrierwerte wenn du deinen Zähler schreibst?
Wenn nicht, dann bedeutet das, dass auch Bytes beschädigt werden auf die
nicht zu gegriffen wurde. Das passiert z.B. wenn die der Eeprom intern
Page basierend arbeitet. D.h. auch wenn du nur ein Byte änderst wird
intern die gesamte Pages (z.B. 128 Bytes) neu geschrieben.
Wenn das so ist, dann wird es dir auch nichts helfen wenn du den Zähler
an mehreren benachbarten Positionen speicherst. Im Fehlerfall wäre die
gesamte Page reiner Zufall. In dem Fall müsstest du den Zähler auf
mehrere Pages verteilen und auch die Kalibrierdaten müssen auf eine
separate Page.
Hast du die Möglichkeit die Versorgungsspannung z.B. durch einen
Komparator zu überwachen? Dann würde ich bei 3,0V ein Interrupt auslösen
und den Prozessor in den Sleep legen. So verringerst du den Strombedarf
des Prozessors wodurch im Fehlerfall die Spannung langsamer
zusammenbricht. Das gibt die vielleicht ein paar Millisekunden sodass
der Eepromzugriff intern noch beendet werden kann.
Matthias X. schrieb:> Schreibst du auch die Kalibrierwerte wenn du deinen Zähler schreibst?
Hallo. Im Normalbetrieb wird nur der Zähler geschrieben.
Kalibrierdaten nur einmalig im Werk.
Das mit den Pages ist ist ne Idee.
Aber ist das nicht nur im Flash Speicher so, dass die gesamte page
gelöscht wird ?
IM EEPROM kann man doch byteweise löschen und dann schreiben ?
Dirk F schrieb:> Matthias X. schrieb:>> Schreibst du auch die Kalibrierwerte wenn du deinen Zähler schreibst?>> Hallo. Im Normalbetrieb wird nur der Zähler geschrieben.> Kalibrierdaten nur einmalig im Werk.>> Das mit den Pages ist ist ne Idee.> Aber ist das nicht nur im Flash Speicher so, dass die gesamte page> gelöscht wird ?> IM EEPROM kann man doch byteweise löschen und dann schreiben ?
Ja, kann man. Intern ist das EEPROM aber ebenfalls blockweise aufgebaut.
Beim Schreiben wird ein Block (Page) in einen Puffer geladen, geändert
und wieder zurückgeschrieben. Da geschieht viel in Hardware. Dadurch
können bei einem Schreibfehler auch andere Bytes der gleichen Page
beschädigt werden.
Vorschlag 1:
Kalibrierdaten in der letzten Page des Flash speichern. Damit sind diese
Daten erstmal in Sicherheit, denn das Flash wird ja im Betrieb nicht
geschrieben.
Vorschlag 2:
Ich gehe mal davon aus, dass Du im Flash nicht mehr als 256 Bytes
brauchst. Dann teile Dein EEPROM in 4 256 Byte Blöcke auf, und schreibe
reihum immer in einen anderen Block. Das verteilt die Schreibzugriffe,
Dein EEPROM wird länger leben, und im Fehlerfall sollte nur ein Block
betroffen sein. Jeder Block hat natürlich eine Prüfsumme, um Fehler zu
erkennen. Beim Starten suchst Du Dir einfach den Block mit dem höchsten
Zählerstand bei korrekter Prüfsumme aus.
Vorschlag 3:
BOR hochsetzen und nach einem Reset in RCON nachschauen, ob Reset durch
BOR verursacht wurde. Wenn ja, dann internes RAM prüfen (Prüfsumme!) und
EEPROM prüfen und ggf. den letzten, defekten Block löschen.
fchk
Dirk F schrieb:> Wenn die Spannung mal ausfällt, dann fehlen u.U bis zu 100> Maschinenzyklen, das ist aber egal.
Warum wird der Spannungsausfall nicht detektiert, bevor er beim µC
ankommt. Dann könnte man jegliche EEPROM-Aktivität sicher abschließen,
bevor dem µC die Luft aus geht.
Wolfgang schrieb:> Warum wird der Spannungsausfall nicht detektiert, bevor er beim µC> ankommt. Dann könnte man jegliche EEPROM-Aktivität sicher abschließen,> bevor dem µC die Luft aus geht.
Ja, aber die Hardware ist hierfür leider nicht vorhanden.
Einige 1000 Geräte schon geliefert.....
Also zusammengefasst:
* Fürs Ausschalten alle möglichen Quellen auf Tauglichkeit untersuchen
(vielleicht messt ihr die Versorgungsspannung oder habt ein Signal, was
indirekt darauf schließen lässt)
* Blockgröße Deines EEPROMS kennen und beachten (Konsistenzen immer
innerhalb von Blöcken sicherstellen)
* 3 Blöcke zur Sicherung vorhalten:
Block 0: Hier schreibst Du den neuen Blockinhalt rein
Block 1: Hier schreibst Du die Nummer des zu schreibenden Blocks rein
Block 2: Kopie von 1
Block x: löschen
Block x: diesen nun wie Block 0 beschreiben
Block 2: löschen
Block 1: löschen
Block 0: löschen
Beim Aufstarten checkst Du, ob Block 1/2 noch ein unfertiger
Schreibzugriff geloggt ist und beendest ihn ggf. . Block 2 ist
notwendig, da Block 1 auch müll enthalten kann
Wenn bei Netzausfall die Spannung am uC nicht abrupt, sondern im Rahmen
von z.B. 100-200ms linear abfällt, dann könnte man vor einem Schreiben
des EEProms eine Messung per ADC machen und nur bei genügend Spannung
den Schreibvorgang ausführen. Benötigt würde ein nicht verwendeter
ADC-Pin den man per Pullup auf VCC zieht und mit interner Referenz
misst.
MWS schrieb:> Wenn bei Netzausfall die Spannung am uC nicht abrupt, sondern im Rahmen> von z.B. 100-200ms linear abfällt, dann könnte man vor einem Schreiben> des EEProms eine Messung per ADC machen und nur bei genügend Spannung> den Schreibvorgang ausführen. Benötigt würde ein nicht verwendeter> ADC-Pin den man per Pullup auf VCC zieht und mit interner Referenz> misst.
Auch hierfür muß die Hardware modifiziert werden. Scheidet erst mal aus.
Ich suche die beste Lösung per Software für ein Firmwareupdate.
fchk schrieb:> Ja, kann man. Intern ist das EEPROM aber ebenfalls blockweise aufgebaut.> Beim Schreiben wird ein Block (Page) in einen Puffer geladen, geändert> und wieder zurückgeschrieben. Da geschieht viel in Hardware. Dadurch> können bei einem Schreibfehler auch andere Bytes der gleichen Page> beschädigt werden.
Im Datenblatt des PIC18F ist keine Blockgröße angegeben.
Also fraglich, ob bei MC die EEPROMS wirklich in Blöcke aufgeteilt sind.
fchk schrieb:> Vorschlag 2:> Ich gehe mal davon aus, dass Du im Flash nicht mehr als 256 Bytes> brauchst. Dann teile Dein EEPROM in 4 256 Byte Blöcke auf, und schreibe> reihum immer in einen anderen Block. Das verteilt die Schreibzugriffe,> Dein EEPROM wird länger leben, und im Fehlerfall sollte nur ein Block> betroffen sein. Jeder Block hat natürlich eine Prüfsumme, um Fehler zu> erkennen. Beim Starten suchst Du Dir einfach den Block mit dem höchsten> Zählerstand bei korrekter Prüfsumme aus.
Sehr guter Vorschlag.
Aktuell sind meine Daten im EEPROM wie folgt organisiert:
0-95 Kalibrierdaten
100...103 Taktzähler
...117 Sonstiges. z.B Passwort
Ab 512:
Backup von den o.g. Daten, um ein Reset zu Factory Default zu machen.
Bleibt also zu klären, ob das interne EEPROM wirklich blockweise oder
Byteweise gelöscht wird.
Danke für bisherige Tipps.
Dirk F schrieb:> Auch hierfür muß die Hardware modifiziert werden.
Vielleicht hilft es ja:
22.0 HIGH/LOW-VOLTAGE DETECT (HLVD)
PIC18F2XK20/4XK20 devices have a High/Low-Voltage
Detect module (HLVD). This is a programmable circuit
that allows the user to specify both a device voltage trip
point and the direction of change from that point
HyperMario schrieb:> Vielleicht hilft es ja:>> 22.0 HIGH/LOW-VOLTAGE DETECT (HLVD)
Hi MArio,
sehr guter Hinweis.
So wie ich das Datenblatt verstehe,
kann man die Betriebsspannung der MCU ohne externe Beschaltung gegen
eine interne Referenz vergleichen.
Schaltpunkt in 16 Stufen einstellbar.
Messe gleich mal mit dem Oszi, wie langsam die MCU Spannunng bei
Netzausfall abfällt.
Ob die Zeit reicht, einen begonnen Schreibvorgang zu vollenden.
Dirk F schrieb:> So wie ich das Datenblatt verstehe,> kann man die Betriebsspannung der MCU ohne externe Beschaltung gegen> eine interne Referenz vergleichen.
Hab das selber nicht getestet, so ist es aber gedacht.
> Messe gleich mal mit dem Oszi, wie langsam die MCU Spannunng bei> Netzausfall abfällt.
Würde mich interessieren, inkl, Kapazität vom (falls vorhanden)
Siebelko.
Also habe mir eben den Code nochmal angeschaut.
Immer wenn der Zähler die 100er Grenze erreicht, dann spreichere ich den
kompletten Datensatz (117 Byte) im EEPROM ab.
Das dauert ca. 500 ms.
Werde den Code ändern, dass nur die 4 Byte des Zählers abgespeichert
werden.
Durch die wesentlich kürzere Speicherzeit (ca. 20 ms) ist die
Wahrscheinlichkeit dass dann ein Spromausfall auftritt um das 32-fache
geringer......
Als erste Maßnahme....
Dirk F schrieb:> Durch die wesentlich kürzere Speicherzeit (ca. 20 ms) ist die> Wahrscheinlichkeit dass dann ein Spromausfall auftritt um das 32-fache> geringer......
Ich habe das bei meinem Betriebsstundenzähler so gelöst, dass ich in
einen Ringpuffer im EEPROM schreibe. Also z.B. 10x4 Byte für 10
Datensätze.
Nach dem Starten sucht der µC dann in diesen 10 Plätzen den größten Wert
und prüft außerdem, ob dieser Wert = Vorgängerwert + 1 ist.
Dadurch kann ein korrupter Wert verworfen werden.
chris schrieb:> Ich habe das bei meinem Betriebsstundenzähler so gelöst, dass ich in> einen Ringpuffer im EEPROM schreibe
Ich habe schon in der 5. Antwort vorgeschlagen mindestens einen
doppelten Buffer zu verwenden und die Werte abzusichern, du bist jetzt
der dritte, wenn ich nichts übersehen habe. Wir wissen dass das
funktioniert (mache ich seit mehr als 30 Jahren so), aber offensichtlich
mag der TO so eine Lösung nicht. Da er nicht mal drauf eingeht hat er es
wahrscheinlich überhaupt nicht verstanden. Da kann man halt nichts
machen, Ende der Beteiligung.
Georg
georg schrieb:> chris schrieb:>> Ich habe das bei meinem Betriebsstundenzähler so gelöst, dass ich in>> einen Ringpuffer im EEPROM schreibe>> Ich habe schon in der 5. Antwort vorgeschlagen mindestens einen> doppelten Buffer zu verwenden und die Werte abzusichern, du bist jetzt> der dritte, wenn ich nichts übersehen habe. Wir wissen dass das> funktioniert (mache ich seit mehr als 30 Jahren so), aber offensichtlich> mag der TO so eine Lösung nicht. Da er nicht mal drauf eingeht hat er es> wahrscheinlich überhaupt nicht verstanden. Da kann man halt nichts> machen, Ende der Beteiligung.>> Georg
LESEN ist generell keine Stärke der Beteiligten, sonst wäre der Thread
mindestens 4/5 kürzer. Zum Glück gibt es in unserem Portfolio kein
einziges Modul, welches nicht mindestens die (primäre)
Versorgungsspannung misst.
Neben Eeprom gibt es ja auch noch viele andere Erfordernisse, die einen
geregelten Shutdown erfordern, oft auch Themen der Betriebssicherheit.
Aber richtig:
Mit einer Absicherung der Daten geht es beim Eeprom auch, nur eben mit
höherem Software-Aufwand. Idealerweise räumt man die Schrottdaten beim
nächsten Booten auf, damit spart man sich eine Verkomplizierung im
anschließenden Betrieb.
Dirk F schrieb:> Auch hierfür muß die Hardware modifiziert werden. Scheidet erst mal aus.
Für das Setzen eines internen Pullups und Verwendung des ADC muss keine
Hardware geändert werden.
Falls die Versorgungsspannung intern zu messen ist, umso besser.
Aber wenigstens scheinst Du die Idee verstanden zu haben.
Dirk F schrieb:> Durch die wesentlich kürzere Speicherzeit (ca. 20 ms) ist die> Wahrscheinlichkeit dass dann ein Spromausfall auftritt um das 32-fache> geringer......
Wenn Du das jetzt mit einer vorherigen Prüfung der Versorgung
verbindest, dann hast Du tatsächlich etwas erreicht, nämlich eine
Problemlösung, die ich Dir mit meinem Vorschlag nahelegte.
Wird jetzt noch der Spannungsverlauf oszillographiert und festgestellt,
dass z.B. 100ms zum Schreiben bleibt, dann kannst Du sogar sicher sein,
das nichts mehr passiert.
Dann musst Du nicht lediglich die Wahrscheinlichkeit verringern, bis
Dein Murks ausfällt.
fchk schrieb:> Ja, kann man. Intern ist das EEPROM aber ebenfalls blockweise aufgebaut.> Beim Schreiben wird ein Block (Page) in einen Puffer geladen, geändert> und wieder zurückgeschrieben. Da geschieht viel in Hardware. Dadurch> können bei einem Schreibfehler auch andere Bytes der gleichen Page> beschädigt werden.
Habe das Problem auch mal im Microchip Forum gestellt.
Die Antwort war, dass das interne EEPROM des PIC18 nicht in Pages
aufgeteilt ist, sondern Byteweise.
MWS schrieb:> Wird jetzt noch der Spannungsverlauf oszillographiert und festgestellt,> dass z.B. 100ms zum Schreiben bleibt, dann kannst Du sogar sicher sein,> das nichts mehr passiert.
Habe ich gemacht.
600 ms nachdem die Netzspannung ausfällt passiert folgendes mit der
Versorgungsspannung des PIC: Anlage
Es bleiben weniger als 10 ms von Erkennung bis zum BOR übrig.
Zu wenig um das EEPROM zu beschreiben.
Dirk F schrieb:> 600 ms nachdem die Netzspannung ausfällt passiert folgendes mit der> Versorgungsspannung des PIC: Anlage>> Es bleiben weniger als 10 ms von Erkennung bis zum BOR übrig.> Zu wenig um das EEPROM zu beschreiben.
Dann musst du die Spannung vor dem 3.3V Regler messen um den Ausfall
rechtzeitig zu erkennen.
Tja das ist der Punkt wo auch in anderen kommerziellen Geräten mal noch
irgendwo ein Draht reingelötet wird.
Sascha
Sascha W. schrieb:> Dann musst du die Spannung vor dem 3.3V Regler messen um den Ausfall> rechtzeitig zu erkennen.>> Tja das ist der Punkt wo auch in anderen kommerziellen Geräten mal noch> irgendwo ein Draht reingelötet wird.
Ist leider mit einer Drahtbrücke alleine nicht getan.
Mindesetens ein Spannungsteiler aus 2 Widerständen müsste dann noch
rein.
LG Dirk