sdfs_nand_sd.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include <zephyr/types.h>
  2. #include <strings.h>
  3. #include <stddef.h>
  4. #include <sys/types.h>
  5. #include <device.h>
  6. #include <sdfs.h>
  7. #include <storage/flash_map.h>
  8. #include <partition/partition.h>
  9. #include <linker/linker-defs.h>
  10. #include <drivers/flash.h>
  11. #include <spicache.h>
  12. #define CACHE_INVALID (0xffffffff)
  13. #define S_CACHE_SZ (2*1024)
  14. #define S_CACHE_NUM (16)
  15. #define L_CACHE_SZ (32*1024)
  16. #define L_CACHE_NUM (15)
  17. #define ALL_CACHE_SZ (S_CACHE_SZ*S_CACHE_NUM + L_CACHE_SZ*L_CACHE_NUM)
  18. #define ALL_CACHE_NUM (S_CACHE_NUM + L_CACHE_NUM)
  19. #define TBUF_SEC_LEN (CONFIG_SDFS_CACHE_BUF_LEN / 512)
  20. typedef struct cache_item_s {
  21. sys_dnode_t node; // used for link list*/
  22. uint32_t cache_off; // offset in bytes
  23. uint32_t cache_len; // in bytes
  24. u8_t *cache_buf; // cache buffer
  25. uint32_t hit_cnt; // hit count
  26. } cache_item_t;
  27. static sys_dlist_t cache_list;
  28. static uint32_t cache_hit_cnt;
  29. static uint32_t cache_miss_cnt;
  30. static cache_item_t __aligned(4) sdfs_cache_item[ALL_CACHE_NUM] __in_section_unique(RES_PSRAM_REGION);
  31. static char __aligned(4) sdfs_cache_buf[ALL_CACHE_SZ] __in_section_unique(RES_PSRAM_REGION);
  32. #ifdef CONFIG_SDFS_READ_BY_CACHE
  33. static char __aligned(4) sdfs_tmp_buf[CONFIG_SDFS_CACHE_BUF_LEN] __in_section_unique(system.bss.sdfs_cache);
  34. #else
  35. static char __aligned(4) sdfs_tmp_buf[CONFIG_SDFS_CACHE_BUF_LEN] __in_section_unique(RES_PSRAM_REGION);
  36. #endif
  37. static const struct device *g_sd_dev;
  38. static const struct device *g_nand_dev;
  39. K_MUTEX_DEFINE(sdfs_mutex);
  40. static void nand_sd_cache_init(void)
  41. {
  42. uint32_t idx;
  43. cache_item_t *item = sdfs_cache_item;
  44. u8_t *buf = sdfs_cache_buf;
  45. sys_dlist_init(&cache_list);
  46. cache_hit_cnt = 0;
  47. cache_miss_cnt = 0;
  48. for (idx = 0; idx < ALL_CACHE_NUM; idx ++) {
  49. // init cache item
  50. sys_dnode_init(&item->node);
  51. item->cache_off = CACHE_INVALID;
  52. if (idx < S_CACHE_NUM) {
  53. item->cache_len = S_CACHE_SZ;
  54. } else {
  55. item->cache_len = L_CACHE_SZ;
  56. }
  57. item->cache_buf = buf;
  58. item->hit_cnt = 0;
  59. buf += item->cache_len;
  60. // add cache item to list
  61. sys_dlist_append(&cache_list, &item->node);
  62. item ++;
  63. }
  64. }
  65. static cache_item_t* nand_sd_cache_find(uint32_t addr, uint32_t size)
  66. {
  67. cache_item_t *item;
  68. cache_item_t *cache_item = NULL;
  69. // check size
  70. if (size > (L_CACHE_SZ - S_CACHE_SZ / 2)) {
  71. return NULL;
  72. }
  73. // find node from first to last
  74. SYS_DLIST_FOR_EACH_CONTAINER(&cache_list, item, node) {
  75. if ((item->cache_off <= addr) && ((item->cache_off + item->cache_len) >= (addr + size))) {
  76. cache_hit_cnt ++;
  77. item->hit_cnt ++;
  78. cache_item = item;
  79. break;
  80. }
  81. }
  82. // move node to first
  83. if (cache_item && !sys_dlist_is_head(&cache_list, &cache_item->node)) {
  84. sys_dlist_remove(&cache_item->node);
  85. sys_dlist_prepend(&cache_list, &cache_item->node);
  86. }
  87. return cache_item;
  88. }
  89. static cache_item_t* nand_sd_cache_alloc(uint32_t addr, uint32_t size)
  90. {
  91. cache_item_t *cache_item = (cache_item_t*)sys_dlist_peek_tail(&cache_list);
  92. uint32_t cache_len;
  93. // check size
  94. if (size > (L_CACHE_SZ - S_CACHE_SZ / 2)) {
  95. return NULL;
  96. }
  97. if (size > S_CACHE_SZ / 2) {
  98. cache_len = L_CACHE_SZ;
  99. } else {
  100. cache_len = S_CACHE_SZ;
  101. }
  102. // find node from last to first
  103. while (cache_item) {
  104. if (cache_item->cache_len == cache_len) {
  105. cache_miss_cnt ++;
  106. cache_item->cache_off = addr & ~(S_CACHE_SZ / 2 - 1);
  107. cache_item->hit_cnt = 0;
  108. break;
  109. }
  110. cache_item = (cache_item_t*)sys_dlist_peek_prev(&cache_list, &cache_item->node);
  111. }
  112. // move node to first
  113. if (cache_item && !sys_dlist_is_head(&cache_list, &cache_item->node)) {
  114. sys_dlist_remove(&cache_item->node);
  115. sys_dlist_prepend(&cache_list, &cache_item->node);
  116. }
  117. return cache_item;
  118. }
  119. static void nand_sd_cache_dump(uint32_t level)
  120. {
  121. static uint32_t ratio_saved = 0;
  122. cache_item_t *item;
  123. uint32_t ratio = 0;
  124. if ( (cache_hit_cnt + cache_miss_cnt) > 0) {
  125. ratio = cache_hit_cnt * 100 / (cache_hit_cnt + cache_miss_cnt);
  126. }
  127. if (ratio_saved != ratio) {
  128. printk("[sdfs_cache] hit=%d, miss=%d, hit-rate=%d%%\n", cache_hit_cnt, cache_miss_cnt, ratio);
  129. ratio_saved = ratio;
  130. }
  131. if (level > 0) {
  132. // find node from first to last
  133. SYS_DLIST_FOR_EACH_CONTAINER(&cache_list, item, node) {
  134. if (item->cache_off != CACHE_INVALID) {
  135. printk(" [%d] off=0x%08x, len=%d\n", item->hit_cnt, item->cache_off, item->cache_len);
  136. }
  137. }
  138. }
  139. }
  140. static const struct device *nand_sd_dev(u8_t stor_id)
  141. {
  142. if(STORAGE_ID_NAND == stor_id)
  143. return g_nand_dev;
  144. if(STORAGE_ID_SD == stor_id)
  145. return g_sd_dev;
  146. printk("sdfs dev err:%d\n", stor_id);
  147. return NULL;
  148. }
  149. #if 0
  150. static void dump(void *data, size_t len)
  151. {
  152. uint8_t *buf = data;
  153. size_t i, width = 8;
  154. for (i = 0; i < len; i++) {
  155. if ((i % width) == 0) {
  156. printk("0x%08lx\t", POINTER_TO_INT(buf + i));
  157. }
  158. printk("%02x ", buf[i]);
  159. if (((i + 1) % width) == 0 || i == (len - 1)) {
  160. printk("\n");
  161. }
  162. }
  163. }
  164. #endif
  165. static int nand_sd_data_read(const struct device *dev, char *buf,uint32_t adfs_addr, uint32_t size)
  166. {
  167. cache_item_t *item = nand_sd_cache_find(adfs_addr, size);
  168. uint32_t byte_off, sec_off, len;
  169. int ret;
  170. // printk("[sdfs] 0x%x %d\n", adfs_addr, size);
  171. // cache miss
  172. if (item == NULL) {
  173. item = nand_sd_cache_alloc(adfs_addr, size);
  174. if (item) {
  175. #ifdef CONFIG_SDFS_READ_BY_CACHE
  176. // read flash to cache
  177. ret = flash_read(dev, item->cache_off, sdfs_tmp_buf, item->cache_len);
  178. if(ret < 0)
  179. return -1;
  180. // copy to cache
  181. memcpy(item->cache_buf, sdfs_tmp_buf, item->cache_len);
  182. #else
  183. ret = flash_read(dev, item->cache_off, item->cache_buf, item->cache_len);
  184. if(ret < 0)
  185. return -1;
  186. #endif
  187. }
  188. }
  189. // cache copy
  190. if (item) {
  191. memcpy(buf, item->cache_buf + (adfs_addr - item->cache_off), size);
  192. return 0;
  193. }
  194. // large read
  195. byte_off = adfs_addr & 0x1ff;
  196. sec_off = adfs_addr >> 9;
  197. #ifdef CONFIG_SDFS_READ_BY_CACHE
  198. sec_end = (adfs_addr + size + 0x1ff) >> 9;
  199. while (sec_off < sec_end) {
  200. // read flash
  201. len = sec_end - sec_off;
  202. if (len > TBUF_SEC_LEN) {
  203. len = TBUF_SEC_LEN;
  204. }
  205. ret = flash_read(dev, sec_off<<9, sdfs_tmp_buf, len<<9);
  206. if(ret < 0)
  207. return -2;
  208. sec_off += len;
  209. // copy to buf
  210. len = (len << 9) - byte_off;
  211. if (len > size) {
  212. len = size;
  213. }
  214. memcpy(buf, sdfs_tmp_buf + byte_off, len);
  215. spi1_cache_ops(SPI_CACHE_FLUSH_ALL, buf + byte_off, len);
  216. buf += len;
  217. size -= len;
  218. byte_off = 0;
  219. }
  220. #else
  221. // read first sector
  222. if (byte_off > 0) {
  223. // read flash
  224. ret = flash_read(dev, sec_off<<9, sdfs_tmp_buf, 1<<9);
  225. if(ret < 0)
  226. return -1;
  227. sec_off += 1;
  228. // copy to buf
  229. len = 512 - byte_off;
  230. memcpy(buf, sdfs_tmp_buf + byte_off, len);
  231. buf += len;
  232. size -= len;
  233. }
  234. // read large
  235. if (size >= 512) {
  236. // read flash
  237. len = (size >> 9);
  238. ret = flash_read(dev, sec_off<<9, buf, len<<9);
  239. if(ret < 0)
  240. return -1;
  241. sec_off += len;
  242. len = (len << 9);
  243. buf += len;
  244. size -= len;
  245. }
  246. // read last sector
  247. if (size > 0) {
  248. // read flash
  249. ret = flash_read(dev, sec_off<<9, sdfs_tmp_buf, 1<<9);
  250. if(ret < 0)
  251. return -1;
  252. // copy to buf
  253. memcpy(buf, sdfs_tmp_buf, size);
  254. }
  255. #endif
  256. // dump cache
  257. nand_sd_cache_dump(0);
  258. return 0;
  259. }
  260. static struct sd_dir * nand_sd_find_dir_by_addr(const struct device *dev, const char *filename, void *buf_size_32, uint32_t adfs_addr)
  261. {
  262. int num, total, offset;
  263. struct sd_dir *sd_dir = buf_size_32;
  264. printk("read off=0x%x, file=%s\n", adfs_addr, filename);
  265. if(nand_sd_data_read(dev, (char *)buf_size_32, adfs_addr, sizeof(*sd_dir))){
  266. printk("dev=%s, read fail\n", dev->name);
  267. return NULL;
  268. }
  269. if(memcmp(sd_dir->fname, "sdfs.bin", 8) != 0)
  270. {
  271. printk("sdfs.bin invalid, offset=0x%x\n", adfs_addr);
  272. return NULL;
  273. }
  274. total = sd_dir->offset;
  275. for(offset = adfs_addr + sizeof(*sd_dir), num = 0; num < total; offset += 32)
  276. {
  277. nand_sd_data_read(dev, (char *)buf_size_32, offset, 32);
  278. //printk("%d,file=%s, size=0x%x\n", num, sd_dir->fname, sd_dir->size);
  279. if(strncasecmp(filename, sd_dir->fname, 12) == 0)
  280. {
  281. return sd_dir;
  282. }
  283. num++;
  284. }
  285. return NULL;
  286. }
  287. struct sd_dir * nand_sd_find_dir(u8_t stor_id, u8_t part, const char *filename, void *buf_size_32)
  288. {
  289. struct sd_dir * sd_d;
  290. const struct device *dev;
  291. const struct partition_entry *parti;
  292. dev = nand_sd_dev(stor_id);
  293. if(dev == NULL)
  294. return NULL;
  295. parti = partition_get_stf_part(stor_id, part+PARTITION_FILE_ID_SDFS_PART_BASE);
  296. if(parti == NULL)
  297. return NULL;
  298. k_mutex_lock(&sdfs_mutex, K_FOREVER);
  299. sd_d = nand_sd_find_dir_by_addr(dev, filename, buf_size_32, parti->offset);
  300. k_mutex_unlock(&sdfs_mutex);
  301. if(sd_d) {
  302. sd_d->offset += parti->offset;
  303. return sd_d;
  304. }
  305. return NULL;
  306. }
  307. int nand_sd_sd_fread(u8_t stor_id, struct sd_file *sd_file, void *buffer, int len)
  308. {
  309. const struct device *dev;
  310. dev = nand_sd_dev(stor_id);
  311. if(dev == NULL)
  312. return -1;
  313. k_mutex_lock(&sdfs_mutex, K_FOREVER);
  314. nand_sd_data_read(dev, (char *)buffer, sd_file->readptr, len);
  315. k_mutex_unlock(&sdfs_mutex);
  316. sd_file->readptr += len;
  317. return len;
  318. }
  319. static int nand_sd_fs_init(const struct device *dev)
  320. {
  321. g_sd_dev = device_get_binding("sd");
  322. g_nand_dev = device_get_binding("spinand");
  323. if (!g_sd_dev) {
  324. printk("sdfs cannot found device sd\n");
  325. }
  326. if (!g_nand_dev) {
  327. printk("sdfs cannot found device spinand\n");
  328. }
  329. nand_sd_cache_init();
  330. //printk("sdfs nand init\n");
  331. return 0;
  332. }
  333. SYS_INIT(nand_sd_fs_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);