Linux下NAND FLASH驱动开发
此处是参考 2.6.29 版本的 Linux 源码中的 /drivers/mtd/nand/s3c2410.c ,以 2410 为例。 1. 在 nand flash 驱动加载后,第一步,就是去调用对应的 init 函数, s3c2410_nand_init, 去将在 nand flash 驱动注册到 Linux 驱动框架中。 2. 驱动本身,真正开始,是从 probe 函数, s3c2410_nand_probe->s3c24xx_nand_probe, 在 probe 过程中,去用 clk_enable 打开 nand flash 控制器的 clock 时钟,用 request_mem_region 去申请驱动所需要的一些内存等相关资源。然后,在 s3c2410_nand_inithw 中,去初始化硬件相关的部分,主要是关于时钟频率的计算,以及启用 nand flash 控制器,使得硬件初始化好了,后面才能正常工作。 3. 需要多解释一下的,是这部分代码: for (setno = 0; setno nr_sets; setno++, nmtd++) { pr_debug(initialising set %d (%p, info %p)/n, setno, nmtd, info); /* 调用 init chip 去挂载你的 nand 驱动的底层函数到 nand flash 的结构体中,以及设置对应的 ecc mode ,挂载 ecc 相关的函数 */ s3c2410_nand_init_chip(info, nmtd, sets); /* scan_ident ,扫描 nand 设备,设置 nand flash 的默认函数,获得物理设备的具体型号以及对应各个特性参数,这部分算出来的一些值,对于 nand flash 来说,是最主要的参数,比如 nand falsh 的芯片的大小,块大小,页大小等。 */ nmtd->scan_res = nand_scan_ident(nmtd->mtd, (sets) ? sets->nr_chips : 1); if (nmtd->scan_res == 0) { s3c2410_nand_update_chip(info, nmtd); /* scan tail ,从名字就可以看出来,是扫描的后一阶段,此时,经过前面的 scan_ident ,我们已经获得对应 nand flash 的硬件的各个参数,然后就可以在 scan tail 中,根据这些参数,去设置其他一些重要参数,尤其是 ecc 的 layout ,即 ecc 是如何在 oob 中摆放的,最后,再去进行一些初始化操作,主要是根据你的驱动,如果没有实现一些函数的话,那么就用系统默认的。 */ nand_scan_tail(nmtd->mtd); /* add partion ,根据你的 nand flash 的分区设置,去分区 */ s3c2410_nand_add_partition(info, nmtd, sets); } if (sets != NULL) sets++; } 4. 等所有的参数都计算好了,函数都挂载完毕,系统就可以正常工作了。 上层访问你的 nand falsh 中的数据的时候,通过 MTD 层,一层层调用,最后调用到你所实现的那些底层访问硬件数据 / 缓存的函数中。 关于上面提到的,在 nand_scan_tail 的时候,系统会根据你的驱动,如果没有实现一些函数的话,那么就用系统默认的。如果实现了自己的函数,就用你的。 估计很多人就会问了,那么到底我要实现哪些函数呢,而又有哪些是可以不实现,用系统默认的就可以了呢。 此问题的,就是我们下面要介绍的,也就是,你要实现的,你的驱动最少要做哪些工作,才能使整个 nand flash 工作起来。 1. 对于驱动框架部分 其实,要了解,关于驱动框架部分,你所要做的事情的话,只要看看三星的整个 nand flash 驱动中的这个结构体,就差不多了: static struct platform_driver s3c2410_nand_driver = { .probe = s3c2410_nand_probe, .remove = s3c2410_nand_remove, .suspend = s3c24xx_nand_suspend, .resume = s3c24xx_nand_resume, .driver = { .name = s3c2410-nand, .owner = THIS_MODULE, }, }; 对于上面这个结构体,没多少要解释的。从名字,就能看出来: ( 1 ) probe 就是系统“探测”,就是前面解释的整个过程,这个过程中的多数步骤,都是和你自己的 nand flash 相关的,尤其是那些硬件初始化部分,是你必须要自己实现的。 ( 2 ) remove ,就是和 probe 对应的,“反初始化”相关的动作。主要是释放系统相关资源和关闭硬件的时钟等常见操作了。 (3)suspend 和 resume ,对于很多没用到电源管理的情况下,至少对于我们刚开始写基本的驱动的时候,可以不用关心,放个空函数即可。 2. 对于 nand flash 底层操作实现部分 而对于底层硬件操作的有些函数,总体上说,都可以在上面提到的 s3c2410_nand_init_chip 中找到: static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, struct s3c2410_nand_mtd *nmtd, struct s3c2410_nand_set *set) { struct nand_chip *chip = nmtd->chip; void __iomem *regs = info->regs; chip->write_buf = s3c2410_nand_write_buf ; chip->read_buf = s3c2410_nand_read_buf ; chip->select_chip = s3c2410_nand_select_chip ; chip-
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
