Hallo Forengemeinde,
ich habe ein grundelgendes Verständnissproblem und bin jetzt langsam
schon stinkesauer über mich, dass ich das nicht alleine gebacken
bekomme. Bitte klärt mich jemand mal auf, bevor ich das nächste Jahr
nicht mehr erlebe.
Folgendes Standard-Problem:
Ich möchte in einem ATMega128 verschiedene Werte abspeichern, damit die
erhalten bleiben.
Da das Teil später einen Bootloader bekommen soll, damit einfache
FW-Updates möglich sind, kann ich wohl diese - wohl zu 99% verwendete
EEPROM-Erweiterung
bekommen zwar eine 16bit-Adresse, aber die Funktionen in der eeprom.h
akzeptieren nur 8bit Address-Zeiger und deswegen wird hier wohl
gecastet.
Wenn ich jetzt aber die EEPReadByte mit z.B. 256 aufrufe, dann wird da
gecastet und die eeprom_read_byte bekommt als Paramter wieder nur 1....
Ich hoffe, dass ich mich verständlich ausdrücken konnte.
Vielen Dank im voraus und viele Grüße,
Michael
Neuling schrieb:> Wenn ich jetzt aber die EEPReadByte mit z.B. 256 aufrufe, dann wird da> gecastet und die eeprom_read_byte bekommt als Paramter wieder nur 1....
Das ist ein Missverständnis. Da wird nicht nach uint8_t gecastet,
sondern nach uint8_t* - also auf einen Pointer auf uint8_t.
Und ein Pointer ist ein Pointer ist ein Pointer - unabhängig von der
Größe des Objektes, auf das er zeigt.
Neuling schrieb:> Wenn ich jetzt aber die EEPReadByte mit z.B. 256 aufrufe, dann wird da> gecastet und die eeprom_read_byte bekommt als Paramter wieder nur 1....
Nein wird es nicht. Der 16-Bit unsigned Integer wird zu einem 16-Bit
breiten Zeiger gecastet, der auf einen uint8_t zeigt.
Gruß Oliver
Vielen Dank für die schnellen Antworten.
Leider verstehe ich es jetzt trotzdem noch nicht so ganz...
Wenn ich jetzt mal kurz in die "Win32"-Welt schweife, dann ist es ja so,
dass man nur bis 4GB adressieren kann, weil die Pointer da (ganz gleich
auf welchen Typ - int, struct, byte...) immer 4 Byte groß sind und somit
2^32 (eben 4GB) addressieren kann...
In der Atmega128-Welt befinden wir uns ja in einer 8Bit-Umgebung; also
sind die Pointer da auch alle 8 Bit groß. Das erklärt dann auch das
(uint8_t*)-gecaste...
In dem AVR-Tutorial steht ja ganz gut beschrieben, wie man das mit den
Registern dann macht (eben EEARH und EEARL benutzen). Somit hätte ich ja
meine 16 Byte; aber wie das AVR-GHCC macht, verstehe ich leider noch
nicht.
Ich glaub, ich seh den Wald vor lauter Bäumen nicht. Ist zwar peinlich,
aber ich sitze da jetzt echt schon 3 Stunden drüber. Ich glaube, ich
habe mich jetzt echt in eine Irr-Gedanken verrannt und verstehe gar
nichts mehr... Wo bekommt AVR-GCC die 16-Bit-Adresse her?
Sorry :-(
Neuling schrieb:
n 4GB) addressieren kann...
>> In der Atmega128-Welt befinden wir uns ja in einer 8Bit-Umgebung; also> sind die Pointer da auch alle 8 Bit groß. Das erklärt dann auch das> (uint8_t*)-gecaste...
Die Pointer sind nicht 8-Bit gross. Wie sollte uC denn sonst mit 128KB
Flash umgehen? Lies dir doch mal das datenblatt zu deinem uC-Core durch.
Einmal
drüber schlafen...
Ah, o.k.; das ist ja dann schon mal ein wichtiger Punkt... Ich bin echt
von 8Bit ausgegangen... Und auch, dass erst diese XMega dann 32bit
haben...
Und wie ist das dann also speziell in meinem Fall?
Nehmen wir an, ich will einen 1Byte-Wert an derdezimalen EEPROM-Adresse
2048 lesen, muss ich das dann mit den GCC-Funktionen so machen:
Statt die Bytes im EEPROM zu Fuss durchzunummerieren kannst du auch eine
einzíge Variable hinein legen. Die liegt dann immer an der gleichen
Adresse. Und diese Variable ist eine struct.
Neuling schrieb:> In der Atmega128-Welt befinden wir uns ja in einer 8Bit-Umgebung; also> sind die Pointer da auch alle 8 Bit groß.
die Größe des Pointers hat nichts mit den 8-Bit des Prozessors zu tun,
die 8-Bit sind die "Breite" der Daten,
die Adressen entsprechen der "Anzahl" der Daten.
Neuling schrieb:> uint16_t nAddr = 2048;> uint8_t nValue = eeprom_read_byte((uint8_t *)nAddr);
nAddr ist aber 2 Byte groß, du liest also nur die Hälfte davon
Bernd schrieb:> nAddr ist aber 2 Byte groß, du liest also nur die Hälfte davon
???? Super; und jetzt dachte ich echt kurz, dass ich es begriffen habe.
Und wie sieht es dann mit GCC richtig aus, wenn ich an EEPROM Adresse
2048 ein einziges Byte lesen will?
Bernd schrieb:> Neuling schrieb:>> uint16_t nAddr = 2048;>> uint8_t nValue = eeprom_read_byte((uint8_t *)nAddr);>> nAddr ist aber 2 Byte groß, du liest also nur die Hälfte davon
Er möchte EIN byte von der EEPROM-Adresse 2048. Welche Hälfte verpasse
ich?
Coder schrieb:> uint16_t nAddr = 2048;> uint8_t nValue = eeprom_read_byte((uint8_t *)nAddr);>> Sollte funktionieren.
ach das ist gemeint, die unnötige Variable hat mich verwirrt,
dann würde ich es aber so schreiben:
uint8_t nValue = eeprom_read_byte((uint8_t *)2048);
Grrr. Ich dreh jetzt echt bald durch... Ich habe auch keine Ahnung, wie
man sowas debuggen kann... Im Anhang habe ich jetzt mal ein kurzes
Demo-Projekt, dass eigentlich was Vernüntiges tun hätte sollen...
Tut es aber nicht.
Kurzfassung: Zuerst lese ich ein Byte ein und vergleiche es mit 0xFF
(dem default eines uninitialisierten Speichers).
Wenn dort ein Wert ungleich 0xFF ist, lese ich bis zur Null-Terminierung
und gebe den String zurück;
Beim Schreiben habe ich noch versucht, diese
1
eeprom_update_byte(&eeFooByte,myByte);
Funktionalität mit einzubauen...
Der Test sollte bei einem frischen ATMega128 also etwas in der Art
liefern:
1
StarteEEPROM-Test...
2
LesePIN-Wertaus...
3
KonntekeinePINlesen(1.Durchlauf??)
4
SchreibejetztPIN0815
5
Fertig;jetzterneutlesen:DiegelesenePINlautet:0815
Dann, nach einem Reset oder generellem Neustart sollte sowas kommen:
1
StarteEEPROM-Test...
2
LesePIN-Wertaus...
3
DiegelesenePINlautet:0815
4
SchreibejetztPIN0815
5
Fertig;jetzterneutlesen:DiegelesenePINlautet:0815
Hm, aber was kommt:
1
StarteEEPROM-Test...
2
LesePIN-Wertaus...
3
KonntekeinePINlesen(1.Durchlauf??)
4
SchreibejetztPIN0815
5
Fertig;jetzterneutlesen:
6
KonntekeinePINlesen(JetztechterFehler)
Wie finde ich jetzt heraus, ob das Lesen oder das Schreiben (oder
beides? :-() nicht geklappt hat?
Was ich noch vergessen habe, im Code jetzt für diese "Veröffentlichung"
zu dokomentieren: In der "ReadStringFromEEPROM()"-Funktion mache ich im
Fehlerfall ein memset mit dem Wert 0x30; das ist nur, dass ich beim
"Debuggen" sehen konnte, ob da dann 50 "0er" drin stehen (was auch der
Fall ist).
Später kommt dann da wieder 0xFF rein, um den "Gelöscht-Zustand"
herbeizuführen. Also bitte nicht verwirren lassen; im Eifer des Gefechts
habe ich den Kommentar jetzt leider vergessen.
O.k.; ich sollte jetzt doch schlafen gehen. Ich habe eben einen schweren
Fehler in der Read... gefunden (überschreibe immer wieder das erste Byte
im Puffer); mal sehen, ob ich den nich fixe.
An alle erstmal recht herzlichen Dank für Eure Unterstützung.
O.k., Fehler behoben; anbei die verbesserten und lauffähigen Sourcen
(für den Fall, dass jemand mal die gleichen Probleme hat wie ich jetzt
am Anfang :-))
Das neue Jahr kann kommen :-)
Nochmals danke für die Erklärungen.