Forum: Compiler & IDEs EEPROM


von Daniel (Gast)


Lesenswert?

Hallo,

Ich versuche verzweifelt mehrere Daten im ein Block in den EEPROM
schreiben.

eeprom_write_block (&ee_buf, 10, sizeof (ee_buf));

Hier meldet sich der Compiler mit einer Warnung (warning: passing arg 2
of `eeprom_write_block' makes pointer from integer without a cast) ,
aber die Daten werden korrekt ab Adresse 10 geschrieben.


wenn ich aber die 10 durch eine Variable ersetze, dann ist der Compiler
zufrieden, jedoch die Daten werden sonst wo hineingeschrieben  nur nicht
ab Adresse 10.

Uint16_t block1 = 10;
eeprom_write_block (&ee_buf, &block1, sizeof (ee_buf));

kann mir jemand sagen was ich falsch mache?

danke im Voraus für die Mühe

von OldBug (Gast)


Lesenswert?

Hi!

Probiers mal mit

void *block1 = (void *) 10;
eeprom_write_block (&ee_buf, block1, sizeof (ee_buf));

oder

eeprom_write_block(&ee_buf, (void *) 10, sizeof (ee_buf));

von Volkmar (Gast)


Lesenswert?

Hallo,

ich mache das so:

// Definition der Datenstruktur fuers EEPROM
typedef struct {
  uint8_t var1;
  uint16_t var2;
} struct_eeprom_data;

// EEPROM-Daten definieren
const struct_eeprom_data eeprom_data _attribute_ ((section
(".eeprom"))) = { 0, 1 }

// RAM-Kopie für einfacheren Zugriff definieren
struct_eeprom_data ee_buf;

// Daten vom EEPROM ins RAM kopieren
eeprom_read_block(&ee_buf, &eeprom_data, sizeof(ee_buf));

// Daten ins EEPROM kopieren
eeprom_write_block(&ee_buf, &eeprom_data, sizeof(ee_buf));

Vorteil:
Ich erhalte eine Datei mit Werten die ich direkt ins EEPROM als
Default-Werte brennen kann. Die genaue Adresse der EEPROM-Daten
interessiert mich dann (eigentlich) nicht mehr. Kann der Compiler sich
selber aussuchen. Zugriff auf die Daten erhalte ich dann zB mit
"ee_buf.var1".

Volkmar

von Daniel (Gast)


Lesenswert?

Danke für die schnelle Antwort.
Es funktioniert !!

Daniel

von Stefan Kleinwort (Gast)


Lesenswert?

Hallo Daniel,

>eeprom_write_block (&ee_buf, 10, sizeof (ee_buf));

10 ist eine Zahl und kein Pointer. Deshalb bringt er die Warnung. Der
Compiler kann zwar 10 als Adresse ansehen. In der Regel dürfte dies
aber nicht Absicht (so wie bei Dir), sondern ein Programmiererfehler
sein, dshalb die Warnung.

Du kannst dem Compiler aber mitteilen, dass Du einen Ptr auf dieAdresse
10 meinst, so wie OldBug geschrieben hat:

eeprom_write_block (&ee_buf[0], (uint8_t*)10, sizeof (ee_buf));

(uint8_t*) bedeutet: die folgende Zahl (oder Variable) ist ein Pointer
auf eine uint8_t Variable. Oder einfacher ausgedrückt: die Adresse 10.
Das Ganze nennt man "type-casten".

>wenn ich aber die 10 durch eine Variable ersetze, dann ist der
>Compiler zufrieden, jedoch die Daten werden sonst wo
>hineingeschrieben  nur nicht ab Adresse 10.
>
>Uint16_t block1 = 10;
>eeprom_write_block (&ee_buf, &block1, sizeof (ee_buf));

Hier bekommt die Variable block1 den Wert 10. An die Funktion übergibst
Du aber nicht die 10, sondern die Adresse der Variablen block1. Und das
kann alles mögliche sein.


@Volkmar:
>Ich erhalte eine Datei mit Werten die ich direkt ins EEPROM als
>Default-Werte brennen kann.

Du bekommst eine Datei nur mit den EEPROM-Werten? Wie machst Du das
genau? Macht das der Linker, mit welcher Einstellung?

Stefan

von Volkmar (Gast)


Lesenswert?

Hallo Stefan,

ich benutze das Beispiel-makefile von WinAVR. Dort gibt es einen
Abschnitt für das Eeprom:

%.eep: %.elf
  @echo
  @echo $(MSG_EEPROM) $@
  -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
  --change-section-lma .eeprom=0 -O $(FORMAT) $< $@

Volkmar

von Stefan Kleinwort (Gast)


Lesenswert?

Hallo Volkmar,

>ich benutze das Beispiel-makefile von WinAVR. Dort gibt es einen
>Abschnitt für das Eeprom:

Ja klasse, benutze ich auch. Bloss habe ich es wohl weniger
durchgelesen ;-))
Ich werde mir die .eep Ausgabe so modifizieren, dass ich eine
Binärdatei erhalte. Die kann ich dann per Befehl an den AVR schicken
(UART), um den Default-Zustand wiederherzustellen.

Vielen Dank, Stefan

von Hans Müller (Gast)


Lesenswert?

Hallo Leute,

ich benutze das Beispiel-makefile von WinAVR..

#include <avr/io.h>
#include <avr/eeprom.h>

int main (void)
/* That's the way to define a eeprom variable */

static uint8_t val1_attribute_((section(".eeprom")));

unit8_t val2;
DDRF = 0xFF;
eeprom_write_byte ((uint8_t)& val1, 0xAA);     /* writing the val1 */
val2 = eeprom_read_byte ((uint8_t) & val1);    /* reading of val1*/

PORTF = val2;

for (;;) {}


Hier meldet sich der Compiler mit einer Warnung :
make -k all
Building file: ../test.c
Invoking: AVR-GCC C Compiler
avr-gcc -c -fmessage-length=0 -Wall -Wstrict-prototypes
-IC:\WinAVR\avr\include -mmcu=atmega128 -minit-stack=__stack -O0
-fshort-enums -fpack-struct -funsigned-char -funsigned-bitfields
-std=gnu99 -g2 -otest.o ../test.c
../test.c: In function `main':
../test.c:496: Fehler: Syntaxfehler vor »(«-Zeichen
../test.c:496: Fehler: Speicherklasse für Parameter
»val1_attribute_« angegeben
../test.c:496: Warnung: Funktionsdeklaration ist kein Prototyp
make: *** [test.o] Error 1
make: Target `all' not remade because of errors.
Build complete for project AVRTest_local

kann mir jemand sagen was ich falsch mache (funktion static meine
ich)?


Danke..

von Volkmar (Gast)


Lesenswert?

Bzgl. der EEPROM-Definition würde ich folgendes schreiben:

static uint8_t _attribute_ ((section(".eeprom")));

Beachte auch das Leerzeichen vor der Klammer. Woher hast Du das
vall_attribute?

Volkmar

von Rolf Magnus (Gast)


Lesenswert?

So würde ich es nicht schreiben, denn so hat die Variable keinen Namen.

Ich würde auch das Makro EEMEM aus der avr-libc verwenden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Beachte auch das Leerzeichen vor der Klammer.

Das ist redundant.  Das Leerzeichen vor _attribute_ jedoch
nicht. ;-)  (Und es sind 2 x 2 Unterstriche.)

> val2 = eeprom_read_byte ((uint8_t) & val1);

Flasch.  Du nimmst korrekt die Adresse (die könntest du, wie sie
ist, an eeprom_read_byte() weiterreichen), verkürzt sie ggf. auf
nur noch 8 Bits (das wird ein Problem, falls dein EEPROM mehr als
256 Bytes hat und deine EEPROM-Variable weit hinten liegt), und
reichst anschließend den so gewonnenen Integer-Wert wieder an die
Funktion, die einen Pointer erwartet, sodass der Compiler eine
implizite Typwandlung von Integer nach Pointer machen muss.

von gast (Gast)


Lesenswert?

Hallo Leute,

ich habe uc AT90usb1286 und Ich versuche einfach einen Daten  in den 
EEPROM zu schreiben und zu lesen.
/* float */
float eeFooFloat EEMEM;

float myFloat = 20,5;

   union {
      float r;
      uint8_t i[sizeof(float)];
   } u;

int main()
{
  u.r = myFloat;

 /* float in EEPROM */
   eeprom_write_block(&(u.i),&eeFooFloat,sizeof(float));
   //EEPROM_write(&eeFooFloat,sizeof(float));

   /* float aus EEPROM */
   eeprom_read_block(&(u.i),&eeFooFloat,sizeof(float));
   /* u.r wieder 20,5*/

  return 0;

}
 der Compiler meldet wieder einer Warnung noch ein fehler und trotzdem , 
wenn ich in den Register anschau, sehe ich dass es nicht geschrieben 
wurde.
und ich kann auch nicht lesen, weil nicht in den EEPROM  drin ist.
kann mir jemand hilfen.
dank in voraus!!

von Johannes M. (johnny-m)


Lesenswert?

gast wrote:
> float myFloat = 20,5;
Das international übliche Dezimaltrennzeichen ist nicht das Komma, 
sondern der Punkt!

Abgesehen davon: Für sowas muss man keinen Uralt-Thread wieder 
rauskramen...

von Sven P. (Gast)


Lesenswert?

Du brauchst auch nicht den Umweg über die Struktur zu gehen.

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.