歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> ARM-Linux驅動--MTD驅動分析

ARM-Linux驅動--MTD驅動分析

日期:2017/3/1 10:39:09   编辑:Linux編程

主機: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數據結構

[cpp]
  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. /* "Major" erase size for the device. Naïve users may take this
  6. * to be the only erase size available, or may use the more detailed
  7. * information below if they desire
  8. */
  9. uint32_t erasesize;//最小的擦除塊大小
  10. /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
  11. * though individual bits can be cleared), in case of NAND flash it is
  12. * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
  13. * it is of ECC block size, etc. It is illegal to have writesize = 0.
  14. * Any driver registering a struct mtd_info must ensure a writesize of
  15. * 1 or larger.
  16. */
  17. uint32_t writesize;//編程塊大小
  18. uint32_t oobsize; // Amount of OOB data per block (e.g. 16)//oob(Out of band)塊大小
  19. uint32_t oobavail; // Available OOB bytes per block//每塊的可用的oob字節
  20. /*
  21. * If erasesize is a power of 2 then the shift is stored in
  22. * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
  23. */
  24. unsigned int erasesize_shift;
  25. unsigned int writesize_shift;
  26. /* Masks based on erasesize_shift and writesize_shift */
  27. unsigned int erasesize_mask;
  28. unsigned int writesize_mask;
  29. // Kernel-only stuff starts here.
  30. const char *name;
  31. int index;
  32. /* ecc layout structure pointer - read only ! */
  33. struct nand_ecclayout *ecclayout;//eec布局結構
  34. /* Data for variable erase regions. If numeraseregions is zero,
  35. * it means that the whole device has erasesize as given above.
  36. */
  37. int numeraseregions;//擦除區域個數,通常為1
  38. struct mtd_erase_region_info *eraseregions;//擦除區域的區域信息地址
  39. /*
  40. * Erase is an asynchronous operation. Device drivers are supposed
  41. * to call instr->callback() whenever the operation completes, even
  42. * if it completes with a failure.
  43. * Callers are supposed to pass a callback function and wait for it
  44. * to be called before writing to the block.
  45. */
  46. int (*erase) (struct mtd_info *mtd, struct erase_info *instr);//函數指針,erase函數的功能是將一個erase_info加入擦除隊列
  47. /* This stuff for eXecute-In-Place */
  48. /* phys is optional and may be set to NULL */
  49. int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
  50. size_t *retlen, void **virt, resource_size_t *phys);//point函數功能是允許片內執行(XIP)
  51. /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
  52. void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);//unpoint函數與point函數相反,是禁止片內執行(XIP)
  53. /* Allow NOMMU mmap() to directly map the device (if not NULL)
  54. * - return the address to which the offset maps
  55. * - return -ENOSYS to indicate refusal to do the mapping
  56. */
  57. //如果不是NULL,則允許無MMU單元的地址映射,返回偏移地址
  58. unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
  59. unsigned long len,
  60. unsigned long offset,
  61. unsigned long flags);
  62. /* Backing device capabilities for this device
  63. * - provides mmap capabilities
  64. */
  65. struct backing_dev_info *backing_dev_info;
  66. //MTD設備的讀寫函數
  67. int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  68. int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
  69. /* In blackbox flight recorder like scenarios we want to make successful
  70. writes in interrupt context. panic_write() is only intended to be
  71. called when its known the kernel is about to panic and we need the
  72. write to succeed. Since the kernel is not going to be running for much
  73. longer, this function can break locks and delay to ensure the write
  74. succeeds (but not sleep). */
  75. int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
  76. //用於MTD設備的OBB數據讀寫
  77. int (*read_oob) (struct mtd_info *mtd, loff_t from,
  78. struct mtd_oob_ops *ops);
  79. int (*write_oob) (struct mtd_info *mtd, loff_t to,
  80. struct mtd_oob_ops *ops);
  81. /*
  82. * Methods to access the protection register area, present in some
  83. * flash devices. The user data is one time programmable but the
  84. * factory data is read only.
  85. */
  86. int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
  87. int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  88. int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
  89. int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  90. int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
  91. int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
  92. /* kvec-based read/write methods.
  93. NB: The 'count' parameter is the number of _vectors_, each of
  94. which contains an (ofs, len) tuple.
  95. */
  96. int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
  97. /* Sync */
  98. //MTD設備的同步函數
  99. void (*sync) (struct mtd_info *mtd);
  100. /* Chip-supported device locking */
  101. //芯片的加鎖和解鎖
  102. int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
  103. int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
  104. /* Power Management functions */
  105. //支持電源管理函數
  106. int (*suspend) (struct mtd_info *mtd);
  107. void (*resume) (struct mtd_info *mtd);
  108. /* Bad block management functions */
  109. //壞塊管理函數
  110. int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
  111. int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
  112. struct notifier_block reboot_notifier; /* default mode before reboot */
  113. /* ECC status information */
  114. struct mtd_ecc_stats ecc_stats;//ECC狀態信息
  115. /* Subpage shift (NAND) */
  116. int subpage_sft;
  117. void *priv;//私有數據指針
  118. struct module *owner;
  119. struct device dev;
  120. int usecount;//記錄用戶的個數
  121. /* If the driver is something smart, like UBI, it may need to maintain
  122. * its own reference counting. The below functions are only for driver.
  123. * The driver may register its callbacks. These callbacks are not
  124. * supposed to be called by MTD users */
  125. //驅動回調函數
  126. int (*get_device) (struct mtd_info *mtd);
  127. void (*put_device) (struct mtd_info *mtd);
  128. };
2、mtd_part結構體信息

[cpp]
  1. /* Our partition linked list */
  2. static LIST_HEAD(mtd_partitions);//分區鏈表

[cpp]
  1. /* Our partition node structure */
  2. //分區結構信息
  3. struct mtd_part {
  4. struct mtd_info mtd;//mtd_info數據結構,會被加入mtd_table中
  5. struct mtd_info *master;//該分區的主分區
  6. uint64_t offset;//該分區的偏移地址
  7. struct list_head list;//分區鏈表
  8. };
3、mtd_partition描述mtd具體分區結構

[cpp]
  1. /*
  2. * Partition definition structure:
  3. *
  4. * An array of struct partition is passed along with a MTD object to
  5. * add_mtd_partitions() to create them.
  6. *
  7. * For each partition, these fields are available:
  8. * name: string that will be used to label the partition's MTD device.
  9. * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
  10. * will extend to the end of the master MTD device.
  11. * offset: absolute starting position within the master MTD device; if
  12. * defined as MTDPART_OFS_APPEND, the partition will start where the
  13. * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
  14. * mask_flags: contains flags that have to be masked (removed) from the
  15. * master MTD flag set for the corresponding MTD partition.
  16. * For example, to force a read-only partition, simply adding
  17. * MTD_WRITEABLE to the mask_flags will do the trick.
  18. *
  19. * Note: writeable partitions require their size and offset be
  20. * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
  21. */
  22. struct mtd_partition {
  23. char *name; /* identifier string 分區名*/
  24. uint64_t size; /* partition size 分區大小*/
  25. uint64_t offset; /* offset within the master MTD space 偏移地址*/
  26. uint32_t mask_flags; /* master MTD flags to mask out for this partition */
  27. struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
  28. };
下篇分析MTD設備基本管理 http://www.linuxidc.com/Linux/2012-01/51744p2.htm
Copyright © Linux教程網 All Rights Reserved