s3c2410_gpio_setpin

转载 2012年03月23日 18:21:14
上个月在qq2440的光盘里发现了一段简单的LED驱动程序,大致看了一下明白了大意;但是由于里面的宏定义很是麻烦,看起来绕来绕去,于是我也懒得看明白了,干脆在CU论坛里发了个帖一问了事。 
    然而,等了几天后,寥寥几个回复。更不爽的是,唯一那个被加了分的回复一看就感觉不对劲,可我自己也没弄清楚缘由,因此也说不清。 
    过完了十一,觉得又该学习了,突然想起来这个事。想想还是完全看懂比较好,毕竟自己对kernel的源码包还不算很熟悉,就当是学习kernel吧。 
    首先是代码中的几个宏定义: 

/linux/include/asm/hardware/s3c2410/regs-gpio.h 中: 

01 #define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
02  
03 #define S3C2410_GPIO_BANKA   (32*0)
04 #define S3C2410_GPIO_BANKB   (32*1)
05 #define S3C2410_GPIO_BANKC   (32*2)
06 ....
07  
08 #define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
09 #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
10  
11 #define S3C2410_GPBCON       S3C2410_GPIOREG(0x10)
12 #define S3C2410_GPBDAT       S3C2410_GPIOREG(0x14)
13 #define S3C2410_GPBUP       S3C2410_GPIOREG(0x18)
14  
15 /* no i/o pin in port b can have value 3! */
16  
17 #define S3C2410_GPB0         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
18 #define S3C2410_GPB0_INP     (0x00 << 0)
19 #define S3C2410_GPB0_OUTP    (0x01 << 0)
20 #define S3C2410_GPB0_TOUT0   (0x02 << 0)
21  
22 #define S3C2410_GPB1         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 1)
23 #define S3C2410_GPB1_INP     (0x00 << 2)
24 #define S3C2410_GPB1_OUTP    (0x01 << 2)
25 #define S3C2410_GPB1_TOUT1   (0x02 << 2)

.... 

driver中有这样的代码: 
    
1 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
2     s3c2410_gpio_setpin(led_table[i], 1);

其中 
01 static unsigned long led_table [] = {
02     S3C2410_GPB5,
03     S3C2410_GPB6,
04     S3C2410_GPB7,
05     S3C2410_GPB8,
06 };
07  
08 static unsigned int led_cfg_table [] = {
09     S3C2410_GPB5_OUTP,
10     S3C2410_GPB6_OUTP,
11     S3C2410_GPB7_OUTP,
12     S3C2410_GPB8_OUTP,
13 };
 

    开始一直不明白的是那个32怎么得来,于是找到了s3c2410_gpio_cfgpin和s3c2410_gpio_setpin,在我的linux/arch/arm/mach-s3c2410/gpio.c中: 

01 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
02 {
03     void __iomem *base = S3C2410_GPIO_BASE(pin);
04     unsigned long mask;
05     unsigned long con;
06     unsigned long flags;
07  
08     if (pin < S3C2410_GPIO_BANKB) {
09         mask = 1 << S3C2410_GPIO_OFFSET(pin);
10     else {
11         mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
12     }
13  
14     local_irq_save(flags);
15  
16     con  = __raw_readl(base + 0x00);
17     con &= ~mask;
18     con |= function;
19  
20     __raw_writel(con, base + 0x00);                 //config the GPXCON
21  
22     local_irq_restore(flags);
23 }
24  
25 EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
26  
27  
28 void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
29 {
30     void __iomem *base = S3C2410_GPIO_BASE(pin);
31     unsigned long offs = S3C2410_GPIO_OFFSET(pin);
32     unsigned long flags;
33     unsigned long dat;
34  
35     local_irq_save(flags);
36  
37     dat = __raw_readl(base + 0x04);
38     dat &= ~(1 << offs);
39     dat |= to << offs;
40     __raw_writel(dat, base + 0x04);                 //config the GPXDAT
41  
42     local_irq_restore(flags);
43 }
44  
45 EXPORT_SYMBOL(s3c2410_gpio_setpin);
 

    发现S3C24XX_VA_GPIO这个虚拟地址不知道怎么得来,于是又找到linux/include/asm-arm/arch-s3c2410/map.h里这样一段: 

01 #ifndef __ASSEMBLY__
02 #define S3C2410_ADDR(x)      ((void __iomem *)0xF0000000 + (x))
03 #else
04 #define S3C2410_ADDR(x)      (0xF0000000 + (x))                 
05 #endif
06  
07 #define S3C2400_ADDR(x)      S3C2410_ADDR(x)
08  
09 /* GPIO ports */
10 #define S3C24XX_VA_GPIO       S3C2410_ADDR(0x00E00000)
11 #define S3C2400_PA_GPIO       (0x15600000)
12 #define S3C2410_PA_GPIO       (0x56000000)
13 #define S3C24XX_SZ_GPIO       SZ_1M



    这才终于把整个线索理清: 
    2410中的寄存器在I/O内存中根据0xF0000000这个base加上一个偏移值就简单的得到了VA(想不到2410里的MMU映射也太简单了点)。而且不同的寄存器偏移值都相差0x100000,比如 

1 #define S3C24XX_VA_RTC       S3C2410_ADDR(0x00F00000)
2 #define S3C24XX_VA_GPIO       S3C2410_ADDR(0x00E00000)
3 #define S3C24XX_VA_IIS       S3C2410_ADDR(0x00D00000)


 等等.. 

    有个GPIO的虚拟地址base,接下来分析下面的: 

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

 

    原来这句话的意思是:根据GPIO的VA,由得到的pin数,可以得到一组I/O的base。比如GPA得到的是 
0x10+S3C24XX_VA_GPIO,GPB是0x20+S3C24XX_VA_GPIO,GPC是0x30+S3C24XX_VA_GPIO... 
    由此可知,之前的32是为了方便统计每组I/O的pin数,因为A组含23个(最多),尽管GPACON,GPBCON,GPCCON...之间的地址只相差0x10,但是用16无法满足,所以只得用32了。如果每组最多也不超多16个寄存器,我认为16是可以实现的,只是S3C2410_GPIO_BASE(pin)里不需要那个右移操作了。总之,32更多的是因为GPIO管脚设置的实现而采取的一个数字,与32位总线倒关系不大。如果GPA含33个,这里就一定得是64了。 
    其实想想这代码也不难理解,只是宏定义和函数的实现分散在kernel包的各个文件内,因此不太容易寻找。线索齐了后,就一目了然了。

举报

相关文章推荐

s3c2410_gpio_setpin()系列函数

转自:http://blog.csdn.net/muyuyuzhong/article/details/7680678 系列函数的定义在arch/arm/mach-s3c2410/gpio.c,相关...

s3c2410_gpio_setpin()系列函数

系列函数的定义在arch/arm/mach-s3c2410/gpio.c,相关的宏定义在include/asm-arm/arch-s3c2410/regs-gpio.h (1)void s3c2...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

控制IO端口 s3c2410_gpio_setpin()的使用

本文基于FL2440 ARM开发板Linux内核版本 2.6.28.7arm-linux-gcc 3.4.1转载请标明出处http://blog.csdn.net/yming0221 #include...

一个函数分析(s3c2410_gpio_setpin),浅析ARM GPIO地址转换

一个函数分析(s3c2410_gpio_setpin),浅析ARM GPIO地址转换   http://blog.163.com/ruoshui723 目录: 1 S3c...

s3c2410_gpio_setpin() 及GPIO虚拟地址,物理地址

s3c2410_gpio_setpin() 及GPIO虚拟地址,物理地址 2011-05-01 20:44 在mini2440_leds_misc.c里有这样的一段代码,而纵观整个c文件里面...

s3c2410_gpio_setpin() 及GPIO虚拟地址,物理地址

在mini2440_leds_misc.c里有这样的一段代码,而纵观整个c文件里面,其实真正核心的代码,我感觉就一句了: s3c2410_gpio_setpin(led_table[i], !c...

s3c2410_gpio_setpin()与s3c2410_gpio_cfgpin()函数定义

s3c2410_gpio_setpin()在gpio.c中 作用:设置相应GPIO口的值, 如pin=S3C2410_GPB5    to=0   则:设置S3C2410_GPB5的输出值为0...

LED驱动中s3c2410_gpio_setpin s3c2410_gpio_cfgpin函数的定义

这2个函数都是内核已经定义好了的 。 s3c2410_gpio_setpin()在gpio.c中 /*在LED中设置s3c2410_gpio_setpin(led_table[i], 0)...

s3c2410_gpio_cfgpin 、s3c2410_gpio_setpin函数分析 --linux(tq2440开发板)的gpio驱动分析

#define S3C2410_GPIO_BANKA (32*0) #define S3C2410_GPIO_BANKB (32*1) #define S3C2410_GPIO_BANKC...
  • s_a_n_
  • s_a_n_
  • 2013-04-01 12:11
  • 1011

Windows CE下操作GPIO的方法(以ARM9 S3C2410为例)

GPIO 是ARM芯片最基本的输入输出通道,在ADS下操作就是一个单片机工作,直接读写其寄存器。在ARM9平台上,Windows CE系统将GPIO的实地址(例如2410的GPIO的基地址为0x560...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)