之前在調試傳感器模塊的時候發現,在結構體聲明的時候irq成員使用gpio_to_irq會報錯,而動態使用的話就沒有問題。就對gpio_to_irq為什么不能靜態使用產生了疑問。恰巧最近又有朋友遇到了同樣的問題,也就提醒了我,去找出原因。
轉自:http://blog.csdn.net/airk000/article/details/23339257
開始測試
我寫了一個簡單的linux執行程序進行測試,因為在內核源碼中發現不同平臺對gpio_to_irq的定義不同,有的是宏定義,而更多的則直接是函數。所以在這個測試程序中我也以這一點作為切入點,進行測試。
?
函數
#include <stdio.h>static int plus_one(int x){return (x + 1);}struct test {int num;char *name;};struct test test1 = { .num = plus_one(5),.name = "test",};int main(void){printf("%d %s\n", test1.num, test1.name);return 0;}
編譯,果然出錯了:
main.c:14:5: error: initializer element is not constant.num = plus_one(5),^
main.c:14:5: error: (near initialization for ‘test1.num’)
可見,函數是不能作為結構體聲明靜態使用的。那么改為動態試一試看:
struct test test1 = { .name = "test",};int main(void){test1.num = plus_one(5);printf("%d %s\n", test1.num, test1.name);return 0;}
編譯,通過,能夠輸出想要的結果。
結論:函數不能在結構體聲明等代碼中靜態使用,即使函數內容再簡單。只能以動態方式使用函數。在Linux內核的omap2平臺代碼中也印證了這一點,許多設備資源都是在初始化函數中(即資源生效前)進行gpio_to_irq的動態賦值。
?
宏定義
使用宏定義代替上述代碼中的plus_one函數
#define plus_one(x) ((x) + 1)...struct test test1 = { .num = plus_one(5),.name = "test",};int main(void){printf("%d %s\n", test1.num, test1.name);return 0;}
編譯,通過,輸出我們希望的結果。這證明宏定義可以靜態使用,那么動態呢?
struct test test1 = { .name = "test",};int main(void){test1.num = plus_one(5);printf("%d %s\n", test1.num, test1.name);return 0;}
編譯,通過,輸出想要的結果。OK,這說明宏定義同樣可以進行動態引用。
結論:宏定義在代碼中無論是靜態引用還是動態引用均可以。
?
總結
通過測試代碼可以看出函數的使用有局限性:只能動態引用,而不能靜態使用。宏定義就顯得友好多了,靜態、動態使用均可。回到開始的問題gpio_to_irq為什么不能靜態使用?就是因為很多平臺代碼都將gpio_to_irq實現成為了函數,而非宏定義,這樣就只能進行動態引用。但是,這在驅動編寫中也不是什么問題,在上面已經說過,只要在設備資源生效前(設備注冊前)將其irq動態賦值好就可以了,現有的很多成熟平臺也是這樣做的,并沒有問題。這里我探究這個問題只是因為自己的好奇心而已。