GPIO驱动Word文档下载推荐.docx

上传人:b****6 文档编号:8351066 上传时间:2023-05-11 格式:DOCX 页数:25 大小:60.39KB
下载 相关 举报
GPIO驱动Word文档下载推荐.docx_第1页
第1页 / 共25页
GPIO驱动Word文档下载推荐.docx_第2页
第2页 / 共25页
GPIO驱动Word文档下载推荐.docx_第3页
第3页 / 共25页
GPIO驱动Word文档下载推荐.docx_第4页
第4页 / 共25页
GPIO驱动Word文档下载推荐.docx_第5页
第5页 / 共25页
GPIO驱动Word文档下载推荐.docx_第6页
第6页 / 共25页
GPIO驱动Word文档下载推荐.docx_第7页
第7页 / 共25页
GPIO驱动Word文档下载推荐.docx_第8页
第8页 / 共25页
GPIO驱动Word文档下载推荐.docx_第9页
第9页 / 共25页
GPIO驱动Word文档下载推荐.docx_第10页
第10页 / 共25页
GPIO驱动Word文档下载推荐.docx_第11页
第11页 / 共25页
GPIO驱动Word文档下载推荐.docx_第12页
第12页 / 共25页
GPIO驱动Word文档下载推荐.docx_第13页
第13页 / 共25页
GPIO驱动Word文档下载推荐.docx_第14页
第14页 / 共25页
GPIO驱动Word文档下载推荐.docx_第15页
第15页 / 共25页
GPIO驱动Word文档下载推荐.docx_第16页
第16页 / 共25页
GPIO驱动Word文档下载推荐.docx_第17页
第17页 / 共25页
GPIO驱动Word文档下载推荐.docx_第18页
第18页 / 共25页
GPIO驱动Word文档下载推荐.docx_第19页
第19页 / 共25页
GPIO驱动Word文档下载推荐.docx_第20页
第20页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

GPIO驱动Word文档下载推荐.docx

《GPIO驱动Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《GPIO驱动Word文档下载推荐.docx(25页珍藏版)》请在冰点文库上搜索。

GPIO驱动Word文档下载推荐.docx

90intret;

91inti;

92for(i=0;

i<

4;

i++){

93 

//设置LED对应的端口寄存器为输出(OUTPUT)

94 

 

if(s3c_gpio_cfgpin(led_table[i],led_cfg_table[i])<

0)

printk(KERN_INFO"

configpin%dfailed"

i);

95printk(KERN_INFO"

95 

//设置LED对应的端口寄存器为低电平输出,在模块加载>

结束后,四个LED应该是全部都是发光

96 

状态

97 

s3c2410_gpio_setpin(led_table[i],0);

98}

99 

ret=misc_register(&

misc);

//注册设备

100printk(DEVICE_NAME"

/tinitialized/n"

);

//打印初始化信息

101returnret;

102}

可以看到,这里涉及到两个函数,分别是s3c2410_gpio_cfgpin,s3c2410_gpio_setpin,这两个函数分别对四个LED进行配置,从函数名来看,cfgpin对引脚寄存器状态进行配置,而setpin应该是对寄存器数据值进行配置,我们在分析函数之前先弄清楚传入的参数到底是什么。

led_table[i]

28 

//LED对应的GPIO端口列表

29staticunsignedlongled_table[]={

30 

S3C2410_GPB(5),

31 

S3C2410_GPB(6),

32 

S3C2410_GPB(7),

33 

S3C2410_GPB(8),

34};

这里S3C2410_GPB宏定义在mach/gpio-nrs.h中 

/*GPIObanksizes*/

#defineS3C2410_GPIO_A_NR(32)

#defineS3C2410_GPIO_B_NR(32)

#defineS3C2410_GPIO_C_NR(32)

#defineS3C2410_GPIO_D_NR(32)

#defineS3C2410_GPIO_E_NR(32)

#defineS3C2410_GPIO_F_NR(32)

#defineS3C2410_GPIO_G_NR(32)

#defineS3C2410_GPIO_H_NR(32)

#defineS3C2410_GPIO_J_NR(32)/*technically16.*/

#defineS3C2410_GPIO_K_NR(32)/*technically16.*/

#defineS3C2410_GPIO_L_NR(32)/*technically15.*/

#defineS3C2410_GPIO_M_NR(32)/*technically2.*/

#ifCONFIG_S3C_GPIO_SPACE!

=0

#errorCONFIG_S3C_GPIO_SPACEcannotbezeroatthemoment

#endif 

#defineS3C2410_GPIO_NEXT(__gpio)/

((__gpio##_START)+(__gpio##_NR)+CONFIG_S3C_GPIO_SPACE+0)

//这里的CONFIG_S3C_GPIO_SPAC是内核配置选项,在.config中可以找到,我的配置为:

CONFIG_S3C_GPIO_SPACE=0 

enums3c_gpio_number{

S3C2410_GPIO_A_START 

=0,

S3C2410_GPIO_B_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_A),

S3C2410_GPIO_C_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_B),

S3C2410_GPIO_D_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_C),

S3C2410_GPIO_E_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_D),

S3C2410_GPIO_F_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_E),

S3C2410_GPIO_G_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_F),

S3C2410_GPIO_H_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_G),

S3C2410_GPIO_J_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_H),

S3C2410_GPIO_K_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_J),

S3C2410_GPIO_L_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_K),

S3C2410_GPIO_M_START=S3C2410_GPIO_NEXT(S3C2410_GPIO_L),

};

#defineS3C2410_GPB(_nr) 

(S3C2410_GPIO_B_START+(_nr)) 

因此,以S3C2410_GPB(5)为例,其宏展开为:

S3C2410_GPIO_NEXT(S3C2410_GPIO_A)+5 

=>

(S3C2410_GPIO_A_START 

S3C2410_GPIO_A_NR 

CONFIG_S3C_GPIO_SPACE+0)+ 

很显然, 

S3C2410_GPB(5)就是从GPA的首地址+GPA个数+GPB的offset就是当前GPB的IO偏移量,即

0+32+5=37,同理

S3C2410_GPB(0)相当于32

S3C2410_GPB(5)相当于37

S3C2410_GPB(6)相当于38

S3C2410_GPB(7)相当于39

S3C2410_GPB(8)相当于40

led_cfg_table[i]

36 

//LED对应端口将要输出的状态列表

37staticunsignedintled_cfg_table[]={

38S3C2410_GPIO_OUTPUT,

39S3C2410_GPIO_OUTPUT,

40S3C2410_GPIO_OUTPUT,

41S3C2410_GPIO_OUTPUT,

42};

S3C2410_GPIO_OUTPUT定义在mach/regs-gpio.h

#defineS3C2410_GPIO_LEAVE(0xFFFFFFFF) 

//最后两位是设置,11表示RESERVE

#defineS3C2410_GPIO_INPUT(0xFFFFFFF0)/*notavailableonA*/ 

//最后两位是设置,00表示INPUT

#defineS3C2410_GPIO_OUTPUT(0xFFFFFFF1) 

//最后两位是设置,01表示OUTPUT

#defineS3C2410_GPIO_IRQ(0xFFFFFFF2)/*notavailableforall*/

#defineS3C2410_GPIO_SFN2(0xFFFFFFF2)/*bankA=>

addr/cs/nand*/

#defineS3C2410_GPIO_SFN3(0xFFFFFFF3)/*notavailableonA*/

根据前面的分析,s3c2410传入了当前GPIO的偏移地址,以及OUTPUT状态

现在我们深入前面的两个函数:

定义在linux/arch/arm/plat-s3c/gpio-config.c

int 

s3c_gpio_cfgpin(unsignedintpin,unsignedintconfig)

{

structs3c_gpio_chip*chip= 

s3c_gpiolib_getchip(pin);

//得到对应GPIO结构体首指针,里面包含了该GPIO的各种参数

unsignedlongflags;

intoffset;

intret;

if(!

chip)

return-EINVAL;

//没找到的话,返回invalid

offset=pin-chip->

chip.base;

//否则offset等于该GPIO引脚相对于GPX(0)的偏移量,每个偏移1

s3c_gpio_lock(chip,flags);

//自旋锁锁住该GPIO,通过chip指针指向lock,看下面的define和图

ret= 

s3c_gpio_do_setcfg(chip,offset,config);

//设置该GPIO状态寄存器的数值为config

s3c_gpio_unlock(chip,flags);

//解锁

//自旋锁操作

/*lockingwrapperstodealwithmultipleaccesstothesamegpiobank*/

//#define 

s3c_gpio_lock(_oc,_fl)spin_lock_irqsave(&

(_oc)->

lock,_fl)

s3c_gpio_unlock(_oc,_fl)spin_unlock_irqrestore(&

//s3c_gpio_do_setcfg操作

staticinlineint 

s3c_gpio_do_setcfg(structs3c_gpio_chip*chip,

unsignedintoff,unsignedintconfig)

return(chip->

config->

set_config)(chip,off,config);

}

//这里的set_config是一个函数指针,由后面的分析知道,如果针对GPA,该函数指针指向s3c_gpio_setcfg_s3c24xx_a 

 

如果针对GPX应该是指向s3c_gpio_setcfg_s3c24xx——但发现,如果是其他GPX,根本没有定义set_config!

!

(这个问题已经解决,见后文s3c24xx_gpiolib_init函数,事实上,其余的config的确指向s3c_gpio_do_setcfg函数)

struct 

s3c_gpio_cfg 

s3c24xx_gpiocfg_default={

.set_config=s3c_gpio_setcfg_s3c24xx,

.get_config=s3c_gpio_getcfg_s3c24xx,

s3c_gpio_setcfg_s3c24xx_a(structs3c_gpio_chip*chip,unsignedintoff,unsignedintcfg)

void__iomem*reg=chip->

base;

//GPXCON的物理基地址

unsignedintshift=off;

//每个GPA对应一位

u32con;

if(s3c_gpio_is_cfg_special(cfg)){ 

//OUTPUT状态是否为(0xfffffffX),是,返回1

cfg&

=0xf;

//cfg=0xX

/*Mapoutputto0,andSFN2to1*/ 

本实验不会运行到这

cfg-=1;

if(cfg>

1)

return-EINVAL;

cfg<

<

=shift;

con=__raw_readl(reg);

//先读出该GPXCON的值,32位

con&

=~(0x1<

shift);

// 

con|=cfg;

//

__raw_writel(con,reg);

//将新值写入GPXCON

PS:

#define__raw_writeb(v,a)(__chk_io_ptr(a),*(volatileunsignedchar__force*)(a)=(v))

#define__raw_writew(v,a)(__chk_io_ptr(a),*(volatileunsignedshort__force*)(a)=(v))

#define__raw_writel(v,a)(__chk_io_ptr(a),*(volatileunsignedint__force*)(a)=(v))

#define__raw_readb(a)(__chk_io_ptr(a),*(volatileunsignedchar__force*)(a))

#define__raw_readw(a)(__chk_io_ptr(a),*(volatileunsignedshort__force*)(a))

#define__raw_readl(a)(__chk_io_ptr(a),*(volatileunsignedint__force*)(a))

return0;

如果针对GPX情况

s3c_gpio_setcfg_s3c24xx(structs3c_gpio_chip*chip,

unsignedintoff,unsignedintcfg)

unsignedintshift=off*2;

//每个GPX对应2位

if(s3c_gpio_is_cfg_special(cfg)){

cfg&

3)

cfg<

//将cfg的0,1两位左移offset

//读对应的GPXCON值

=~(0x3<

//将GPXCON(pin)的两bits请0

//设置config值

//写入新的GPXCON

returnret;

//end 

s3c_gpio_cfgpin

这里涉及到了一个重要的数据结构,s3c_gpio_chip,此数据结构比较复杂,我贴出这个数据结构的结构图:

这个重要的数据结构中可以记录每个GPIO所需要的所有数据,后面会遇到的s3c24xx_gpios[]结构体就是该结构体的集合,描述了芯片中所有的GPIO端口,之后我们需要时时回头看看这个结构。

我们先来看s3c_gpiolib_getchip 

,它实现了返回对应pin值的GPIO结构体首指针的功能

#include<

mach/gpio-core.h>

staticinlinestructs3c_gpio_chip*s3c_gpiolib_getchip(unsignedintpin)

structs3c_gpio_chip*chip;

if(pin>

S3C_GPIO_END) 

//如果超过GPJ(32)就returnNULL

returnNULL;

chip=&

s3c24xx_gpios[pin/32];

//根据偏移,计算出对应pin的GPIO结构体指针

return((pin-chip->

chip.base)<

chip->

chip.ngpio)?

chip:

NULL;

// 

这里验证,如果pin偏移超过了GPIO的个数,说明出错了,否则就返回该GPIO的结构体指针

回想以下之前s3c2410_gpio_cfgpin中,我们传入的参数是led_table[i]和 

led_cfg_table[i],

/*GPIOsizesforvariousSoCs:

*

2442

*24102412244024432416

*--------------------

*A23 

22 

25 

16 

25

*B11 

11 

11 

9

*C16 

15 

16

*D16 

*E16 

16 

16

*F8 

8

*G16 

*H11 

15 

15

*J-- 

-- 

13 

--

*K-- 

-- 

*L-- 

7

*M-- 

2

*/ 

structs3c_gpio_chip 

s3c24xx_gpios[]={

[0]={

.base=S3C2410_GPACON, 

//datasheet上地址为0x56000000

//#defineS3C2410_GPACON 

S3C2410_GPIOREG(0x00)

#defineS3C2410_GPIOREG(x)((x)+S3C24XX_VA_GPIO) 

#defineS3C24XX_VA_GPIO 

((S3C24XX_PA_GPIO-S3C24XX_PA_UART)+S3C24XX_VA_UART)

S3C24XX_PA_GPIO相当于(0x15600000) 

S3C24XX_PA_UART相当于(0x15000000) 

#defineS3C_VA_UART 

S3C_ADDR(0x01000000) 

/*UART*/ 

#defineS3C_ADDR_BASE0xF6000000

#ifndef__ASSEMBLY__

#defineS3C_ADDR(x)((void__iomem__force*

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2