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 (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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.