Dummy für __flash bzw PROGMEN

Persönliche Seite #5697299
Lesenswert?

Hi,

ich würde gerne eine große Menge Strings, die ich für den  avr-gcc 
Compiler definiert habe im normalen gcc verwenden.

Daher bin ich auf der Suche nach einem geschickten Makro, dass mir diese 
attribute wieder entfernt/redefiniert.
1
...
2
#ifdef GCC
3
    #define __flash ?
4
    #define PROGMEM ??
5
#endif
6

7
const __flash cahr strHund[] = "Hund";
8
const char strKatze[] PROGMEM = "Katze";
9
...

Mir ist klar, dass ich alles doppelt definieren könnte a la:
1
...
2
#ifdef GCC
3
    const _cahr strHund[] = "Hund";
4
    const char strKatze[] = "Katze";
5
#else
6
const __flash cahr strHund[] = "Hund";
7
const char strKatze[] PROGMEM = "Katze";
8
#endif
9
...

Diese Pflege möchte ich mir jedoch sparen, auch wenn ein CnP mit 
modernen IDEs, die "Column Selection Mode" unterstützen recht schnell 
geht.

Grüße David
#5697314
Lesenswert?

Statt der <pgmspace.h> "include" ich in meinen gemischen Projekten die 
folgendete "pgmspace.h":
1
#ifndef PGMSPACE_H
2
    #define PGMSPACE_H
3

4
    #ifdef AVR
5
      #define constflash const __flash
6
    #include <avr/pgmspace.h>
7
        #include <stdio.h>
8

9
  #elif defined(STM32F10x) || defined(STM32F4XX) || defined __MINGW64__ \
10
        || defined __MING32__ || defined __linux__
11
        #define PGMSPACE_EMULATION 1
12

13
    #else
14
        #error "undefined platform"
15

16
    #endif
17

18

19
    #if PGMSPACE_EMULATION
20
    #define PROGMEM
21
    #define pgm_read_byte(a) (*(a))
22
    #define pgm_read_word(a) (*(a))
23
    #define pgm_read_pointer(a) (*(a))
24
    #define constflash const
25
    #define PSTR(a) (a)
26

27
    #define strlen_P strlen
28
    #define strncpy_P strncpy
29

30
    #define vsnprintf_P vsnprintf
31
    #define printf_P printf
32
    #define fprintf_P fprintf
33
    #define fputs_P fputs
34

35
        // snprintf_P sollte wegen eines Fehlers in einer AVR-GCC-Version nicht verwendet
36
        // werden. Als Workaround wird die Funktion wasnprintf_P eingefuehrt.
37
    #define snprintf_P 1 // Fuehrt zu einem Fehler bei einem Build mit der Funktion
38
                         // snprintf_P()
39

40
    // Workaround-snprintf-Funktion
41
    #define wasnprintf_P snprintf
42

43
  #endif
44
#endif // PGMSPACE_H

(Vor dem Edit stand hier nur eine "Prinzip-Variante")
Persönliche Seite #5698552
Lesenswert?

Oliver S. schrieb:
> avr-gcc ist ein gcc. Also ist das auch definiert.

Der GCC definiert "__GNUC__" aber nicht "GCC". Da es sich um ein 
Compiler-Spezifisches Makro handelt, darf es nicht mit eventuellen 
Bezeichnern im User-Code kollidieren. Stell dir vor jemand hat dieses 
absolut korrekte und standardkonforme C-Programm verfasst:
1
int main () {
2
  int GCC = 42;
3
  return 0;
4
}
Wenn der GCC ein Makro namens "GCC" definieren würde, würde dieser 
standarkonforme Code nicht mehr funktionieren, wodurch der GCC nicht 
standardkonform wäre. Daher fängt das Makro mit 2 Unterstrichen an. 
Würde jemand ein Programm dieser Art verfassen:
1
int main () {
2
  int __GNUC__ = 42;
3
  return 0;
4
}
funktioniert es vielleicht in manchen Compilern, aber da Bezeichner mit 
2 Unterstrichen im User-Code verboten sind, ist es falsch und nicht 
standard-konform. Daher ist es ok wenn dieses Programm nicht im GCC 
funktioniert, was auch der Fall ist, da der GCC "__GNUC__" definiert.

Also: Kein Compiler wird ein Makro namens "GCC" definieren oder sonst 
irgendein compilerspezifisches Makro ohne 2 Unterstriche oder 
Unterstrich+Großbuchstabe. "__GNUC__" ist das was man will.

Siehe auch hier, es gibt noch ein paar mehr Details zu beachten:
https://sourceforge.net/p/predef/wiki/Compilers/
Moderator Persönliche Seite #5698599
Lesenswert?

PROGMEM kannst du gern in eigenem Code definieren, aber __flash gehört 
zum implementation namespace, davon solltest du die Finger lassen.

Umschreib' das besser komplett anders, bspw.:
1
#ifdef __AVR__
2
#  define FLASHSTRING(sym, str) const char sym[] __flash = str
3
#else
4
#  define FLASHSTRING(sym, str) const char sym[] = str
5
#endif
6

7
// ...
8
FLASHSTRING(msg1, "Hello, world!\n");
9
FLASHSTRING(msg2, "Good bye!\n");
Persönliche Seite #5698702
Lesenswert?

Oliver S. schrieb:
> avr-gcc ist ein gcc. Also ist das auch definiert.

Und damit ist es hier unbrauchbar, um zwischen GCC für AVR und GCC für 
das Wirtssystem zu unterscheiden. Deshalb fragte ich danach.

Also ist
1
#ifndef __AVR__
2
    #define __flash
3
    #define PROGMEM
4
#endif

eine simple Lösung.

Jörgs Ansatz ist natürlich der bessere, erfordert aber mehr Arbeit.

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