Linux头文件中s3c2410 GPIO的宏

来源:互联网 发布:js touchend 触发多次 编辑:程序博客网 时间:2024/05/21 02:21

一、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        #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的范围: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口设置高电平或低电平输出。具体宏展开如下:

代码
  1. #define write_gpio_bit(x, v)    
  2.                              ({      
  3. GPDAT(GRAB_PORT((x))) &= ~(0x1 << GRAB_OFS((x)));    
  4. GPDAT(GRAB_PORT((x))) |= ((v) << GRAB_OFS((x)));    
  5. })  


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)等价于下面两条语句:

GPDAT(6) &= ~(0x1<<12);  //GPGDAT寄存器第12位清零
GPDAT(6) | = 1<<12;       // 向GPGDAT寄存器第12位写入‘1’

到此,我们知道了write_gpio_bit(GPIO_G12,1)这条语句是将GPG12这个引脚拉成高电平。

四、set_gpio_ctrl(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口的上拉电阻功能。R=0,上拉电阻使能;R=1,上拉电阻失效。M字段用来设置IO口的工作模式,M=0,IO口为输入端口;M=1,IO口为输出端口;M=2,可选功能1;M=3,可选功能2。

set_gpio_ctrl宏就是通过写相应GPIO所在组的GPXCON(X为A~H)的相应位来设置IO口模式(GPACON每一个位控制一个IO口,而GPBCON~GPHCON都是两个位控制一个IO口的模式),通过写GPXUP(X为A~H)来决定是否启用上拉电阻。典型的set_gpio_ctrl调用方式如下:

set_gpio_ctrl(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G12);

代码
  1. #define set_gpio_ctrl(x)    
  2.        ({ GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2));    
  3.           GPCON(GRAB_PORT(x)) |= (GRAB_MODE(x) << (GRAB_OFS((x))*2));    
  4.           GPUP(GRAB_PORT((x))) &= ~(1 << GRAB_OFS((x)));    
  5.           GPUP(GRAB_PORT((x))) |= (GRAB_PULLUP((x)) << GRAB_OFS((x))); })  

 

这条语句是将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)等,实现方法和上述类似,在此不再一一赘述!


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 履约保函到期了怎么办 续贷高校未通过怎么办 安卓手机网速慢怎么办 探探性别错了怎么办 尿酸高导致脚肿怎么办 联通光猫复位后怎么办 头部和脸部出油怎么办 vcd解码板坏了怎么办 脚崴了里面筋疼怎么办 长寿龟身上烂了怎么办 纱裙没有腰身显胖怎么办 橘子平台下载速度慢怎么办 换手机号了支付宝账号怎么办 怀孕期间脚扭了怎么办 买了临街房后悔怎么办 绝地求生困在废车里怎么办 身体出现辅助睡眠状态怎么办 扁桃体发炎喉咙痒咳嗽怎么办 电脑玩英雄杀卡怎么办 康佳冰箱显示2e怎么办 高考登陆系统登录密码错误怎么办 苹果遇到ad登录问题怎么办? 小孩2天不拉屎怎么办 20天宝宝不大便怎么办 小孩几天不拉大便怎么办 宝宝经常不拉大便怎么办 宝宝便秘 肛裂了怎么办 3个月宝宝不便便怎么办 宝宝8个月不便便怎么办 宝宝在幼儿园不爱说话怎么办 广东学考考了d怎么办 上嘴唇干燥紧绷怎么办 美国大学gpa非常低怎么办 大学手机作弊通报教务处怎么办 崩坏3邮箱验证码过期怎么办 快递员被顾客恶意投诉怎么办 5岁幼儿逻辑思维差怎么办 脸一边胖一边瘦怎么办 夏天穿鞋子脚痒怎么办 脚痒怎么办但不是脚气 脚气脚趾缝烂了怎么办