ARM Linux下訪問GPIO連接埠

來源:互聯網
上載者:User

 

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_GPB0        S3C2410_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_GPC0           S3C2410_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); *******************************************************************************

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.