第19章Flash设备驱动之Linux Flash驱动结构

本章重点

    Flash 在嵌入式系统中必不可少,Flash是 BootLoader、Linux 内核和文件系统的最佳载体。在 Linux 内核中,引入 MTD(内存技术设备) 层为 NOR Flash 和NAND Flash 设备提供统一的接口,使得 Flash 驱动的设计工作大为简化。

    1、 Linux Flash 驱动的结构,主要讲解MTD 系统的层次结构和接口。

    2、讲解NOR Flash 和 NAND Flash 驱动的设计方法,给出设计模板。

    3、以 S3C6410 外围 NOR Flash 和 NAND Flash 为实例讲解NOR Flash 和 NAND Flash 驱动的设计。

    4、如何在 Flash 上建立 cramfs、jffs/jffs2、yaffs/yaffs2 及ubifs 文件系统

19.1 Linux Flash驱动结构

19.1.1 Linux MTD 系统层次

    在 Linux 系统中,提供 MTD(MemoryTechnology Device,内存技术设备)系统来建立Flash 针对 Linux 的统一、抽象的接口。MTD 将文件系统与底层的 Flash 存储器进行隔离,使Flash 驱动工程师无须关心 Flash 作为字符设备和块设备与 Linux 内核的接口。

    如图 19.1 所示,在引入 MTD 后,Linux系统中的 Flash 设备驱动及接口可分为 4 层,从上到下依次是:设备节点MTD 设备层MTD 原始设备层硬件驱动层,这 4 层的作用如下。


图19.1 Linux MTD 系统

1、硬件驱动层:Flash 硬件驱动层负责 Flash 硬件设备的读、写、擦除,Linux MTD 设备的NOR Flash 芯片驱动位于 drivers/mtd/chips 子目录下,NAND 型 Flash 的驱动程序则位于drivers/mtd/nand 子目录下。

2、MTD 原始设备层:MTD 原始设备层由两部分组成,一部分是 MTD 原始设备的通用代码,另一部分是各个特定的 Flash 的数据,例如分区。

3、MTD 设备层:基于 MTD 原始设备,Linux 系统可以定义出 MTD 的块设备(主设备号31)和字符设备(设备号 90),构成 MTD 设备层。MTD 字符设备的定义在 mtdchar.c中实现,通过注册一系列 file_operation 函数(lseek、open、close、read、write、ioctl)可实现对 MTD 设备的读写和控制。MTD 块设备定义了一个描述 MTD 块设备的结构 mtdblk_dev,并声明一个名为 mtdblks 的指针数组,这数组中的每一个 mtdblk_dev

和 mtd_table 中的每一个 mtd_info 一一对应。

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

19.1.2 Linux MTD 系统接口

    如图 19.2 所示,在引入 MTD 后,底层 Flash 驱动直接与 MTD 原始设备层交互,利用其提供的接口注册设备和分区。


图19.2 底层 Flash 驱动

        描述 MTD 原始设备的数据结构是 mtd_info,定义了大量关于 MTD 的数据和操作函数,如代码清单 19.1 所示。mtd_info 是表示 MTD 原始设备的结构体,每个分区也被认为是一个 mtd_info,例如,如果有两个MTD 原始设备,每个上有 3 个分区,在系统中就有 6 个 mtd_info 结构体,这些 mtd_info 的指针被存放在名为 mtd_table 的数组里。

代码清单 19.1 mtd_info 结构体

include/linux/mtd/mtd.h

struct mtd_info {
        u_char type;/* 内存技术的类型 */
        u_int32_t flags;/*标志位*/
        u_int32_t size;  /*mtd 设备的大小*/

        /* "Major" erase size for the device. Naïve users may take this
         * to be the only erase size available, or may use the more detailed
         * information below if they desire
         */
        u_int32_t erasesize;/*主要的擦除块大小*/
        /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
         * though individual bits can be cleared), in case of NAND flash it is
         * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
         * it is of ECC block size, etc. It is illegal to have writesize = 0.
         * Any driver registering a struct mtd_info must ensure a writesize of
         * 1 or larger.
         */
        u_int32_t writesize;/*最小的可写单元的字节数*/

        u_int32_t oobsize;  /* OOB 字节数*/
        u_int32_t oobavail;  /*可用的 OOB 字节数*/

        // Kernel-only stuff starts here.
        char *name;
        int index;

        /* ecc layout structure pointer - read only ! */
        struct nand_ecclayout *ecclayout;/*ECC 布局结构体指针*/

        /* Data for variable erase regions. If numeraseregions is zero,
         * it means that the whole device has erasesize as given above.
         */
        int numeraseregions;
        struct mtd_erase_region_info *eraseregions;

        int (*erase) (struct mtd_info *mtd, struct erase_info *instr);

        /* This stuff for eXecute-In-Place */
        int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);

        /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
        void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);

        int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

        int (*read_oob) (struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
        int (*write_oob) (struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);

        /*
         * Methods to access the protection register area, present in some
         * flash devices. The user data is one time programmable but the
         * factory data is read only.
         */
        int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
        int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
        int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);

        /* kvec-based read/write methods.
           NB: The 'count' parameter is the number of _vectors_, each of
           which contains an (ofs, len) tuple.
        */
        int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);

        /* Sync */
        void (*sync) (struct mtd_info *mtd);

        /* Chip-supported device locking */
        int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
        int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);

        /* Power Management functions */
        int (*suspend) (struct mtd_info *mtd);
        void (*resume) (struct mtd_info *mtd);

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值