Morgen zusammen!
Mal eine Frage: Wie beschreibt / lest ihr eure EEPROMs? Macht ihr eine
Funktion, in der der Controller ann erstmal solange hängt, bis alles
fertig ist, oder macht ihr es in der Form von einem Array, in dem die zu
schreibenden Daten gespeichert sind und schickt eines los und per
"fertige-übertragenes-Zeichen"-Interrupt holt sich die ISR automatisch
das nächste Zeichen?
Ich bin mir grad nicht sicher, wie ich es am besten machen soll - der
Controller könnte ja in der Zeit was anderes machen und die Übertragung
würde von alleine vonstatten gehen. Wenn ich zum Beispiel jetzt eine
komplette Page von 64Byte übertrage, dann wäre die Wartezit ja schon
beträchtlich.
Gruß und Danke!
Achso, sorry, mit Polling meine ich natürlich, dass ich in der Funktion
zum Beschreiben des EEPROMs bin und halt in einer Schleife ständig das
IFG pollen muss, um zu gucken, ob der Buffer wieder frei ist.
Was für ein EEPROM?
Das in einem uC wird ganz anders behandelt als das an einem SPI- oder
I2C- Bus.
Im uC:
Je nach Controller 1..n Bytes schreiben und per IRQ auf "Fertig" warten.
Dann weiter schreiben. Dabei ein Flag setzen, dass das EEPROM im Zugriff
ist, sonst liest man womöglich aus anderen Teilen der Firmware noch alte
oder nur teilweise aktulisierte Daten.
I2C / SPI
Bei I2C schreibt man immer Teiler einer Page oder eine komplette Page in
das EEPROM, dann ist es busy, was man daran merkt, dass es sich am Bus
nicht mehr meldet. Also per ACK-Polling regelmäßig nachfragen, ob es
sich zurück gemeldet hat. Auch hier aufpassen, dass man keine veralteten
Daten liest, weil sie noch nicht überschrieben wurden.
habe noch nie ein SPI EEPROM genutzt, aber ich vermute, dass es sich
entweder ähnlich verhält, oder ein Busy-Flag hat.
Das Problem mit den alten Daten kann man umgehen, wenn man ein Shadow
RAM nutzt, das die aktuellen Daten beinhaltet. Es wird immer
aktualisiert und aus ihm heraus, werden Zyklisch die Daten ins EEPROM
kopiert, natürlich nur, wenn etwas geändert wurde. Das Lesen läuft immer
über das Shadow, damit sind die Daten immer aktuell und auch nicht durch
einen langsamen Bus verzögert.
Gruß, Ulrich
Danke schonmal!
Sorry, die Info übers EEPROM hab ich mal direkt zurückgehalten. Es ist
ein SPI-EEPROM.
Also du meinst, ich sollte alle relevanten Daten stets im RAM speichern?
Das EEPROM ist 256k groß, davon ist natürlich nicht alles stets
relevant, sondern es sind größtenteils Messdaten, die ich zyklisch
speichern will. Dies müsste auf Grund der Größe dann jedoch direkt
passieren, da ich soviel RAM selbtsverständlich nicht habe.
Hallo,
Messdaten im RAM geht sinnvollerweise nicht, gemeint waren die Variablen
des Programms, falls nach Stromausfall ein Wiederanlauf nötig ist.
Für die Messdaten würde ich eine Art einfache Zustandsmaschine nehmen: 0
= idle, gibt nix zu tun. Wenn Messdaten zu schreiben sind, ans EEProm
schicken und Zustand = 1, sonst läuft alles normal weiter, aber von Zeit
zu Zeit (Timer ISR) prüfen, ob EEProm wieder bereit. Wenn ja EEProm
lesen und mit RAM vergleichen, wenn gleich, Zustand wieder 0 und
Messdaten im RAM löschen.
Man kann die Daten im Ram auch erst löschen, wenn der verfügbare RAM
überläuft. Fehler muss man natürlich merken, man kann auch einen
weiteren Block schreiben und den Zustand auf 2 setzen - nützt aber nix,
wenn das EEProm kaputt ist.
Gruss Reinhard
PS die Ursprungsfrage habe ich ganz vergessen - ob man im Zustand 1 per
Timer-ISR pollt oder auf einen IRQ vom EEProm wartet, ist ziemlich egal.
Für meinen Geschmack ist Polling ein kleines bisschen sicherer, und der
Aufwand für einen zusätzlichen IRQ (Hardware und Software) entfällt.
Dorean schrieb:> Wenn ich zum Beispiel jetzt eine> komplette Page von 64Byte übertrage, dann wäre die Wartezit ja schon> beträchtlich.
Ich benutze nur I2C EEPROM (24C512) und da dauert eine Page oder ein
Byte gleichlang (~5ms).
Nach dem Schreiben der Page kannst Du sofort was anderes machen. Der
EEPROM macht den Rest intern. Er stellt sich für ~5ms tot.
Peter
Das sollte auch bei SPI EEPROMs nicht anders sein, auch sie puffern
zuerst die nicht überschriebenen Daten einer Page, übernehmen die neuen
Daten und schreiben dann die ganze Page zurück.
Das Polling kann ruhig jede Millisekunde passieren und sollte bis zur
maximalen Flash-Zeit plus etwas extra probiert werden. Erst dann mmuss
ein Fehlermechanismus greifen und das Problem anzeigen.
Die Programmierzeit variiert mit der Versorgungsspannung, dem Alter und
der Temperatur der Speicher. Ein neues EEPROM hat die Daten gerne schon
mal nach 2.5ms geschrieben, ein altes braucht 4ms. Nach 15ms meldet
meine Firmware, dass es keinen Sinn mehr macht.
Wer Messdaten zuverlässig und oft schreiben will, der kann ja auch auf
FRAM umsteigen. Die altern nicht und brauchen auch den Delay nach dem
Schreiben nicht. Sind aber natürlich deutlich teurer als vergleichbare
EEPROMs.
Dafür ist die Ansteuerung identisch zum EEPROM ( I2C oder SPI).
Gruß, Ulrich
Also da melde ich mich nochmal zurück.
Ich habe jetzt ein bisschen rumprobiert mit Pageweisem schreiben und
eben einzelne 8-Bitter. Da muss ich meine Aussage von oben mal direkt
zurückziehen!
Wenn ich Byteweise schreibe, dann dauert mein gesamter Vorgang ca. 57s.
Darin beeinhaltet ist:
64 Bytes erzeugen in einem Array
Dann geht es los...
Prüfen ob EEPROM noch intern beschäftigt ist
Schreibbefehl senden
1 Byte schreiben aus Array
Gegen Beschreiben sichern
Dann wieder prüfen, ob noch beschäftigt
Lesebefehl senden
1 Bytes lesen in ein anderes Array
Gelesene und geschriebene Bytes auf Gleichheit überprüfen
Das sende-Array einmal komplett verändern
Addresse um eins erhöhen
...und ab da das ganze von vorne, bis ich alle 32768 Adressen einmal
geschrieben und wieder gelesen habe und dabei eben auch auf Konsitenz
überprüft habe.
So: Wenn ich nun anstatt des einen Bytes jeweils eine Page, also direkt
64 Bytes schreibe, so dauert dieser gesamte Vorgang gerade mal 2,8s!
Was halt aufhält ist das ständige Prüfen auf Bereitschaft des EEPROMs,
jedoch ohne bekomme ich ohne diese Prüfung nur Bytefehler.
Und hier lag auch die Frage mit dem Interrupt-gesteuertem Beschreiben,
da ich momentan ja in Form von
1
while(solangeBitfürbeschäftigtgesetztist)
2
{}
das weitere vorgehen in einer Null-Nummern-Schleife ausbremse und der
Controller nichts anderes machen kann.
Interruptgesteuert habe ich es auch schon probiert, jedoch ist das super
kompliziert, da zwischen den RX und TX-Interrupts ständig Variablen
übergeben werden müssen, damit alles richtig abläuft.
Dazu kommt, dass wenn mir ein anderer Interrupt dazwischen haut, ich
nicht sicher sein kann, dass noch alles richtig funktioniert. In der
Zeit Interrupts immer disablen will ich auch nicht, da andere Interrupts
von Timern wesentlich wichtiger sind.
Müsste man nicht immer senden um auch was zu empfangen, wäre das ganze
einfacher ; ) (finde ich) - aber nunja, so ist es nunmal! Nur leider
erzeugt das Senden halt einen Interrupt, wenn der Puffer wieder frei
ist, und das Empfangen, wenn ein Zeichen da ist.
Ich kann also nicht z.b. im Sende-Interrupt direkt den RX-Puffer
auslesen, da ein freier Sendepuffer nicht automatisch ein empfangenes
Zeichen sicherstellt.
Was meint ihr dazu?