Forum: Mikrocontroller und Digitale Elektronik EEPROM Adressen über 255


von Neuling (Gast)


Lesenswert?

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
1
uint8_t eeFooByte EEMEM = 123;
nicht benutzen und muss den EEPROM-Speicher selbst verwalten.
Siehe hierzu:
Beitrag "Re: Konfiguration in EEPROM speichern"

Ich "muss" wohl wissen, wo welche Werte liegen, weil ich diesen 
Bootloader hier:
Beitrag "MMC/SD Bootloader füt ATMega128"
verwenden will, der Versionsnummern etc. an einer bestimmten Stelle 
erwartet.

Also wollte ich erste Tests nach dieser Beschreibung hier machen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Direkter_Zugriff_auf_EEPROM-Adressen

Was ich jetzt aber nicht verstehe: Wie addressiere ich Bereiche größer 
255?
Die hier angegebenen Funktionen:
1
#include <avr/eeprom.h>
2
 
3
// Byte aus dem EEPROM lesen
4
uint8_t EEPReadByte(uint16_t addr)
5
{
6
  return eeprom_read_byte((uint8_t *)addr);
7
}
8
 
9
// Byte in das EEPROM schreiben
10
void EEPWriteByte(uint16_t addr, uint8_t val)
11
{
12
  eeprom_write_byte((uint8_t *)addr, val);
13
}

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Oliver J. (skriptkiddy)


Lesenswert?

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

von Neuling (Gast)


Lesenswert?

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 :-(

von Coder (Gast)


Lesenswert?

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...

von Neuling (Gast)


Lesenswert?

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:
1
uint16_t nAddr = 2048;
2
uint8_t nValue = eeprom_read_byte((uint8_t *)nAddr);

von (prx) A. K. (prx)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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

von Neuling (Gast)


Lesenswert?

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?

von Coder (Gast)


Lesenswert?

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?

von Coder (Gast)


Lesenswert?

1
uint16_t nAddr = 2048;
2
uint8_t nValue = eeprom_read_byte((uint8_t *)nAddr);

Sollte funktionieren.

von Bernd (Gast)


Lesenswert?

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);

von Neuling (Gast)


Angehängte Dateien:

Lesenswert?

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
Starte EEPROM-Test...
2
Lese PIN-Wert aus...
3
Konnte keine PIN lesen (1. Durchlauf??)
4
Schreibe jetzt PIN 0815
5
Fertig; jetzt erneut lesen: Die gelesene PIN lautet: 0815

Dann, nach einem Reset oder generellem Neustart sollte sowas kommen:
1
Starte EEPROM-Test...
2
Lese PIN-Wert aus...
3
Die gelesene PIN lautet: 0815
4
Schreibe jetzt PIN 0815
5
Fertig; jetzt erneut lesen: Die gelesene PIN lautet: 0815


Hm, aber was kommt:
1
Starte EEPROM-Test...
2
Lese PIN-Wert aus...
3
Konnte keine PIN lesen (1. Durchlauf??)
4
Schreibe jetzt PIN 0815
5
Fertig; jetzt erneut lesen:
6
Konnte keine PIN lesen (Jetzt echter Fehler)

Wie finde ich jetzt heraus, ob das Lesen oder das Schreiben (oder 
beides? :-() nicht geklappt hat?

von Neuling (Gast)


Lesenswert?

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.

von Neuling (Gast)


Lesenswert?

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.

von Neuling (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Oliver J. (skriptkiddy)


Lesenswert?

Neuling schrieb:
> Und auch, dass erst diese XMega dann 32bit
> haben...

Da steckt auch nur ein AVR-Core drinnen. Also 16-Bit.

Gruß Oliver

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.