一下是学习附件led的驱动在网上找的资料
比较好   可以参考下 
 
s3c2410_gpio_setpin()在gpio.c中
作用:设置相应GPIO口的值,
如pin=S3C2410_GPB5    to=0   则:设置S3C2410_GPB5的输出值为0
如pin=S3C2410_GPB5    to=1 则:设置S3C2410_GPB5的输出值为1
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
    void __iomem *base = S3C2410_GPIO_BASE(pin);
    unsigned long offs = S3C2410_GPIO_OFFSET(pin);
    unsigned long flags;
    unsigned long dat;
    local_irq_save(flags);
    dat = __raw_readl(base + 0x04);
    dat &= ~(1 << offs);
    dat |= to << offs;
    __raw_writel(dat, base + 0x04);
    local_irq_restore(flags);
}
EXPORT_SYMBOL(s3c2410_gpio_setpin);
说明:
1.
S3C2410_GPIO_BASE(pin)-------------
在linux/include/asm/hardware/s3c2410/regs-gpio.h中
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) +S3C24XX_VA_GPIO)
S3C24XX_VA_GPIO------------
在linux/include/asm-arm/arch-s3c2410/map.h中
#define S3C24XX_VA_GPIO       S3C2410_ADDR(0x00E00000)
----GPIO的虚拟偏移地址:0x00E00000
#define S3C2410_ADDR(x)    (0xF0000000 + (x))
----所有寄存器的虚拟首地址:0xF0000000
则:
S3C24XX_VA_GPIO =0xF0E0 0000        ----GPIO的虚拟首地址
如:pin = S3C2410_GPB5
而在linux/include/asm/hardware/s3c2410/regs-gpio.h中
#define S3C2410_GPB5         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
#define S3C2410_GPIO_BANKB (32*1)
则:
S3C2410_GPB5 =32*1+5=37
由:
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) +S3C24XX_VA_GPIO)
pin = S3C2410_GPB5 = 37
S3C24XX_VA_GPIO =0xF0E0 0000
则:
S3C2410_GPIO_BASE(S3C2410_GPB5)   ((((S3C2410_GPB5) & ~31) >> 1) +0xF0E0 0000 )
S3C2410_GPIO_BASE(37)   ((((37) & ~31) >> 1) +0xF0E0 0000 )
S3C2410_GPIO_BASE(37) =((10 0101 &0 0000)>>1)+0xF0E0 0000
                                              =     1 0000+0xF0E0 0000
                                              =    0xF0E1 0000
~31主要是为了清除S3C2410_GPB5的后5位,
2.
S3C2410_GPIO_OFFSET(pin);

s3c2410_gpio_pullup()在gpio.c中
作用:设置相应GPIO口的上拉电阻,
如pin=S3C2410_GPB5    to=0   则:设置S3C2410_GPB5的不要上拉电阻
如pin=S3C2410_GPB5    to=1 则:设置S3C2410_GPB5的要上拉电阻
void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long up;
if (pin < S3C2410_GPIO_BANKB)
return;
local_irq_save(flags);
up = __raw_readl(base + 0x08);
[color=Red]up &= ~(1L << offs);
up |= to << offs;[/color]
__raw_writel(up, base + 0x08);
local_irq_restore(flags);
}
EXPORT_SYMBOL(s3c2410_gpio_pullup);
s3c2410_gpio_cfgpin()在gpio.c中
作用:配置相应GPIO口的功能,
如pin=S3C2410_GPB5    function=00   则:设置S3C2410_GPB5为输入口
如pin=S3C2410_GPB5    function=01 则:设置S3C2410_GPB5为输出口
如pin=S3C2410_GPB5    function=10   则:设置S3C2410_GPB5为多功能口
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
    void __iomem *base = S3C2410_GPIO_BASE(pin);
    unsigned long mask;
    unsigned long con;
    unsigned long flags;
    if (pin < S3C2410_GPIO_BANKB) {
        mask = 1 << S3C2410_GPIO_OFFSET(pin);
    } else {
        mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
    }
    local_irq_save(flags);
    con = __raw_readl(base + 0x00);
    con &= ~mask;
    con |= function;
    __raw_writel(con, base + 0x00);
    local_irq_restore(flags);
}
EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
 
s3c2410_gpio_getcfg()在gpio.c中
作用:用于返回相应GPIO口的配置
如:pin=S342410_GPB5    则:返回S3C2410_GPB5的配置情况
unsigned int s3c2410_gpio_getcfg(unsigned int pin)
{
    void __iomem *base = S3C2410_GPIO_BASE(pin);
    unsigned long mask;
    if (pin < S3C2410_GPIO_BANKB) {
        mask = 1 << S3C2410_GPIO_OFFSET(pin);
    } else {
        mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
    }
    return __raw_readl(base) & mask;
}
EXPORT_SYMBOL(s3c2410_gpio_getcfg);
 
由简单的LED驱动分析内核源码包中的s3c2410寄存器宏定义及物理/虚拟内存映射 - gmkernel
s3c2410相关   2009-09-16 10:31   阅读29   评论1   字号: 大大  中中  小小
上个月在qq2440的光盘里发现了一段简单的LED驱动程序,大致看了一下明白了大意;但是由于里面的宏定义很是麻烦,看起来绕来绕去,于是我也懒得看明白了,干脆在CU论坛里发了个帖一问了事。

    然而,等了几天后,寥寥几个回复。更不爽的是,唯一那个被加了分的回复一看就感觉不对劲,可我自己也没弄清楚缘由,因此也说不清。
    过完了十一,觉得又该学习了,突然想起来这个事。想想还是完全看懂比较好,毕竟自己对kernel的源码包还不算很熟悉,就当是学习kernel吧。
    首先是代码中的几个宏定义:
/linux/include/asm/hardware/s3c2410/regs-gpio.h 中:
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
#define S3C2410_GPIO_BANKA   (32*0)
#define S3C2410_GPIO_BANKB   (32*1)
#define S3C2410_GPIO_BANKC   (32*2)
....
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
#define S3C2410_GPBCON       S3C2410_GPIOREG(0x10)
#define S3C2410_GPBDAT       S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP       S3C2410_GPIOREG(0x18)
/* no i/o pin in port b can have value 3! */
#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 S3C2410_GPB1         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 1)
#define S3C2410_GPB1_INP     (0x00 << 2)
#define S3C2410_GPB1_OUTP    (0x01 << 2)
#define S3C2410_GPB1_TOUT1   (0x02 << 2)
....
driver中有这样的代码:
    s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
    s3c2410_gpio_setpin(led_table[i], 1);
其中
static unsigned long led_table [] = {
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8,
};
static unsigned int led_cfg_table [] = {
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};
    开始一直不明白的是那个32怎么得来,于是找到了s3c2410_gpio_cfgpin和s3c2410_gpio_setpin,在我的linux/arch/arm/mach-s3c2410/gpio.c中:
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
    void __iomem *base = S3C2410_GPIO_BASE(pin);
    unsigned long mask;
    unsigned long con;
    unsigned long flags;
    if (pin < S3C2410_GPIO_BANKB) {
        mask = 1 << S3C2410_GPIO_OFFSET(pin);
    } else {
        mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
    }
    local_irq_save(flags);
    con  = __raw_readl(base + 0x00);
    con &= ~mask;
    con |= function;
    __raw_writel(con, base + 0x00);                 //config the GPXCON
    local_irq_restore(flags);
}
EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
    void __iomem *base = S3C2410_GPIO_BASE(pin);
    unsigned long offs = S3C2410_GPIO_OFFSET(pin);
    unsigned long flags;
    unsigned long dat;
    local_irq_save(flags);
    dat = __raw_readl(base + 0x04);
    dat &= ~(1 << offs);
    dat |= to << offs;
    __raw_writel(dat, base + 0x04);                 //config the GPXDAT
    local_irq_restore(flags);
}
EXPORT_SYMBOL(s3c2410_gpio_setpin);
    发现S3C24XX_VA_GPIO这个虚拟地址不知道怎么得来,于是又找到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
    这才终于把整个线索理清:
    2410中的寄存器在I/O内存中根据0xF0000000这个base加上一个偏移值就简单的得到了VA(想不到2410里的MMU映射也太简单了点)。而且不同的寄存器偏移值都相差0x100000,比如
#define S3C24XX_VA_RTC       S3C2410_ADDR(0x00F00000)
#define S3C24XX_VA_GPIO       S3C2410_ADDR(0x00E00000)
#define S3C24XX_VA_IIS       S3C2410_ADDR(0x00D00000) 等等..
    有个GPIO的虚拟地址base,接下来分析下面的:
#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包的各个文件内,因此不太容易寻找。线索齐了后,就一目了然了。
 

创建于: 2008-10-06 23:31:23,修改于: 2008-10-06 23:31:23,已浏览592次,有评论6条
网友评论  内容:分析得很彻底!不过在最后一段,我有点小问题: GPACON,GPBCON,GPCCON...之间的地址只相差0x10, GPA得到的应该是0x00+VA,…… 问题1:为什么GPA与GPB地址相差0x10呢?是因为用于GPA的寄存器有4个(搂主说的23个寄存器其实是说GPA对应的23个引脚,只是23个位而已),GPACON,GPADATA,GPAUP,RESERVED,每个寄存器占有32(4字节)位的地址,所以它们之间相差16个字节(0x10)。问题2:为什么要右移1位呢?我认为开始的32*0和32*1……之所以采用32,可能还是因为32位总线的问题,如果用16的话可以不用右移1位而直接得到相差0x10的地址差, 本站网友 评论于:2008-12-02 10:19:23 (59.41.253.★) 内容:对于问题2: 先看这两个定义: (1)#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO) pin&1111 1111 1110 0000 #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31) pin&0001 1111 很显然低5位是用作GPn的偏移地址,高位用作基地址,当然得用32了 kk 评论于:2008-12-02 10:41:34 (59.41.253.★) 内容:简单地说,就是GPA是32位的寄存器,可能对应32个引脚,需要用5个位来对应,而源代码是使用S3C2410_GPIO_BASE(S3C2410_GPIO_OFFSET)来获得基地址的,这样就确保引用GPA每个引脚都是对应GPA基地址 kk 评论于:2008-12-02 11:09:33 (59.41.253.★) 内容:GPA是否应该是0x00+S3C24XX_VA_GPIO? 而GPB=0x01+S3C24XX_VA_GPIO? 本站网友 评论于:2009-05-20 09:37:05 (220.248.55.★) 内容:GPB 地址应该是0x56000010 而这样算出来S3C24xx_VA_GPIO 是0xF0E00000 这样算出来,不对哦,请问各位是什么原因。 小谢 评论于:2009-05-21 10:03:06 (210.41.87.★) 内容:“GPB 地址应该是0x56000010 而这样算出来S3C24xx_VA_GPIO 是0xF0E00000 这样算出来,不对哦,请问各位是什么原因。 ” 请参考“重映射”相关知识。 本站网友 评论于:2009-06-18 10:49:43 (125.88.5.★) 

简单的led驱动 了解下相关推荐

  1. linux的led驱动的实验总结,linux设备驱动归纳总结(五):4.写个简单的LED驱动

    linux设备驱动归纳总结(五):4.写个简单的LED驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  2. linux设备驱动归纳总结(五):4.写个简单的LED驱动

    http://blog.csdn.net/fh400/article/details/6929309

  3. i.MX283开发板第一个Linux驱动-LED驱动

    字符设备驱动开发 字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的.比如我们最常见的点灯.按键.IIC.SPI,LCD ...

  4. linux串口驱动ioremap,S3C2440开发板LED驱动——ioremap 映射

    刚开始学字符设备驱动,感觉最难的是驱动和底层硬件的连接.linux上的驱动程序,是基于操作系统之上的,他并不直接和底层的硬件打交道,但是我们写的驱动必须能使硬件"跑"起来,即与硬件 ...

  5. linux 查看led设备,Linux下LedButton设备驱动——详细设计

    数据结构 点击(此处)折叠或打开 struct pca9555_led { u8 id; struct i2c_client *client; char *name; struct led_class ...

  6. 【正点原子Linux连载】第四十四章 设备树下的LED驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  7. linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...

    Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...

  8. 【正点原子MP157连载】第二十四章 设备树下的LED驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  9. 韦东山 IMX6ULL和正点原子_「正点原子Linux连载」第四十四章设备树下的LED驱动实验...

    1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 上一章我们详细的讲解了设备树语法以及在驱 ...

最新文章

  1. 626B. Cards
  2. java什么叫元素_什么是Java做什么 - 每个元素使它们成为对象类型?
  3. 《Objective-C入门经典》——2.1节Objective-C世界中的面向对象程序设计
  4. bat中文乱码_详解Windows下获取时间bat脚本总结,值得收藏
  5. 第五十三天:优化网站的常用方法
  6. 艾伟_转载:Cookie是什么?用法是怎样?与SESSION有什么区别?(二)
  7. Java同步组件之CountDownLatch,Semaphore
  8. 微信小程序发送验证码短信SDK及文档
  9. 大话移动通信(第2版)!(文末赠书福利)
  10. Power BI——数据建模案例分析
  11. 机载激光雷达原理与应用科普(八)
  12. 动态规划问题经典例题
  13. 微信小程序:凑单满减计算神器
  14. UnknownError: Failed to get convolution algorithm. This is probably because cuDNN failed to initial
  15. popstate求解决方案~
  16. wordpress用户注册_如何在WordPress网站上允许用户注册
  17. elasticsearch-river-jdbc
  18. 3-Openwrt ipv6之-odhcpd服务器
  19. 内存计算技术应对大数据挑战
  20. 马斯克进军餐饮业:开设特斯拉餐厅

热门文章

  1. CSP-J 2021 网络连接
  2. 苏州新导RFID化工厂人员定位系统中的应用,化工厂人员定位你get到了吗?
  3. 记一次实验报告:基于Linux的中小型企业网络架构
  4. Linux远程登录xftp,xshell下载以及简单使用教程
  5. 计算机组成原理与体系结构 - 6分
  6. 海信合作徕卡首款激光电视将于9月亮相;SK海力士成功研发全球最高层238层4D NAND闪存 | 美通企业日报...
  7. matlab 母小波,小波变换的定义.ppt
  8. 【观察】首款7nm芯片服务器亮相,联想驱动数据中心再创新
  9. Web网站模板-横向滚动个人简历响应式网站模板(HTML+CSS+JavaScript)
  10. 程序员五一被拉去相亲,结果彻底搞懂了HTTP常用状态码