Linux MTD系统剖析【转】
转自:http://blog.csdn.net/lwj103862095/article/details/21545791
版权声明:本文为博主原创文章,未经博主允许不得转载。
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口。MTD将文件系统与底层FLASH存储器进行了隔离。
如上图所示,MTD设备通常可分为四层,从上到下依次是:设备节点、MTD设备层、MTD原始设备层、硬件驱动层。
Flash硬件驱动层:Flash硬件驱动层负责对Flash硬件的读、写和擦除操作。MTD设备的Nand Flash芯片的驱动则drivers/mtd/nand/子目录下,Nor Flash芯片驱动位于drivers/mtd/chips/子目录下。
MTD原始设备层:用于描述MTD原始设备的数据结构是mtd_info,它定义了大量的关于MTD的数据和操作函数。其中mtdcore.c: MTD原始设备接口相关实现,mtdpart.c : MTD分区接口相关实现。
MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。其中mtdchar.c : MTD字符设备接口相关实现,mtdblock.c : MTD块设备接口相关实现。
设备节点:通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90)。通过访问此设备节点即可访问MTD字符设备和块设备
MTD数据结构:
1.Linux内核使用mtd_info结构体表示MTD原始设备,这其中定义了大量关于MTD的数据和操作函数(后面将会看到),所有的mtd_info结构体存放在mtd_table结构体数据里。在/drivers/mtd/mtdcore.c里:
- struct mtd_info *mtd_table[MAX_MTD_DEVICES];
2.Linux内核使用mtd_part结构体表示分区,其中mtd_info结构体成员用于描述该分区,大部分成员由其主分区mtd_part->master决定,各种函数也指向主分区的相应函数。
- struct mtd_part {
- struct mtd_info mtd; /* 分区信息, 大部分由master决定 */
- struct mtd_info *master; /* 分区的主分区 */
- uint64_t offset; /* 分区的偏移地址 */
- int index; /* 分区号 (Linux3.0后不存在该字段) */
- struct list_head list; /* 将mtd_part链成一个链表mtd_partitons */
- int registered;
- };
mtd_info结构体主要成员,为了便于观察,将重要的数据放在前面,不大重要的编写在后面。
- struct mtd_info {
- u_char type; /* MTD类型,包括MTD_NORFLASH,MTD_NANDFLASH等(可参考mtd-abi.h) */
- uint32_t flags; /* MTD属性标志,MTD_WRITEABLE,MTD_NO_ERASE等(可参考mtd-abi.h) */
- uint64_t size; /* mtd设备的大小 */
- uint32_t erasesize; /* MTD设备的擦除单元大小,对于NandFlash来说就是Block的大小 */
- uint32_t writesize; /* 写大小, 对于norFlash是字节,对nandFlash为一页 */
- uint32_t oobsize; /* OOB字节数 */
- uint32_t oobavail; /* 可用的OOB字节数 */
- unsigned int erasesize_shift; /* 默认为0,不重要 */
- unsigned int writesize_shift; /* 默认为0,不重要 */
- unsigned int erasesize_mask; /* 默认为1,不重要 */
- unsigned int writesize_mask; /* 默认为1,不重要 */
- const char *name; /* 名字, 不重要*/
- int index; /* 索引号,不重要 */
- int numeraseregions; /* 通常为1 */
- struct mtd_erase_region_info *eraseregions; /* 可变擦除区域 */
- void *priv; /* 设备私有数据指针,对于NandFlash来说指nand_chip结构体 */
- struct module *owner; /* 一般设置为THIS_MODULE */
- /* 擦除函数 */
- int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
- /* 读写flash函数 */
- 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);
- /* 带oob读写Flash函数 */
- 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);
- 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);
- int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
- int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
- /* Sync */
- void (*sync) (struct mtd_info *mtd);
- /* Chip-supported device locking */
- int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
- int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
- /* 电源管理函数 */
- int (*suspend) (struct mtd_info *mtd);
- void (*resume) (struct mtd_info *mtd);
- /* 坏块管理函数 */
- int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
- int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
- void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
- unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
- unsigned long len,
- unsigned long offset,
- unsigned long flags);
- struct backing_dev_info *backing_dev_info;
- struct notifier_block reboot_notifier; /* default mode before reboot */
- /* ECC status information */
- struct mtd_ecc_stats ecc_stats;
- int subpage_sft;
- struct device dev;
- int usecount;
- int (*get_device) (struct mtd_info *mtd);
- void (*put_device) (struct mtd_info *mtd);
- };
mtd_info结构体中的read()、write()、read_oob()、write_oob()、erase()是MTD设备驱动要实现的主要函数,幸运的是Linux大牛已经帮我们实现了一套适合大部分FLASH设备的mtd_info成员函数。
如果MTD设备只有一个分区,那么使用下面两个函数注册和注销MTD设备。
- int add_mtd_device(struct mtd_info *mtd)
- int del_mtd_device (struct mtd_info *mtd)
如果MTD设备存在其他分区,那么使用下面两个函数注册和注销MTD设备。
- int add_mtd_partitions(struct mtd_info *master,const struct mtd_partition *parts,int nbparts)
- int del_mtd_partitions(struct mtd_info *master)
其中mtd_partition结构体表示分区的信息
- struct mtd_partition {
- char *name; /* 分区名,如TQ2440_Board_uboot、TQ2440_Board_kernel、TQ2440_Board_yaffs2 */
- uint64_t size; /* 分区大小 */
- uint64_t offset; /* 分区偏移值 */
- uint32_t mask_flags; /* 掩码标识,不重要 */
- struct nand_ecclayout *ecclayout; /* OOB布局 */
- struct mtd_info **mtdp; /* pointer to store the MTD object */
- };
- 其中nand_ecclayout结构体:
- struct nand_ecclayout {
- __u32 eccbytes; /* ECC字节数 */
- __u32 eccpos[64]; /* ECC校验码在OOB区域存放位置 */
- __u32 oobavail;
- /* 除了ECC校验码之外可用的OOB字节数 */
- struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
- };
关于nand_ecclayout结构体实例,更多可参考drivers/mtd/nand/nand_base.c下的nand_oob_8、nand_oob_16、nand_oob_64实例。
MTD设备层:
mtd字符设备接口:
/drivers/mtd/mtdchar.c文件实现了MTD字符设备接口,通过它,可以直接访问Flash设备,与前面的字符驱动一样,通过file_operations结构体里面的open()、read()、write()、ioctl()可以读写Flash,通过一系列IOCTL 命令可以获取Flash 设备信息、擦除Flash、读写NAND 的OOB、获取OOB layout 及检查NAND 坏块等(MEMGETINFO、MEMERASE、MEMREADOOB、MEMWRITEOOB、MEMGETBADBLOCK IOCRL)
mtd块设备接口:
/drivers/mtd/mtdblock.c文件实现了MTD块设备接口,主要原理是将Flash的erase block 中的数据在内存中建立映射,然后对其进行修改,最后擦除Flash 上的block,将内存中的映射块写入Flash 块。整个过程被称为read/modify/erase/rewrite 周期。 但是,这样做是不安全的,当下列操作序列发生时,read/modify/erase/poweroff,就会丢失这个block 块的数据。
MTD硬件驱动层:
Linux内核再MTD层下实现了通用的NAND驱动(/driver/mtd/nand/nand_base.c),因此芯片级的NAND驱动不再需要实现mtd_info结构体中的read()、write()、read_oob()、write_oob()等成员函数。
MTD使用nand_chip来表示一个NAND FLASH芯片, 该结构体包含了关于Nand Flash的地址信息,读写方法,ECC模式,硬件控制等一系列底层机制。
- struct nand_chip {
- void __iomem *IO_ADDR_R; /* 读8位I/O线地址 */
- void __iomem *IO_ADDR_W; /* 写8位I/O线地址 */
- /* 从芯片中读一个字节 */
- uint8_t (*read_byte)(struct mtd_info *mtd);
- /* 从芯片中读一个字 */
- u16 (*read_word)(struct mtd_info *mtd);
- /* 将缓冲区内容写入芯片 */
- void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- /* 读芯片读取内容至缓冲区/ */
- void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
- /* 验证芯片和写入缓冲区中的数据 */
- int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- /* 选中芯片 */
- void (*select_chip)(struct mtd_info *mtd, int chip);
- /* 检测是否有坏块 */
- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
- /* 标记坏块 */
- int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
- /* 命令、地址、数据控制函数 */
- void (*cmd_ctrl)(struct mtd_info *mtd, int dat,unsigned int ctrl);
- /* 设备是否就绪 */
- int (*dev_ready)(struct mtd_info *mtd);
- /* 实现命令发送 */
- void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
- int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
- /* 擦除命令的处理 */
- void (*erase_cmd)(struct mtd_info *mtd, int page);
- /* 扫描坏块 */
- int (*scan_bbt)(struct mtd_info *mtd);
- int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
- /* 写一页 */
- int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int page, int cached, int raw);
- int chip_delay; /* 由板决定的延迟时间 */
- /* 与具体的NAND芯片相关的一些选项,如NAND_NO_AUTOINCR,NAND_BUSWIDTH_16等 */
- unsigned int options;
- /* 用位表示的NAND芯片的page大小,如某片NAND芯片
- * 的一个page有512个字节,那么page_shift就是9
- */
- int page_shift;
- /* 用位表示的NAND芯片的每次可擦除的大小,如某片NAND芯片每次可
- * 擦除16K字节(通常就是一个block的大小),那么phys_erase_shift就是14
- */
- int phys_erase_shift;
- /* 用位表示的bad block table的大小,通常一个bbt占用一个block,
- * 所以bbt_erase_shift通常与phys_erase_shift相等
- */
- int bbt_erase_shift;
- /* 用位表示的NAND芯片的容量 */
- int chip_shift;
- /* NADN FLASH芯片的数量 */
- int numchips;
- /* NAND芯片的大小 */
- uint64_t chipsize;
- int pagemask;
- int pagebuf;
- int subpagesize;
- uint8_t cellinfo;
- int badblockpos;
- nand_state_t state;
- uint8_t *oob_poi;
- struct nand_hw_control *controller;
- struct nand_ecclayout *ecclayout; /* ECC布局 */
- struct nand_ecc_ctrl ecc; /* ECC校验结构体,里面有大量的函数进行ECC校验 */
- struct nand_buffers *buffers;
- struct nand_hw_control hwcontrol;
- struct mtd_oob_ops ops;
- uint8_t *bbt;
- struct nand_bbt_descr *bbt_td;
- struct nand_bbt_descr *bbt_md;
- struct nand_bbt_descr *badblock_pattern;
- void *priv;
- };
最后,我们来用图表的形式来总结一下,MTD设备层、MTD原始设备层、FLASH硬件驱动层之间的联系。
版权声明:本文为博主原创文章,未经博主允许不得转载。
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口。MTD将文件系统与底层FLASH存储器进行了隔离。
如上图所示,MTD设备通常可分为四层,从上到下依次是:设备节点、MTD设备层、MTD原始设备层、硬件驱动层。
Flash硬件驱动层:Flash硬件驱动层负责对Flash硬件的读、写和擦除操作。MTD设备的Nand Flash芯片的驱动则drivers/mtd/nand/子目录下,Nor Flash芯片驱动位于drivers/mtd/chips/子目录下。
MTD原始设备层:用于描述MTD原始设备的数据结构是mtd_info,它定义了大量的关于MTD的数据和操作函数。其中mtdcore.c: MTD原始设备接口相关实现,mtdpart.c : MTD分区接口相关实现。
MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。其中mtdchar.c : MTD字符设备接口相关实现,mtdblock.c : MTD块设备接口相关实现。
设备节点:通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90)。通过访问此设备节点即可访问MTD字符设备和块设备
MTD数据结构:
1.Linux内核使用mtd_info结构体表示MTD原始设备,这其中定义了大量关于MTD的数据和操作函数(后面将会看到),所有的mtd_info结构体存放在mtd_table结构体数据里。在/drivers/mtd/mtdcore.c里:
- struct mtd_info *mtd_table[MAX_MTD_DEVICES];
2.Linux内核使用mtd_part结构体表示分区,其中mtd_info结构体成员用于描述该分区,大部分成员由其主分区mtd_part->master决定,各种函数也指向主分区的相应函数。
- struct mtd_part {
- struct mtd_info mtd; /* 分区信息, 大部分由master决定 */
- struct mtd_info *master; /* 分区的主分区 */
- uint64_t offset; /* 分区的偏移地址 */
- int index; /* 分区号 (Linux3.0后不存在该字段) */
- struct list_head list; /* 将mtd_part链成一个链表mtd_partitons */
- int registered;
- };
mtd_info结构体主要成员,为了便于观察,将重要的数据放在前面,不大重要的编写在后面。
- struct mtd_info {
- u_char type; /* MTD类型,包括MTD_NORFLASH,MTD_NANDFLASH等(可参考mtd-abi.h) */
- uint32_t flags; /* MTD属性标志,MTD_WRITEABLE,MTD_NO_ERASE等(可参考mtd-abi.h) */
- uint64_t size; /* mtd设备的大小 */
- uint32_t erasesize; /* MTD设备的擦除单元大小,对于NandFlash来说就是Block的大小 */
- uint32_t writesize; /* 写大小, 对于norFlash是字节,对nandFlash为一页 */
- uint32_t oobsize; /* OOB字节数 */
- uint32_t oobavail; /* 可用的OOB字节数 */
- unsigned int erasesize_shift; /* 默认为0,不重要 */
- unsigned int writesize_shift; /* 默认为0,不重要 */
- unsigned int erasesize_mask; /* 默认为1,不重要 */
- unsigned int writesize_mask; /* 默认为1,不重要 */
- const char *name; /* 名字, 不重要*/
- int index; /* 索引号,不重要 */
- int numeraseregions; /* 通常为1 */
- struct mtd_erase_region_info *eraseregions; /* 可变擦除区域 */
- void *priv; /* 设备私有数据指针,对于NandFlash来说指nand_chip结构体 */
- struct module *owner; /* 一般设置为THIS_MODULE */
- /* 擦除函数 */
- int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
- /* 读写flash函数 */
- 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);
- /* 带oob读写Flash函数 */
- 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);
- 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);
- int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
- int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
- /* Sync */
- void (*sync) (struct mtd_info *mtd);
- /* Chip-supported device locking */
- int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
- int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
- /* 电源管理函数 */
- int (*suspend) (struct mtd_info *mtd);
- void (*resume) (struct mtd_info *mtd);
- /* 坏块管理函数 */
- int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
- int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
- void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
- unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
- unsigned long len,
- unsigned long offset,
- unsigned long flags);
- struct backing_dev_info *backing_dev_info;
- struct notifier_block reboot_notifier; /* default mode before reboot */
- /* ECC status information */
- struct mtd_ecc_stats ecc_stats;
- int subpage_sft;
- struct device dev;
- int usecount;
- int (*get_device) (struct mtd_info *mtd);
- void (*put_device) (struct mtd_info *mtd);
- };
mtd_info结构体中的read()、write()、read_oob()、write_oob()、erase()是MTD设备驱动要实现的主要函数,幸运的是Linux大牛已经帮我们实现了一套适合大部分FLASH设备的mtd_info成员函数。
如果MTD设备只有一个分区,那么使用下面两个函数注册和注销MTD设备。
- int add_mtd_device(struct mtd_info *mtd)
- int del_mtd_device (struct mtd_info *mtd)
如果MTD设备存在其他分区,那么使用下面两个函数注册和注销MTD设备。
- int add_mtd_partitions(struct mtd_info *master,const struct mtd_partition *parts,int nbparts)
- int del_mtd_partitions(struct mtd_info *master)
其中mtd_partition结构体表示分区的信息
- struct mtd_partition {
- char *name; /* 分区名,如TQ2440_Board_uboot、TQ2440_Board_kernel、TQ2440_Board_yaffs2 */
- uint64_t size; /* 分区大小 */
- uint64_t offset; /* 分区偏移值 */
- uint32_t mask_flags; /* 掩码标识,不重要 */
- struct nand_ecclayout *ecclayout; /* OOB布局 */
- struct mtd_info **mtdp; /* pointer to store the MTD object */
- };
- 其中nand_ecclayout结构体:
- struct nand_ecclayout {
- __u32 eccbytes; /* ECC字节数 */
- __u32 eccpos[64]; /* ECC校验码在OOB区域存放位置 */
- __u32 oobavail;
- /* 除了ECC校验码之外可用的OOB字节数 */
- struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
- };
关于nand_ecclayout结构体实例,更多可参考drivers/mtd/nand/nand_base.c下的nand_oob_8、nand_oob_16、nand_oob_64实例。
MTD设备层:
mtd字符设备接口:
/drivers/mtd/mtdchar.c文件实现了MTD字符设备接口,通过它,可以直接访问Flash设备,与前面的字符驱动一样,通过file_operations结构体里面的open()、read()、write()、ioctl()可以读写Flash,通过一系列IOCTL 命令可以获取Flash 设备信息、擦除Flash、读写NAND 的OOB、获取OOB layout 及检查NAND 坏块等(MEMGETINFO、MEMERASE、MEMREADOOB、MEMWRITEOOB、MEMGETBADBLOCK IOCRL)
mtd块设备接口:
/drivers/mtd/mtdblock.c文件实现了MTD块设备接口,主要原理是将Flash的erase block 中的数据在内存中建立映射,然后对其进行修改,最后擦除Flash 上的block,将内存中的映射块写入Flash 块。整个过程被称为read/modify/erase/rewrite 周期。 但是,这样做是不安全的,当下列操作序列发生时,read/modify/erase/poweroff,就会丢失这个block 块的数据。
MTD硬件驱动层:
Linux内核再MTD层下实现了通用的NAND驱动(/driver/mtd/nand/nand_base.c),因此芯片级的NAND驱动不再需要实现mtd_info结构体中的read()、write()、read_oob()、write_oob()等成员函数。
MTD使用nand_chip来表示一个NAND FLASH芯片, 该结构体包含了关于Nand Flash的地址信息,读写方法,ECC模式,硬件控制等一系列底层机制。
- struct nand_chip {
- void __iomem *IO_ADDR_R; /* 读8位I/O线地址 */
- void __iomem *IO_ADDR_W; /* 写8位I/O线地址 */
- /* 从芯片中读一个字节 */
- uint8_t (*read_byte)(struct mtd_info *mtd);
- /* 从芯片中读一个字 */
- u16 (*read_word)(struct mtd_info *mtd);
- /* 将缓冲区内容写入芯片 */
- void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- /* 读芯片读取内容至缓冲区/ */
- void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
- /* 验证芯片和写入缓冲区中的数据 */
- int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- /* 选中芯片 */
- void (*select_chip)(struct mtd_info *mtd, int chip);
- /* 检测是否有坏块 */
- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
- /* 标记坏块 */
- int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
- /* 命令、地址、数据控制函数 */
- void (*cmd_ctrl)(struct mtd_info *mtd, int dat,unsigned int ctrl);
- /* 设备是否就绪 */
- int (*dev_ready)(struct mtd_info *mtd);
- /* 实现命令发送 */
- void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
- int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
- /* 擦除命令的处理 */
- void (*erase_cmd)(struct mtd_info *mtd, int page);
- /* 扫描坏块 */
- int (*scan_bbt)(struct mtd_info *mtd);
- int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
- /* 写一页 */
- int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int page, int cached, int raw);
- int chip_delay; /* 由板决定的延迟时间 */
- /* 与具体的NAND芯片相关的一些选项,如NAND_NO_AUTOINCR,NAND_BUSWIDTH_16等 */
- unsigned int options;
- /* 用位表示的NAND芯片的page大小,如某片NAND芯片
- * 的一个page有512个字节,那么page_shift就是9
- */
- int page_shift;
- /* 用位表示的NAND芯片的每次可擦除的大小,如某片NAND芯片每次可
- * 擦除16K字节(通常就是一个block的大小),那么phys_erase_shift就是14
- */
- int phys_erase_shift;
- /* 用位表示的bad block table的大小,通常一个bbt占用一个block,
- * 所以bbt_erase_shift通常与phys_erase_shift相等
- */
- int bbt_erase_shift;
- /* 用位表示的NAND芯片的容量 */
- int chip_shift;
- /* NADN FLASH芯片的数量 */
- int numchips;
- /* NAND芯片的大小 */
- uint64_t chipsize;
- int pagemask;
- int pagebuf;
- int subpagesize;
- uint8_t cellinfo;
- int badblockpos;
- nand_state_t state;
- uint8_t *oob_poi;
- struct nand_hw_control *controller;
- struct nand_ecclayout *ecclayout; /* ECC布局 */
- struct nand_ecc_ctrl ecc; /* ECC校验结构体,里面有大量的函数进行ECC校验 */
- struct nand_buffers *buffers;
- struct nand_hw_control hwcontrol;
- struct mtd_oob_ops ops;
- uint8_t *bbt;
- struct nand_bbt_descr *bbt_td;
- struct nand_bbt_descr *bbt_md;
- struct nand_bbt_descr *badblock_pattern;
- void *priv;
- };
最后,我们来用图表的形式来总结一下,MTD设备层、MTD原始设备层、FLASH硬件驱动层之间的联系。
Linux MTD系统剖析【转】的更多相关文章
- Linux MTD系统剖析
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...
- linux MTD系统解析(转)
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...
- Linux的系统级性能剖析工具-perf
一直在找个靠谱且易用的性能分析工具,perf 貌似是很符合要求的,先给出阿里整理的几篇文档: Linux的系统级性能剖析工具-perf-1.pdf Linux的系统级性能剖析工具-perf-2.pdf ...
- Linux MTD子系统 _从模型分析到Flash驱动模板
MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...
- [转帖]Linux内核系统体系概述
Linux内核系统体系概述 https://www.cnblogs.com/alantu2018/p/8447369.html Linux 内核主要由 5 个模块构成,它们分别是: 进程调度模块 用来 ...
- MTD系统架构和yaffs2使用、Nandflash驱动设计
一.MTD系统架构 1.MTD设备体验 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系统的最佳载体. 在Linux内核中引入了MTD子系统为NORFLASH和N ...
- 【原创】Linux RCU原理剖析(二)-渐入佳境
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- Linux查看系统状态命令
Linux查看系统状态命令 iostat iostat 命令详细地显示了存储子系统方面的情况.你通常用iostat来监控存储子系统总体上运行状况如何,并且在用户注意到服务器运行缓慢之前提早 ...
- 82 fsck-检查与修复 Linux 档案系统
Linux fsck命令用于 检查与修复 Linux 档案系统,可以同时检查一个或多个 Linux 档案系统. 语法 fsck [-sACVRP] [-t fstype] [--] [fsck-opt ...
随机推荐
- 获取Spring的ApplicationContext的方法
在网上搜了一下,写一下我试用的两个方法. 1 2 ApplicationContext ctx=new FileSystemXmlApplicationContext("/applica ...
- preg_match_all
<meta charset="utf8"> <?php set_time_limit (0); for($i=1;$i<34;$i++){ $url = & ...
- thinkphp 最简单的引入百度编辑器的方法
后台肯定是框架了...编辑器放在框架里面... 后台首页比如是这样的... <html> <frameset cols="10%,90%"> <fra ...
- 几个系统调用分析 glibc中的malloc调用和共享内存原理
本文主要分析内存以及I/O相关的系统调用和库函数的实现原理,根据原理给出在使用过程中需要注意的问题和优化的侧重点,本文涉及到的系统调用包括readahead,pread/pwrite,read/wri ...
- Windows 8上使用SQL 2012 Configuration Manager
现在使用Windows 8 + Sql Server 2012,而今天想用SQL 2012 Configuraton Manager, 设置别名来访问不同的开发数据库.但发现没能找到SQL 2012 ...
- 测试App运行状态
示例代码: #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - ...
- (Abstract Factory)抽象工厂
定义: 抽象工厂同工厂方法有相似处:都提供了对子类创建的封装,都是有工厂方法的接口实现类的中决定了子类被创建为什么对象. 不同于工厂方法之处:工厂方法创建的对象只是一个类型的子类,而抽象工厂创建的对象 ...
- Effective C++ 2.构造 析构 赋值运算
//条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...
- PostgreSQL中initdb做了什么
在使用数据库前,是启动数据库,启动数据库前是initdb(初始化数据库):一起来看一下initdb做了什么吧. 初始化数据库的操作为: ./initdb -D /usr/local/pgsql/dat ...
- nyist 673 悟空的难题
http://acm.nyist.net/JudgeOnline/problem.php?pid=673 悟空的难题 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 ...