Forum: Compiler & IDEs Cortex M3/M4 im Präprozessor erkennen


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

gibt es beim GCC eine Möglichkeit, per Präprozessor-Direktive zu 
erkennen, ob für einen Cortex M0, M3 oder M4 kompiliert wird?

Beim Keil-Compiler wird durch die Toolchain __CORTEX_M0, __CORTEX_M3, 
__CORTEX_M4 definiert, beim GCC nicht.

Gibt es beim GCC entsprechendes, oder läuft es darauf hinaus, eine 
entsprechende Präprozessorvariable selbst definieren zu müssen?

Oder anders gefragt: Wie stellt ihr fest, welche Intrisics für die 
Ziel-Plattform zur Verfügung stehen? Wie wählt ihr die richtige 
Header-Datei aus?
1
#if ????
2
    #include "core_cm3.h"
3
#elif ????
4
    #include "core_cm4.h"
5
#else
6
    #error "unknown target"
7
#endif




Viele Grüße
W.T.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Walter T. schrieb:
> __CORTEX_M0, __CORTEX_M3,
> __CORTEX_M4

in der Form gibt's das nicht, aber hier:

http://micro-os-plus.sourceforge.net/wiki/Predefined_macros

gibt's eine hübsche Darstellung, wie man die Kerls trotzdem 
auseinanderhalten kann.

von Walter T. (nicolas)


Lesenswert?

Auf die Makros bin ich auch schon gestoßen. Irgendwie erscheint es mir 
aber wie "hinten durch die Brust ins Auge":
1
#if defined(__arm__) && !defined(__ARM_FEATURE_SAT)
2
    #include "core_cm0.h"
3
#elif defined(__arm__) && defined(__ARM_FEATURE_SAT) && !defined(__ARM_FEATURE_SIMD32)
4
    #include "core_cm3.h"
5
#elif defined(__arm__) && defined(__ARM_FEATURE_SAT) && defined(__ARM_FEATURE_SIMD32)
6
    #include "core_cm4.h"
7
#else
8
    #error "unknown target"
9
#endif

von eagle user (Gast)


Lesenswert?

Walter T. schrieb:
> Oder anders gefragt: Wie stellt ihr fest, welche Intrisics für die
> Ziel-Plattform zur Verfügung stehen? Wie wählt ihr die richtige
> Header-Datei aus?

Die Trennung nach M0/M3/M4... deckt ja nur einen winzigen Teil der 
Unterschiede von Chip zu Chip ab, jeder braucht seine eigenen 
Definitionen für die Hardware. Also gibt es hier ein Verzeichnis pro 
Chip. Bei allen M0-Chips steht da eine Kopie von "core_cm0.h" drin, bei 
den M3-Chips eine von "core_cm3.h"... Die Kopie heißt hier aber immer 
"asm.h".

Im Makefile wird das passende Chip-Header-Verzeichnis mit der Option 
"-I" angegeben und in den Quellen steht immer "asm.h".


So quasi das Gegenteil von deinem Wunsch ist wahrscheinlich möglich. Ein 
Quell-Datei kann angeblich die gcc-Option "-mcpu" umschalten:
https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html

von eagle user (Gast)


Lesenswert?

Es geht doch wenigstens etwas direkter:
1
touch foo.h
2
/opt/gcc/install/bin/arm-none-eabi-cpp -mthumb -mcpu=cortex-m3 -dM foo.h > m3
3
/opt/gcc/install/bin/arm-none-eabi-cpp -mthumb -mcpu=cortex-m4 -dM foo.h > m4
4
diff -c0 m4 m3
liefert alle predefined macros für die jeweilige CPU und diff zeigt die 
Unterschiede zwischen m3 und m4.
"grep ARCH" liefert:
1
                       m0   m3   m4   m7  m23
2
__ARM_ARCH              6    7    7    7    8
3
__ARM_ARCH_6M__         1   --   --   --   --
4
__ARM_ARCH_7M__        --    1   --   --   --
5
__ARM_ARCH_7EM__       --   --    1    1   --
6
__ARM_ARCH_8M_BASE__   --   --   --   --    1
7
__ARM_ARCH_PROFILE     77   77   77   77   77
8
__ARM_ARCH_ISA_THUMB    1    2    2    2    1
9
__ARM_ARCH_EXT_IDIV__  --    1    1    1    1

von Walter T. (nicolas)


Lesenswert?

Ich habe es dann doch noch ganz anders gemacht: Nämlich genauso wie in 
der arm_math.h:
1
#if defined(ARM_MATH_CM7)
2
  ...
3
#elif defined (ARM_MATH_CM4)
4
  ...
5
#elif defined (ARM_MATH_CM3)
6
  ...
7
#elif defined (ARM_MATH_CM0)
8
  ...
9
#else
10
  #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0"
11
#endif

Wenn ich diese Makros ohnehin global definieren muß, kann ich sie auch 
direkt anderweitig weiterverwenden.

von Christopher J. (christopher_j23)


Lesenswert?

Im Grunde steckt doch alles in den CMSIS-Core Headern drin, auf denen 
jeder Hersteller dann seine ominösen Libraries aufbaut. Hast du z.B. 
einen STM32F446, dann wird (zumindest indirekt) irgendwo per #include 
eine "stm32f4xx.h" eingebunden. Dieser Header bindet dann wiederum je 
nachdem welcher #define für das eigentliche Device gesetzt ist einen 
spezifischeren Header ein. Für den F446 ist es "stm32f446xx.h" und hast 
du einen F407, dann ist es "stm32f407xx.h". In diesen 
(Device-spezifischen) Header-Dateien wird der passende Header für den 
Cortex-M Kern eingebunden, das heißt in diesem Beispiel (egal ob F407 
oder F446) jeweils "core_cm4.h". In dieser "core_cm4.h" gibt es dann 
direkt ein
1
#define __CORTEX_M (4U)

Wie genau die #defines für die anderen Cortex-M sind kannst du jeweils 
in der "core_cmX.h" herauslesen. Jedenfalls wird diese "core_cmX.h" ganz 
automagisch indirekt über den Device-Header eingebunden und das ist 
(soweit ich weiß) immer der Fall, nicht nur bei ST.

von Walter T. (nicolas)


Lesenswert?

Das stimmt zwar  - aber wie nützt das?

Wie würdest Du die Defines und Includes einer *.C- und der zugehörigen 
*.H-Datei machen, die als "mathematische Library" Funktionen, die in 
Integer/Float32 gerechnet werden, zur Verfügung stellt?

Wenn ich für den Cortex M4 kompiliere, will ich die sättigenden 
Operationen und die Multiply-Accumulate natürlich nutzen, wenn ich für 
Windows kompiliere, soll natürlich der Ersatzcode für die M0/M3 zum 
Einsatz kommen.

Im Wesentlichen läuft das ja darauf hinaus, den richtigen Header zu 
includieren. Danach kann ich fallweise prüfen, ob die Intrinsics, die 
ich für eine Operation brauche, definiert sind und Ersatzcode 
bereitstellen (der GCC scheint ja die Idiome [noch?] nicht zu erkennen).

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Walter T. schrieb:
> Wenn ich für den Cortex M4 kompiliere, will ich die sättigenden
> Operationen und die Multiply-Accumulate natürlich nutzen, wenn ich für
> Windows kompiliere, soll natürlich der Ersatzcode für die M0/M3 zum
> Einsatz kommen.

Du willst also wissen, ob es gesättigte Arithmetik gibt, findest aber 
die dafür richtige Abfrage nach exakt dieser Feature per 
__ARM_FEATURE_SAT seltsam und bevorzugst die falsche Frage nach dem 
Core?

von Seher (Gast)


Lesenswert?

In einer bunten IDE klickst du irgendwo den gewünschten µC an. Die 
deklariert dann das Makro.
Wenn du zu Fuß unterwegs bist, musst du es selber setzen. Egal, ob mit 
Keil oder GCC. Der Compiler kann deinen µC nicht erraten. Oder du nimmst 
den spezifischen Header für genau den µC. Da steckt es i. d. R. auch 
drin.

von Carl D. (jcw2)


Lesenswert?

Seher schrieb:
> In einer bunten IDE klickst du irgendwo den gewünschten µC an. Die
> deklariert dann das Makro.
> Wenn du zu Fuß unterwegs bist, musst du es selber setzen. Egal, ob mit
> Keil oder GCC. Der Compiler kann deinen µC nicht erraten. Oder du nimmst
> den spezifischen Header für genau den µC. Da steckt es i. d. R. auch
> drin.

Egal ob IDE oder makefile, der Compiler will schon wissen ob er M3 oder 
M4 Code erzeugen soll. ARM ist nur bedingt gleich ARM.

von Seher (Gast)


Lesenswert?

Carl D. schrieb:
> Egal ob IDE oder makefile, der Compiler will schon wissen ob er M3 oder
> M4 Code erzeugen soll.

Was verstehst du daran nicht?

Seher schrieb:
> Der Compiler kann deinen µC nicht erraten.

von Walter T. (nicolas)


Lesenswert?

A. K. schrieb:
> Du willst also wissen, ob es gesättigte Arithmetik gibt,

Das auch - aber das war nicht meine Frage, weil es sich einfach 
herausfinden läßt. Meine Frage bezog sich darauf, den richtigen Header 
einzubinden.

von Seher (Gast)


Lesenswert?

Carl D. schrieb:
> der Compiler will schon wissen ob er M3 oder
> M4 Code erzeugen soll. ARM ist nur bedingt gleich ARM.

<Klugscheissmodus>
Es geht um Cortex und nicht reinen ARM. Code für den M0 ist ohne 
Änderung auf einem M3 oder M4 lauffähig. Das ist ein Entwicklungsprinzip 
der ARM-Company. Frag sie mal.
</Klugscheissmodus>

von Christopher J. (christopher_j23)


Lesenswert?

Walter T. schrieb:
> Das stimmt zwar  - aber wie nützt das?
>
> Wie würdest Du die Defines und Includes einer *.C- und der zugehörigen
> *.H-Datei machen, die als "mathematische Library" Funktionen, die in
> Integer/Float32 gerechnet werden, zur Verfügung stellt?

Sorry, ich hatte die Frage nicht richtig verstanden. Was ich geschrieben 
habe ist für deine Anwendung natürlich quatsch. Die passendste Antwort 
hat denke ich Markus direkt zu Beginn gegeben.

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.