Forum: Compiler & IDEs Stringarray im Flash


von Günter (Gast)


Lesenswert?

Hallo Ihr,

ein Anfänger hat ein Problem mit einem Stringarray im Flash.

Randbedingungen:
Compiler Avr-GCC
MCU: Atmega103


-------Code-------

const char text1[] PROGMEM = "Parameter laden   ";
const char text2[] PROGMEM = "Parameter ändern  ";
const char text3[] PROGMEM = "Parameter senden  ";

PGM_P dmenu[9] PROGMEM = { text1, text2, text3};



int main(void)
{


    char buffer[10];

    strcpy_P( buffer, dmenu[1] );

    lcd_putc(buffer)
    for(;;);
}



So funktioniert es, wenn ich nun aber das Array im Progmem nicht direkt 
anspreche [1], sondern über einen Variablenindex [var], dann geht es 
nicht mehr.
Also so:

int main(void)
{
unsigned int disp;
char buffer[10];

   disp=1;
   strcpy_P( buffer, dmenu[disp] );
   lcd_putc(buffer)
   for(;;);

}



Kann mir jemand helfen,was ich falsch mache?

Gruss Günter

von Günter (Gast)


Lesenswert?

Sorry,

mit nicht funktionieren meine ich, dass der String der aufs Display 
geschrieben wird versaut ist. Also irgendwelche zeichen, aber nicht die 
gewollten. Also zugriffsfehler im Speicher.

von Joerg Wunsch (Gast)


Lesenswert?

Das hier:

dmenu[1]

will etwas aus dem RAM lesen.  Du hast aber explizit gesagt,
daß das im ROM sein solle.  Da mußt Du Dich vorher mit __lpm_inline
drum kümmern, daß es aus dem ROM erstmal in (temporären) RAM
kommt.

Oder aber, Du läßt zwar die Strings selbst im ROM, aber das
Array nicht.  6 Bytes RAM dafür sind ja nicht gerade viel.
Du würdest mehr RAM sparen, wenn Du das nicht erst mit
strcpy_P() in einen temporären RAM-Puffer kopieren müßtest,
sonder gleich ein lcd_putc_P() noch lieferst, das die Strings
direkt aus dem Flash verarbeiten kann.

von Günter (Gast)


Lesenswert?

Hallo Jörg,

nun hast Du mich ganz verwirrt...

Aber trotzdem mal:

Hab die LCD-Routinen von Peter Fleury verwendet. Dort ist ja auch ein 
lcd_puts_p dabei, das ein String stück für stück aus dem Progmem liest 
und dann aufs Display schickt.

Aber auch da hab ich das selbe Problem.
Soll heissen, ich kann mein Stringarray direkt addressieren, in dem ich 
die lcd_putc_p routine, wie auch oben beim strcpy_P, mit ner Zahl als 
Index aufrufe. Aber sobald ich die Zahl mit ner variablen ersetze, 
springt er mir zum Teufel...
Begreif das im Moment noch nicht... wo ist der Unterschied zwischen 
dmenu(2) und dmenu(test), mit test=2;

Oder steh ich jetzt so gnadenlos auf dem Schlauch?

Gruss Günter

von Joerg Wunsch (Gast)


Lesenswert?

Nein, was Du noch nicht begriffen hast ist, daß Du das
Herauspopeln aus dem Flash grundsätzlich erstmal selbst
vornehmen mußt, wenn Du etwas im Flash ablegst.  Der Compiler
tut das nicht für Dich.  Von daher ist es keine sonderlich
praktische Idee, das Array selbst im Flash anzulegen, sondern
laß für das Array all die PROGMEM & Co weg, dann funktioniert
es.

von Peter Fleury (Gast)


Lesenswert?

Für dieses kleine Array kann es schon sinnvol sein, das Array im RAM 
abzulegen. Aber z.B. bei einer komplexen Menu-Struktor sollte das Array 
und der Text im Flash abgelegt werden.

Wenn der Index eine konstante ist (dmenu[2]), kann der Compiler der 
Flash-Adresse einfügen:

lcd_puts_p( dmenu[1] );

Wenn der Index aber eine Variable ist, muss man die Adresse
mittels LPM Befehlen herauslesen:

for (i=0; i<3; i++) lcd_puts_p( PRG_RDW(&dmenu[i]) );

Im <avr/pgmspace.h> gibt es zwar ein PRG_RDB() Makro, aber kein 
PRG_RDW() Makro, ich habe deshalb folgendes definiert:

#define PRG_RDW(a) (PRG_RDB((a))+0x100*PRG_RDB((uint16_t)(a)+1))

Besser wäre allerding wenn man PRG_RDW() als Inline-Asm realiseren würde 
und <avr/pgmspace.h> ergänzen würde.






   p = (char *)PRG_RDW(&menu[menuState].text);
   lcd_puts_p(p);

von Günter (Gast)


Lesenswert?

Hallo Joerg und Peter,

vielen Dank fürs "unter die Arme Greifen"... nun hab ichs geschnallt... 
und siehe da: ES funktioniert! Jubel.

Nochmals Danke....

Grüssle Günter

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.