www.mikrocontroller.net

Forum: Compiler & IDEs Bedingte Kompilierung


Autor: ALex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich arbeite mit AVR Studio und möchte abhänging vom Device meinen 
Quellcode compilieren. Dazu möchte ich "MCU" auswerten und zwischen 
ATMEGA und ATTINY unterscheiden.

Meine Frage: gibt es eine möglichkeit, bei #if bzw. #ifdef usw. zu 
schauen, ob in "MCU" ATTINY oder ATMEGA steht und den Rest (bei ATMEGA 
32,16,8 usw.) auszublenden, durch Wildcards oder ähnlich??

Gruß, Alex

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, wildcards gibt es nicht.  Du musst schon einzeln testen:
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__)
#  define THIS megaTHIS
#elif defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny261__)
#  define THIS tinyTHIS
#else
#  error "Unknown MCU type"
#endif

Autor: mikro_sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

da häng ich mich doch gleich mit dran, wenn so ein Thema schonmal offen 
ist:

Ich habe ein ähnliches Problem, ich will eine Initialisierung meines 
verwendeten Controllers vornehmen. Dazu will ich über eine Art 
"Case-Struktur" entscheiden, welcher Controller gewählt wurde und nur 
den dafür zutreffenden Code compilieren lassen. Die restlichen Cases 
brauch ich aber ja nicht im Code, würde nur Platz verschwenden.

Nun dachte ich an eine Bibliothek, die ich dann ins eigentliche Programm 
einbinde. Im Hauptprogramm wird dann beispielsweise über
#define mcu tiny25
der Controller festgelegt. In der Bibliothek würde ich dann - wie oben 
beschrieben - über ifdefs den linker entscheiden lassen, welchen 
Init-Code er compiliert. Aber das kann doch unglaublich umfangreich 
werden, oder nicht?

Jetzt hab ich aber mit C leider noch nicht allzu große Erfahrung und 
frage mich, ob das überhaupt Funktioniert bzw. guter Stil ist, oder ob 
man besser anders vorgeht. Könnte man das ganze auch über ein Makefile 
lösen und wenn, wie sollte man da am Besten vorgehen? Ich habe schon 
einige Beispiele über Makefiles gelesen (u. a. auch den Exkurs im 
GCC-Tutorial), aber bedingte Compilierungen hab ich da nicht gefunden.

Viele Grüße und Danke für eure Vorschläge!

Sven

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte man im Makefile nach WinAVR-Vorlage so lösen:

# fuer alle controller
SRC=wieauchimmer.c egal.c foo.c
# controllerspezifischer code
ifeq($(MCU),atmega128)
SRC+=codefueratmega128.c
endif
ifeq($(MCU),atmega16)
SRC+=codefueratmega16.c
endif

Vgl. z.B. http://www.siwawi.arubi.uni-kl.de/avr_projects/#avrprog_boot

Ob das nun übersichtlicher ist, als den Preprocessor zu bemühen, mag 
jeder selbst entscheiden. Meist sind die Unterschiede nicht so gross, 
dass eigene Quellcodedateien benötigt werden.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In der Bibliothek würde ich dann - wie oben beschrieben -
> über ifdefs den linker entscheiden lassen, welchen
> Init-Code er compiliert.

Das geht so nicht. Präprozessoranweisungen wie #ifdef werden vom 
Präprozessor ausgewertet, und dessen Resultat landet im Compiler. Der 
Linker bekommt Präprozessoranweisungen nie zu sehen.

Dein Ansatz kann -leicht abgewandelt- dennoch funktionieren:
Den Prozessorspezifischen Code packst Du in eigene Module (mindestens 
eines pro Prozessor) und die darin enthaltenen Funktionen benennst Du 
entsprechend eindeutig, also beispielsweise

  m128_init in m128.c
  m32_init in m32.c
  m16_init in m16.c

etc.

Die alle übersetzt Du und packst sie in eine Library. Etwaig verwendete 
globale Variablen müssen ebenfalls dieser Nomenklatur gehorchen.

Dein diese Library nutzender Code bindet eine Headerdatei ein, in der 
per Präprozessoranweisungen aus dem generischen "init" der jeweils zu 
verwendende Name erzeugt wird:

  #if defined(_AVR_ATmega16_)
  #define init m16_init
  #endif

  #if defined(_AVR_ATmega128_)
  #define init m128_init
  #endif

Dein Code ruft "init" auf; durch die Präprozessoranweisung wird das 
korrekte implementierungsabhängige "init" daraus gemacht und der Linker 
linkt aus der Library das Modul, in dem der zugehörige Code enthalten 
ist.

So ginge es.

Autor: G. L. (sprintersb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht hilft Dir das builtin Define _ARV_ARCH_ ?


http://www.roboternetz.de/wissen/index.php/Avr-gcc...

Autor: mikro_sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten!

@rufus: Gute Idee! Zum testen habe ich mir die entsprechenden Module und 
die Library erstellt. Das Header-File (msp_init.h) sieht nun so aus:
int msp430_1_init(void);
int msp430_2_init(void);
int msp430_3_init(void);

#if defined(_MSP430_1_)
#define init msp430_1_init
#endif

#if defined(_MSP_430_2_)
#define init msp430_2_init
#endif

#if defined(_MSP_430_3_)
#define init msp430_3_init
#endif

Meine Main hab ich so geschrieben:
#include "msp_init.h"
#define MSP430_1

int main(void)
{
  init();
}

Nun bekomme ich leider einen Fehler, dass "init" nicht definiert ist. 
Verstehe ich das richtig, dass der Präprozessor im Header-File bei den 
Präprozessoranweisungen in meinem Fall 'init' mit 'msp430_1_init' 
ersetzt, da ich in der Main ja gesagt habe '#define MSP430_1'? Dann 
würde im Code ja statt der Funktionsaufruf 'init();' der Aufruf 
'msp430_1_init();' erfolgen.

Ich komm da grad nicht drauf...

Viele Grüße
Sven

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include "msp_init.h"
#define MSP430_1

ist wohl die falsche Reihenfolge.

Generell wäre es auch sinnvoll, ein #if...#elif..#else error "no device 
defined"-Konstrukt zu verwenden, dann bekommst du eine aussagekräftige 
Fehlermeldung.

Oliver

Autor: mikro_sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Perfekt! Danke, das war's. Warum sieht man solche Kleinigkeiten alleine 
nur so schwer?!

Nur zur Info: Zusätzlich muss ich in der Main ja überhaupt
#define _MSP430_1_

statt
#define MSP430_1

schreiben ;-)

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.