<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          ARM Linux下訪問GPIO端口

          作者: 時(shí)間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
          GPIO(GeneralPurpose Input/Output的縮寫)就是芯片的引腳,引腳是可編程的可對引腳的工作模式進(jìn)行設(shè)置:輸入模式(檢測輸入信號(hào)),輸出模式(輸出0或1),高阻狀態(tài)(常用于AD轉(zhuǎn)換),還有禁止或允許上內(nèi)部下拉電阻(上拉:管腳通過電阻接高電平,下拉:管腳通過電阻接地,也可以外部接上拉或下拉電阻),還有管腳復(fù)用等功能,即通過對內(nèi)部寄存器的設(shè)置使引腳既可以工作在一般模式,作為普通的GPIO口使用,也可以工作在特殊模式,比如作為外部中斷信號(hào)輸入引腳等等。如果不設(shè)置GPIO引腳,CPU工作時(shí)有一個(gè)初始化模式,可以從datasheet(芯片手冊)上了解。對GPIO的控制是編寫驅(qū)動(dòng)程序最常見和重要的一項(xiàng)工作內(nèi)容。在Linux內(nèi)核代碼中,已經(jīng)提供了針對三星S3C2410/S3C2440等芯片GPIO的控制。

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

          本文引用地址:http://www.ex-cimer.com/article/201611/319972.htm

          linux-2.6.30.4archarmplat-s3cincludeplat 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.4archarmplat-s3c24xxincludeplat 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.4archarmplat-s3c24xxincludeplat 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的實(shí)現(xiàn)方法

          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個(gè)端口

          #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的數(shù)據(jù)寄存器

          #define S3C2400_GPACON S3C2410_GPIOREG(0x00)

          #define S3C2400_GPADAT S3C2410_GPIOREG(0x04)

          #defineS3C2410_GPA0 S3C2410_GPIONO(S3C2410_GPIO_BANKA, 0)//A組GPIO的第0個(gè)的pin數(shù)

          #define S3C2410_GPA0_OUT(0<<0)//設(shè)置A0為輸出功能

          #define S3C2410_GPA0_ADDR0(1<<0)//設(shè)置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)// 其中參數(shù)pin是要配置的GPIO引腳,參數(shù)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端口時(shí),它是用兩位來配置具體的引腳,故掩碼為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);// 關(guān)中斷

          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位)根據(jù)端口編號(hào)pin,算出端口所在組的虛擬基址。((pin) & ~31)是去掉pin當(dāng)中小于等于31的零頭(清0低5位),>>1的原因是每組GPIO中最多可以有32個(gè)端口,控制這些端口需要4個(gè)寄存器空間,4個(gè)寄存器空間就需要4*4=16個(gè)字節(jié)進(jìn)行編址,32/16=2,左移一位剛好滿足。也就是說,上一組端口和下一組端口的編號(hào)相差32,而控制寄存器的地址相差16。

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

          //根據(jù)端口編號(hào)pin,算出端口所在組的偏移量。((pin) & 31)即去掉比31大的數(shù)

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

          s3c2410_gpio_cfgpin //配置端口的GPIO的功能
          s3c2410_gpio_getcfg//讀取功能配置
          s3c2410_gpio_pullup//配置上拉電阻
          s3c2410_modify_misccr //雜項(xiàng)配置

          s3c2410_gpio_getirq//給定端口,轉(zhuǎn)換出IRQ號(hào)
          s3c2410_gpio_irqfilter//配置IRQ過濾使能與否

          s3c2410_gpio_setpin//寫數(shù)據(jù)到端口
          s3c2410_gpio_getpin//從端口讀數(shù)據(jù)

          以下代碼摘自Leds的驅(qū)動(dòng)程序,旨在說明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:

          //設(shè)置指定引腳的輸出電平為0

          s3c2410_gpio_setpin(led_table[arg], 0);

          return0;

          caseIOCTL_LED_OFF:

          //設(shè)置指定引腳的輸出電平為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);// 設(shè)置相應(yīng)GPIO口的值

          }

          ret= misc_register(&misc);

          printk(DEVICE_NAME" initializedn");

          returnret;

          }

          static void __exit dev_exit(void)

          {

          misc_deregister(&misc);

          }

          module_init(dev_init);

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



          關(guān)鍵詞: ARMLinuxGPIO端

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();