注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

Linux MTD子系统学习2—MTD子系统的准备工作  

2011-12-30 19:57:33|  分类: LINUX内核驱动 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

Linux MTD子系统学习2—MTD子系统的准备工作

 

MTD子系统的工作的整个流程图如下:

 

             2011年12月30日 - 还东国 - 还东国的博客   

2011年12月30日 - 还东国 - 还东国的博客

 涉及到的主要文件包括:

 

 

2011年12月30日 - 还东国 - 还东国的博客

1. 硬件驱动层

 

FLASH硬件驱动层负责FLASH硬件设备的读、写、擦出,LINUX MTD设备的NOR FLASH驱动位于/driver/mtd/chips子目录下,NAND FLASH驱动则位于/driver/mtd/nand子目录下。 

2. MTD原始设备层:MTD原始设备层由两部分构成,一部分是MTD原始设备的通用代码(mtdcore.c、mtdpart.c),另一部分是各个特定的FLASH的数据,例如分区。

3. MTD设备层:基于MTD原始设备,LINUX系统可以定义出MTD的块设备(主设备号31)www.linuxidc.com和字符设备(设备号90),构成设备层。MTD字符设备在mtdchar.c实现,MTD块设备在mtdblock.c实现。 

4. 设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和块设备节点(主设备号为31),用户通过访问此设备节点即可访问MTD字符设备和块设备。

(以上为网友BLOG上的介绍) 

明白了整个框架概念,再学习MTD子系统的源码就事半功倍了,整个LINUX下的驱动都是从module_init(s3c2410_nand_init);开始,到module_exit(s3c2410_nand_exit);结束,这两个模块的运行机制这里不深究,大家有兴趣可以去学习LDD3,上面说得很好。那么模块的初始化我们看到,s3c2410_nand_init这个函数,好,就从这里开刀,开始我们的MTD系统的学习。(drivers\mtd\nand\s3c2410.c中)

static int __init s3c2410_nand_init(void)

{

         printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");

 

         return platform_driver_register(&s3c24xx_nand_driver);

}

在这个函数里,除了一条打印语句外,是另外一个函数platform_driver_register,好,再跳进去。

int platform_driver_register(struct platform_driver *drv)

{

         drv->driver.bus = &platform_bus_type;

         if (drv->probe)//  如果不为NULL,则设置platform_driver结构体中成员device_driver中probe函数

                   drv->driver.probe = platform_drv_probe;

         if (drv->remove)

                   drv->driver.remove = platform_drv_remove;

         if (drv->shutdown)

                   drv->driver.shutdown = platform_drv_shutdown;

 

         return driver_register(&drv->driver);

}

注意drv->driver.probe = platform_drv_probe;这行,跳进去:

static int platform_drv_probe(struct device *_dev)

{

         struct platform_driver *drv = to_platform_driver(_dev->driver);

         struct platform_device *dev = to_platform_device(_dev);

 

         return drv->probe(dev);

}

看到最后一行没有return drv->probe(dev);,跳过去,(include\linux\platform_device.h)

struct platform_driver {

         int (*probe)(struct platform_device *);

         int (*remove)(struct platform_device *);

         void (*shutdown)(struct platform_device *);

         int (*suspend)(struct platform_device *, pm_message_t state);

         int (*resume)(struct platform_device *);

         struct device_driver driver;

         struct platform_device_id *id_table;

};

再回到s3c2410.c中,找到下面的代码:

static struct platform_driver s3c24xx_nand_driver = {

         .probe                = s3c24xx_nand_probe,

         .remove            = s3c24xx_nand_remove,

         .suspend  = s3c24xx_nand_suspend,

         .resume            = s3c24xx_nand_resume,

         .id_table  = s3c24xx_driver_ids,

         .driver                = {

                   .name       = "s3c24xx-nand",

                   .owner     = THIS_MODULE,

         },

};

(注意:真正的调用probe函数的过程在后面的学习6设备注册过程中会有详细说明,这里只是一个简要的并不规范的说明)

看到.probe木有,这个函数指针重载到了s3c24xx_nand_probe,好,真正的故事,就从这里开始。

在本节最后说一下BUS,DRIVER和DEVICE的关系,一个设备可能会有多个驱动,比如一个USB设备可能既是键盘又是音乐设备,而BUS是将DEVICE和DRIVER连接起来的通道,在s3c2410.c里,MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);将设备ID注册到平台设备上,在查找设备时,ID匹配成功后,会调用相应设备的驱动开始工作。也就是开始上面提到的probe函数指针指向的函数。(还有一件比较重要的事,分区,后面会详细的单独讲)

最后说的一句话:

成功始于足下,努力不辍今朝。

  评论这张
 
阅读(999)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017