Forum: Compiler & IDEs Arrays im Flash beim Atmega


von Rene Z. (renezimmermann)


Lesenswert?

Hallo,

ich habe ein kleines Problem mit Arrays im Flash eines ATmega32. Ich 
nutze AVR GCC als Compiler. Nun zum Problem:

Ich habe eine ganze Reihe Strings im Flash:
1
const char id06374[] PROGMEM = "Zimmer  7";
2
const char id06379[] PROGMEM = "Zimmer  9";
3
const char id06384[] PROGMEM = "Zimmer 11";
4
const char id06399[] PROGMEM = "Zimmer 21";

nun brauche ich noch ein Array aus einer Structur im Flash was immer 
schön einen 16 bit Wert hat und danach die Adresse zu den obrigen 
'Strings'.

etwa so:
1
static struct{
2
  uint16_t Adresse;
3
  uint16_t* p_auf_ID_string;
4
} p_adr[] PROGMEM = {6374,id06374,6379,id06379,6384,id06384,6399,id06399};

Das funzt natürlich nicht, war ja klar ;-) .

Könnte mir da jemand weiter helfen? Ich denke ich habe das mit den 
Sectionen im Flash noch nicht begriffen und auch bei Zeigern hapert es 
wohl.

Gruß Rene

von Rene Z. (renezimmermann)


Lesenswert?

Mist,
falsches Forum sollte bei GCC landen.

von Falk B. (falk)


Lesenswert?

@ Rene Zimmermann (renezimmermann)

>Das funzt natürlich nicht, war ja klar ;-) .

Ich glaube da fehlen nur Klammern.
1
static struct{
2
  uint16_t Adresse;
3
  uint16_t* p_auf_ID_string;
4
} p_adr[] PROGMEM = {{6374,id06374},
5
           {6379,id06379},
6
           {6384,id06384},
7
             {6399,id06399}};

MfG
Falk

von Philipp (Gast)


Lesenswert?

Nicht eher das der Pointer p_auf_ID_string aufs Flash zeigen soll?
So zeigt er ja ins SRAM oder?

von Karl H. (kbuchegg)


Lesenswert?

Philipp wrote:
> Nicht eher das der Pointer p_auf_ID_string aufs Flash zeigen soll?
> So zeigt er ja ins SRAM oder?

Das ist dem gcc sowieso egal. Pointer ist Pointer.
Das der Pointer ins Flash zeigt, must du durch die Art
der Verwendung des Pointers berücksichtigen.
Sprich: keine * - Derferenzierung sondern pgm_read_xxx
Funktionen benutzen.

Mal anders gefragt: Wie ist diese Aussage
Das funzt natürlich nicht, war ja klar ;-) .
zu begreifen. Hast du Fehlermeldungen vom Compiler oder
ein Runtime Problem?

von Philipp (Gast)


Lesenswert?

@kbuchegg
Ah, ach so, sorry, kenn das nur so vom IAR... ;)

von Rene Z. (renezimmermann)


Lesenswert?

Hallo,

erst mal Danke für die schnellen Antworten. Ich bekomme die Warnung:
1
main.c:58: warning: initialization from incompatible pointer type

also hier:
1
} p_adr[] PROGMEM = {{6374,id06374},{6379,id06379},{6384,id06384},{6399,id06399}};

Noch was zum Verständnis, grundsätzlich sollen beide Arrays im Flash 
liegen. Das erste Array besteht nur aus Strings die auf das LCD 
ausgegeben werden. Das zweite Array hat als erstes die Adresse die über 
den Bus kommt. Selbige wird dann verglichen und wenn sie ausgegeben 
werden soll dann wird über den dazugehörigen Pointer auf den richtigen 
String aus Array 1 zugegriffen. Aber irgendwie habe ich ein Problem mit 
den Zeigern.

Gruß Rene

von Karl H. (kbuchegg)


Lesenswert?

>
1
> static struct{
2
>   uint16_t Adresse;
3
>   uint16_t* p_auf_ID_string;
4
> }
5
>

main.c:58: warning: initialization from incompatible pointer type

Na ja. Ein Pointer auf einen String ist ja auch nicht
unbedingt ein uint16_t*;

static struct{
  uint16_t Adresse;
  const char* p_auf_ID_string;
};

das sollte abhelfen.

von Rene Z. (renezimmermann)


Lesenswert?

Jo,
das funzt perfekt, frage mich nur wie oft ich diesen Fehler noch machen 
will. ;-)

Gruß Rene

von Rene Z. (renezimmermann)


Lesenswert?

Hallo, habe schon wieder ein Problem:
1
148:                  if (p_adr[z].Adresse == empfDaten.Adresse){
2
+000004E3:   91200067    LDS     R18,0x0067       Load direct from data space
3
+000004E5:   91300068    LDS     R19,0x0068       Load direct from data space
4
+000004E7:   E0E0        LDI     R30,0x00         Load immediate
5
+000004E8:   E0F0        LDI     R31,0x00         Load immediate
6
+000004E9:   E6A1        LDI     R26,0x61         Load immediate
7
+000004EA:   E0B1        LDI     R27,0x01         Load immediate
8
+000004EB:   918D        LD      R24,X+           Load indirect and postincrement
9
+000004EC:   919C        LD      R25,X            Load indirect
10
+000004ED:   9711        SBIW    R26,0x01         Subtract immediate from word
11
+000004EE:   1782        CP      R24,R18          Compare
12
+000004EF:   0793        CPC     R25,R19          Compare with carry
13
+000004F0:   F0C1        BREQ    PC+0x19          Branch if equal

p-adr[] ist ein Array im Flash ab 0x161 aber der Compiler nimmt an das 
es im Ram ist wie man an den LDS/LDI/LD sieht. Wie kann ich das Teil 
dazu bewegen den LPM Befehl zu benutzen?

Gruß Rene

von Simon K. (simon) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:
> Sprich: keine * - Derferenzierung sondern pgm_read_xxx
> Funktionen benutzen.

von Rene Z. (renezimmermann)


Lesenswert?

Morgen,

ja das habe ich auch schon probiert. Meiner Meinung nach müßte es so 
aussehen:
1
const char id06374[] PROGMEM = "Zimmer  7";
2
const char id06379[] PROGMEM = "Zimmer  9";
3
const char id06384[] PROGMEM = "Zimmer 11";
4
const char id06399[] PROGMEM = "Zimmer 21";
5
const char id06427[] PROGMEM = "Zimmer 36";
6
const char id06438[] PROGMEM = "Zimmer 42";
7
const char id06522[] PROGMEM = "Zimmer 49";
8
const char id06612[] PROGMEM = "Zimmer 52";
9
const char id06637[] PROGMEM = "Zimmer 55";
10
const char id06645[] PROGMEM = "Zimmer 59";
11
12
13
struct{
14
  uint16_t Adresse;
15
  const char* p_auf_ID_string;
16
} p_adr[] PROGMEM = {  {6374,id06374},{6379,id06379},{6384,id06384},{6399,id06399},{6427,id06427},
17
            {6438,id06438},{6522,id06522},{6612,id06612},{6637,id06637},{6645,id06645}};
18
19
for (uint8_t z=0; z<10; z++){                      // Lese alle möglichen Adressen
20
  if (pgm_read_word(p_adr[z].Adresse) == empfDaten.Adresse){      // und vergleiche sie mit der empfangenen
21
    strcpy_P(buffer, pgm_read_word(p_adr[z].p_auf_ID_string));    // wenn gleich, Flashstring in Rambuffer kopieren
22
    break;                              // wenn Adresse gefunden, Fertig
23
  }
24
}
Das gibt aber mal wieder eine Compilerwarnung:
1
main.c:151: warning: passing argument 2 of 'strcpy_P' makes pointer from integer without a cast

Aber wahrscheinlich habe ich mal wieder nur einen kleinen Fehler 
gemacht.

Gruß Rene

von Rolf Magnus (Gast)


Lesenswert?

pgm_read_word gibt einen integer zurück, aber strcpy_P will natürlich 
einen Zeiger haben.

Ich denke auch, daß du statt:
1
if (pgm_read_word(p_adr[z].Adresse) == empfDaten.Adresse){
eigentlich neinstest:
1
  if (pgm_read_word(&p_adr[z].Adresse) == empfDaten.Adresse){

von Rene Z. (renezimmermann)


Lesenswert?

Hi,

meinste so?
1
          for (uint8_t z=0; z<10; z++){                      // Lese alle möglichen Adressen
2
            if (pgm_read_word(&p_adr[z].Adresse) == empfDaten.Adresse){      // und vergleiche sie mit der empfangenen
3
              strcpy_P(buffer, (char*)pgm_read_word(p_adr[z].p_auf_ID_string));    // wenn gleich, Flashstring in Rambuffer kopieren
4
              break;                              // wenn Adresse gefunden, Fertig
5
            }
6
          }
Gruß Rene

von Rolf Magnus (Gast)


Lesenswert?

Ja

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.