Forum: Compiler & IDEs AVR: Problem mit eeprom_read_byte()


von Eugen (Gast)


Lesenswert?

Hallo!

Ich habe das folgende Problem: Ich will beim Initialisieren bereits im 
EEPROM abgelegten Daten nacheinander in ein Array einlesen, um sie im 
weiteren Programmverlauf zu verwenden, habe aber ein Problem mit der 
Adresse der einzulesenden Bytes. Der Code dazu sieht folgendermaßen aus:

1
void init(void)                /* Initialisiert den Mikrocontroller*/
2
{
3
uint8_t lettercnt, letrow;
4
uint16_t eepr_addr=0;
5
6
select_char=0;
7
8
strcpy(showstring,"LFB[XQ");
9
10
11
sei();                    // Interrupts an
12
TIMSK=1;
13
TCCR0=5;
14
15
DDRA=255;                  // Input
16
DDRB=255;
17
DDRC=0;
18
DDRD=255;
19
20
Clkport=0;                // Output
21
Dataport=255;
22
23
24
PORTB=255;
25
PORTC=255;               
26
27
28
29
// Aus EEPROM Bitmuster für Buchstaben auslesen
30
31
32
33
for (lettercnt=0;lettercnt<40;lettercnt++)
34
  {
35
    eepr_addr=lettercnt*8;
36
  
37
    for(letrow=0;letrow<8;letrow++)
38
      {
39
        while (!eeprom_is_ready())
40
        {
41
        
42
        }
43
        
44
        letter[lettercnt][letrow]=eeprom_read_byte(eepr_addr);
45
        eepr_addr++;
46
    }
47
  }
48
49
50
51
}




Der Compiler bringt eine Warnung, und wenn ich das Programm auf dem 
Mikorcontroller übertrage, bleibt er beim Initialisieren hängen. Ich 
weiß, dass eeprom_read_byte() eine Adresse als Parameter benötigt, 
dennoch müsste es so auch ohne Typecast funktionieren. Ich habe schon 
alles abgesucht und es scheint alles richtig zu sein. Vielleicht habe 
ich etwas übersehen? Für Eure Hilfe wäre ich sehr dankbar!

Es handelt sich um den ATMEGA16 Controller

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Für den ATmega16 wird in der avr-libc ein Workarount für einen bekannten 
Silicon-Bug nicht implementiert, möglicherweise ist's das? (der µC löst 
eine IRQ aus, was zu einem RESET führt, wenn die entsprechende ISR nicht 
implementiert ist)

Beitrag "Re: Riesige Änderungen zwischen WinAVR 030913 und der aktuellen Version?"

BTW: wie wär's mit eeprom_read_block?

von Der Neugierige (Gast)


Lesenswert?

Was für eine Warnung denn?

Warnungen zur Compilerzeit, werden zu Fehlern in der Laufzeit.
Alte Regel.

von Eugen (Gast)


Lesenswert?

Die Warnung lautet:

warning: passing argument 1 of 'eeprom_read_byte' makes pointer from 
integer without a cast

Habe es bereits probiert mit eeprom_read_block(). Die dazugehörige Zeile 
müsste dann so heißen, oder?

1
eeprom_read_block((void*)&letter[lettercnt][letrow], (const void*)eepr_addr, 1);

Das Ergebnis ist aber das Gleiche, der Mikrocontroller kommt über das 
Auslesen nicht hinaus.

Eine andere interessante Sache, die ich festgestellt habe: Das Programm 
läuft wenn ich mit Optimierungsstufen "s" oder "3" kompiliere. Ich 
brauche es aber ohne Optimierung, da mir ansonsten die eingebauten 
Warteschleifen wegopitmiert werden. Die sind aber notwendig, da der 
Mikrocontroller einen Flachbildschirm ansteuern muss, der da nicht 
mitziehen würde.

von Eugen (Gast)


Lesenswert?

P.S.: Mit Optimierungsstufe 2 läuft es auch, aber nicht mit den Stufen 1 
und 0

von ... .. (docean) Benutzerseite


Lesenswert?

Dann sind deine Warteschleifen Schrott...

Entweder nimm "util/delay.h" oder nimm Timer!!

von Matthias L. (Gast)


Lesenswert?

>Ich
>brauche es aber ohne Optimierung, da mir ansonsten die eingebauten
>Warteschleifen wegopitmiert werden. Die sind aber notwendig, da der
>Mikrocontroller einen Flachbildschirm ansteuern muss, der da nicht
>mitziehen würde.

Das ist kein Argument für delay! Dafür gibt es Timer.

PS: Damit Warteschleifen nicht wegoptimiert werden, must du die 
Zählvariable volatile deklarieren.


Mal ne Frage:
>warning: passing argument 1 of 'eeprom_read_byte' makes pointer from
>integer without a cast

Die Fehlermeldung bekomme ich immer, wenn ich eine Variable übergebe, wo 
eigentlich die Adresse derselben Variable hin soll.

Da du hier aber den Inhalt der Variablen als Adresse haben willst, 
könnte das evtl der Grund sein warum das nicht geht.
Der Compiler könnte (durch die Warnung angezeigt) da die (SRAM)Adresse 
der Variablen eepr_addr übergeben. Somit wird mit einer SRAM-Adresse 
im EEPROM gesucht.

Mach das mal richtig, so wie es gedacht ist:
1
uint8_t  VarImEE[40][8]  EEMEM;
2
uint8_t  letter[40][8];
3
...
4
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

(Ich bin mir jetzt bei der genauen Syntax nicht sicher)

von Eugen (Gast)


Lesenswert?

Die Warteschleifen sehen folgendermaßen aus:
1
for (warten=0; warten<deltatime; warten++){}

Ich kann es zwar anders probieren mit den Warteschleifen, aber das tut 
ja nichts zur Sache. Fakt ist, dass ein Befehl, der funktionieren 
sollte, einfach nicht funktioniert, obwohl die Syntax richtig zu sein 
scheint.

von Eugen (Gast)


Lesenswert?

Also einfach nur "long volatile warten"? Damit funktioniert es nicht

>Die Fehlermeldung bekomme ich immer, wenn ich eine Variable übergebe, wo 
>eigentlich die Adresse derselben Variable hin soll.

Eben, bei mir ist es nicht so, dass ich die Adresse der Variable 
"eepr_addr" haben will, da diese Adresse sich irgendwo im RAM befindet 
und in meiner Ausleseschleife der Wert von "eepr_addr" zwar erhöht wird, 
aber die Adresse bleibt ja gleich. Demnach würde so in das ganze Array 
die gleiche Bitfolge eingeschrieben werden, falls ich "&eepr_adr" 
verwenden würde. So würde es zwar der Compiler ohne wenn und aber 
schlucken, aber es müsste ohne "&" richitg funktionieren. Ich versuche 
es aber gliech mal mit
1
uint8_t  VarImEE[40][8]  EEMEM;
2
uint8_t  letter[40][8];
3
...
4
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

von Matthias L. (Gast)


Lesenswert?

>Also einfach nur "long volatile warten"? Damit funktioniert es nicht
1
volatile long warten


>Eben, bei mir ist es nicht so, dass ich die Adresse der Variable
>"eepr_addr" haben will, da diese Adresse sich irgendwo im RAM befindet
>und in meiner Ausleseschleife der Wert von "eepr_addr" zwar erhöht wird,
>aber die Adresse bleibt ja gleich.

Wenn die (zu lesende EEPROM) Adresse immer gleich bleibt, könnte das ja 
die ursache sein.

Vielleicht solltest du es doch mit einem Cast (des Wertes auf Adresse) 
probieren:
1
letter[lettercnt][letrow] = eeprom_read_byte( (uint8_t*)eepr_addr );

von Eugen (Gast)


Lesenswert?

@ Matthias

Die Adresse würde nur dann gleich bleiben, wenn ich ein "&" davor 
verwende. Deshlab wäre ohne schon richtig. Den von Dir vorgeschlagenen 
Typecast habe ich bereits vor dem Post ausprobiert. Bringt aber nichts.

Habe Deinen Vorschlag mit

uint8_t  VarImEE[40][8]  EEMEM;
uint8_t  letter[40][8];
...
eeprom_read_block( letter, VarImEE, sizeof(VarImEE)  );

nun ausprobiert.

Auch damit ist es so, dass es ohne Optimierung nicht funktioniert. Ganz 
nebenbei gefragt: es müsste ja egal sein, ob sich das Array 
"VarImEE[40][8]" im EEMEM befindet oder nicht? Denn die einzige 
Verwendung davon ist nur die Abfrage der Arraygröße mit 
"sizeof(VarImEE)". Da ich weiß, dass ich ab der Adresse 0 auslesen will, 
klappt es bei mir auch in der Form:

1
eeprom_read_block(&letter, 0, sizeof(VarImEE));

von Matthias L. (Gast)


Lesenswert?

>Die Adresse würde nur dann gleich bleiben, wenn ich ein "&" davor
>verwende. Deshlab wäre ohne schon richtig.

Nein eben nicht. Deine oben gepostete Warnung sagt doch aus, dass der 
Compiler ein Pointer draus gemacht hat. Also macht er von allein ein & 
davor!


>es müsste ja egal sein, ob sich das Array...
Sollte so sein.

von Eugen (Gast)


Lesenswert?

Ich habe es jetzt hinbekommen. Es handelt sich bei dem Problem ganz 
offensichtlich um einen Bug des Compilers. Ein Kollege hatte 
glücklicherweise eine ältere Version von WinAVR mit der GCC Ver. 3.4.5. 
Mit dieser Version hat er auch seinerzeit sein Programm compiliert, 
welches gelaufen ist und auf dem ich meins aufgebaut habe. Nachdem ich 
mir die alte Compiler-Version draufgespielt habe, hat es auf ein Mal 
funktioniert, auch mit dem von mir anfangs geposteten Code. Wobei ich 
mich dann für die von Matthias vorgeschlagene Methode mit 
eeprom_read_block() entschieden habe, da dann auch der Compiler 
zufrieden ist und ohne Warnung wegen der Parameterübergabe auskommt.

Schon ärgerlich das Ganze, dnen ich habe drei Tage lang nichts Anderes 
gemacht als diese eine Zeile angestarrt und alles Mögliche ausprobiert, 
ohne Aussicht auf Erfolg.

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.