Linux內核頭文件中關於s3c2410 GPIO的宏

一、GPIO寄存器定義

1#define GPCON(x)   __REG2(0x56000000, (x) * 0x10)

這句是定義2410GPIO控制寄存器,注意:__REG2的參數是寄存器的物理地址,這個物理地址經_REG2宏轉換爲虛擬地址,對照2410的手冊可以得到一下對應關係:

GPCON1 ------ PORT A  0x56000000

GPCON2 ------ PORT B  0x56000010

GPCON3 ------ PORT C  0x56000020

  .           .           .         .

  .           .           .         .

  .           .           .         .

GPCON8 ------ PORT H  0x56000070

2#define GPDAT(x)   __REG2(0x56000004, (x) * 0x10)

這句是定義2410GPIO的數據寄存器,定義方法同GPCON宏。

GPDAT1 ------ PORT A  0x56000004

GPDAT2 ------ PORT B  0x56000014

GPDAT3 ------ PORT C  0x56000024

  .           .           .         .

  .           .           .         .

  .           .           .         .

GPDAT8 ------ PORT H  0x56000074

3#define GPUP(x)      __REG2(0x56000008, (x) * 0x10)

這句是定義2410GPIO上拉電阻屏蔽/激活寄存器,定義方法同GPCON宏。

GPUP1 ------ PORT A  0x56000008

GPUP2 ------ PORT B  0x56000018

GPUP3 ------ PORT C  0x56000028

  .           .           .         .

  .           .           .         .

  .           .           .         .

GPUP8 ------ PORT H  0x56000078

二、GPIO端口號定義

GPIO_G12來說明在內核頭文件$(KERNEL_INCLUDE)/asm-arm/arch/s3c2410.h中是如何來定義IO port的端口號的。定義GPIO端口主要涉及到以下幾個宏:

#define MAKE_GPIO_NUM(p, o)         ( (p << GPIO_PORT_SHIFTT) |  /

(o << GPIO_OFS_SHIFT))

#define GPIO_G12               MAKE_GPIO_NUM(PORTG_OFS, 12)

GPIO_PORT_SHIFTT值爲8,代表GPIO組號在整個GPIO端口號(如GPIO_G12)字段中的位移

GPIO_OFS_SHIFT值爲0,代表GPIO組內偏移號在整個GPIO端口號(如GPIO_G12)字段中的位移

   s3c2410117個多功能input/output port pins。分爲以下八組:

— Port A (GPA): 23-output port                    #define PORTA_OFS                 0

— Port B (GPB): 11-input/output port               #define PORTB_OFS                1

— Port C (GPC): 16-input/output port               #define PORTC_OFS             2

— Port D (GPD): 16-input/output port               #define PORTD_OFS                3

— Port E (GPE): 16-input/output port                #define PORTE_OFS           4

— Port F (GPF): 8-input/output port                #define PORTF_OFS           5

— Port G (GPG): 16-input/output port               #define PORTG_OFS            6

— Port H (GPH): 11-input/output port                #define PORTH_OFS           7

 

GPG12屬於G組,組內偏移爲12,從上述兩個宏定義中,我們可以很清楚地看出GPIO_G12結構:

 

                    圖1  GPIO端口號結構圖

端口一共有8組,從上面的宏定義可以看出,端口組號p的範圍:07。而組內偏移各組不盡相同,Port A23個輸出口,因此它的組內偏移o022Port G16IO口,它的組內偏移o015,其他組的GPIO以此類推。

三、write_gpio_bit(x,v)宏分析

write_gpio_bit宏傳入兩個參數,第一個爲GPIO端口號,如GPIO_G12;第二個參數爲10爲相應IO口設置高電平或低電平輸出。具體宏展開如下:

#define write_gpio_bit(x, v) /

                             ({  /

GPDAT(GRAB_PORT((x))) &= ~(0x1 << GRAB_OFS((x))); /

                               GPDAT(GRAB_PORT((x))) |= ((v) << GRAB_OFS((x))); /

})

GRAB_PORT宏的參數是GPIO端口號,功能是從GPIO端口號中解析出組號,具體定義如下:

#define GRAB_PORT(x)              (((x) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFTT)

其中GPIO_PORT_MASK是組號的掩碼,值爲0x0000ff00,從圖1中也可看出。

GRAB_OFSGRAB_PORT類似,它的功能是從GPIO端口號中解析出組內偏移:

#define GRAB_OFS(x)            (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT)

其中偏移值掩碼GPIO_OFS_MASK0x000000ff

現在我們結合上述說明來分析write_gpio_bit(GPIO_G12,1)這條語句:由GPIO_G12的宏定義可計算出其值爲0x0000060CGRAB_PORTGPIO_G12)解析得到所操作的IO屬於G組,組號爲6GRAB_OFSGPIO_G12)解析得到此IO口爲G組的第12個引腳(從0開始算起),爲GPG12,表達式值爲12。則write_gpio_bit(GPIO_G12,1)等價於下面兩條語句:

GPDAT(6) &= ~(0x1<<12);  //GPGDAT寄存器第12位清零

GPDAT(6) | = 1<<12;       // GPGDAT寄存器第12位寫入1

到此,我們知道了write_gpio_bit(GPIO_G12,1)這條語句是將GPG12這個引腳拉成高電平。

四、set_gpio_ctrl(x)宏分析

#define set_gpio_ctrl(x) /

       ({ GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2)); /

          GPCON(GRAB_PORT(x)) |= (GRAB_MODE(x) << (GRAB_OFS((x))*2)); /

          GPUP(GRAB_PORT((x))) &= ~(1 << GRAB_OFS((x))); /

          GPUP(GRAB_PORT((x))) |= (GRAB_PULLUP((x)) << GRAB_OFS((x))); })

完成了對write_gpio_bit宏的分析,現在來看set_gpio_ctrl就很簡單了!在它的宏展開中只多了GRAB_MODE(x) GRAB_PULLUP(x)分別表示從參數x中解析出IO口的模式和使能/屏蔽此端口的上拉電阻值得注意的是set_gpio_ctrl的參數x不僅僅表示GPIO端口號,其高16位還帶有模式狀態和上拉電阻控制信息,參數x的結構如下圖:

 

 

 


2 set_gpio_ctrl的參數字段結構圖

 

    16位即爲前面所述的GPIO的端口號,高16位中的R字段用來屏蔽/使能IO口的上拉電阻功能。R0,上拉電阻使能;R1,上拉電阻失效。M字段用來設置IO口的工作模式,M0IO口爲輸入端口;M1IO口爲輸出端口;M2,可選功能1M3,可選功能2

set_gpio_ctrl宏就是通過寫相應GPIO所在組的GPXCONXAH)的相應位來設置IO口模式(GPACON每一個位控制一個IO口,而GPBCONGPHCON都是兩個位控制一個IO口的模式),通過寫GPXUPXAH)來決定是否啓用上拉電阻。典型的set_gpio_ctrl調用方式如下:

set_gpio_ctrl(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G12);

這條語句是將GPG12設置成輸出模式,並且不使用端口的上拉電阻。

五、結束

以上主要結合《S3C2410X 32-BIT RISC MICROPROCESSOR USER'S MANUAL》分析了$(LINUX_KERNEL_INCLUDE)/asm-arm/arch/s3c2410.h中所定義的對2410GPIO進行操作的幾個宏,除了文中提及的幾個宏,除此還有read_gpio_bit(x)read_gpio_reg(x) write_gpio_reg(x, v)等,實現方法和上述類似,在此不再一一贅述!

                        

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章