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

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.