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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Naj H. (janiiix3)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Die Suchen & Ersetzen Funktion Deines Editors ? Suche "char", ersetze 
durch ...

von Naj H. (janiiix3)


Bewertung
0 lesenswert
nicht 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)


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

von Naj H. (janiiix3)


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht lesenswert

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-1 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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 Naj H. (janiiix3)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.