您的位置 首页 应用

ARM Linux下拜访GPIO端口

GPIO(GeneralPurposeInputOutput的缩写)就是芯片的引脚,引脚是可编程的可对引脚的工作模式进行设置:输入模式(检测输入信号),输出模

GPIO(GeneralPurpose Input/Output的缩写)便是芯片的引脚,引脚是可编程的可对引脚的作业形式进行设置:输入形式(检测输入信号),输出形式(输出0或1),高阻状况(常用于AD转化),还有制止或答应上内部下拉电阻(上拉:管脚经过电阻接高电平,下拉:管脚经过电阻接地,也能够外部接上拉或下拉电阻),还有管脚复用等功用,即经过对内部寄存器的设置使引脚既能够作业在一般形式,作为一般的GPIO口运用,也能够作业在特别形式,比方作为外部中止信号输入引脚等等。假如不设置GPIO引脚,CPU作业时有一个初始化形式,能够从datasheet(芯片手册)上了解。对GPIO的操控是编写驱动程序最常见和重要的一项作业内容。在Linux内核代码中,现已供给了针对三星S3C2410/S3C2440等芯片GPIO的操控。

*******************************************************************************

linux-2.6.30.4\arch\arm\plat-s3c\include\plat\ map-base.h

#defineS3C_ADDR_BASE (0xF4000000)

#ifndef __ASSEMBLY__

#define S3C_ADDR(x) ((void__iomem __force *)S3C_ADDR_BASE+ (x))

#else

#defineS3C_ADDR(x) (S3C_ADDR_BASE+ (x))

#endif

#define S3C_VA_IRQ S3C_ADDR(0x00000000) /* irq controller(s) */

#define S3C_VA_SYS S3C_ADDR(0x00100000) /* system control */

#define S3C_VA_MEM S3C_ADDR(0x00200000) /* system control */

#define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */

#define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */

#define S3C_VA_UART S3C_ADDR(0x01000000) /*UART */

linux-2.6.30.4\arch\arm\plat-s3c24xx\include\plat\ map.h

/* UARTs */

#defineS3C24XX_VA_UART S3C_VA_UART

#define S3C2410_PA_UART (0x50000000)

#define S3C24XX_SZ_UART SZ_1M

#define S3C_UART_OFFSET (0x4000)

UART映射后的虚拟地址是0xF4000000+0x01000000

linux-2.6.30.4\arch\arm\plat-s3c24xx\include\plat\ map.h

/* GPIO ports */

#define S3C2410_PA_GPIO (0x56000000)

#defineS3C24XX_VA_GPIO ((S3C24XX_PA_GPIO- S3C24XX_PA_UART) + S3C24XX_VA_UART)//GPIO的虚拟地址

#define S3C24XX_SZ_GPIO SZ_1M

GPIO的基地址为 0xfb000000

S3C24XX_VA_GPIO在不同的linux版别中或许不一样,2.6.30.4是依照上面的办法,下图是2.6.22.6的完成办法

linux/include/asm-arm/arch-s3c2410/map.h

#ifndef __ASSEMBLY__

#define S3C2410_ADDR(x) ((void __iomem *)0xF0000000 + (x))

#else

#define S3C2410_ADDR(x) (0xF0000000 + (x))

#endif

#define S3C2400_ADDR(x) S3C2410_ADDR(x)

/* GPIO ports */

#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)

#define S3C2400_PA_GPIO (0x15600000)

#define S3C2410_PA_GPIO (0x56000000)

#define S3C24XX_SZ_GPIO SZ_1M

arch/arm/mach-s3c2410/include/mach/regs-gpio.h

#defineS3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)//在GPIO的虚拟地址上直接偏移

#define S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)

linux-2.6.30.4/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h

#defineS3C2410_GPIONO(bank,offset)((bank) + (offset))

#defineS3C2410_GPIO_BANKA (32*0)//每组最多32个端口

#define S3C2410_GPIO_BANKB(32*1)

#define S3C2410_GPIO_BANKC(32*2)

#define S3C2410_GPIO_BANKD(32*3)

#define S3C2410_GPIO_BANKE(32*4)

#define S3C2410_GPIO_BANKF(32*5)

#define S3C2410_GPIO_BANKG(32*6)

#define S3C2410_GPIO_BANKH (32*7)

arch/arm/mach-s3c2410/include/mach/regs-gpio.h

#defineS3C2410_GPACON S3C2410_GPIOREG(0x00)//A组GPIO的操控寄存器

#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)//A组GPIO的数据寄存器

#define S3C2400_GPACON S3C2410_GPIOREG(0x00)

#define S3C2400_GPADAT S3C2410_GPIOREG(0x04)

#defineS3C2410_GPA0 S3C2410_GPIONO(S3C2410_GPIO_BANKA, 0)//A组GPIO的第0个的pin数

#define S3C2410_GPA0_OUT(0<<0)//设置A0为输出功用

#define S3C2410_GPA0_ADDR0(1<<0)//设置A0作为地址线ADDR0

*******************************************************************************

#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)

#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)

#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)

#define S3C2410_GPB0S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)

#define S3C2410_GPB0_INP(0x00 << 0)

#define S3C2410_GPB0_OUTP(0x01 << 0)

#define S3C2410_GPB0_TOUT0(0x02 << 0)

#define S3C2400_GPB0_DATA16(0x02 << 0)

*******************************************************************************

#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)

#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)

#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)

#define S3C2410_GPC0S3C2410_GPIONO(S3C2410_GPIO_BANKC, 0)

#define S3C2410_GPC0_INP (0x00<< 0)

#define S3C2410_GPC0_OUTP (0x01<< 0)

#define S3C2410_GPC0_LEND (0x02<< 0)

#define S3C2400_GPC0_VD0 (0x02<< 0)

*******************************************************************************

#define S3C2410_GPDCON S3C2410_GPIOREG(0x30)

#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)

#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)

— Port A(GPA): 25-output port

— Port B(GPB): 11-input/out port

— Port C(GPC): 16-input/output port

— Port D(GPD): 16-input/output port

— Port E(GPE): 16-input/output port

— Port F(GPF): 8-input/output port

— Port G(GPG): 16-input/output port

— Port H(GPH): 9-input/output port

— Port J(GPJ): 13-input/output port

Register Address R/W Description Reset Value

GPACON 0x56000000 R/W Configures the pins of port A 0xffffff

GPADAT 0x56000004 R/W The data register for port A Undef.

Reserved 0x56000008 – Reserved Undef

Reserved 0x5600000c – Reserved Undef

Register Address R/W Description Reset Value

GPBCON 0x56000010 R/W Configures the pins of port B 0x0

GPBDAT 0x56000014 R/W The data register for port B Undef.

GPBUP 0x56000018 R/W Pull-up disable register for port B 0x0

Reserved 0x5600001c

Register Address R/W Description Reset Value

GPCCON 0x56000020 R/W Configures the pins of port C 0x0

GPCDAT 0x56000024 R/W The data register for port C Undef.

GPCUP 0x56000028 R/W Pull-up disable register for port C 0x0

Reserved 0x5600002c – – –

Register Address R/W Description Reset Value

GPDCON 0x56000030 R/W Configures the pins of port D 0x0

GPDDAT 0x56000034 R/W The data register for port D Undef.

GPDUP 0x56000038 R/W Pull-up disable register for port D 0xf000

Reserved 0x5600003c – – –

*******************************************************************************

void s3c2410_gpio_cfgpin(unsignedint pin, unsigned int function)// 其间参数pin是要装备的GPIO引脚,参数function是要装备的功用

{

void __iomem *base = S3C24XX_GPIO_BASE(pin);

unsignedlong mask;

unsignedlong con;

unsignedlong flags;

if(pin < S3C2410_GPIO_BANKB){

mask= 1 << S3C2410_GPIO_OFFSET(pin);

}else {

mask= 3 << S3C2410_GPIO_OFFSET(pin)*2;

}

//假如引脚为A端口之外GPIO端口时,它是用两位来装备详细的引脚,故掩码为2位

switch(function) {

caseS3C2410_GPIO_LEAVE:

mask= 0;

function= 0;

break;

caseS3C2410_GPIO_INPUT:

caseS3C2410_GPIO_OUTPUT:

caseS3C2410_GPIO_SFN2:

caseS3C2410_GPIO_SFN3:

if(pin < S3C2410_GPIO_BANKB){

function-= 1;

function&= 1;

function<<= S3C2410_GPIO_OFFSET(pin);

}else {

function&= 3;

function<<= S3C2410_GPIO_OFFSET(pin)*2;

}

}

/* modify thespecified register wwith IRQs off */

local_irq_save(flags);// 关中止

con= __raw_readl(base + 0x00);

con &= ~mask;

con |= function;

__raw_writel(con, base + 0x00);

local_irq_restore(flags);// 开中止

}

arch/arm/mach-s3c2410/include/mach/regs-gpio.h

#define S3C2410_GPIO_BASE(pin)((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

//每组GPIO的虚拟基地址(要先屏蔽最低的5位)依据端口编号pin,算出端口地点组的虚拟基址。((pin) & ~31)是去掉pin傍边小于等于31的零头(清0低5位),>>1的原因是每组GPIO中最多能够有32个端口,操控这些端口需求4个寄存器空间,4个寄存器空间就需求4*4=16个字节进行编址,32/16=2,左移一位刚好满意。也便是说,上一组端口和下一组端口的编号相差32,而操控寄存器的地址相差16。

#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

//依据端口编号pin,算出端口地点组的偏移量。((pin) & 31)即去掉比31大的数

linux/arch/arm/plat-s3c24xx/gpio.c

s3c2410_gpio_cfgpin //装备端口的GPIO的功用
s3c2410_gpio_getcfg//读取功用装备
s3c2410_gpio_pullup//装备上拉电阻
s3c2410_modify_misccr //杂项装备

s3c2410_gpio_getirq//给定端口,转化出IRQ号
s3c2410_gpio_irqfilter//装备IRQ过滤使能与否

s3c2410_gpio_setpin//写数据到端口
s3c2410_gpio_getpin//从端口读数据

以下代码摘自Leds的驱动程序,旨在阐明linux下怎么拜访寄存器

static unsigned long led_table [] =

{

S3C2410_GPB5,

S3C2410_GPB6,

S3C2410_GPB7,

S3C2410_GPB8,

};

/* 用来指定GPIO引脚的功用:输出 */

static unsigned int led_cfg_table [] =

{

S3C2410_GPB5_OUTP,

S3C2410_GPB6_OUTP,

S3C2410_GPB7_OUTP,

S3C2410_GPB8_OUTP,

};

static int gt2440_leds_ioctl(

structinode *inode,

structfile *file,

unsignedint cmd,

unsignedlong arg)

{

if(arg > 4)

{

return-EINVAL;

}

switch(cmd)

{

caseIOCTL_LED_ON:

//设置指定引脚的输出电平为0

s3c2410_gpio_setpin(led_table[arg], 0);

return0;

caseIOCTL_LED_OFF:

//设置指定引脚的输出电平为1

s3c2410_gpio_setpin(led_table[arg], 1);

return0;

default:

return-EINVAL;

}

}

static struct file_operations dev_fops = {

.owner = THIS_MODULE,

.ioctl = gt2440_leds_ioctl,

};

static struct miscdevice misc = {

.minor= MISC_DYNAMIC_MINOR,

.name= DEVICE_NAME,

.fops= &dev_fops,

};

static int __init dev_init(void)

{

intret;

inti;

for(i = 0; i < 4; i++)

{

s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i],0);// 设置相应GPIO口的值

}

ret= misc_register(&misc);

printk(DEVICE_NAME” initialized\n”);

returnret;

}

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}

module_init(dev_init);

module_exit(dev_exit); *******************************************************************************

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/262376.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部