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/s 3c 2410.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)字段中的位移

   s 3c 2410117个多功能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的宏定义可计算出其值为0x 0000060C GRAB_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)等,实现方法和上述类似,在此不再一一赘述!

                        

 

你可能感兴趣的:(c,linux,IO,user,include,linux内核)