GPIO 2

2019-07-13 02:58发布

1.在嵌入式Linux GPIO表示为“S3C2410_GPx(n)”,其中x的取值为“A,B,C,D,E,F,G,H.....”,表示那个GPIO口,n的取值为“1,2,3,.....”表示第几个管脚。 例如 B口的第六管教:S3C2410_GPB(6) D口的第12管教:S3C2410_GPD(12) ..... 注 这些宏定义在arch/arm/mach-s3c2410/include/mach/gpio-nrs.h,使用#include 以下包含#include 2.设置gpio的工作模式是输入,输出还是其他的 voids3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 参数 function 表示该管脚配置的功能 一般只能配置下列参数 S3C2410_GPIO_INPUT:该管脚配置为输入 S3C2410_GPIO_OUTPUT:该管脚配置为输出 S3C2410_GPIO_SFN1 S3C2410_GPIO_SFN2 S3C2410_GPIO_LEAVE 3.返回对应的GPIO的配置情况是输入,输出还是其他的
unsignedint s3c2410_gpio_getcfg(unsigned int pin) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 返回值 S3C2410_GPIO_INPUT:该管脚配置为输入 S3C2410_GPIO_OUTPUT:该管脚配置为输出 .... 4.设置相应的GPIO的上拉电阻 voids3c2410_gpio_pullup(unsigned int pin, unsigned int to) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 参数 to  当to为1时候,相应的pin引脚设置为1,表示该GPIO要上拉电阻,to为0时候,相应的pin引脚配置为0,表示不要上拉电阻 5.ints3c2410_gpio_getpull(unsigned int pin) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 返回值 为1时候,表示该GPIO有上拉电阻;为0时候,表示没有上拉电阻 6.当GPIO的工作为输出时候,设置某个GPIO的值 voids3c2410_gpio_setpin(unsigned int pin, unsigned int to) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 参数 to  当to为1时候,相应的pin引脚设置为高电平,to为0时候,相应的pin引脚配置为低电平 7.当GPIO的工作为输入时候,设置某个GPIO的值 unsigned ints3c2410_gpio_getpin(unsigned int pin) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 返回值 为1时候,表示该GPIO输入高电平;为0时候,表示输入低电平 8.给定端口,转换出irq号 ints3c2410_gpio_getirq(unsigned int pin) 参数 pin 表示配置的管脚 形如“S3C2410_GPB(6)”的实参 返回值 irq 9.杂项配置 unsigned ints3c2410_modify_misccr(unsigned int clear, unsigned int change)
        GPIO(GeneralPurpose Input/Output的缩写)就是芯片的引脚,引脚是可编程的可对引脚的工作模式进行设置:输入模式(检测输入信号),输出模式(输出0或1),高阻状态(常用于AD转换),还有禁止或允许上内部下拉电阻(上拉:管脚通过电阻接高电平,下拉:管脚通过电阻接地,也可以外部接上拉或下拉电阻),还有管脚复用等功能,即通过对内部寄存器的设置使引脚既可以工作在一般模式,作为普通的GPIO口使用,也可以工作在特殊模式,比如作为外部中断信号输入引脚等等。如果不设置GPIO引脚,CPU工作时有一个初始化模式,可以从datasheet(芯片手册)上了解。对GPIO的控制是编写驱动程序最常见和重要的一项工作内容。在Linux内核代码中,已经提供了针对三星S3C2410/S3C2440等芯片GPIO的控制。 ******************************************************************************* 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的实现方法                                                                             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 ");          returnret; }   static void __exit dev_exit(void) {        misc_deregister(&misc); }   module_init(dev_init); module_exit(dev_exit);