Forum: Mikrocontroller und Digitale Elektronik Pointer String mit PROGMEM?!


von Jan H. (janiiix3)


Lesenswert?

Hallo,

Gibt es eine einfache Möglichkeit die ganzen Pointer Strings mit PROGMEM 
zu versehen?
1
/*
2
*  Strings for LCD Display
3
*/
4
typedef struct
5
{
6
  char *PrjName;
7
  char *SWV;
8
  char *HWV;
9
  char *SetTime;
10
  char *SetDate;
11
  char *SetIllumination;
12
  char *Time[10];  
13
  char *SwitchTimeEnable;
14
  char *ToggleTriac;
15
  char *ManuelMode;
16
  char *TriacOn;
17
  char *TriacOff;  
18
  char *SubmenueTime[5];
19
  char *SubmenueExit;
20
  char *hours;
21
  char *minutes;
22
  char *seconds;
23
}AppStrings_t;

von fop (Gast)


Lesenswert?

Die Suchen & Ersetzen Funktion Deines Editors ? Suche "char", ersetze 
durch ...

von Jan H. (janiiix3)


Lesenswert?

fop schrieb:
> Die Suchen & Ersetzen Funktion Deines Editors ? Suche "char", ersetze
> durch ...

So meinte ich das nicht.

Ich möchte gerne die Variablen mit im Programmspeicher einbetten (sind 
Konstante Pointer Strings), aktuell sind sie ja im SRAM.


1
AppStrings_t const Strings PROGMEM; // das bewirkt nichts...

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

Ein schneller Blick in die libc-Hilfe zeigt beim Thema pgmspace, dass es 
z.B. den Typ PGM_p gibt.

von Jan H. (janiiix3)


Lesenswert?

Georg G. schrieb:
> Ein schneller Blick in die libc-Hilfe zeigt beim Thema pgmspace, dass es
> z.B. den Typ PGM_p gibt.


Habe ich bereits gesehen. Das funktioniert aber nur mit char Array´s?!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Das müsste eigentlich so gehen:
1
const char PrjName[] PROGMEM = "Hallo";
2
const char SWV[]     PROGMEM = "Welt";
3
...
4
5
typedef struct
6
{
7
   const char * const PROGMEM PrjName;
8
   const char * const PROGMEM SWV;
9
   ...
10
}AppStrings_t;
11
12
AppStrings_t mystrings =
13
{
14
    PrjName,
15
    SWV,
16
    ...
17
};

: Bearbeitet durch Moderator
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
>    const char * const PROGMEM PrjName;

Das sollte einen Fehler geben.
1
const __flash char PrjName[] = "Hallo";
2
const __flash char SWV[] = "Welt";
3
...
4
5
typedef struct
6
{
7
   const __flash char *PrjName;
8
   const __flash char *SWV;
9
   ...
10
}AppStrings_t;
11
12
AppStrings_t mystrings = // mystrings im RAM
13
{
14
    PrjName,
15
    SWV,
16
    ...
17
};
18
19
const __flash AppStrings_t mystrings = // mystrings im Flash
20
{
21
    PrjName,
22
    SWV,
23
    ...
24
};

Analog mit PROGMEM, nur dass man dann noch #include avr/pgmspace.h und 
pgm_read_xxx braucht (mit __flash genügt "normales" C).

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?


von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
>>    const char * const PROGMEM PrjName;
>
> Das sollte einen Fehler geben.

Nö. Ich hatte das vorher getestet. Der avr-gcc nimmt das anstandslos.

> const __flash AppStrings_t mystrings = // mystrings im Flash
> {

Die adäquate Version mit PROGMEM - falls eine ältere avr-gcc-Version 
benutzt wird, die noch kein __flash versteht:

const AppStrings_t mystrings PROGMEM =
{

von Peter D. (peda)


Lesenswert?

Eigentlich macht man ja eine Struct, damit man nicht für jedes Element 
einen extra Pointer braucht, sondern nur einen Pointer auf die Struct, 
um schnell und codesparend mit Displacement auf die einzelnen Elemente 
zugreifen zu können.

Insbesondere die Pointer in den Flash zu legen, hieße ja, die Adressen 
sind zur Compilezeit bekannt. Wozu also die Umstände mit Pointern?

von Wilhelm M. (wimalopaan)


Lesenswert?

Und bei der PROGMEM Variante aufpassen, dass man die PROGMEM C-Strings 
bei der Ausgabe anders behandeln muss als "normale" Stringliterale oder 
char-Arrays.

In C++ habe ich entsprechende Datentypen dafür und muss den Unterschied 
nicht selbst beachten.

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

Peter D. schrieb:
> Eigentlich macht man ja eine Struct, damit man nicht für jedes Element
> einen extra Pointer braucht, sondern nur einen Pointer auf die Struct,
> um schnell und codesparend mit Displacement auf die einzelnen Elemente
> zugreifen zu können.
>
> Insbesondere die Pointer in den Flash zu legen, hieße ja, die Adressen
> sind zur Compilezeit bekannt. Wozu also die Umstände mit Pointern?

Ich gebe dir Recht, aber wie baut man sich diese Struktur zusammen? Wenn 
ich nicht die Pointer sondern die Texte direkt im struct ablegen will, 
muss ich ja die Arraygrößen bzw die länder der Texten mitangeben:
1
const __flash struct {
2
  char helloWorld[14];
3
  char swVersion[6];
4
} flashTexts = {
5
  "Hello, World!",
6
  "v0.01"
7
};
Geht, ist aber ziemlich fehleranfällig.

von Eric B. (beric)


Lesenswert?

hmm...

1) Definiere alle Texte mit einem Makro
1
// flashtexts.inc
2
3
// define all flash texts here
4
// TEXT(name, value)
5
TEXT(helloWorld, "Hello, World!")
6
TEXT(swVersion,  "0.01beta")
7
TEXT(breakfast, "Continental")

2) Header-file zum inkludieren wo man die Text(e) benutzen möchte:
1
// flashtexts.h
2
#ifndef FLASHTEXTS_H
3
#define FLASHTEXTS_H
4
5
#undef  TEXT
6
#define TEXT(NAME,VALUE) NAME[ sizeof(VALUE) ];
7
8
extern const __flash struct {
9
#include "flashtexts.inc"
10
} texts;
11
12
#endif

3) C Modul worin die Texte angelegt werden:
1
// flashtexts.c
2
#include "flashtexts.h"
3
4
5
#undef  TEXT
6
#define TEXT(NAME,VALUE) VALUE,
7
8
texts = {
9
#include "flashtexts.inc"
10
};

4) Benutzen:
1
#include "flashtexts.h"
2
3
int main()
4
{
5
  printf(texts.helloWorld);
6
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Johann L. schrieb:
>>>    const char * const PROGMEM PrjName;
>>
>> Das sollte einen Fehler geben.
>
> Nö. Ich hatte das vorher getestet. Der avr-gcc nimmt das anstandslos.

Sonderlich sinnvoll ist so ein Code aber nicht.  Es ist ungefähr so 
sinnvoll, wie unterschiedliche Komponenten eines Struct in 
unterschiedliche Sections legen zu wollen.

Immerhin bekomme ich eine Warnung, dass progmem ignoriert wird -- 
vorausgesetzt, es steht nach dem "PrjName".

von Rabe (Gast)


Lesenswert?

Eric B. schrieb:

>
1
> const __flash struct {
2
>   char helloWorld[14];
3
>   char swVersion[6];
4
> } flashTexts = {
5
>   "Hello, World!",
6
>   "v0.01"
7
> };
8
>

> Geht, ist aber ziemlich fehleranfällig.

Was ist daran fehleranfällig?

von Peter D. (peda)


Lesenswert?

Ich benutze die pgmspace.h möglichst nicht und "verschwende" RAM mit der 
C-konformen Schreibweise.
Meistens lohnt sich die Mühe auch nicht.
Beim ATMega1284 (16KB RAM) muß mit RAM nicht so geizen.

von Jan H. (janiiix3)


Lesenswert?

Also in den meisten Quelltexten sehe ich nur Strings mit Arrays.
1
char Str[] = "Test_String";

Wie macht ihr das denn?

von Arduinoquäler (Gast)


Lesenswert?

Peter D. schrieb:
> Beim ATMega1284 (16KB RAM) muß mit RAM nicht so geizen.

Beim Arduino Uno und Consorten (alle kleineren AVRs) ist man
häufig sehr dankbar wenn man das RAM zu Lasten des Flash von
den vielen Nicht-Variablen befreien kann.

von Eric B. (beric)


Lesenswert?

Rabe schrieb:

> Was ist daran fehleranfällig?

Dass ich aufpassen muss, dass die Längenangaben und tatsächliche 
Textlängen passen, und die Reihenfolge der Texte und deren Definitionen 
die gleiche ist.
1
const __flash struct {
2
  char helloWorld[200];
3
  char swVersion[2];
4
} flashTexts = {
5
  "v0.01",
6
  "Hello, World!" 
7
};

von Peter D. (peda)


Lesenswert?

Ich hab auch festgestellt, daß die pgmspace.h leider nicht abwärts 
kompatibel ist.
Wenn man ältere Projekte aus WINAVR 2010 mit neueren AVR-GCC compiliert, 
gibt es Fehlermeldungen (und umgekehrt).
Daher fasse ich die nur noch mit der Kneifzange an.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Ich hab auch festgestellt, daß die pgmspace.h leider nicht abwärts
> kompatibel ist.
> Wenn man ältere Projekte aus WINAVR 2010 mit neueren AVR-GCC compiliert,
> gibt es Fehlermeldungen (und umgekehrt).

Es gibt Fehler, wenn man versucht, nicht-const Objekte ins Flash zu 
legen.  Das ist dann aber ein Problem des Project-Codes, nicht von 
pgmspace.h.

Dass avr-gcc nicht-const Daten im Flash ablehnt, ist auch den Release 
Notes entnehmbar; wenn man also asbach uralt Projekte übersetzten will, 
sollte man auch eine asbach uralt Toolchain verwenden.

Und hast du ein Beispiel, dass Code, der mit einer aktuellen Toolchain 
übersetzt, dass mit einem WinAVR-20100110 nicht mehr tut (abgesehen von 
damals noch nicht unterstützten Devices, Optionen, Qualifiern, etc).

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Dass avr-gcc nicht-const Daten im Flash ablehnt, ist auch den Release
> Notes entnehmbar; wenn man also asbach uralt Projekte übersetzten will,
> sollte man auch eine asbach uralt Toolchain verwenden.

Braucht man nicht. Dann schreibt man const davor und schon läuft es mit 
der alten und mit der neuen Toolchain.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Johann L. schrieb:
>> Dass avr-gcc nicht-const Daten im Flash ablehnt, ist auch den Release
>> Notes entnehmbar; wenn man also asbach uralt Projekte übersetzten will,
>> sollte man auch eine asbach uralt Toolchain verwenden.
>
> Braucht man nicht. Dann schreibt man const davor und schon läuft es mit
> der alten und mit der neuen Toolchain.

Ja, ich weiß.  Hilft aber zunächst nicht weiter, wenn jemand ein Projekt 
mit einer neuen Toolchain generieren will und dann Fehler bekommt. 
Beispiel ist USBasp

http://www.fischl.de/usbasp/

Da kannst dann erst mal auf die Suche gehen, wo das const hin muss...

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.