diskio_cache.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include <diskio.h>
  2. #include <disk/disk_access.h>
  3. #include <ffconf.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <init.h>
  7. #include <os_common_api.h>
  8. #include <mem_manager.h>
  9. #include <memory/mem_cache.h>
  10. #define SYS_LOG_DOMAIN "diskio_cache"
  11. #define SYS_LOG_LEVEL SYS_LOG_LEVEL_INFO
  12. /*#include <logging/sys_log.h>*/
  13. #define DISKIO_TIMEOUT OS_FOREVER
  14. #define DISKIO_CACHE_POOL_NUM 1
  15. #define DISKIO_CACHE_POOL_SIZE 2048
  16. #define DISKIO_CACHE_STACK_SIZE 1536
  17. #define DISKIO_DIRECT_READ 0
  18. #define DISKIO_DEFAULT_PRIORITY 2
  19. /*static char __in_section_unique(diskio.cache.stack)__aligned(STACK_ALIGN) diskio_cache_thread_stack[1152];*/
  20. static OS_THREAD_STACK_DEFINE(diskio_cache_thread_stack, DISKIO_CACHE_STACK_SIZE);
  21. OS_MUTEX_DEFINE(diskio_cache_mutex);
  22. struct diskio_cache_item {
  23. u32_t cache_valid:1;
  24. u32_t busy_flag:1;
  25. u32_t write_valid:1;
  26. u32_t err_flag:1;
  27. u32_t disk_type:8;
  28. u32_t cache_sector;
  29. struct disk_info *disk;
  30. const char *pdrv;
  31. u8_t cache_data[DISKIO_CACHE_POOL_SIZE];
  32. };
  33. enum {
  34. REQ_FLUSH,
  35. REQ_LOAD,
  36. };
  37. struct diskio_cache_req {
  38. void *fifo_reserved;
  39. struct disk_info *req_disk;
  40. u8_t req_type;
  41. s8_t req_priority;
  42. u32_t req_sector;
  43. os_sem req_sem;
  44. const char *pdrv;
  45. };
  46. struct diskio_cache_context {
  47. os_fifo cache_req_fifo;
  48. u32_t terminal:1;
  49. u32_t inited:1;
  50. u32_t cache_index:8;
  51. u32_t thread_id;
  52. struct diskio_cache_item cache_pool[DISKIO_CACHE_POOL_NUM];
  53. };
  54. #ifdef CONFIG_SOC_NO_PSRAM
  55. __in_section_unique(diskio.noinit.cache_pool)
  56. #endif
  57. struct diskio_cache_context diskio_cache __aligned(4);
  58. static struct diskio_cache_item *_diskio_find_cache_item(struct disk_info *disk, DWORD sector, UINT count)
  59. {
  60. struct diskio_cache_item *cache_item = NULL;
  61. u8_t cace_sector_cnt = DISKIO_CACHE_POOL_SIZE / disk->sector_size;
  62. for (int i = 0; i < DISKIO_CACHE_POOL_NUM; i++) {
  63. if (diskio_cache.cache_pool[i].cache_sector <= sector
  64. && diskio_cache.cache_pool[i].disk == disk
  65. && diskio_cache.cache_pool[i].cache_sector + cace_sector_cnt >= sector + count
  66. && diskio_cache.cache_pool[i].cache_valid == 1){
  67. cache_item = &diskio_cache.cache_pool[i];
  68. }
  69. }
  70. return cache_item;
  71. }
  72. static int _diskio_cache_invalid(const char *pdrv, struct disk_info *disk, DWORD sector, UINT count)
  73. {
  74. struct diskio_cache_item *cache_item = NULL;
  75. u8_t cace_sector_cnt = DISKIO_CACHE_POOL_SIZE / disk->sector_size;
  76. u8_t cache_index = 0;
  77. for (int i = 0; i < DISKIO_CACHE_POOL_NUM; i++) {
  78. if (diskio_cache.cache_pool[i].cache_sector + cace_sector_cnt >= sector
  79. && diskio_cache.cache_pool[i].cache_sector < sector + count
  80. && diskio_cache.cache_pool[i].disk == disk
  81. && diskio_cache.cache_pool[i].cache_valid == 1){
  82. cache_item = &diskio_cache.cache_pool[i];
  83. if (cache_item->write_valid) {
  84. if (disk_access_write(pdrv, cache_item->cache_data, cache_item->cache_sector,
  85. cace_sector_cnt)) {
  86. SYS_LOG_ERR("sector %d len %d\n", cache_item->cache_sector, cace_sector_cnt);
  87. }
  88. }
  89. cache_item->cache_valid = 0;
  90. cache_item->write_valid = 0;
  91. cache_index = i;
  92. }
  93. }
  94. return cache_index;
  95. }
  96. static struct diskio_cache_item *_diskio_new_cache_item(const char *pdrv, struct disk_info *disk, DWORD sector)
  97. {
  98. struct diskio_cache_item *cache_item = NULL;
  99. u8_t cace_sector_cnt = DISKIO_CACHE_POOL_SIZE / disk->sector_size;
  100. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  101. cache_item = &diskio_cache.cache_pool[diskio_cache.cache_index++];
  102. diskio_cache.cache_index = diskio_cache.cache_index % DISKIO_CACHE_POOL_NUM;
  103. if (cache_item->write_valid && cache_item->cache_valid) {
  104. if (disk_access_write(pdrv, cache_item->cache_data, cache_item->cache_sector,
  105. cace_sector_cnt)) {
  106. SYS_LOG_ERR("sector %d len %d\n", cache_item->cache_sector, cace_sector_cnt);
  107. }
  108. }
  109. cache_item->cache_valid = 1;
  110. cache_item->cache_sector = sector;
  111. cache_item->disk = disk;
  112. cache_item->write_valid = 0;
  113. cache_item->err_flag = 0;
  114. cache_item->busy_flag = 0;
  115. os_mutex_unlock(&diskio_cache_mutex);
  116. return cache_item;
  117. }
  118. static int _diskio_load_to_cache_req(const char *pdrv, struct disk_info *disk, DWORD sector)
  119. {
  120. struct diskio_cache_req cache_req;
  121. memset(&cache_req, 0, sizeof(cache_req));
  122. os_sem_init(&cache_req.req_sem, 0, 1);
  123. cache_req.pdrv = pdrv;
  124. cache_req.req_disk = disk;
  125. cache_req.req_sector = sector;
  126. cache_req.req_type = REQ_LOAD;
  127. cache_req.req_priority = k_thread_priority_get(k_current_get());
  128. os_fifo_put(&diskio_cache.cache_req_fifo, &cache_req);
  129. if (os_sem_take(&cache_req.req_sem, DISKIO_TIMEOUT) == -EAGAIN) {
  130. SYS_LOG_ERR("timeout");
  131. return -EAGAIN;
  132. }
  133. return 0;
  134. }
  135. static int _diskio_flush_cache_req(const char *pdrv)
  136. {
  137. struct disk_info *disk = disk_access_get_di(pdrv);
  138. if ((disk == NULL) || (disk->ops == NULL))
  139. return -EINVAL;
  140. struct diskio_cache_req cache_req;
  141. memset(&cache_req, 0, sizeof(cache_req));
  142. os_sem_init(&cache_req.req_sem, 0, 1);
  143. cache_req.pdrv = pdrv;
  144. cache_req.req_disk = disk;
  145. cache_req.req_type = REQ_FLUSH;
  146. os_fifo_put(&diskio_cache.cache_req_fifo, &cache_req);
  147. if (os_sem_take(&cache_req.req_sem, DISKIO_TIMEOUT) == -EAGAIN) {
  148. SYS_LOG_ERR("timeout");
  149. return -EAGAIN;
  150. }
  151. return 0;
  152. }
  153. static void _diskio_cache_timeout_flush(void)
  154. {
  155. int ret = 0;
  156. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  157. for (int i = 0; i < DISKIO_CACHE_POOL_NUM; i++) {
  158. if (diskio_cache.cache_pool[i].cache_valid == 1
  159. && diskio_cache.cache_pool[i].write_valid == 1){
  160. struct diskio_cache_item *cache_item = &diskio_cache.cache_pool[i];
  161. ret = disk_access_write(cache_item->pdrv, cache_item->cache_data,
  162. cache_item->cache_sector,
  163. DISKIO_CACHE_POOL_SIZE / cache_item->disk->sector_size);
  164. if (ret) {
  165. SYS_LOG_ERR("sector %d len %d\n", cache_item->cache_sector, DISKIO_CACHE_POOL_SIZE);
  166. } else {
  167. cache_item->write_valid = 0;
  168. }
  169. printk("diskio cache timeout flush\n");
  170. }
  171. }
  172. os_mutex_unlock(&diskio_cache_mutex);
  173. }
  174. int diskio_cache_read(
  175. const char *pdrv,
  176. BYTE *buff, /* Data buffer to store read data */
  177. DWORD sector, /* Start sector in LBA */
  178. UINT count /* Number of sectors to read */)
  179. {
  180. int ret = 0;
  181. struct diskio_cache_item *cache_item = NULL;
  182. struct disk_info *disk = disk_access_get_di(pdrv);
  183. int cache_index = 0;
  184. if ((disk == NULL) || (disk->ops == NULL))
  185. return -EINVAL;
  186. if (!diskio_cache.inited) {
  187. return disk_access_read(pdrv, buff, sector, count);
  188. }
  189. if (DISKIO_DIRECT_READ || (count * disk->sector_size >= DISKIO_CACHE_POOL_SIZE)) {
  190. cache_index = _diskio_cache_invalid(pdrv, disk, sector, count);
  191. return disk_access_read(pdrv, buff, sector, count);
  192. }
  193. try_to_read:
  194. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  195. cache_item = _diskio_find_cache_item(disk, sector, count);
  196. /**cache hit */
  197. if (cache_item) {
  198. cache_item->busy_flag = 1;
  199. if (!cache_item->err_flag) {
  200. memcpy(buff, cache_item->cache_data
  201. + (sector - cache_item->cache_sector) * disk->sector_size,
  202. count * disk->sector_size);
  203. ret = 0;
  204. } else {
  205. cache_item->cache_valid = 0;
  206. ret = -EIO;
  207. }
  208. cache_item->busy_flag = 0;
  209. }
  210. os_mutex_unlock(&diskio_cache_mutex);
  211. /**cache miss */
  212. if (!cache_item) {
  213. _diskio_load_to_cache_req(pdrv, disk, sector);
  214. goto try_to_read;
  215. }
  216. return ret;
  217. }
  218. int diskio_cache_write(
  219. const char *pdrv,
  220. const BYTE *buff, /* Data to be written */
  221. DWORD sector, /* Start sector in LBA */
  222. UINT count /* Number of sectors to write */)
  223. {
  224. int ret = 0;
  225. struct diskio_cache_item *cache_item = NULL;
  226. struct disk_info *disk = disk_access_get_di(pdrv);
  227. int cache_index = 0;
  228. if ((disk == NULL) || (disk->ops == NULL))
  229. return -EINVAL;
  230. if (!diskio_cache.inited) {
  231. return disk_access_write(pdrv, buff, sector, count);
  232. }
  233. if (count * disk->sector_size > DISKIO_CACHE_POOL_SIZE) {
  234. cache_index = _diskio_cache_invalid(pdrv, disk, sector, count);
  235. return disk_access_write(pdrv, buff, sector, count);
  236. }
  237. try_to_write:
  238. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  239. cache_item = _diskio_find_cache_item(disk, sector, count);
  240. /**cache hit */
  241. if (cache_item) {
  242. cache_item->busy_flag = 1;
  243. if (!cache_item->err_flag) {
  244. memcpy(cache_item->cache_data
  245. + (sector - cache_item->cache_sector) * disk->sector_size,
  246. buff, count * disk->sector_size);
  247. cache_item->write_valid = 1;
  248. cache_item->pdrv = pdrv;
  249. ret = 0;
  250. } else {
  251. cache_item->cache_valid = 0;
  252. ret = -EIO;
  253. }
  254. cache_item->busy_flag = 0;
  255. }
  256. os_mutex_unlock(&diskio_cache_mutex);
  257. /**cache miss */
  258. if (!cache_item) {
  259. _diskio_load_to_cache_req(pdrv, disk, sector);
  260. goto try_to_write;
  261. }
  262. return ret;
  263. }
  264. int diskio_cache_flush(const char *pdrv)
  265. {
  266. return _diskio_flush_cache_req(pdrv);
  267. }
  268. int diskio_cache_invalid(const char *pdrv)
  269. {
  270. struct diskio_cache_item *cache_item = NULL;
  271. struct disk_info *disk = disk_access_get_di(pdrv);
  272. if ((disk == NULL) || (disk->ops == NULL))
  273. return -EINVAL;
  274. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  275. for (int i = 0; i < DISKIO_CACHE_POOL_NUM; i++) {
  276. if (diskio_cache.cache_pool[i].disk == disk
  277. && diskio_cache.cache_pool[i].cache_valid == 1) {
  278. cache_item = &diskio_cache.cache_pool[i];
  279. cache_item->cache_valid = 0;
  280. cache_item->write_valid = 0;
  281. }
  282. }
  283. os_mutex_unlock(&diskio_cache_mutex);
  284. return 0;
  285. }
  286. static void _diskio_cache_thread_loop(void *p1, void *p2, void *p3)
  287. {
  288. int ret = 0;
  289. struct diskio_cache_context *diskio_cache_ctx = (struct diskio_cache_context *)p1;
  290. while (!diskio_cache_ctx->terminal) {
  291. struct diskio_cache_req *cache_req = NULL;
  292. struct diskio_cache_item *cache_item = NULL;
  293. struct disk_info *disk = NULL;
  294. cache_req = os_fifo_get(&diskio_cache.cache_req_fifo, CONFIG_DISKIO_CACHE_TIMEOUT);
  295. if (!cache_req) {
  296. _diskio_cache_timeout_flush();
  297. continue;
  298. }
  299. os_mutex_lock(&diskio_cache_mutex, OS_FOREVER);
  300. if (cache_req->req_priority < DISKIO_DEFAULT_PRIORITY){
  301. k_thread_priority_set(k_current_get(), cache_req->req_priority > 0 ? cache_req->req_priority - 1:0);
  302. }
  303. switch (cache_req->req_type) {
  304. case REQ_LOAD:
  305. {
  306. cache_item = _diskio_new_cache_item(cache_req->pdrv, cache_req->req_disk, cache_req->req_sector);
  307. disk = cache_req->req_disk;
  308. if (cache_item) {
  309. ret = disk_access_read(cache_req->pdrv, cache_item->cache_data, cache_req->req_sector,
  310. DISKIO_CACHE_POOL_SIZE / disk->sector_size);
  311. if (ret) {
  312. cache_item->err_flag = 1;
  313. }
  314. cache_item->cache_valid = 1;
  315. }
  316. break;
  317. }
  318. case REQ_FLUSH:
  319. {
  320. for (int i = 0; i < DISKIO_CACHE_POOL_NUM; i++) {
  321. if (diskio_cache.cache_pool[i].disk == cache_req->req_disk
  322. && diskio_cache.cache_pool[i].cache_valid == 1
  323. && diskio_cache.cache_pool[i].write_valid == 1) {
  324. cache_item = &diskio_cache.cache_pool[i];
  325. disk = cache_req->req_disk;
  326. ret = disk_access_write(cache_req->pdrv, cache_item->cache_data,
  327. cache_item->cache_sector,
  328. DISKIO_CACHE_POOL_SIZE / disk->sector_size);
  329. if (ret) {
  330. SYS_LOG_ERR("sector %d len %d\n", cache_item->cache_sector, DISKIO_CACHE_POOL_SIZE);
  331. } else {
  332. cache_item->write_valid = 0;
  333. }
  334. }
  335. }
  336. break;
  337. }
  338. default:
  339. break;
  340. }
  341. os_sem_give(&cache_req->req_sem);
  342. if (cache_req->req_priority < DISKIO_DEFAULT_PRIORITY) {
  343. k_thread_priority_set(k_current_get(),DISKIO_DEFAULT_PRIORITY);
  344. }
  345. os_mutex_unlock(&diskio_cache_mutex);
  346. }
  347. }
  348. int diskio_cache_init(const struct device *unused)
  349. {
  350. ARG_UNUSED(unused);
  351. memset(&diskio_cache, 0, sizeof(struct diskio_cache_context));
  352. os_fifo_init(&diskio_cache.cache_req_fifo);
  353. diskio_cache.thread_id = os_thread_create((char *)diskio_cache_thread_stack,
  354. DISKIO_CACHE_STACK_SIZE,
  355. _diskio_cache_thread_loop,
  356. &diskio_cache, NULL, NULL,
  357. DISKIO_DEFAULT_PRIORITY,
  358. 0, OS_NO_WAIT);
  359. os_thread_name_set((struct k_thread *)diskio_cache.thread_id, "diskio_cache");
  360. diskio_cache.inited = 1;
  361. return 0;
  362. }
  363. int diskio_cache_deinit(void)
  364. {
  365. memset(&diskio_cache, 0, sizeof(struct diskio_cache_item));
  366. return 0;
  367. }
  368. SYS_INIT(diskio_cache_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);