本帖最后由 forlinx2013 于 2014-1-24 09:21 编辑
欢迎大家来到飞凌爱板网专区,对嵌入式技术感兴趣的朋友不妨多多关注一下,我们提供了公司所有开发板的所有资料,也会更新大量技术文章,欢迎大家一块学习提高!!!
主机:Gentoo Linux 11.2 with linux kernel 3.0.6 硬件平台:FL2440(S3C2440)with linux kernel 2.6.35
MTD(memory technology device内存技术设备) 在硬件和文件系统层之间的提供了一个抽象的接口,MTD是用来访问内存设备(如:ROM、flash)的中间层,它将内存设备的共有特性抽取出来,从而使增加新的内存设备驱动程序变得更简单。MTD的源代码都在/drivers/mtd目录中。 MTD中间层细分为四层,按从上到下依次为:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。MTD中间层层次结构图如下:
从上图可以看出,原始设备是MTD字符设备和MTD块设备的抽象。 MTD设备层、MTD原始设备层和Flash硬件驱动层之间的接口关系如下图: 下面首先分析下MTD原始层设备 1、mtd_info数据结构 1 struct mtd_info { 2 u_char type;//内存技术类型,例如MTD_RAM,MTD_ROM,MTD_NORFLASH,MTD_NAND_FLASH,MTD_PEROM等 3 uint32_t flags;//标志位 4 uint64_t size; // Total size of the MTD//MTD设备的大小 5 6 /* "Major" erase size for the device. Naïve users may take this 7 * to be the only erase size available, or may use the more detailed 8 * information below if they desire 9 */ 10 uint32_t erasesize;//最小的擦除块大小 11 /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 12 * though individual bits can be cleared), in case of NAND flash it is 13 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 14 * it is of ECC block size, etc. It is illegal to have writesize = 0. 15 * Any driver registering a struct mtd_info must ensure a writesize of 16 * 1 or larger. 17 */ 18 uint32_t writesize;//编程块大小 19 20 uint32_t oobsize; // Amount of OOB data per block (e.g. 16)//oob(Out of band)块大小 21 uint32_t oobavail; // Available OOB bytes per block//每块的可用的oob字节 22 23 /* 24 * If erasesize is a power of 2 then the shift is stored in 25 * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. 26 */ 27 unsigned int erasesize_shift; 28 unsigned int writesize_shift; 29 /* Masks based on erasesize_shift and writesize_shift */ 30 unsigned int erasesize_mask; 31 unsigned int writesize_mask; 32 33 // Kernel-only stuff starts here. 34 const char *name; 35 int index; 36 37 /* ecc layout structure pointer - read only ! */ 38 struct nand_ecclayout *ecclayout;//eec布局结构 39 40 /* Data for variable erase regions. If numeraseregions is zero, 41 * it means that the whole device has erasesize as given above. 42 */ 43 int numeraseregions;//擦除区域个数,通常为1 44 struct mtd_erase_region_info *eraseregions;//擦除区域的区域信息地址 45 46 /* 47 * Erase is an asynchronous operation. Device drivers are supposed 48 * to call instr->callback() whenever the operation completes, even 49 * if it completes with a failure. 50 * Callers are supposed to pass a callback function and wait for it 51 * to be called before writing to the block. 52 */ 53 int (*erase) (struct mtd_info *mtd, struct erase_info *instr);//函数指针,erase函数的功能是将一个erase_info加入擦除队列 54 55 /* This stuff for eXecute-In-Place */ 56 /* phys is optional and may be set to NULL */ 57 int (*point) (struct mtd_info *mtd, loff_t from, size_t len, 58 size_t *retlen, void **virt, resource_size_t *phys);//point函数功能是允许片内执行(XIP) 59 60 /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ 61 void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);//unpoint函数与point函数相反,是禁止片内执行(XIP) 62 63 /* Allow NOMMU mmap() to directly map the device (if not NULL) 64 * - return the address to which the offset maps 65 * - return -ENOSYS to indicate refusal to do the mapping 66 */ 67 //如果不是NULL,则允许无MMU单元的地址映射,返回偏移地址 68 unsigned long (*get_unmapped_area) (struct mtd_info *mtd, 69 unsigned long len, 70 unsigned long offset, 71 unsigned long flags); 72 73 /* Backing device capabilities for this device 74 * - provides mmap capabilities 75 */ 76 struct backing_dev_info *backing_dev_info; 77 78 //MTD设备的读写函数 79 int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 80 int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); 81 82 /* In blackbox flight recorder like scenarios we want to make successful 83 writes in interrupt context. panic_write() is only intended to be 84 called when its known the kernel is about to panic and we need the 85 write to succeed. Since the kernel is not going to be running for much 86 longer, this function can break locks and delay to ensure the write 87 succeeds (but not sleep). */ 88 89 int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); 90 91 //用于MTD设备的OBB数据读写 92 int (*read_oob) (struct mtd_info *mtd, loff_t from, 93 struct mtd_oob_ops *ops); 94 int (*write_oob) (struct mtd_info *mtd, loff_t to, 95 struct mtd_oob_ops *ops); 96 97 /* 98 * Methods to access the protection register area, present in some 99 * flash devices. The user data is one time programmable but the 100 * factory data is read only. 101 */ 102 int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); 103 int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 104 int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); 105 int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 106 int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 107 int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); 108 109 /* kvec-based read/write methods. 110 NB: The 'count' parameter is the number of _vectors_, each of 111 which contains an (ofs, len) tuple. 112 */ 113 int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); 114 115 /* Sync */ 116 //MTD设备的同步函数 117 void (*sync) (struct mtd_info *mtd); 118 119 /* Chip-supported device locking */ 120 //芯片的加锁和解锁 121 int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 122 int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 123 124 /* Power Management functions */ 125 //支持电源管理函数 126 int (*suspend) (struct mtd_info *mtd); 127 void (*resume) (struct mtd_info *mtd); 128 129 /* Bad block management functions */ 130 //坏块管理函数 131 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); 132 int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); 133 134 struct notifier_block reboot_notifier; /* default mode before reboot */ 135 136 /* ECC status information */ 137 struct mtd_ecc_stats ecc_stats;//ECC状态信息 138 /* Subpage shift (NAND) */ 139 int subpage_sft; 140 141 void *priv;//私有数据指针 142 143 struct module *owner; 144 struct device dev; 145 int usecount;//记录用户的个数 146 147 /* If the driver is something smart, like UBI, it may need to maintain 148 * its own reference counting. The below functions are only for driver. 149 * The driver may register its callbacks. These callbacks are not 150 * supposed to be called by MTD users */ 151 //驱动回调函数 152 int (*get_device) (struct mtd_info *mtd); 153 void (*put_device) (struct mtd_info *mtd); 154 }; struct mtd_info { u_char type;//内存技术类型,例如MTD_RAM,MTD_ROM,MTD_NORFLASH,MTD_NAND_FLASH,MTD_PEROM等 uint32_t flags;//标志位 uint64_t size; // Total size of the MTD//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 */ uint32_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. */ uint32_t writesize;//编程块大小
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)//oob(Out of band)块大小 uint32_t oobavail; // Available OOB bytes per block//每块的可用的oob字节
/* * If erasesize is a power of 2 then the shift is stored in * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. */ unsigned int erasesize_shift; unsigned int writesize_shift; /* Masks based on erasesize_shift and writesize_shift */ unsigned int erasesize_mask; unsigned int writesize_mask;
// Kernel-only stuff starts here. const char *name; int index;
/* ecc layout structure pointer - read only ! */ struct nand_ecclayout *ecclayout;//eec布局结构
/* Data for variable erase regions. If numeraseregions is zero, * it means that the whole device has erasesize as given above. */ int numeraseregions;//擦除区域个数,通常为1 struct mtd_erase_region_info *eraseregions;//擦除区域的区域信息地址
/* * Erase is an asynchronous operation. Device drivers are supposed * to call instr->callback() whenever the operation completes, even * if it completes with a failure. * Callers are supposed to pass a callback function and wait for it * to be called before writing to the block. */ int (*erase) (struct mtd_info *mtd, struct erase_info *instr);//函数指针,erase函数的功能是将一个erase_info加入擦除队列
/* This stuff for eXecute-In-Place */ /* phys is optional and may be set to NULL */ int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, resource_size_t *phys);//point函数功能是允许片内执行(XIP)
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */ void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);//unpoint函数与point函数相反,是禁止片内执行(XIP)
/* Allow NOMMU mmap() to directly map the device (if not NULL) * - return the address to which the offset maps * - return -ENOSYS to indicate refusal to do the mapping */ //如果不是NULL,则允许无MMU单元的地址映射,返回偏移地址 unsigned long (*get_unmapped_area) (struct mtd_info *mtd, unsigned long len, unsigned long offset, unsigned long flags);
/* Backing device capabilities for this device * - provides mmap capabilities */ struct backing_dev_info *backing_dev_info;
//MTD设备的读写函数 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);
/* In blackbox flight recorder like scenarios we want to make successful writes in interrupt context. panic_write() is only intended to be called when its known the kernel is about to panic and we need the write to succeed. Since the kernel is not going to be running for much longer, this function can break locks and delay to ensure the write succeeds (but not sleep). */
int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
//用于MTD设备的OBB数据读写 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 */ //MTD设备的同步函数 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);
/* Power Management functions */ //支持电源管理函数 int (*suspend) (struct mtd_info *mtd); void (*resume) (struct mtd_info *mtd);
/* Bad block management functions */ //坏块管理函数 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
struct notifier_block reboot_notifier; /* default mode before reboot */
/* ECC status information */ struct mtd_ecc_stats ecc_stats;//ECC状态信息 /* Subpage shift (NAND) */ int subpage_sft;
void *priv;//私有数据指针
struct module *owner; struct device dev; int usecount;//记录用户的个数
/* If the driver is something smart, like UBI, it may need to maintain * its own reference counting. The below functions are only for driver. * The driver may register its callbacks. These callbacks are not * supposed to be called by MTD users */ //驱动回调函数 int (*get_device) (struct mtd_info *mtd); void (*put_device) (struct mtd_info *mtd); };
2、mtd_part结构体信息
155 /* Our partition linked list */ 156 static LIST_HEAD(mtd_partitions);//分区链表 /* Our partition linked list */ static LIST_HEAD(mtd_partitions);//分区链表
157 /* Our partition node structure */ 158 //分区结构信息 159 struct mtd_part { 160 struct mtd_info mtd;//mtd_info数据结构,会被加入mtd_table中 161 struct mtd_info *master;//该分区的主分区 162 uint64_t offset;//该分区的偏移地址 163 struct list_head list;//分区链表 164 }; /* Our partition node structure */ //分区结构信息 struct mtd_part { struct mtd_info mtd;//mtd_info数据结构,会被加入mtd_table中 struct mtd_info *master;//该分区的主分区 uint64_t offset;//该分区的偏移地址 struct list_head list;//分区链表 };
3、mtd_partition描述mtd具体分区结构
165 /* 166 * Partition definition structure: 167 * 168 * An array of struct partition is passed along with a MTD object to 169 * add_mtd_partitions() to create them. 170 * 171 * For each partition, these fields are available: 172 * name: string that will be used to label the partition's MTD device. 173 * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition 174 * will extend to the end of the master MTD device. 175 * offset: absolute starting position within the master MTD device; if 176 * defined as MTDPART_OFS_APPEND, the partition will start where the 177 * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. 178 * mask_flags: contains flags that have to be masked (removed) from the 179 * master MTD flag set for the corresponding MTD partition. 180 * For example, to force a read-only partition, simply adding 181 * MTD_WRITEABLE to the mask_flags will do the trick. 182 * 183 * Note: writeable partitions require their size and offset be 184 * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). 185 */ 186 187 struct mtd_partition { 188 char *name; /* identifier string 分区名*/ 189 uint64_t size; /* partition size 分区大小*/ 190 uint64_t offset; /* offset within the master MTD space 偏移地址*/ 191 uint32_t mask_flags; /* master MTD flags to mask out for this partition */ 192 struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ 193 };
|