Forum: Compiler & IDEs Concatenation (token pasting) und #define-Auflösung


von Max G. (l0wside) Benutzerseite


Lesenswert?

Hallo zusammen,

um bei der Portkonfiguration des MSP430 nicht das gleiche zweimal 
schreiben zu müssen, würde ich mir gerne die zugehörigen Registernamen 
mit dem Präprozessor zusammenstricken. Beispiel:

UART soll auf P4.6 liegen, dazu brauche ich im CCS die Anweisung
1
P4MAP6 = PM_UCA1TXD;

Mittels Token Pasting kann man sich wunderbar so etwas bauen
1
#define PMC_PORT(PORT,BIT) P ## PORT ## MAP ## BIT

Die Anweisung
1
PMC_PORT(4,6) = PM_UCA1TXD;

löst dann auch anstandslos auf zu
1
P4MAP6 = PM_UCA1TXD;

Nun will ich das ganze aber parametrieren, d.h. Port und Bit über 
#defines festlegen. Das geht schief, denn bei Token Pasting werden 
Makros nicht aufgelöst. Ein
1
PMC_PORT(UART_P,UART_B) = PM_UCA1TXD;

wird zu
1
PUART_PMAPUART_B = PM_UCA1TXD;

worüber sich der Compiler natürlich dann beklagt.


Kennt jemand einen passenden Workaround?

Grüße,

Max

P.S.: Bei der (erfolglosen) Google-Recherche zum Thema bin ich auch über 
den Versuch gestolpert, mittels Token Pasting ein #define 
zusammenzubauen. Elegantes Verfahren - aber vom Standard leider nicht 
gedeckt.

von Peter D. (peda)


Lesenswert?

Max G. schrieb:
> Das geht schief, denn bei Token Pasting werden
> Makros nicht aufgelöst.

Also beim AVR-GCC geht es. Man muß noch ein Zwischenmacro benutzen:
1
#include<avr/io.h>
2
3
// Access bits like variables:
4
struct bits {
5
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
6
} __attribute__((__packed__));
7
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
8
#define SBIT(x,y)       SBIT_(x,y)
9
10
11
#define PORT_C3         SBIT( PORTC, PC3 )
12
#define PIN_D7          SBIT( PIND,  PD7 )
13
14
15
int main()
16
{
17
  for(;;){
18
    PORT_C3 = ! PIN_D7;
19
  }
20
}


Peter

von Max G. (l0wside) Benutzerseite


Lesenswert?

Genial, da wäre ich nicht drauf gekommen. Danke!

Mein Code sieht nun so aus:
1
#define PMC_REG_(PORT,BIT) P##PORT##MAP##BIT
2
#define PMC_REG(PORT,BIT) PMC_REG_(PORT,BIT) 
3
4
#define POUT_SET_(PORT,BIT,VAL) { if (VAL == 0) { POUT ## PORT &= (~(1 << BIT)); } else { POUT ## PORT |= (1 << BIT); }
5
#define POUT_SET(PORT,BIT,VAL) POUT_SET_(PORT,BIT,VAL)
6
7
#define UART_P 4   // UART: P4.6
8
#define UART_B 6 
9
10
[...]
11
12
PMC_REG(UART_P,UART_B) = PM_UCA1TXD;
13
POUT_SET(UART_P,UART_B,1);

...compiliert ohne weitere Klagen, und der Preprocessor Output sieht 
auch gut aus.

Ich bin mal wieder beeindruckt von Tempo und Qualität der Antwort. 
Super!

Gruß,

Max

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.