2010-02-04 112 views
3

我希望有人可能對如何控制/指定宏擴展的順序有一個想法。這裏是上下文:有沒有辦法控制宏擴展命令


// 32 bit increments, processor has registers for set, clear and invert 
#define CLR_OFF 1 
#define SET_OFF 2 
#define INV_OFF 3 


#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits 
//Now if I use this I can do it quite nicely with 
#define STATUS_LED 0x0040; 
SET(LATB, STATUS_LED); // LATB is port of the LED. 

其實我已經不得不四處相當多的移動硬件爲晚,所以我決定把與STATUS_LED像這樣的LATB信息...


#define STATUS_LED_PORT LATB 
#define STATUS_LED_MASK 0x0040; 
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK 

//And I try to use it via 
SET(STATUS_LED); 

但是,唉,LATB,0x0040被傳遞給SET宏的參數1。當不作爲宏觀這種方法正常工作:


inline void SET(u32_t *reg, u32_t bits) { ((volatile u32_t *) (((u32_t)reg) + SET_OFF*4)) = bits; } 
//Change the STATUS_LED macro to 
#define STATUS_LED &STATUS_LED_PORT, STATUS_LED_MASK 
SET(STATUS_LED); //Works great! 

但不幸的是我的編譯器不看到需要內聯函數,並導致6個指令設置寄存器,而不是4,所以同時使用位 - 它是不可預知的。

我希望有人可能知道的方式來擴大STATUS_LED宏觀第一,是這樣的: SET(##STATUS_LED)

目前我的解決辦法繼續前進是有兩個宏SET和SETRM(寄存器的設定,面罩)但我覺得應該有一個解決方案,因爲設置的代碼看起來像......


#define SETRM(reg,bits) ... 
#define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE?? 

最後,我的處理器的編譯器不支持正參數宏,我想我可能能夠發揮與那,但唉:(。

非常感謝您的時間,我會很感激任何想法,我可以繼續前進,但如果我可以在任何地方都使用SET,它會更加清潔。

回答

4

換人發生在一組的方式。在#運算符或##的任一側之後不出現的所有參數在被替換時完全被宏展開,而不是類似宏的宏展開之前。

這意味着要讓單個宏成爲兩個宏參數,必須在所需函數(如宏)自身展開之前進行一輪宏替換。

這意味着像擴展到所需功能類宏的第二個函數的解決方案是最簡單的解決方案。

即給原來的SET定義

#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits 

和擴展到兩個潛在的爭論

#define STATUS_LED_PORT LATB 
#define STATUS_LED_MASK 0x0040; 
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK 

宏必須使用另一個函數宏,以獲得您所需要的替換。

例如

#define SET2(x) SET(x) 

然後SET2(STATUS_LED)擴展如下。

SET(LATB , 0x0040;) 

然後

*((volatile unsigned long*)(& LATB + 2)) = 0x0040; 

這是無效的,因爲沒有足夠的參數給SET宏;在參數發生任何擴展之前,參數都與參數匹配。我的編譯器生成一個錯誤;行爲沒有定義。

SET(STATUS_LED) 
1

如果根的名字始終是相同的,你可以使用:在函數宏擴展的參數

#define SET_COMPOSITE(root) SET(root##_PORT, root##_MASK) 
相關問題