Forum: Mikrocontroller und Digitale Elektronik EEPROM mit Interrupt oder Polling beschreiben / auslesen?


von Dorean (Gast)


Lesenswert?

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!

von Dorean (Gast)


Lesenswert?

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.

von Ulrich P. (uprinz)


Lesenswert?

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

von Dorean (Gast)


Lesenswert?

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.

von Reinhard Kern (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Ulrich P. (uprinz)


Lesenswert?

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

von Dorean (Gast)


Lesenswert?

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 (solange Bit für beschäftigt gesetzt ist) 
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?

von Dorean (Gast)


Lesenswert?

Als Takt benutze ich 1,8 MHz zum Beschreiben (Systemtakt).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.