Forum: Compiler & IDEs Eprom verwendung


von LaserBrenner (Gast)


Lesenswert?

Hallo Ihr guten Menschen,
ich habe da mal ein Problem mit der ablage meiner Programmeinstellung 
ins  Eprom.

Ziel ist die Konfiguration meines Programmes ins Eprom abzulegen um nach 
einen Stromausfall/ Reset nicht wieder alles neu einstellen zu müssen.

Hier mal ein Teil meines Programms:
1
#include <avr/eeprom.h>
2
3
4
        //für eprom
5
  uint8_t    eeprom_def_EEProm_beschrieben EEMEM;  
6
  uint16_t   eeprom_def_Rel_out_mask EEMEM;  
7
  uint16_t   eeprom_def_Rel_auto_mask EEMEM;  
8
  uint16_t   eeprom_def_IO_Feld[20][5] EEMEM;  
9
10
int main(void)
11
{
12
  initMcu();    
13
  menu_Init();          //Menu init
14
  lesen();    //Eprom lesen
15
  i2c_init();    //I2C-Bus einrichten
16
  sei();      // Global Interrupts aktivieren
17
18
    
19
  while(1) // MAIN Schleife //
20
  {
21
        Wenn hier im Programm Konfiguriert wird, 
22
        wird schreiben(); aufgerufen.         
23
        }
24
}
25
26
27
void schreiben(void)
28
{
29
  eeprom_busy_wait ();
30
  eeprom_update_byte(&eeprom_def_EEProm_beschrieben, 1);
31
  eeprom_busy_wait ();
32
  eeprom_update_word(&eeprom_def_Rel_out_mask, Rel_out_mask); 
33
  eeprom_busy_wait ();
34
  eeprom_update_word(&eeprom_def_Rel_auto_mask, Rel_auto_mask); 
35
  eeprom_busy_wait ();
36
  eeprom_update_block (IO_Feld, eeprom_def_IO_Feld, sizeof(IO_Feld));
37
}
38
39
void lesen(void)
40
{
41
    // nur lesen wenn eprom beschrieben worden ist
42
    eeprom_busy_wait ();
43
    if ((eeprom_read_byte (&eeprom_def_EEProm_beschrieben)) == 1)  
44
    {
45
  eeprom_busy_wait ();
46
  Rel_out_mask =eeprom_read_word (&eeprom_def_Rel_out_mask);
47
  eeprom_busy_wait ();
48
  Rel_auto_mask = eeprom_read_word (&eeprom_def_Rel_auto_mask);
49
  eeprom_busy_wait ();
50
  eeprom_read_block (IO_Feld, eeprom_def_IO_Feld, sizeof(IO_Feld));
51
    }
52
    else
53
    {
54
  nop();
55
    }
56
}
Wenn ich die Speierung von IO_Feld weg lasse funktioniert alles soweit, 
erst wenn ich IO_Feld ins eprom schreibe überschreibt er glaube meine 
vorherigen werte!

Warum?

Habt Ihr eine Idee?

gruß
Matthias und danke schon mal für eure hilfe.

von andi-gast (Gast)


Lesenswert?

solltest du nicht

  lesen();    //Eprom lesen
  i2c_init();    //I2C-Bus einrichten

tauschen

  i2c_init();    //I2C-Bus einrichten
  lesen();    //Eprom lesen

in der Annahme es ist ein I2C EEprom

Gruß
Andi

von LaserBrenner (Gast)


Lesenswert?

Hallo,
es handelt sich bei den Eprom um den internen 4K Byte Eprom von einen 
ATmega2560.
Aber du hast recht es wäre schöner erst die Init's fertig zu machen und 
dann zu lesen.

von LaserBrenner (Gast)


Lesenswert?

So hab's mal in einer anderen Reihenfolge geschrieben:

void schreiben(void)
{
  eeprom_busy_wait ();
  eeprom_update_block (IO_Feld, eeprom_def_IO_Feld, sizeof(IO_Feld));
  eeprom_busy_wait ();
  eeprom_update_byte(&eeprom_def_EEProm_beschrieben, 1);
  eeprom_busy_wait ();
  eeprom_update_word(&eeprom_def_Rel_out_mask, Rel_out_mask);
  eeprom_busy_wait ();
  eeprom_update_word(&eeprom_def_Rel_auto_mask, Rel_auto_mask);
}


jetzt geht es!?! aber warum? Warum überschreibt IO_Feld die ersten Eprom 
Speicherzellen?

von Laserbrenner (Gast)


Lesenswert?

Auch wenn es Jetzt so geht, würde ich gerne wissen wo der Fehler ist - 
hat denn nimand eine idee?

Gruß
Matthias

von Axel S. (a-za-z0-9)


Lesenswert?

Ich glaube nicht daß es jetzt geht. Durch die andere Reihenfolge werden 
jetzt halt nur andere Daten überschrieben. Hast du denn mal ins mapfile 
geschaut, auf welche Adressen deine EEMEM Variablen gemappt werden?

Randbemerkungen:

1. es heißt EEPROM, nicht EPROM. Das ist ein himmelweiter Unterschied!
2. das ganze busy_wait() Getue kannst du dir sparen. Lies die Doku!
3. zwischen Funktionsname und öffnende Klammer gehört kein Leerzeichen.


XL

von LaserBrenner (Gast)


Lesenswert?

Hallo und DANKE erst mal für deine Unterstützung.

Ich bin mir nicht sicher aber ich glaube du meinst diesen eintrag aus 
der *.map:

.eeprom         0x00810000       0xce
 *(.eeprom*)
 .eeprom        0x00810000       0xce lcd_menu.o
                0x00810000                eeprom_def_Licht_GW
                0x00810001                eeprom_def_IO_Feld
                0x008100c9                eeprom_def_Rel_auto_mask
                0x008100cb                eeprom_def_Rel_out_mask
                0x008100cd                eeprom_def_EEProm_beschrieben
                0x008100ce                __eeprom_end = .

sehe ich das richtig, mein EEprom fängt bei Adresse 0x00810000.
und  eeprom_def_Licht_GW (uint8_t) liegt da.

eeprom_def_IO_Feld (uint16_t   eeprom_def_IO_Feld[20][5]) fängt bei 
0x00810001 an und geht bis 0x008100c8 also besitzt 0Xc8 Adressen => 200.

Mein IO_Feld in der *.h mit "extern uint16_t IO_Feld[20][6];" deklariert 
und da ist schon der erste Fehler (einmal [20][5]und einmal [20][6])!

Warum aber bei IO_Feld[20][5] 200 Adressen und bei IO_Feld[20][6] 240 
Adressen?
0-20=21 und 0-5=6 =>21*6=126 Adressen ?!? oder Gedanken Fehler.

So ich glaube der Fehler ist weg war wohl die IO_Feld[20][5] Sache. Aber 
das mit der anzahl der Adressen würde ich auch ganz gerne mal wissen.

gruß
Matthias

von LaserBrenner (Gast)


Lesenswert?

Hallo Axel,
kannst du mir nochmal einen Link geben, wegen der Busy_wait Sache - find 
nur Erklärungen wo es verwendet wird.

danke

Matthias

von Daniel C. (cecky)


Lesenswert?

LaserBrenner schrieb:
> Warum aber bei IO_Feld[20][5] 200 Adressen und bei IO_Feld[20][6] 240
> Adressen?

Dann frag dich mal wieviele Bytes dein Array "IO_Feld[20][5]" mit dem 
Datentyp "uint16_t" im EEPROM wohl belegt.

gruß
Cecky

von LaserBrenner (Gast)


Lesenswert?

na hab ich doch schon versucht

0-20=21 und 0-5=6 =>21*6=126 Adressen ?!? oder Gedanken Fehler.

wenn es stimmt das 2 Byte pro Adresse Platz haben!
126 Felder mal 2Byte = 252 Byte - macht doch 126 Adressen?!?

gruß

von Daniel C. (cecky)


Lesenswert?

LaserBrenner schrieb:
> 0-20=21 und 0-5=6 =>21*6=126 Adressen ?!?

??? Da kommt bei meiner Rechnung aber was anderes raus:

IO_Feld[20][5] = 100 Elemente * uint16_t = 200 Byte

LaserBrenner schrieb:
> wenn es stimmt das 2 Byte pro Adresse Platz haben!
Wie kommst du da drauf?

gruß
Cecky

von Karl H. (kbuchegg)


Lesenswert?

LaserBrenner schrieb:

> Warum aber bei IO_Feld[20][5] 200 Adressen und bei IO_Feld[20][6] 240
> Adressen?
> 0-20=21 und 0-5=6 =>21*6=126 Adressen ?!? oder Gedanken Fehler.

Öh,

Ein Array
1
  int test[5];

hat 5 Elemente.
test[0], test[1], test[2], test[3], test[4]
Zähl nach, es sind genau 5 Elemente.
Bei der Definition gibst du die Länge an und nicht den höchsten Index!

[20][5] sind daher 20*5 gleich 100 Arrayelemente und wenn jedes 
Array-Element 2 Bytes gross ist, dann sind das 200 Bytes.

> So ich glaube der Fehler ist weg war wohl die IO_Feld[20][5] Sache. Aber
> das mit der anzahl der Adressen würde ich auch ganz gerne mal wissen.

Du solltest dir zumindest das erste Drittel eines ordentlichen C Buchs 
durcharbeiten. Das sind ziemliche Basics.

von Karl H. (kbuchegg)


Lesenswert?

LaserBrenner schrieb:

> Mein IO_Feld in der *.h mit "extern uint16_t IO_Feld[20][6];" deklariert
> und da ist schon der erste Fehler (einmal [20][5]und einmal [20][6])!

Jetzt hast du auch rausgefunden, warum man derartige Konstanten (sog. 
magische Konstanten) nicht direkt in den verwendenden Code schreibt, 
sondern sich einen #define dafür macht. Denn dann passiert einem sowas 
nicht
1
#define NR_ROWS 5
2
#define NR_COLS 20
3
...
4
uint16_t   eeprom_def_IO_Feld[NR_COLS][NR_ROWS] EEMEM;  
5
...
6
extern uint16_t IO_Feld[NR_COLS][NR_ROWS];
7
...

Jetzt kann es dir per Defintion nicht mehr passieren, dass dir die 
Zahlen auseinanderlaufen. Denn die konkrete Zahl steht nur an EINER 
EINZIGEN Stelle im ganzen Programm und alle verwendenden Stellen 
beziehen sich darauf. Ändert sich die Anzahl, dann ändert man das an 
EINER Stelle und der Rest des Codes (inklusive von zb. for-Schleifen, 
die zur Abarbeitung der Arrays benutzt werden) werden durch den 
Präprozessor angepasst ohne dass du dich groß darum kümmern musst.
1
  for( i = 0; i < NR_ROWS; i++ ) {
2
    ....

von Laserbrenner (Gast)


Lesenswert?

Hallo Ihr guten,
vielen vielen Dank für eure Erklärung, auch den Tip von Karl Heinz werde 
ich zukünftig beherzigen :-) und mir auch nochmal ein paar Grundlagen 
aneigenen.

also nochmal Danke, toll das es Menschen wie euch gibt...

gruß
Matthias

von Axel S. (a-za-z0-9)


Lesenswert?

LaserBrenner schrieb:
> Hallo Axel,
> kannst du mir nochmal einen Link geben, wegen der Busy_wait Sache - find
> nur Erklärungen wo es verwendet wird.

http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

"All of the read/write functions first make sure the EEPROM is ready to 
be accessed. Since this may cause long delays if a write operation is 
still pending, time-critical applications should first poll the EEPROM 
e. g. using eeprom_is_ready() before attempting any actual I/O."


XL

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.