硬件平台: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数据结构
- 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结构体信息
- /* Our partition linked list */
- static LIST_HEAD(mtd_partitions);//分区链表
- /* 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具体分区结构
- /*
- * Partition definition structure:
- *
- * An array of struct partition is passed along with a MTD object to
- * add_mtd_partitions() to create them.
- *
- * For each partition, these fields are available:
- * name: string that will be used to label the partition's MTD device.
- * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
- * will extend to the end of the master MTD device.
- * offset: absolute starting position within the master MTD device; if
- * defined as MTDPART_OFS_APPEND, the partition will start where the
- * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
- * mask_flags: contains flags that have to be masked (removed) from the
- * master MTD flag set for the corresponding MTD partition.
- * For example, to force a read-only partition, simply adding
- * MTD_WRITEABLE to the mask_flags will do the trick.
- *
- * Note: writeable partitions require their size and offset be
- * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
- */
- struct mtd_partition {
- char *name; /* identifier string 分区名*/
- uint64_t size; /* partition size 分区大小*/
- uint64_t offset; /* offset within the master MTD space 偏移地址*/
- uint32_t mask_flags; /* master MTD flags to mask out for this partition */
- struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
- };
上一篇:ARM-Linux驱动--MTD驱动分析(二)
下一篇:ARM-Linux移植攻略--yaffs2 Partially written block xxx detected 问题解决
推荐阅读最新更新时间:2024-03-16 14:51