Zugriff string Konstante im PROGMEM eleganterer, einfacherer Weg?

Gast #1670567
Lesenswert?
• ▲
▼
Hi!

Nun wird mein SRAM langsam knapp und ich muss meine String Konstanten in 
den PROGMEM verschieben. Derzeit behelfe ich mir so, das geht doch gibt 
es einen eleganteren Weg?
1
void get_id_name(uint8_t id, char *out) {
2
  static char strA[] PROGMEM = "Alfons";
3
  static char strB[] PROGMEM = "Julia";
4
  static char strC[] PROGMEM = "Seb";
5
  static char strD[] PROGMEM = "Olaf";
6
  static char strE[] PROGMEM = "unknown";
7

8
  switch (id) {
9
    case 0: copy_pgmstr_to_ram(strA, out); break;
10
    case 1: copy_pgmstr_to_ram(strB, out); break;
11
    case 2: copy_pgmstr_to_ram(strC, out); break;
12
    case 3: copy_pgmstr_to_ram(strD, out); break;
13
    case 4: copy_pgmstr_to_ram(strE, out); break;
14
  }
15
}

Ich brauche also zu der ID dann einen Zeiger auf die Zeichenkette.
Meine Versuche mit einer direkte Deklaration eines Array funktioniert 
nicht.

Danke für jeden Tip!

Gruß AVRli...
#1670603
Lesenswert?
• ▲
▼
Erspart dir den char PROGMEM Teil. Eleganter (und schneller) geht es, 
indem du die Zeiger auf die einzelnen Strings in ein Array packst.
1
static char strA[] PROGMEM = "Alfons";
2
static char strB[] PROGMEM = "Julia";
3
static char strC[] PROGMEM = "Seb";
4
static char strD[] PROGMEM = "Olaf";
5
static char strE[] PROGMEM = "unknown";
6

7
static char strings[] = {
8
  strA,
9
  strB,
10
 ...
11
};
12

13
void get_id_name(uint8_t id, char *out) {
14
  strcpy_P(out, &(strings[id]);
15
}

Logischerweise kannst du auch diesen in den PROGMEM legen. Spart dir 
dann je 2 Byte/Eintrag, nur musst du dann vorher auch diesen aus dem 
Flash lesen, siehe [1].

gruß
Mobius

[1] http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
Gast #1671190
Lesenswert?
• ▲
▼
Hallo!

Danke für Eure Hinweise.
Ich habe mich nun an das Beispiel gehalten aber das sorgt nun dafür das 
mein Programm nun überhaupt nicht mehr anläuft. :-(

Das wird nun aber auch so in [1] beschrieben.

Ob ich das mit den Zeigern jemals verstehen werde??? :-(

Gruß AVRli...
1
void get_id_name(uint8_t id, char *out) {
2

3
char string_1[] PROGMEM = "String 1";
4
char string_2[] PROGMEM = "String 2";
5
char string_3[] PROGMEM = "String 3";
6
char string_4[] PROGMEM = "String 4";
7
char string_5[] PROGMEM = "String 5";
8

9
PGM_P string_table[] PROGMEM = 
10
{
11
    string_1,
12
    string_2,
13
    string_3,
14
    string_4,
15
    string_5
16
};
17

18
    strcpy_P(out, (PGM_P)pgm_read_word(&(string_table[id])));
19
}
#1671220
Lesenswert?
• ▲
▼
Deine Strings stehen so ja auch gar nicht im Flash (und die 
Pointer-Liste auch nicht). Du bekommst doch auch garantiert "attribute 
ignored"-Wanungen vom Compiler. Entweder schreibst du noch ein static 
davor, oder du machst globale Variablen daraus.

PS: Und für die Zukunft merken: Warnungen nicht einfach ignorieren, und 
bei Fragen hier mit angeben.
#1671227
Lesenswert?
• ▲
▼
Mir ist nicht klar, warum du nicht den allereinfachsten Weg gehst
1
void get_id_name(uint8_t id, char *out) {
2
  switch (id) {
3
    case 0:  copy_pgmstr_to_ram(PSTR( "Alfons" ),  out); break;
4
    case 1:  copy_pgmstr_to_ram(PSTR( "Julia" ),   out); break;
5
    case 2:  copy_pgmstr_to_ram(PSTR( "Seb" ),     out); break;
6
    case 3:  copy_pgmstr_to_ram(PSTR( "Olaf" ),    out); break;
7
    default: copy_pgmstr_to_ram(PSTR( "unknown" ), out); break;
8
  }
9
}

Das PSTR Makro sorgt dafür, dass der String ins Flash verbannt wird.
Gast #1671516
Lesenswert?
• ▲
▼
Karl heinz Buchegger schrieb:
> Mir ist nicht klar, warum du nicht den allereinfachsten Weg gehst

Ja mir wohl auch nicht. :-(
Das ist wirklich ein sehr interessanter Weg! :-D
So konnte ich ohne viel deklarieren meine ganzen Zeichenkette in den 
PROGMEM legen. Gut die ganzen str Funktionen müssen dann natürlich die 
mit _P sein das war aber nicht so schwer.

Satte 30% hab ich im RAM mit Zeichenketten "verballert". Nun im 
Programmspeicher ist noch genügend Platz, auf Geschwindigkeit kommt es 
bei der Anwendung nicht an.

Und nebenbei meine Funktion
1
copy_pgmstr_to_ram(PSTR( "Alfons" ),  out);

Gibt es ja auch schon, ach wenn man nicht immer das Rad neu erfinden 
würde wollen. Gut ich hab was bei gelernt aber die folgende nehme ich 
nun. ;-)
1
strcpy_P(out, PSTR( "Alfons" );


Danke!
Gruß AVRli...
#1671616
Lesenswert?
• ▲
▼
@AVRli (Gast)

>Satte 30% hab ich im RAM mit Zeichenketten "verballert". Nun im
>Programmspeicher ist noch genügend Platz, auf Geschwindigkeit kommt es
>bei der Anwendung nicht an.

Aus dem RAM lesen dauert beim AVR 2 Takte (ld), aus dem Flash 3 Takte 
(lpm). Plus den ganzen Schleifenoverhead ist beides annähernd gleich 
schnell.

MfG
Falk

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren