nand_sim.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <rtdevice.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <dfs_def.h>
  6. // #define NAND_TRACE rt_kprintf
  7. #define NAND_TRACE(...)
  8. #define NAND_SIM "nand.bin"
  9. struct nand_device
  10. {
  11. struct rt_mtd_nand_device parent;
  12. FILE * file;
  13. };
  14. static struct nand_device _nand;
  15. #define NAND_DEVICE(device) (( struct nand_device*)(device))
  16. #define PAGE_DATA_SIZE 2048 /* page data size in bytes */
  17. #define PAGE_SPARE_SIZE 64 /* oob size in bytes */
  18. #define BLOCK_PAGES 64 /* the number of pages in a block */
  19. #define BLOCK_SIZE ((PAGE_DATA_SIZE + PAGE_SPARE_SIZE) * BLOCK_PAGES)
  20. #define BLOCK_COUNT 128 /* 128 blocks == 16M */
  21. #define BLOCK_MARK_SPARE_OFFSET 4
  22. static rt_mutex_t lock;
  23. /* RT-Thread device interface */
  24. static rt_err_t k9f1g08_mtd_check_block(
  25. struct rt_mtd_nand_device* device,
  26. rt_uint32_t block)
  27. {
  28. rt_uint8_t block_status;
  29. int result;
  30. struct nand_device * nand;
  31. nand = NAND_DEVICE(device);
  32. fseek(nand->file, block * device->pages_per_block *
  33. (device->page_size + device->oob_size) +
  34. device->page_size + BLOCK_MARK_SPARE_OFFSET,
  35. SEEK_SET);
  36. result = fread(&block_status, 1, 1, nand->file);
  37. if (result < 0)
  38. {
  39. NAND_TRACE("nand fread error\n");
  40. return -RT_ERROR;
  41. }
  42. return block_status == 0xFF ? RT_EOK : -RT_ERROR;
  43. }
  44. static rt_err_t k9f1g08_mtd_mark_bad_block(
  45. struct rt_mtd_nand_device* device,
  46. rt_uint32_t block)
  47. {
  48. rt_uint8_t block_status;
  49. int result;
  50. struct nand_device * nand;
  51. nand = NAND_DEVICE(device);
  52. fseek(nand->file, block * device->pages_per_block *
  53. (device->page_size + device->oob_size) +
  54. device->page_size + BLOCK_MARK_SPARE_OFFSET,
  55. SEEK_SET);
  56. block_status = 0x00;
  57. result = fwrite(&block_status, 1, 1, nand->file);
  58. if (result < 0)
  59. {
  60. NAND_TRACE("nand fwrite error\n");
  61. return -RT_ERROR;
  62. }
  63. return RT_EOK;
  64. }
  65. static char block_buffer[BLOCK_SIZE];
  66. static rt_err_t k9f1g08_mtd_erase_block(
  67. struct rt_mtd_nand_device* device,
  68. rt_uint32_t block)
  69. {
  70. int result;
  71. struct nand_device * nand;
  72. nand = NAND_DEVICE(device);
  73. fseek(nand->file, block * device->pages_per_block *
  74. (device->page_size + device->oob_size),
  75. SEEK_SET);
  76. memset(block_buffer, 0xFF, sizeof(BLOCK_SIZE));
  77. result = fwrite(block_buffer, BLOCK_SIZE, 1, nand->file);
  78. if (result < 0)
  79. {
  80. NAND_TRACE("nand fwrite error\n");
  81. return -RT_ERROR;
  82. }
  83. return RT_EOK;
  84. }
  85. /* return 0, ecc ok, 1, can be fixed , -1 can not be fixed */
  86. static rt_err_t k9f1g08_mtd_read(
  87. struct rt_mtd_nand_device * device,
  88. rt_off_t page,
  89. rt_uint8_t * data, rt_uint32_t data_len, //may not always be 2048
  90. rt_uint8_t * spare, rt_uint32_t spare_len)
  91. {
  92. int result;
  93. int ecc_status = 0;
  94. struct nand_device * nand;
  95. nand = NAND_DEVICE(device);
  96. if (data != RT_NULL && data_len != 0)
  97. {
  98. fseek(nand->file, page * (device->page_size + device->oob_size),
  99. SEEK_SET);
  100. result = fread(data, data_len, 1, nand->file);
  101. if (result < 0)
  102. ecc_status = -1;
  103. }
  104. if (spare != RT_NULL && spare_len != 0)
  105. {
  106. fseek(nand->file, page * (device->page_size + device->oob_size)
  107. +device->page_size,
  108. SEEK_SET);
  109. result = fread(spare, spare_len, 1, nand->file);
  110. if (result < 0)
  111. ecc_status = -1;
  112. }
  113. return ecc_status;
  114. }
  115. static rt_err_t k9f1g08_mtd_write (
  116. struct rt_mtd_nand_device * device,
  117. rt_off_t page,
  118. const rt_uint8_t * data, rt_uint32_t data_len,//will be 2048 always!
  119. const rt_uint8_t * spare, rt_uint32_t spare_len)
  120. {
  121. int result;
  122. int ecc_status = 0;
  123. struct nand_device * nand;
  124. nand = NAND_DEVICE(device);
  125. if (data != RT_NULL && data_len != 0)
  126. {
  127. fseek(nand->file, page * (device->page_size + device->oob_size),
  128. SEEK_SET);
  129. result = fwrite(data, data_len, 1, nand->file);
  130. if (result < 0)
  131. ecc_status = -1;
  132. }
  133. if (spare != RT_NULL && spare_len != 0)
  134. {
  135. fseek(nand->file, page * (device->page_size + device->oob_size)
  136. +device->page_size,
  137. SEEK_SET);
  138. result = fwrite(spare, spare_len, 1, nand->file);
  139. if (result < 0)
  140. ecc_status = -1;
  141. }
  142. return ecc_status;
  143. }
  144. const static struct rt_mtd_nand_driver_ops k9f1g08_mtd_ops =
  145. {
  146. RT_NULL,
  147. k9f1g08_mtd_read,
  148. k9f1g08_mtd_write,
  149. k9f1g08_mtd_erase_block,
  150. k9f1g08_mtd_check_block,
  151. k9f1g08_mtd_mark_bad_block,
  152. };
  153. /* interface of nand and rt-thread device */
  154. static struct rt_mtd_nand_device nand_part[2];
  155. int rt_hw_mtd_nand_init(void)
  156. {
  157. int size;
  158. rt_uint32_t id, total_block;
  159. struct nand_device * nand;
  160. struct rt_mtd_nand_device * nand_part;
  161. nand = &_nand;
  162. nand_part = &(nand->parent);
  163. lock = rt_mutex_create("nand", RT_IPC_FLAG_FIFO);
  164. /* open sd card file, if not exist, then create it */
  165. nand->file = fopen(NAND_SIM, "rb+");
  166. if (nand->file == NULL)
  167. {
  168. int i;
  169. /* create a file to simulate sd card */
  170. nand->file = fopen(NAND_SIM, "wb+");
  171. memset(block_buffer, 0xFF, sizeof(block_buffer));
  172. for(i=0; i<BLOCK_COUNT; i++)
  173. {
  174. fseek(nand->file, i * BLOCK_SIZE, SEEK_SET);
  175. fwrite(block_buffer, BLOCK_SIZE, 1, nand->file);
  176. }
  177. }
  178. fseek(nand->file, 0, SEEK_SET);
  179. /* the first partition of nand */
  180. nand_part->page_size = PAGE_DATA_SIZE;
  181. nand_part->pages_per_block = BLOCK_PAGES;//don't caculate oob size
  182. nand_part->block_start = 0;
  183. nand_part->block_end = BLOCK_COUNT -1;
  184. nand_part->oob_size = PAGE_SPARE_SIZE;
  185. nand_part->ops = &k9f1g08_mtd_ops;
  186. rt_mtd_nand_register_device("nand0", nand_part);
  187. return RT_EOK;
  188. }
  189. #ifdef RT_USING_FINSH
  190. #include <finsh.h>
  191. #endif