Forum: Compiler & IDEs Präprozessor symbolische Zuweisung #if - Problem


von J. -. (Gast)


Lesenswert?

Moin,

Präprozessoren sind kompliziert und doof, aber nützlich. Leider.

Ich will für einen STM32F429 die SPI-Pins festlegen, dazu lebte ich 
bisher pro Pin ganz gut und praktisch mit 4 Parametern, also z.B.

#define SPI3_MOSI_RCC  RCC_AHB1Periph_GPIOD
#define SPI3_MOSI_PORT  GPIOD
#define SPI3_MOSI_PIN   GPIO_Pin_6
#define SPI3_MOSI_SRC   GPIO_PinSource6

Die lege ich am Anfang des Projekts fest.
Damit komme ich bei Verwendung der Standard-lib ganz gut zurecht, und 
habe für den STM32F407 einige Projekte damit laufen lassen.
Die möchte ich jetzt nicht alle ändern/nachbessern.


Zum Punkt: Der STM32F429 hat MOSI3 auf PORT B5,C12 und D6.
Das Bösartige ist, daß für B5 und C12 die AF6 gilt, für D6 aber AF5.
-> man braucht einen 5. Parameter, und definiert für jeden verflixten 
Pin auch noch die AF (doofe Lösung)

ODER

man läßt das den Präprozessor machen:
#if (SPI3_MOSI_PORT==GPIOD) && (SPI3_MOSI_SRC==GPIO_PinSource6)
  GPIO_PinAFConfig(SPI3_MOSI_PORT, SPI3_MOSI_SRC, GPIO_AF_SPI2);
#else
  GPIO_PinAFConfig(SPI3_MOSI_PORT, SPI3_MOSI_SRC, GPIO_AF_SPI3);
#endif


Problem: Der macht das nicht, weil GPIOD in der stm32f4xx.h als 
((GPIO_TypeDef *) GPIOD_BASE) definiert ist, also keinen Zahlenwert hat 
oder nichts, womit der Präproz was anfangen kann.
Schön und gut, dann macht man eben eine unsaubere Lösung und wählt den 
Pin selbst als Entscheidungskriterium (was problematisch wird, wenn ST 
einen Chip herausbringt, bei dem MOSI3 noch auf einem anderen Port x6 
liegt):

#if SPI3_MOSI_PIN==GPIO_Pin_6
  GPIO_PinAFConfig(SPI3_MOSI_PORT, SPI3_MOSI_SRC, GPIO_AF_SPI2);
#else
  GPIO_PinAFConfig(SPI3_MOSI_PORT, SPI3_MOSI_SRC, GPIO_AF_SPI3);
#endif

Aber jetzt die Unverschämtheit: Selbst das frißt er nicht. Auch nicht, 
wenn ich explizit den Pin mit Zahlenwert benenne, also: #if 
SPI3_MOSI_PIN==0x0040 ...


Da komme ich jetzt an die Grenzen meiner Leistungsfähigkeit ;). Wieso 
macht der das nicht? Irgendwie komme ich da mit meinem Verständnis vom 
Präproz als Symbolprozessor ins Schleudern.Tatsache ist, es MUSS mit dem 
Präproz gehen, aber ich stehe gerade auf dem Schlauch, wie.
(IDE ist CooCox, Compiler ist ARM-non-eabi)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jürgen S. schrieb:

> Aber jetzt die Unverschämtheit: Selbst das frißt er nicht.

Das hier steht dazu im STM-Headerfile:
1
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */

Da ist halt ein Typecast drin, von sowas hat der Präprozessor keine
Ahnung.

Es gibt aber keinen vernünftigen Grund, warum du das unbedingt mit
dem Präprozessor erschlagen musst.  Du kannst das auch ganz normal
im Code vergleichen (oder mit dem ternären Operator entscheiden).
Wenn der Compiler feststellt, dass der Bedingungsausdruck für den
Vergleich zur Compilezeit bereits konstant ist, dann setzt er während
der Optimierung fest den richtigen Wert ein und berechnet nichts zur
Laufzeit.

: Bearbeitet durch Moderator
von J. -. (Gast)


Lesenswert?

Ah, das uint16_t führt dann dazu, daß er den Zahlenwert ignoriert. 
Danke.

Ich schaue mal, wie sich der Code verhält, wenn man es zur Laufzeit 
macht, wie von Dir vorgeschlagen.
(Aber ein bißchen ärgert es mich schon, daß ich da keine 
Präprozessorlösung gefunden habe ;) )

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jürgen S. schrieb:
> Ah, das uint16_t führt dann dazu, daß er den Zahlenwert ignoriert.

Naja, der Präprozessor kann einfach nur mit Ganzzahlen rechnen.
Die dürfen zwar so groß sein wie maximal für die Plattform zulässig,
auch Suffixe wie "UL" oder so sind statthaft, aber alles jenseits
einer einfachen Zahl kann der Präprozessor nicht.  Dazu gehört eben
auch ein Typecast.

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.