日期:2014-05-16  浏览次数:20896 次

Linux MTD系统剖析

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;		/*