gpioer
来源:互联网 发布:怎么进行网络直播 编辑:程序博客网 时间:2024/04/30 17:20
一、GPIO寄存器定义
1.#define GPCON(x) __REG2(0x56000000, (x) * 0x10)
这句是定义2410的GPIO的控制寄存器,注意:__REG2的参数是寄存器的物理地址,这个物理地址经_REG2宏转换为虚拟地址,对照2410的手册可以得到一下对应关系:
GPCON(1) ------ PORT A 0x56000000
GPCON(2) ------ PORT B 0x56000010
GPCON(3) ------ PORT C 0x56000020
. . . .
. . . .
. . . .
GPCON(8) ------ PORT H 0x56000070
2.#define GPDAT(x) __REG2(0x56000004, (x) * 0x10)
这句是定义2410的GPIO的数据寄存器,定义方法同GPCON宏。
GPDAT(1) ------ PORT A 0x56000004
GPDAT(2) ------ PORT B 0x56000014
GPDAT(3) ------ PORT C 0x56000024
. . . .
. . . .
. . . .
GPDAT(8) ------ PORT H 0x56000074
3.#define GPUP(x) __REG2(0x56000008, (x) * 0x10)
这句是定义2410的GPIO的上拉电阻屏蔽/激活寄存器,定义方法同GPCON宏。
GPUP(1) ------ PORT A 0x56000008
GPUP(2) ------ PORT B 0x56000018
GPUP(3) ------ PORT C 0x56000028
. . . .
. . . .
. . . .
GPUP(8) ------ 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)字段中的位移
s3c2410有117个多功能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 #definePORTD_OFS 3
— Port E (GPE): 16-input/output port #definePORTE_OFS 4
— Port F (GPF): 8-input/output port #define PORTF_OFS 5
— Port G (GPG): 16-input/output port #definePORTG_OFS 6
— Port H (GPH): 11-input/output port #define PORTH_OFS 7
GPG12属于G组,组内偏移为12,从上述两个宏定义中,我们可以很清楚地看出GPIO_G12结构:
图1 GPIO端口号结构图
端口一共有8组,从上面的宏定义可以看出,端口组号p的范围:0~7。而组内偏移各组不尽相同,Port A有23个输出口,因此它的组内偏移o为0~22,Port G有16个IO口,它的组内偏移o为0~15,其他组的GPIO以此类推。
三、write_gpio_bit(x,v)宏分析
write_gpio_bit宏传入两个参数,第一个为GPIO端口号,如GPIO_G12;第二个参数为1或0,为相应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_OFS宏和GRAB_PORT类似,它的功能是从GPIO端口号中解析出组内偏移:
#define GRAB_OFS(x) (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT)
其中偏移值掩码GPIO_OFS_MASK=0x000000ff。
现在我们结合上述说明来分析write_gpio_bit(GPIO_G12,1)这条语句:由GPIO_G12的宏定义可计算出其值为0x0000060C,GRAB_PORT(GPIO_G12)解析得到所操作的IO属于G组,组号为6;GRAB_OFS(GPIO_G12)解析得到此IO口为G组的第12个引脚(从0开始算起),为GPG12,表达式值为12。则write_gpio_bit(GPIO_G12,1)等价于下面两条语句