首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

如何编写Linux下Nand Flash驱动 - 05

如何编写Linux下Nand Flash驱动 - 05

本帖最后由 samwalton 于 2013-9-7 15:28 编辑

MTD,将Nand Flash,nor flash和其他类型的flash等设备,统一抽象成MTD设备来管理,根据这些设备的特点,上层实现了常见的操作函数封装,底层具体的内部实现,就需要驱动设计者自己来实现了。具体的内部硬件设备的读/写/擦除函数,那就是你必须实现的了。
    HARD drives
    MTD device
    连续的扇区
    连续的可擦除块
    扇区都很小(512B,1024B)
    可擦除块比较大 (32KB,128KB)
    主要通过两个操作对其维护操作:读扇区,写扇区
    主要通过三个操作对其维护操作:从擦除块中读,写入擦除块,擦写可擦除块
    坏快被重新映射,并且被硬件隐藏起来了(至少是在如今常见的LBA硬盘设备中是如此)
    坏的可擦除块没有被隐藏,软件中要处理对应的坏块问题。
    HDD扇区没有擦写寿命超出的问题。
    可擦除块是有擦除次数限制的,大概是104-105次。
    多说一句,关于MTD更多的内容,感兴趣的,去附录中的MTD的主页去看。
    关于mtd设备驱动,感兴趣的可以去参考附录中MTD设备的文章,该文章是比较详细地介绍了整个MTD框架和流程,方便大家理解整个mtd框架和Nand Flash驱动。
    2.2.2.读操作的硬件到软件的映射
    下面这部分主要介绍一下,关于硬件的设计和规范,是如何映射到具体的软件实现的,看了这部分内容之后,你对如何根据硬件的规范去用软件代码实现对应的功能,就有了大概的了解了,然后去实现对应的某硬件的驱动,就有了大概的脉络了。
    关于硬件部分的细节,前面其实已经介绍过了,但是为了方便说明,此处还是以读操作为例去讲解硬件到软件是如何映射的。
    再次贴出上面的那个图:
    图表 13 Nand Flash数据读取操作的时序图
    对于上面的从①到⑥,每个阶段所表示的含义,再简单解释一下:
    ①:此阶段,是读命令第一个周期,发送的命令为0x00。
    ②:此阶段,依次发送列地址,关于这些行地址,列地址等是如何计算出来的,后面的内容会有详细解释。
    ③:此阶段是发送对应的行地址
    ④:此阶段是发送读命令第二周期2nd cycle所对应的命令,0x30
    ⑤:此阶段是等待时间,等待Nand Flash硬件上准备好对应的数据,以便后续读出。
    ⑥:此阶段,就是一点点地把所需要的数据读出来。
    上面的是内容,说的是硬件是如何设计的,而这硬件的设计,即硬件的逻辑时序是如何规定的,对应的软件实现,也就要如何实现。不过可以看出的是,其中很多步骤,比如步骤1和步骤4,那都是固定的,而且,即使其中的步骤2和步骤3,即使是不同厂家和不同的Nand Flash芯片,除了要写入的列地址和行地址可能不同之外,也都是逻辑一样的,同样地,步骤5和6,也都是一样的,唯一不同的,是每家不同的Nand Flash控制器不同,所以具体到步骤6的时候,去读出数据的方式不同,所以,那一部分肯定是你要实现Nand Flash驱动的时候要自己实现的,而对应的其他几个公有的步骤呢,就有了Linux的MTD层帮你实现好了,所以,下面就来介绍一下,关于读取一个Nand Flash的页Page,Linux的MTD层,是如何具体的帮你实现的:
    关于Nand Flash的读操作,即读取一页的数据,这样的读数据的操作,很明显,是从上层文件系统传递过来的,其细节我们在此忽略,但是要知道,上层读取数据的请求,传递到了MTD这一层,其入口是哪个函数,然后我们才能继续往下面分析细节。
    关于下面所要的介绍的代码,如果没有明确指出,都是位于此文件:
    代码位置: \drivers\mtd\nand\nand_base.c
    MTD读取数据的入口是nand_read,然后调用nand_do_read_ops,此函数主体如下:
    static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
    struct mtd_oob_ops *ops)
    {
    ……
    while(1) {
    ……
    /* ㈠:要读取数据,肯定是要先发送对应的读页(read page)的命令 */
    chip- >cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
    ……
    /* ㈡:发送完命令,接着就可以去调用read_page函数读取对应的数据了 */
    ret = chip- >ecc.read_page(mtd, chip, bufpoi,
    buf += bytes;
    ……
    readlen - = bytes;
    if (! readlen)
    break;
    / * For subsequent reads align to page boundary. */
    col = 0;
    / * Increment page address */
    realpage++;
    page = realpage & chip- >pagemask;
    ……
    }
    ……
    } ? end while 1 ?
    ……
    return mtd- >ecc_stats.corrected - stats.corrected ? - EUCLEAN : 0;
    } ? end nand_do_read_ops ?
返回列表