Forum: Compiler & IDEs EEPROM avr-libc Read/Write-Funktionen Warnung


von Karsten B. (karstenbrandt)


Lesenswert?

Hallo Gemeinde,

ich habe ein Verständnisproblem (wohl auch eine Bildungslücke) mit den 
eeprom_read_dword(..) bzw. eeprom_write_dword(..).
Entwicklungsumgebung: AVR Studio 7.0 mit ATxmega32A4u.

Hier mein Programmcode (der Sinn der Funktion ist nicht weiter wichtig):
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword((const uint32_t*)uC_FlashReadFrom); //Warnung hier
6
  temp2 = eeprom_read_dword((const uint32_t*)uC_FlashReadFrom); //und hier
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}

Der Compiler gibt hier eine Warnung aus:
cast to pointer from integer of different size [-Wint-to-pointer-cast]

Nach meinen Recherchen gibt es wohl folgende Lösung:
1
temp1 = eeprom_read_dword((const uint32_t*)(uint16)uC_FlashReadFrom)

Die Funktion eeprom_read_dword benötigt ja eine Adresse einer Variable, 
die die Adresse des EEPROMS als Wert enthält, die gelesen werden soll. 
Durch den cast (uint16_t) mache ich aber aus der
1
uint32_t
 einen
1
uint16_t
, d.h. die oberen beiden bytes werden abgeschnitten.
1
(uint32_t*)
 gibt dann wieder an, dass ab der Adresse 32bit (d.h. 4 Byte) gelesen 
und als
1
 uint32_t
 interpretiert wird.
Was ich nicht verstehe ist, warum erst nach
1
(uint16_t)
 gecastet  werden muss? Führt das casten auf
1
(uint16_t)
 nicht zu Problemen bei EEPROM-Adressen >655535 (sofern es überhaut 
controller mit soviel EEPROM gibt)?

Danke und VG

Karsten

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karsten B. schrieb:
> Was ich nicht verstehe ist, warum erst nach
1
(uint16_t)
 gecastet
> werden muss?

Adressen bei avr-gcc sind 16 Bits lang.  Warum übergibst du ein 32-Bit 
Skalar anstatt einer Adresse?

von Karsten B. (karstenbrandt)


Lesenswert?

Hallo Johann,

vielen Dank für die Rückmeldung.

Ein Skalar finde ich persönlich lesbarer. Wenn ich DIch da richtig 
verstehe, meinst Du so etwas, oder?:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t *uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung hier
6
  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}

Wie würdest Du die Funktion sonst gestalten?

Nur das ich das richtig verstehe: Bei 16-bit Zeigern sind dann auch nur 
max.65K EEPROM adressierbar?

Gruß

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karsten B. schrieb:
> Ein Skalar finde ich persönlich lesbarer.

Dann solltest du Prosa schreiben oder Gedichte anstatt Programmcode.

> temp1 = eeprom_read_dword(uC_FlashReadFrom);
> temp2 = eeprom_read_dword(uC_FlashReadFrom);

Okay, reimt sich schon mal. Also lieber Gedichte.

von Karsten B. (karstenbrandt)


Lesenswert?

Wie wärs denn mal mit einer richtigen Antwort.
Ich bitte ja nicht aus lange Weile um Hilfe.

Die Frage stellt sich nicht nur mir!!

Da Du dich nicht so ganz klar ausgedrückt hast, was an welcher Stelle 
übergeben werden sollte, bin ich sicher nicht der Einzige, der Gedichte 
schreiben sollte.

Ich denke, es ist so gemeint:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t *uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword(&uC_FlashReadFrom); //Warnung hier
6
  temp2 = eeprom_read_dword(&uC_FlashReadFrom); //und hier
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ist mir neu dass es AVRs mit so großem EEprom gibt.

Fakt ist, dass Zeiger 16 Bits groß sind, was einen maximalen Adressraum 
von 64KiB für EEprom, RAM und Flash (Daten) gibt sowie 2*64KiB für Code.

Wenn du darüber hinauswillst musst du Verrenkungen machen, außer beim 
Code.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Karsten Brandt (karstenbrandt)

>Ein Skalar finde ich persönlich lesbarer.

Hä? Ein Skalar ist aber keine Adresse!
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t *uC_FlashReadFrom)

Genau so! Aber du liest nicht vom Flash, sondern vom EEPROM. Das sollte 
in den Namen zum Ausdruck kommen.

>{
>  uint32_t temp1=0, temp2=0;
>  //Get actual EEPROM Read address
>  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung hier
>  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier


>  if(temp2==temp1)

Warum liest du 2x? Denkst du, da wackelt was? Wenn du einen Fehler im 
EEPROM hast, wirst du meistens 2x den gleichen Wert lesen. Dagegen hilft 
nur CRC bzw. FEC.

>  {
>    *pReturnAddress=temp1;

Auch das ist eine maximal irreführende Bezeichung.

>Wie würdest Du die Funktion sonst gestalten?

So wie oben.

>Nur das ich das richtig verstehe: Bei 16-bit Zeigern sind dann auch nur
>max.65K EEPROM adressierbar?

Reicht doch, soviel hat der AVR so oder so nicht. Selbst Zeiger im Flash 
und RAM sind nur 16 Bit.

von Falk B. (falk)


Lesenswert?

@ Karsten Brandt (karstenbrandt)
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t *uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword(&uC_FlashReadFrom); //Warnung hier
6
  temp2 = eeprom_read_dword(&uC_FlashReadFrom); //und hier

SO NICHT! Die Adresse des Pointers willst du dort sicher NICHT haben, 
sondern den Pointer an sich. Vorher war es richtig!

von Karsten B. (karstenbrandt)


Lesenswert?

Hallo FAlk,

vielen Dank für die qualifizierte Antwort :)

Ja, die Namensgebung sollte da noch angepasst werden.

Stimmt, ein Skalar ist keine Adresse. In der Variablen soll ja auch die 
Adresse übergeben werden, aus der im EEPROM gelesen werden soll.
Was mich nur etwas irritiert hat ist, dass die Funktion
1
eeprom_read_dword(uint32_t*)
einen Zeiger auf eine 32 Bit variable verlangt. Mein Verständnis ist 
nun, dass ich der Funktion ein uint32_t-Variable übergebe, die die 
anzusprechende Speicherstelle im EEPROM enthält. Die Übergabe an den 
pointer im Argument von eeprom_read_dword erfolgt doch mit dem 
&-Operator.
Die Funktion eeprom_read_dword() sollte sich dann den Wert holen.

eigentlich müsste die Zeile dann lauten:
1
temp1 = eeprom_read_dword(&uC_FlashReadFrom);

Das bedeutet:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword(&uC_FlashReadFrom); //kein Warnung mehr
6
  temp2 = eeprom_read_dword(&uC_FlashReadFrom); //und hier auch nicht
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}

Gruß

P.S. Habe es gerde ausprobiert: Die Warnungen sind weg. Da habe ich den 
Wald vor lauter Bäumen nicht gesehen.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karsten B. schrieb:
> Was mich nur etwas irritiert hat ist, dass die Funktion
>
>
1
eeprom_read_dword(uint32_t*)
> einen Zeiger auf eine 32 Bit variable verlangt.

Ja, die Funktion will den Zeiger AUF einen 32-Bit Wert, was aber nicht 
bedeutet, dass der Zeiger SELBST 32 Bits hat oder haben muss.  Alles, 
was links vom "*" steht, gehört zum "Zeiger auf".  Genauer ist der 
Prototyp der Funktion
1
uint32_t eeprom_read_dword (const uint32_t *addr)
d.h. das, was an addr steht, wird durch die Funktion nicht verändert.
Auch möglich wäre
1
uint32_t eeprom_read_dword (const void *addr)
also "Zeiger auf irgendwas", der dann von der Auslesefunktion als 
"Zeiger AUF einen 32-Bit Wert" uminterpretiert wird.


> uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t
> uC_FlashReadFrom)
> {
>   uint32_t temp1=0, temp2=0;
>   //Get actual EEPROM Read address
>   temp1 = eeprom_read_dword(&uC_FlashReadFrom); //kein Warnung mehr

Nein, auf gar keinen Fall &uC_FlashReadFrom.  Das macht folgendes: Es 
nimmt die Adresse von uC_FlashReadFrom, also die Adresse einer lokalen 
Variable von FLASH_LoadAddressPointer.  Diese Variable liegt irgendwo 
auf dem Stack, also im SRAM.  Diese Adresse wird dann an 
eeprom_read_dword übergeben, welches die so übergebene Adresse als 
EEPROM-Adresse interpretiert.

Richtig wäre z.B
1
#include <stdint.h>
2
#include <avr/eeprom.h>
3
4
uint32_t ee_wert EEMEM = 123; // Section ".eeprom"
5
6
uint32_t test (const uint16_t *pee_wert)
7
{
8
    return eeprom_read_dword (&ee_wert) + eeprom_read_word (pee_wert16);
9
}

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Karsten Brandt (karstenbrandt)

>Stimmt, ein Skalar ist keine Adresse.

Der erste Schritt zur Erkenntnis.

> In der Variablen soll ja auch die
>Adresse übergeben werden, aus der im EEPROM gelesen werden soll.

Dann tu das doch einfach.

>eigentlich müsste die Zeile dann lauten:

>temp1 = eeprom_read_dword(&uC_FlashReadFrom);

NEIN! Kauf dir ein C-Buch und studiere die Grundlagen von Pointern und 
Variablen. Ist sicher nicht ganz trivial, aber machbar.


>Das bedeutet:

>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t 
>uC_FlashReadFrom)
>{
>  uint32_t temp1=0, temp2=0;
>  //Get actual EEPROM Read address
>  temp1 = eeprom_read_dword(&uC_FlashReadFrom); //kein Warnung mehr
>  temp2 = eeprom_read_dword(&uC_FlashReadFrom); //und hier auch nicht

FALSCH! Sagte ich bereits!

&uC_FlashReadFrom ist hier die Adresse der lokalen Variablen (Skalar!) 
uC_FlashReadFrom. Die interessiert kein Mensch. Du willst den INHALT 
eines Pointers!
1
uint8_t FLASH_LoadAddressPointer(uint32_t *ptarget, uint32_t *readData)
2
  *ptarget = eeprom_read_dword(readData);

SO und nicht anders!

>P.S. Habe es gerde ausprobiert: Die Warnungen sind weg.

Ist trotzdem falsch! So einen Fehler kann kein Compiler der Welt 
erkennen, es sei denn man nutzt den -DAULEVEL9 Schalter!

> Da habe ich den
>Wald vor lauter Bäumen nicht gesehen.

Dir fehlen elementare Grundlagen.

von Karsten B. (karstenbrandt)


Lesenswert?

Gut, da scheint es noch Lücken zu geben.
Vielen Dank für die Rückmeldungen.

Trotdem sollte es aber richtig sein, dass ein Zeiger eine Adresse 
speichert, die mit dem &-Operator übergeben wird.
1
int i=5;
2
int *pzeiger;
3
4
pzeiger = &i;

Mit Funktionen genau so (call by reference):
1
int foo(int *pWert)
2
{
3
  //mach was mit pWert
4
}
5
6
int x=6;
7
8
foo(&x);

So hatte ich das verstanden. Und das ist auch richtig und hat bisher 
immer gut funktioniert.
Die Vorschläge von Euch werde ich nochmal sacken lassen. Ich werde 
nochmal lesen und die Lücken schliessen.
 Genau dieser Punkt sorgt auch bei manch anderen für Verwirrung.

Trotzdem nochmal vielen Dank :)

von Karsten B. (karstenbrandt)


Lesenswert?

Habe meinen Fehler gefunden:

Es war ein Denkfehler bei der Funktion
1
eeprom_read_dword(uint_32* __p)

Habe mir die Doku hierzu nochmal durchgelesen. Da habe ich wohl doch 
noch ein Verständnisproblem gehabt.
Man muss dem Zeiger __p die Adresse aus dem EEPROM zuweisen, von der man 
lesen möchte. Daher muss tatsächlich der Wert der Variablen dem Zeiger 
zugewiesen werden:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  //Erst den übergebenen Wert nach 16-Bit (uint16_t) casten, da pointer im AVR = 16 Bit
6
  //Dann den Inhalt der Variablen 'uC-FlashReadFrom' (=der zu lesenden Adresse im Flash) 
7
  //dem Pointer __P von eeprom_read_dword() zuweisen.
8
  // Der Zeiger zeigt auf einen Wert vom Typ unit32_t (=dword)
9
  temp1 = eeprom_read_dword((const uint32_t*)(uint16_t)uC_FlashReadFrom); 
10
  temp2 = eeprom_read_dword((const uint32_t*)(uint16_t)uC_FlashReadFrom);
11
  
12
  if(temp2==temp1)
13
  {
14
    *pReturnAddress=temp1;
15
    return 0;
16
  }
17
  
18
  return 1;
19
}

Zum Beispiel:
1
uint32_t Adresse = 50;
2
uint32_t AdresseImExternenFlash;
3
4
FLASH_LoadAddressPointer(&AdresseImExternenFlash, Adresse)

Dann macht das auch alles einen Sinn. Ich hoffe das ist halbwegs 
verständlich wiedergegeben.

von Falk B. (falk)


Lesenswert?

@ Karsten Brandt (karstenbrandt)

>Habe meinen Fehler gefunden:

Wirklich?

>Habe mir die Doku hierzu nochmal durchgelesen. Da habe ich wohl doch
>noch ein Verständnisproblem gehabt.

Das hast du immer noch.

>Man muss dem Zeiger __p die Adresse aus dem EEPROM zuweisen, von der man
>lesen möchte.

Ja.

> Daher muss tatsächlich der Wert der Variablen dem Zeiger
> zugewiesen werden:

Irreführende Formulierung! Man muss den ZEIGER übergeben.

>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t 
>uC_FlashReadFrom)

Du hast irgendwie einen Hang zum Murks. SO NICHT!

>  //Erst den übergebenen Wert nach 16-Bit (uint16_t) casten, da pointer >im AVR = 
16 Bit
>  //Dann den Inhalt der Variablen 'uC-FlashReadFrom' (=der zu lesenden >Adresse 
im Flash)
>  //dem Pointer __P von eeprom_read_dword() zuweisen.
>  // Der Zeiger zeigt auf einen Wert vom Typ unit32_t (=dword)
>  temp1 = eeprom_read_dword((const uint32_t*)(uint16_t)uC_FlashReadFrom);

Murks^3!!!

>uint32_t Adresse = 50;
>uint32_t AdresseImExternenFlash;

Du murkst schon wieder. Bei eeprom_read_??? geht es um INTERNEN EEPROM, 
keinen externen Flash. Das muss man trennen. Sonst kommt so wie bei dir 
Murks raus!

>FLASH_LoadAddressPointer(&AdresseImExternenFlash, Adresse)

Nein!

>Dann macht das auch alles einen Sinn. Ich hoffe das ist halbwegs
>verständlich wiedergegeben.

Ist aber falsch!



von Falk B. (falk)


Lesenswert?

@  Karsten Brandt (karstenbrandt)

Es gibt 2 Möglichkeiten.

1.) Sauber und lehrbuchgerecht.

1
uint8_t FLASH_LoadAddressPointer(uint32_t *pTarget, uint32_t *pSource)
2
{
3
  *pTarget = eeprom_read_dword(pSource); 
4
}
5
6
7
uint32_t my_test EEMEM;    // Variable im EEPROM, vom Compiler verwaltet
8
9
int main(void) {
10
  FLASH_LoadAddressPointer(&my_test);
11
}


2.) Leicht gefrickelt und häßlich

1
uint8_t FLASH_LoadAddressPointer(uint32_t *pTarget, uint16_t Source_adr)
2
{
3
  *pTarget = eeprom_read_dword((uint32_t *)Source_adr); 
4
}
5
6
7
uint32_t my_test EEMEM;    // Variable im EEPROM, vom Compiler verwaltet
8
9
int main(void) {
10
  FLASH_LoadAddressPointer((uint16_t)&my_test);
11
}

Hier geht es um INTERNEN EEPROM! Der unterliegt auch der Verwaltung des 
Compilers, also sollte man sich an die Konventionen halten (Lehrbuch!) 
und dem Compiler nicht im Wege stehen und seinen Job machen lassen.
Bei internem Flash, welcher auch vom Compiler verwaltet wird ist das 
ebenso.

Wenn man EXTERNEN Flash ansprechen will, der NICHT direkt vom Compiler 
verwaltet werden kann (serieller Flash, paralleler Flash mit manueller 
Ansteuerung), dann kann man das auch so machen. Hab ich auch schon 
getan, ist HIER auch voll OK.

Externer Flash ausserhalb der Compilerverwaltung.

1
uint8_t FLASH_LoadAddressPointer(uint32_t *pTarget, uint32_t Source_adr)
2
{
3
  uint8_t a,b,c,d;
4
5
  // Beispiel EEPROM mit SPI Anschluss
6
7
  cs_low();
8
  spi_io(0x03);   // Read command;
9
  spi_io(Source_adr>>16);  // 24 Bit address
10
  spi_io(Source_adr>>8);
11
  spi_io(Source_adr>>0);
12
  spi_io(0);        // Dummy
13
  a=spi_io(0);  
14
  b=spi_io(0);
15
  c=spi_io(0);
16
  d=spi_io(0);
17
  cs_high();
18
19
  *pTarget = (uint32_t)a<<24 | (uint32_t)b<<16 | (uint32_t)c<<8 | (uint32_t)a;
20
}
21
22
23
uint32_t my_ext_flash_adr;    // Normale Variable im RAM, enthält eine aber Adresse von Daten im externen Flash, sie ist KEIN C-Pointer!
24
25
int main(void) {
26
  FLASH_LoadAddressPointer(0x123456);
27
  FLASH_LoadAddressPointer(my_ext_flash_adr);
28
}


Capice?

von Karsten B. (karstenbrandt)


Lesenswert?

Hallo Falk,

wie eingangs erwähnt, sind die Namensgebungen für meine Frage nicht von 
Bedeutung. Aber zum Hintergrund: Am Controller hängt ein externes SPI 
Flash mit 32 MBit, das als Ringbuffer verwendet wird. Die aktuellen 
input- und outputzeiger vom BUffer werden im internen EEPROM abgelegt 
bzw. gesichert. Im Programm wird mit einer Arbeitskopie gearbeitet. 
Daher ist die Namensgebung in meinem Kontext durchaus sinnvoll.

Ich gehe ja auch noch mit, dass es sauber ist, das so zu machen:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pTarget, uint32_t *pSource)

Dann muss ich allerdings beim Aufruf der Funktion den 2. Parameter 
casten, da sonst eine Warnung ausgegeben wird:
1
 uint32_t Adresse=100;
2
 uint32_t FlashOutPointer;
3
4
 FLASH_LoadAddressPointer(&FlashOutPointer, (uint32_t*)(uint16_t)Adresse)

Daher habe ich mich für die 2. Möglichkeit entschieden, damit das Casten 
dann in der Funktion FLASH_LoadAddressPointer(..) zentral erledigt wird. 
Zugegeben, nicht ganz elegant und nach Lehrbuch. An dieser Stelle ist 
tatsächlich noch Verbesserungspotential, da hast Du recht.

Der Unterschied zwischen internen EEPROM, internen Programmflash und 
externen Flash ist mir schon bewusst. Die Applikation läuft ja 
schließlich. Ich wollte eigentlich nur die Compilerwarnungen verstehen 
und beseitigen.
Das Problem der Compilerwarnung war, das ein Pointer beim AVR nur 16-Bit 
breit ist, d.h. man muss auf (uint16_t) casten, wenn der übergebende 
Zeiger ungleich uint16_t* ist.

Übrigens: eine sehr schöne Zusammenfassung in Deinem letzten Post.

Problem gelöst. Thread kann geschlossen werden.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Karsten Brandt (karstenbrandt)


>wie eingangs erwähnt, sind die Namensgebungen für meine Frage nicht von
>Bedeutung.

Jain. Eine unklare Sprache führt zu unklarem Denken!

> Aber zum Hintergrund: Am Controller hängt ein externes SPI
>Flash mit 32 MBit, das als Ringbuffer verwendet wird.

AHA! Da hatte ich mal wieder den richtigen Riecher!

> Die aktuellen
>input- und outputzeiger vom BUffer werden im internen EEPROM abgelegt
>bzw. gesichert. Im Programm wird mit einer Arbeitskopie gearbeitet.
>Daher ist die Namensgebung in meinem Kontext durchaus sinnvoll.

Jetzt schon.

>Ich gehe ja auch noch mit, dass es sauber ist, das so zu machen:

>uint8_t FLASH_LoadAddressPointer(uint32_t *pTarget, uint32_t *pSource)

Ja


>Dann muss ich allerdings beim Aufruf der Funktion den 2. Parameter
>casten, da sonst eine Warnung ausgegeben wird:

Nö, du musst dich mal auf den Hosenboden setzen und Grundlagen lernen!

SO geht es sauber ohne Warnungen und sinnlose Casts

[c]
 uint32_t FlashOutPointer_nv EEMEN = 100;   // Sicherung im EEPROM, 
Zugriff nur über eeprom_read_dword();
 uint32_t FlashOutPointer;                  // Arbeitskopie im RAM

 FLASH_LoadAddressPointer(&FlashOutPointer, &FlashOutPointer_nv)
[c]

>Daher habe ich mich für die 2. Möglichkeit entschieden, damit das Casten
>dann in der Funktion FLASH_LoadAddressPointer(..) zentral erledigt wird.

Weil du einen starken Drang zum Murks hast? Cast sollte man immer sehr 
sparsam einsetzen und WIRKLICH wissen was man tut. Einfach den Compiler 
totcasten damit er Ruhe gibt ist selten guter Stil.

>Zugegeben, nicht ganz elegant und nach Lehrbuch. An dieser Stelle ist
>tatsächlich noch Verbesserungspotential, da hast Du recht.

Warum nicht lehrbuchartig? Weniger Schreibarbeit und schöner UND 
allgemein anerkannt. Zu langweilig?

>Der Unterschied zwischen internen EEPROM, internen Programmflash und
>externen Flash ist mir schon bewusst.

Na hoffentlich.

> Die Applikation läuft ja schließlich.

Das tun alle Rumpelapplikationen, auch mit himmelschreiendem Murks.

> Ich wollte eigentlich nur die Compilerwarnungen verstehen
>und beseitigen.

Gut.

>Das Problem der Compilerwarnung war, das ein Pointer beim AVR nur 16-Bit
>breit ist, d.h. man muss auf (uint16_t) casten, wenn der übergebende
>Zeiger ungleich uint16_t* ist.

Falsch! Du hast immer noch nicht den Unterschied zwischen der Größe 
eines Pointers und der Größe des Zielobjekts verstanden.

Ein Pointer ist beim avr gcc 16 Bit breit. Das muss einen aber in den 
allermeisten Fällen nicht interessieren, darum kümmert sich der 
Compiler.
Dein Problem war die unsaubere Unterscheidung zwischen einem einfachen 
32 Bit Skaler/Integerwert und einem Pointer auf einen 32 Bit Wert.

Um es mal im Karl Heinz Buchegger Stil zu erklären. Mein Finger ist der 
Pointer, ca. 10cm lang. Damit kann ich auf einen 20m Langen LKW zeigen 
oder auch auf eine 5mm große Ameise. Die Größe des Pointers hat mit der 
Größe des Zielobjekts nichts zu tun.
Allerdings sollte man, wenn man auf einen LKW zeigt nicht sagen, ich 
zeige auf eine Ameise. Wenn das doch nötig ist, braucht man einen Cast. 
Davon sollte man aber immer sparsam Gebrauch machen, sonst verwechselt 
man irgendwann wirklich mal einen LKW mit einer Ameise. ;-)

>Übrigens: eine sehr schöne Zusammenfassung in Deinem letzten Post.

Danke.

>Problem gelöst. Thread kann geschlossen werden.

Wenn ich das höre, weiß ich meistens, daß es eben nicht so ist ;-)
Wer glaubt zu wissen, muss wissen, er glaubt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Da ist wohl immer noch der Wurm drin.  Der Cast auf uint16_t beseitigt 
das Symptom, also die Warnung, aber er behebt nicht das Problem.

Das eigentliche Problem ist, dass du 2 Adressbereiche hast: einmal den 
externen Flash, den du über eine 32-Bit Adresse verwaltest.  Diese 
Adresse ist ein uint32_t und soweit auch in Ordnung.  Dann hast du eine 
Variable im EEPROM, welche diese Adresse speichert.

Die Adresse der EEPROM-Variablen ist aber nur 16 Bits groß.

Das Problem behabst du nun, indem die 32-Bit XFlash-Adresse zu 16 Bits 
verstümmelt wird und danach als EEPROM-Adresse missbraucht, d.h. du 
versuchst eine 1:1 Korrespondenz zwischen XFlash- und EEPROM-Variablen.

Willst du wirklich diese 1:1 Korrespondenz zwischen XFlash- und 
EEPROM-Variablen? Oder willst du die (aktuelle) Adresse (z.B. Lese- oder 
Schreibposition im XFlash) im EEPROM speichern?

von Falk B. (falk)


Lesenswert?

@Johann L. (gjlayde) Benutzerseite


>Da ist wohl immer noch der Wurm drin.  Der Cast auf uint16_t beseitigt
>das Symptom, also die Warnung, aber er behebt nicht das Problem.

Eben.

>Willst du wirklich diese 1:1 Korrespondenz zwischen XFlash- und
>EEPROM-Variablen?

Nein.

> Oder willst du die (aktuelle) Adresse (z.B. Lese- oder
>Schreibposition im XFlash) im EEPROM speichern?

Ja, in 32 Bit.

von Karsten B. (karstenbrandt)


Lesenswert?

Die EEPROM-Funktionen in der avr-libc sind nicht ganz so einfach zu 
verstehen.
Hab das jetzt über EEMEM-Variablen geregelt.

von Falk B. (falk)


Lesenswert?

@ Karsten Brandt (karstenbrandt)


>Die EEPROM-Funktionen in der avr-libc sind nicht ganz so einfach zu
>verstehen.
>Hab das jetzt über EEMEM-Variablen geregelt.

Langsam wirst du albern.

www.vieleausreden.de

von Karsten B. (karstenbrandt)


Lesenswert?

Hallo Falk,

es reicht mit Deiner Respektlosigkeit. Ich habe keine Ahnung, auf 
welcher Ebene Du Dich bewegst. Deine herablassende Art ist aber langsam 
echt nervig. Auf oberlehrerhaftes Verhalten kann ich verzichten. Dass 
bringt uns hier nicht weiter. Du brauchst hier nicht zu antworten. Es 
zwingt Dich keiner. Aber wenn Du antwortest, dann bitte sachlich.
Vielleicht versetzt Du Dich ja mal in meine Situation.

Ich habe über meinen Tellerrand hinausgeblockt und gesehen, dass auch 
viele andere Leute sich mit dem EEPROM und den avr-libc-Funktionen 
schwer tun. Die sind sicher auch alle nicht dumm und haben keine Ahnung. 
Es ist anmaßend zu behaupten, dass wäre eine Ausrede.
Ich habe nie behauptet perfekt zu allwissend zu sein. Dennoch habe ich 
schon einiges an c Grundlagen (auch pointer). Vielleicht gibt es Lücken. 
Aber Hey:
ich bin für Anregungen und positive Kritik offen.
Mich als dumm hinzustellen geht gar nicht. Du solltest Doch bitte die 
Regeln der höflichen zwischenmenschlichen Kommunikation beherrschen! 
Dieses Forum ist ja schließlich ein Ort, wo man sich austauschen kann 
und Wissen weitergegeben werden sollte.

Für mich gibt es keine dummen(albernen) Fragen, sondern nur dumme 
(alberne) Antworten.

Ich habe andere Quellen aufgetan, die den Sachverhalt deutlich und 
verständlich beschreiben. Für mich persönlich hatte ich die 
EEPROM-Funktionen nicht richtig verstanden.

von Falk B. (falk)


Lesenswert?

@  Karsten Brandt (karstenbrandt)

>es reicht mit Deiner Respektlosigkeit.

Du solltest mal an deiner Kritikfähigkeit arbeiten.

https://de.wikipedia.org/wiki/Kritik

>echt nervig. Auf oberlehrerhaftes Verhalten kann ich verzichten.

Siehe oben.

>zwingt Dich keiner. Aber wenn Du antwortest, dann bitte sachlich.

Das tue ich. Der Schuß Ironie und Sarkassmus ist gratis ;-)

>Vielleicht versetzt Du Dich ja mal in meine Situation.

Das tue ich auch. Und eben weil ich es tue, erkenne ich, was DU nicht 
erkennst. Nämlich daß du entgegen deinen mehrfach vollmundigen Aussagen 
das Problem NICHT verstanden hast.
Das erkennt man leicht daran, daß du in fast jeder Antwort den 
Sachverhalt FALSCH wiedergegeben hast.

>Ich habe über meinen Tellerrand hinausgeblockt und gesehen, dass auch
>viele andere Leute sich mit dem EEPROM und den avr-libc-Funktionen
>schwer tun.

Ja? WO denn? Hast du eine Selbsthilfegruppe gefunden?

>Es ist anmaßend zu behaupten, dass wäre eine Ausrede.

Sie IST es! Deine bisherigen Antworten beweisen es!

Der Spruch "Wer glaubt zu wissen, muss wissen, er glaubt." klingt zwar 
lustig, trifft hier (und anderswo) aber zu!
Das zu erkennen ist schwer. Das für sich selbst zu AKZEPTIEREN noch viel 
mehr.
Das du jetzt sauer bist, ist verständlich.

>Ich habe nie behauptet perfekt zu allwissend zu sein.

Davon redet keiner.

>Dennoch habe ich
>schon einiges an c Grundlagen (auch pointer).

Siehe oben ;-)

> Vielleicht gibt es Lücken.

Bei deren Schließung wir dir hier helfen wollen. Dazu gehört aber auch 
ein gewisses Maß an Zuhören und und auch Zugeben, dass man auf dem 
Holzweg ist und Murks macht!
Wiederum, das zu Erkennen und sich einzugestehen ist charakterlich 
anspruchsvoll.

>ich bin für Anregungen und positive Kritik offen.

Die hast du mehrfach bekommen aber teilweise ignoriert. Ich bin nur ein 
08/15 Hardwerker der ein bisschen programmieren kann.
Der Johann spielt in einer GANZ anderen Liga, der WEIß wie C und avr gcc 
funktioniert SEHR GENAU! Wenigstens DEM solltest du genau zuhören und 
auch mal ein paar Dinge glauben.

>Mich als dumm hinzustellen geht gar nicht.

Reg dich wieder ab.

> Du solltest Doch bitte die
>Regeln der höflichen zwischenmenschlichen Kommunikation beherrschen!

Das tue ich, aber meinen ironisch-sarkastischen Stil werde ich so 
schnell nicht ändern ;-)
(ironisch-sarkastischen? Ich glaube ich bin vom IS!) ;-)

>Für mich gibt es keine dummen(albernen) Fragen, sondern nur dumme
>(alberne) Antworten.

Dazu zählen auch deine! Wie ein trotziges Kind willst du uns erklären 
daß dein Murks schon OK ist. NEIN, er ist es NICHT!

>Ich habe andere Quellen aufgetan, die den Sachverhalt deutlich und
>verständlich beschreiben. Für mich persönlich hatte ich die
>EEPROM-Funktionen nicht richtig verstanden.

Na dann laß uns mal an deinem neuen Wissen teilhaben. Mal sehen ob du es 
WIRKLICH verstanden hast oder nur glaubst es verstanden zu haben.
Trau dich!

von Uwe S. (de0508)


Lesenswert?

Guten Tag,

auch wenn es hier um die C-Syntax des ersten Thread ging,
möchte ich auf die Implementierung von Peter Dannegger (peda) verweisen.

Diese hatte ich mal hier *Smart EEPROM usage*:

# 
http://www.avrfreaks.net/forum/tut-c-smart-eeprom-usage?name=PNphpBB2&file=viewtopic&t=91306

gefunden.

Hier sind noch die zwei Dateien für eigene Projekte.
# https://www.mikrocontroller.net/attachment/256567/eeprom.c
# https://www.mikrocontroller.net/attachment/256568/eeprom.h

von Oliver S. (oliverso)


Lesenswert?

Naja, wenn der TO schon mit den zwei Parametern der avrlibc-Funktionen 
seine Schwierigkeiten hat, wird die PeDa- Lösung ihn nur noch mehr 
verwirren.

Oliver

von Uwe S. (de0508)


Lesenswert?

Oliver,

das mag ich nicht vermuten.
Ich verwende diese Routinen (kleine Lib) manchmal, da sie eine 
Implementierung enthält, um Blockweise Daten zuwischen EEprom, SRam aus 
zutauschen.
Und Schreibzugriffe auf das EEprom nur bei Daten Unterschieden 
durchführt.

von Peter II (Gast)


Lesenswert?

Uwe S. schrieb:
> Und Schreibzugriffe auf das EEprom nur bei Daten Unterschieden
> durchführt.

das macht auch die avr-libc die Funktionen dafür nennen sich update...

von Uwe S. (de0508)


Lesenswert?

Danke Peter,

ist mir bekannt, da ich mir die Implementierung angesehen hatte, aber 
bestimmt nicht alle Mitlesern hier.

Peter II schrieb:
> Uwe S. schrieb:
>> Und Schreibzugriffe auf das EEprom nur bei Daten Unterschieden
>> durchführt.
>
> das macht auch die avr-libc die Funktionen dafür nennen sich update...

Warten wir doch mal ab, was Karsten mit den neuen Infos anfangen kann 
und ob sein Projekt dadurch wieder "fahrt aufnehmen wird".

: Bearbeitet durch User
von Karsten Brandt (Gast)


Lesenswert?

Hallo @all:

Nochmals vielen Dank für die Rückmeldungen.
Das Projekt hat schon immer sehr stabil gelaufen. Ja, und auch die 
Zeiger, die sonst noch im Programm vorhanden sind.
Lediglich ein paar Compiler Warnungen sind noch zu beseitigen. Wie 
gesagt, ich hatte einen Denkfehler bei der avr-libc. Die Brücke von 
Variablen im SRAM bei Benutzung der avr-libc Funktionen war noch nicht 
ganz klar.
Nachdem ich mich nochmal intensiver damit beschäftigt habe, sind nun 
auch die Warnunggen
cast to pointer from integer of different size [-Wint-to-pointer-cast] 
(was mein eigentliches Problem war) weg ohne die verhassten casts zu 
verwenden.
Problem ist nun mit EEMEM-Variablen gelöst.
Alternativ geht das natürlich auch, indem ich eine 16-Bit SRAM Variable 
(Zeiger sind 2 Byte groß beim AVR) an die Funktion übergebe, die die 
Adresse enthält. Je nach Datentyp (byte, word, dword) muss dann 
entsprechend in der eeprom_read_... gecastet (uint8_t*, uint32_t*) 
werden.
Die uint32_t-Variable für die EEPROM-Adresse (2. Parameter) in der 
FLASH_LoadAddressPointer-Funktion macht also keinen Sinn. Hier hätte ein 
uint16_t völlig gereicht.

Das steht ja auch im AVR-GCC Tutorial hier im Forum.
Die Funktion im ersten Post ist ja genau so aufgebaut (vom uint32_t im 
zweiten Parameter mal abgesehen) wie die im AVR-GCC Tutorial 
(EEPROM-Kapitel). Wer meint, dass dies "Murks" ist, der möge das 
Tutorial richtig stellen.

Meine Funktion im ersten Post ist ja nicht ganz so verkehrt. Hätte ich 
im zweiten Parameter uint16_t statt uint32_t verwendet, dann wäre alles 
o.k. und die beschriebene Compiler-Warnung wäre weg.


Wie gesagt, Problem erledigt. Wieder etwas dazugelernt.

Gruß

Karsten

von Falk B. (falk)


Lesenswert?

> Wie gesagt, Problem erledigt. Wieder etwas dazugelernt.

Oder auch nicht ;-)

Q.E.D.

von Karsten Brandt (Gast)


Lesenswert?

>> Wie gesagt, Problem erledigt. Wieder etwas dazugelernt.

>Oder auch nicht ;-)

>Q.E.D.

Was muss ich beweisen?

Was ich eben geschrieben habe, steht auch so im AVR-GCC Tutorial. Ich 
werde das AVG-GCC Tutorial nicht in Frage stellen.
Ausserden findet sich auf den Seiten der Kollegen von avrfreaks.net jede 
menge Fragen zu dem Thema. So einfach kann das mit den EEPROM-Funktionen 
der avr-libc ja dann doch nicht sein. Es gint auch ein hervorragendes 
Tutorial zu den EEPROM-Zugriffen dort.

So ganz falsch bin ich nicht unterwegs. Das AVR-GCC Tutorial bzw. das 
auf avrfreaks.net bestätigt das.

Vielleicht habe ich im vorherigen Post die eine oder andere Stelle 
unglücklich formatiert. Das mag sein.

Konkret:
Variante 1:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint16_t uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //Warnung weg
6
  temp2 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //und hier auch
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}
17
18
uint32_t uC_FlashReadFrom=1000; //EE-Adresse muss selber verwaltet werden
19
uint32_t FlashBufferOutPointer;
20
21
FLASH_LoadAddressPointer(&FlashBufferOutPointer, uc_FlashReadFrom)

bzw.

Variante 2:
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t* uC_FlashReadFrom)
2
{
3
  uint32_t temp1=0, temp2=0;
4
  //Get actual EEPROM Read address
5
  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung hier
6
  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier
7
  
8
  
9
  if(temp2==temp1)
10
  {
11
    *pReturnAddress=temp1;
12
    return 0;
13
  }
14
  
15
  return 1;
16
}
17
18
//Adresse der Variablen im EEPROM durch Compiler festgelegt
19
//Der Anfangswert an der Adresse im EEPROM ist 0.
20
uint32_t EEMEM uC_FlashReadFrom=0; 
21
uint32_t FlashBufferOutPointer;
22
23
//Das die Variablenadresse (z.B. 0x01) im EEPROM (EEPROM-section) sich befindet, 
24
//muss hier der &-Operator verwendet werden! Der Wert der Variablen ist nebensächlich.
25
FLASH_LoadAddressPointer(&FlashBufferOutPointer, &uC_FlashReadFrom)

Ich habe Variante 2 mit der EEMEM-Variable gewählt. Das ist doch ein 
ganzes Stück einfacher und auch übersichtlicher.

Mehr gibt es zu diesem Thema von meiner Seite nicht zu sagen.

von Falk B. (falk)


Lesenswert?

@ Karsten Brandt (Gast)

>Was muss ich beweisen?

Gar nichts, denn du weißt ja jetzt wie das funktioniert.

>Was ich eben geschrieben habe, steht auch so im AVR-GCC Tutorial.

Nö.

>Ich
>werde das AVG-GCC Tutorial nicht in Frage stellen.

Musst du auch nicht.

>Ausserden findet sich auf den Seiten der Kollegen von avrfreaks.net jede
>menge Fragen zu dem Thema. So einfach kann das mit den EEPROM-Funktionen
>der avr-libc ja dann doch nicht sein.

Ach nee? Zugriffsfunktionen mit EINEM Parameter? ;-)
Dort sind mindestens genausoviel "Experten" unterwegs wie hier.
Warum soll es dem Forum besser gehen? ;-)


> Es gint auch ein hervorragendes
> Tutorial zu den EEPROM-Zugriffen dort.

>So ganz falsch bin ich nicht unterwegs. Das AVR-GCC Tutorial bzw. das
>auf avrfreaks.net bestätigt das.

Tun sie das?

>Vielleicht habe ich im vorherigen Post die eine oder andere Stelle
>unglücklich formatiert. Das mag sein.

Schon wieder?

>Konkret:
>Variante 1:

>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint16_t 
>uC_FlashReadFrom)
>{
>  uint32_t temp1=0, temp2=0;
>  //Get actual EEPROM Read address
>  temp1 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //Warnung weg
>  temp2 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //und hier auch

Ja, funktioniert, ist aber handgestricktes Gefrickel. Hab ich dir schon 
mehrfach zu erklären versucht. Leider vergebens. Mein pädagogisches 
Talent ist halt endlich.


>  if(temp2==temp1)
>  {
>    *pReturnAddress=temp1;
>    return 0;
>  }

Das hatten wir auch schon mal. Das funktioniert nicht so wie du denkst. 
Damit wirst du KEINE EEPROM Lesefehler erkennen. Aber das glaubst du mir 
auch nicht.

Beitrag "Re: EEPROM avr-libc Read/Write-Funktionen Warnung"

>uint32_t uC_FlashReadFrom=1000; //EE-Adresse muss selber verwaltet werden

Frickelmist^3.

>uint32_t FlashBufferOutPointer;

>FLASH_LoadAddressPointer(&FlashBufferOutPointer, uc_FlashReadFrom)

Auch Murks. Du verstehst nicht wirklich, welche Arbeiten man besser dem 
Compiler überläßt und was man sinnvoll seber verwalten soll/muss.

>Variante 2:

>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t* 
>uC_FlashReadFrom)
>{
>  uint32_t temp1=0, temp2=0;
>  //Get actual EEPROM Read address
>  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung hier
>  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier

Was für Warnungen? Glaub ich nicht so recht. Das hier ist korrekt und 
erzeugt KEINERLEI Compilerwarnung, es sind auch alle Warnungen 
angeschaltet (Compileroption -Wall)!
1
#include "avr/eeprom.h"
2
3
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t* uC_FlashReadFrom)
4
{
5
    *pReturnAddress = eeprom_read_dword(uC_FlashReadFrom);
6
    return 1;
7
}
8
9
uint32_t   flash_adr_nv EEMEM;
10
uint32_t   flash_adr;
11
12
int main(void) {
13
14
    volatile uint8_t i;
15
    i=FLASH_LoadAddressPointer(&flash_adr, &flash_adr_nv);
16
}


Ich wiederhole mich wiederholt, denn das da hab ich schon mehrfach 
geschrieben.

>//Adresse der Variablen im EEPROM durch Compiler festgelegt
>//Der Anfangswert an der Adresse im EEPROM ist 0.
>uint32_t EEMEM uC_FlashReadFrom=0;

Vorsicht, ich glaube das EEMEM muss HINTER dem Variablennamen stehen.
Nö, gerade getestet, geht auch so rum.

>uint32_t FlashBufferOutPointer;

>//Das die Variablenadresse (z.B. 0x01) im EEPROM (EEPROM-section) sich >befindet,
>//muss hier der &-Operator verwendet werden! Der Wert der Variablen ist 
>nebensächlich.
>FLASH_LoadAddressPointer(&FlashBufferOutPointer, &uC_FlashReadFrom)

Apfelmus ist Mus aus Äpfeln. Wenn eine Funktion eine Adresse/Pointer auf 
irgendwas haben will, muss man IMMER den Adressoperator verwenden. Auch 
bei ganz normalen Variablen im RAM. (Jaja, Strings/Arrays sind die tolle 
Ausnahme, dort ist der Name = Adresse).

>Ich habe Variante 2 mit der EEMEM-Variable gewählt. Das ist doch ein
>ganzes Stück einfacher und auch übersichtlicher.

Nicht wahr.

>Mehr gibt es zu diesem Thema von meiner Seite nicht zu sagen.

Dann ist ja alles gut.

von Karsten Brandt (Gast)


Lesenswert?

>>So ganz falsch bin ich nicht unterwegs. Das AVR-GCC Tutorial bzw. das
>>auf avrfreaks.net bestätigt das.

>Tun sie das?

Ja.

>>Variante 1:

>>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint16_t
>>uC_FlashReadFrom)
>>{
>>  uint32_t temp1=0, temp2=0;
>>  //Get actual EEPROM Read address
>>  temp1 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //Warnung weg
>>  temp2 = eeprom_read_dword((uint32_t*)uC_FlashReadFrom); //und hier auch

>Ja, funktioniert, ist aber handgestricktes Gefrickel. Hab ich dir schon
>mehrfach zu erklären versucht. Leider vergebens. Mein pädagogisches
>Talent ist halt endlich.

Wenn Du der Meinung bist, dass das nicht nach Lehrbuch ist, dann 
korrigiere doch das AVR-GCC-Tutorial:
1
...
2
// Byte aus dem EEPROM lesen
3
uint8_t EEPReadByte(uint16_t addr)
4
{
5
  return eeprom_read_byte((uint8_t *)addr);
6
}
7
...

Natürlich kannst Du auch einen Zeiger übergeben
1
uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint16_t* 
2
uC_FlashReadFrom)
3
{
4
  uint32_t temp1=0, temp2=0;
5
  //Get actual EEPROM Read address
6
  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung weg
7
  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier auch




>>Variante 2:

>>uint8_t FLASH_LoadAddressPointer(uint32_t *pReturnAddress, uint32_t*
>>uC_FlashReadFrom)
>>{
>>  uint32_t temp1=0, temp2=0;
>>  //Get actual EEPROM Read address
>>  temp1 = eeprom_read_dword(uC_FlashReadFrom); //Warnung hier
>>  temp2 = eeprom_read_dword(uC_FlashReadFrom); //und hier

>Was für Warnungen? Glaub ich nicht so recht. Das hier ist korrekt und
>erzeugt KEINERLEI Compilerwarnung, es sind auch alle Warnungen
>angeschaltet (Compileroption -Wall)!

Stimmt, Fehler von mir (copy-paste). Warnungen sind natürlich weg.

>>//Das die Variablenadresse (z.B. 0x01) im EEPROM (EEPROM-section) sich 
>>befindet,
>>//muss hier der &-Operator verwendet werden! Der Wert der Variablen ist
>>nebensächlich.
>>FLASH_LoadAddressPointer(&FlashBufferOutPointer, &uC_FlashReadFrom)

>Apfelmus ist Mus aus Äpfeln. Wenn eine Funktion eine Adresse/Pointer auf
>irgendwas haben will, muss man IMMER den Adressoperator verwenden. Auch
>bei ganz normalen Variablen im RAM. (Jaja, Strings/Arrays sind die tolle
>Ausnahme, dort ist der Name = Adresse).

Eben, soweit reichen meine Kenntnisse auch. Den avr-libc 
eeprom-Funktionen darf keine SRAM-Variable mit &-Operator übergeben 
werden. Vielmehr muss deren Inhalt als Zeiger auf Datentyp gecastet 
werden, z.B.
1
(uint8_t*)IRGENDEINE_SRAM_VARIABLE.

von Falk B. (falk)


Lesenswert?

@Karsten Brandt (Gast)

>Wenn Du der Meinung bist, dass das nicht nach Lehrbuch ist, dann
>korrigiere doch das AVR-GCC-Tutorial:

>// Byte aus dem EEPROM lesen
>uint8_t EEPReadByte(uint16_t addr)
>{
>  return eeprom_read_byte((uint8_t *)addr);
>}

In der Tat, das ist Hackermist. Mal schauen. Es ist ein eher schlechtes 
Beispiel, denn auf absolute Adresse sollte man möglichst nicht zugreifen 
und den Compiler seine Arbeit machen lassen. Natürlich gibt es immer 
Ausnahmen. Deine Anwendung ist KEINE!

>Natürlich kannst Du auch einen Zeiger übergeben

Was sollte dagegen sprechen?

>Stimmt, Fehler von mir (copy-paste). Warnungen sind natürlich weg.

;-)

>Eben, soweit reichen meine Kenntnisse auch. Den avr-libc
>eeprom-Funktionen darf keine SRAM-Variable mit &-Operator übergeben
>werden.

Was nur logisch ist, denn die liegt ja nicht im EEPROM ;-)

> Vielmehr muss deren Inhalt als Zeiger auf Datentyp gecastet
>werden, z.B.

>(uint8_t*)IRGENDEINE_SRAM_VARIABLE.

Ne, das ist schon wieder Handgestricktes. Mach es doch einfach solide so 
wie oben und alles ist gut. Den Rest macht der Compiler.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?


von Oliver S. (oliverso)


Lesenswert?

Falk B. schrieb:
> In der Tat, das ist Hackermist. Mal schauen. Es ist ein eher schlechtes
> Beispiel, denn auf absolute Adresse sollte man möglichst nicht zugreifen

Ma ja, man sollte vieles nicht, aber wenn man es dann doch will, dann 
will man das halt. Und bei der hardwarenahen 
Mikrocomtrollerprogrammierung muß man halt ab und an von der reinen 
Lehre abweichen.

Oliver

von karsten brandt (Gast)


Lesenswert?

>>Natürlich kannst Du auch einen Zeiger übergeben

>Was sollte dagegen sprechen?

Nichts, ausser Faulheit. Der Stiel ist wirklich besser. Ich vermute, du 
spielst auf Typensicherheit an.

von Falk B. (falk)


Lesenswert?

@Oliver S. (oliverso)

>> In der Tat, das ist Hackermist. Mal schauen. Es ist ein eher schlechtes
>> Beispiel, denn auf absolute Adresse sollte man möglichst nicht zugreifen

>Ma ja, man sollte vieles nicht, aber wenn man es dann doch will,

Er "will" bzw. wollte es nur, weil er den korrekten Weg nicht kannte.

> dann
>will man das halt. Und bei der hardwarenahen
>Mikrocomtrollerprogrammierung muß man halt ab und an von der reinen
>Lehre abweichen.

Deutlich seltener als du glaubst. Dieses "Problem" ist mühelos 
lehrbuchartig lösbar. Und das ist auch besser so!
C ist mehr als ein aufgebohrter Assembler! Und selbst dort lässt man in 
den allermeisten Fällen den Assembler die Adressen der Daten verwalten!

von Falk B. (falk)


Lesenswert?

@ karsten brandt (Gast)

>>Was sollte dagegen sprechen?

>Nichts, ausser Faulheit. Der Stiel ist wirklich besser. Ich vermute, du
>spielst auf Typensicherheit an.

Ja. Und sauberer Programmier_STIL hat noch keinem geschadet.

von karsten brandt (Gast)


Lesenswert?

Das hast Du recht. Daran ich arbeiten ;)

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.