Forum: Compiler & IDEs AVR strings im flash mit progmem, direkt als argumente an funktionen?


von Paul H. (powl)


Lesenswert?

Hi,

ist es beim GCC irgendwie möglich, strings ähnlich komfortabel wie 
gewohnt an funktionen zu übergeben, aber sie im flash zu speichern?

so à la

funktion_die_mit_flash_stringkonstanten_umgehen_kann(PROGMEM 
"Stringkonstante im Flash");

wenn nein, geht dann nur folgendes:

const char PROGMEM temp[] = "Stringkonstante im Flash";
funktion_die_mit_flash_stringkonstanten_umgehen_kann(temp);

wenn ich an einer ganz anderen Stelle im Code in einem ganz anderen 
Block irgendwo nochmal die gleiche Stringkonstante nutze:

const char PROGMEM temp[] = "Stringkonstante im Flash";
andere_funktion(temp);

wird das dann wie gewohnt vom Compiler optimiert oder legt der das dann 
doppelt im Flash ab? Ansonsten müsste ich ganz am Anfang eine Tabelle 
mit sämtlichen Stringkonstanten anlegen und könnte auf diese dann nur 
noch über z.B. Tabelle[3] zugreifen, wodurch ich im Code überhaupt nicht 
mehr sehe, was da in der Tabelle an der entsprechenden Stelle nun 
drinsteht.. ziemlich unkomfortabel.

Die Stringkonstanten sind übrigens für ein LCD gedacht.
lg PoWl

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Siehe PSTR in der AVR-Libc

von Paul H. (powl)


Lesenswert?

Ah danke das ist ja genau das, was ich gesucht habe.

Leider optimiert der Compiler das nicht so, dass gleiche Strings 
zusammengefasst werden sondern doppelt im Flash abgelegt werden.

Gibts da einen Workaround?

von N. M. (mani)


Lesenswert?

Paul Hamacher schrieb:
> Leider optimiert der Compiler das nicht so, dass gleiche Strings
> zusammengefasst werden sondern doppelt im Flash abgelegt werden.

Wieso machst Du das überhaupt so?
Es reicht doch den String einmal zu definieren und in Deinen anderen 
c-Files über extern bekannt zu machen.

von Paul H. (powl)


Lesenswert?

Ich bin jetzt nicht sooo der C-Guru, kannst du mir das erläutern? ;)

übrigens handelt es sich um eine einzige C-File. Falls du meinst, dass 
ich die Stringkonstante einmal irgendwo definiere und dann fortan über 
ihre Variable darauf zugreife: das will ich ja gerade durch Benutzung 
von PSTR vermeiden

Ich habe für mein LCD eine State-Machine mit Menüstrukturen. Hin und 
wieder kommt es halt vor, dass da identische Textzeilen ausgegeben 
werden sollen und wenn es möglich ist, soll der Compiler das erkennen 
und hierfür einen gemeinsamen Speicherplatz im Flash benutzen anstatt 
die Strings doppel im Flash abzulegen.

Ist halt komfortabler für mich beim Programmieren und da es sich sowieso 
um Konstanten handelt das einzig richtige.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Paul Hamacher schrieb:
> Ah danke das ist ja genau das, was ich gesucht habe.
>
> Leider optimiert der Compiler das nicht so, dass gleiche Strings
> zusammengefasst werden sondern doppelt im Flash abgelegt werden.
>
> Gibts da einen Workaround?

Siehe http://gcc.gnu.org/PR43746 verfügbar ab 4.7.

Ist aber noch etwas holprig, siehe -fmerge-all-constants und 
http://gcc.gnu.org/PR50739

Siehe auch die 4.7 Release-Notes:

http://gcc.gnu.org/gcc-4.7/changes.html

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Zumindest folgendes kleines Beispiel funktioniert mit avr-gcc 4.7:
1
#include <avr/pgmspace.h> 
2
3
const char * volatile p;
4
5
int main (void)
6
{ 
7
    p = PSTR ("Hallo");
8
    p = PSTR ("nochmal Hallo");
9
    return 0;
10
}
 
mit -Os -fmerge-all-constants wird daraus:
 
1
main:
2
  ldi r24,lo8(__c.1515)
3
  ldi r25,hi8(__c.1515)
4
  sts p+1,r25
5
  sts p,r24
6
  ldi r24,lo8(__c.1517)
7
  ldi r25,hi8(__c.1517)
8
  sts p+1,r25
9
  sts p,r24
10
  ldi r24,0
11
  ldi r25,0
12
  ret
13
14
  .section .progmem.data.str1.1,"aMS",@progbits,1
15
__c.1515:
16
  .string  "Hallo"
17
__c.1517:
18
  .string  "nochmal Hallo"

Die beiden String-Literale liegen in der gleichen Section und haben das 
gleiche Alignment. Zusätzlich ist das erste Literal Suffix des zweiten; 
sie könne also gemergt werden.

objdump zeigt das:
 
1
Disassembly of section .text:
2
3
...
4
5
00000026 <__c.1517>:
6
  26:  6e 6f 63 68 6d 61 6c 20           nochmal 
7
8
0000002e <__c.1515>:
9
  2e:  48 61 6c 6c 6f 00                 Hallo.
10
11
...
12
13
00000056 <main>:
14
  56:  8e e2         ldi  r24, 0x2E  ; 46
15
  58:  90 e0         ldi  r25, 0x00  ; 0
16
  5a:  90 93 61 00   sts  0x0061, r25
17
  5e:  80 93 60 00   sts  0x0060, r24
18
  62:  86 e2         ldi  r24, 0x26  ; 38
19
  64:  90 e0         ldi  r25, 0x00  ; 0
20
  66:  90 93 61 00   sts  0x0061, r25
21
  6a:  80 93 60 00   sts  0x0060, r24
22
  6e:  80 e0         ldi  r24, 0x00  ; 0
23
  70:  90 e0         ldi  r25, 0x00  ; 0
24
  72:  08 95         ret

von Paul H. (powl)


Lesenswert?

Ooooookay ich verstehe noch nicht so ganz wie ich den GCC 4.7 
installieren kann bzw wo ich ihn überhaupt herbekomme. Kann mir da 
jemand auf die Sprünge helfen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

GCC ist ein Open Source Projekt, d.h. es werden die Quellen releast, für 
GCC 4.7.1 zB

http://gcc.gnu.org/ml/gcc/2012-06/msg00198.html

ftp://ftp.gnu.org/gnu/gcc/gcc-4.7.1/

Daraus generiert ma sich dann passende Executables für die gewünschten 
Sprachen (C, C++, Ada, Java, Fortran, ...) das gewünschte OS (Wondows, 
Linus, hp-ux, Mac OS, Solaris, ...) und die gewünschte Zielarchitektur 
(AVr, ARM, PowerPC, x86, ...)

Weil das vielen zu komplizier ist, gibt's auch fertige Toolchains, und 
mit etwas Glück findest du eine wo alle Parameter zu deinen 
Anforderungen passen.

avr-gcc-4.7.1 für Windows zB da verlnks und erklärt:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=963192#963192

Und immer auch die Release-Notes lesen!

http://gcc.gnu.org/gcc-4.7/changes.html

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.