sdfs_nand_sd.c 9.8 KB

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