spiffs_nucleus.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /*
  2. * spiffs_nucleus.h
  3. *
  4. * Created on: Jun 15, 2013
  5. * Author: petera
  6. */
  7. /* SPIFFS layout
  8. *
  9. * spiffs is designed for following spi flash characteristics:
  10. * - only big areas of data (blocks) can be erased
  11. * - erasing resets all bits in a block to ones
  12. * - writing pulls ones to zeroes
  13. * - zeroes cannot be pulled to ones, without erase
  14. * - wear leveling
  15. *
  16. * spiffs is also meant to be run on embedded, memory constraint devices.
  17. *
  18. * Entire area is divided in blocks. Entire area is also divided in pages.
  19. * Each block contains same number of pages. A page cannot be erased, but a
  20. * block can be erased.
  21. *
  22. * Entire area must be block_size * x
  23. * page_size must be block_size / (2^y) where y > 2
  24. *
  25. * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
  26. *
  27. * BLOCK 0 PAGE 0 object lookup 1
  28. * PAGE 1 object lookup 2
  29. * ...
  30. * PAGE n-1 object lookup n
  31. * PAGE n object data 1
  32. * PAGE n+1 object data 2
  33. * ...
  34. * PAGE n+m-1 object data m
  35. *
  36. * BLOCK 1 PAGE n+m object lookup 1
  37. * PAGE n+m+1 object lookup 2
  38. * ...
  39. * PAGE 2n+m-1 object lookup n
  40. * PAGE 2n+m object data 1
  41. * PAGE 2n+m object data 2
  42. * ...
  43. * PAGE 2n+2m-1 object data m
  44. * ...
  45. *
  46. * n is number of object lookup pages, which is number of pages needed to index all pages
  47. * in a block by object id
  48. * : block_size / page_size * sizeof(obj_id) / page_size
  49. * m is number data pages, which is number of pages in block minus number of lookup pages
  50. * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
  51. * thus, n+m is total number of pages in a block
  52. * : block_size / page_size
  53. *
  54. * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
  55. *
  56. * Object lookup pages contain object id entries. Each entry represent the corresponding
  57. * data page.
  58. * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
  59. * An object id being 0x0000 represents a deleted page.
  60. *
  61. * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
  62. * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
  63. * page 2 : data : data for object id 0008
  64. * page 3 : data : data for object id 0001
  65. * page 4 : data : data for object id 0aaa
  66. * ...
  67. *
  68. *
  69. * Object data pages can be either object index pages or object content.
  70. * All object data pages contains a data page header, containing object id and span index.
  71. * The span index denotes the object page ordering amongst data pages with same object id.
  72. * This applies to both object index pages (when index spans more than one page of entries),
  73. * and object data pages.
  74. * An object index page contains page entries pointing to object content page. The entry index
  75. * in a object index page correlates to the span index in the actual object data page.
  76. * The first object index page (span index 0) is called object index header page, and also
  77. * contains object flags (directory/file), size, object name etc.
  78. *
  79. * ex:
  80. * BLOCK 1
  81. * PAGE 256: objectl lookup page 1
  82. * [*123] [ 123] [ 123] [ 123]
  83. * [ 123] [*123] [ 123] [ 123]
  84. * [free] [free] [free] [free] ...
  85. * PAGE 257: objectl lookup page 2
  86. * [free] [free] [free] [free] ...
  87. * PAGE 258: object index page (header)
  88. * obj.id:0123 span.ix:0000 flags:INDEX
  89. * size:1600 name:ex.txt type:file
  90. * [259] [260] [261] [262]
  91. * PAGE 259: object data page
  92. * obj.id:0123 span.ix:0000 flags:DATA
  93. * PAGE 260: object data page
  94. * obj.id:0123 span.ix:0001 flags:DATA
  95. * PAGE 261: object data page
  96. * obj.id:0123 span.ix:0002 flags:DATA
  97. * PAGE 262: object data page
  98. * obj.id:0123 span.ix:0003 flags:DATA
  99. * PAGE 263: object index page
  100. * obj.id:0123 span.ix:0001 flags:INDEX
  101. * [264] [265] [fre] [fre]
  102. * [fre] [fre] [fre] [fre]
  103. * PAGE 264: object data page
  104. * obj.id:0123 span.ix:0004 flags:DATA
  105. * PAGE 265: object data page
  106. * obj.id:0123 span.ix:0005 flags:DATA
  107. *
  108. */
  109. #ifndef SPIFFS_NUCLEUS_H_
  110. #define SPIFFS_NUCLEUS_H_
  111. #define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
  112. #define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
  113. #define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
  114. #define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
  115. #define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
  116. #define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
  117. #define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
  118. #define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
  119. #define SPIFFS_EV_IX_UPD 0
  120. #define SPIFFS_EV_IX_NEW 1
  121. #define SPIFFS_EV_IX_DEL 2
  122. #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
  123. #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
  124. #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
  125. #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
  126. #if SPIFFS_USE_MAGIC
  127. #if !SPIFFS_USE_MAGIC_LENGTH
  128. #define SPIFFS_MAGIC(fs, bix) \
  129. ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
  130. #else // SPIFFS_USE_MAGIC_LENGTH
  131. #define SPIFFS_MAGIC(fs, bix) \
  132. ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
  133. #endif // SPIFFS_USE_MAGIC_LENGTH
  134. #endif // SPIFFS_USE_MAGIC
  135. #define SPIFFS_CONFIG_MAGIC (0x20090315)
  136. #if SPIFFS_SINGLETON == 0
  137. #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
  138. ((fs)->cfg.log_page_size)
  139. #define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
  140. ((fs)->cfg.log_block_size)
  141. #define SPIFFS_CFG_PHYS_SZ(fs) \
  142. ((fs)->cfg.phys_size)
  143. #define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
  144. ((fs)->cfg.phys_erase_block)
  145. #define SPIFFS_CFG_PHYS_ADDR(fs) \
  146. ((fs)->cfg.phys_addr)
  147. #endif
  148. // total number of pages
  149. #define SPIFFS_MAX_PAGES(fs) \
  150. ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  151. // total number of pages per block, including object lookup pages
  152. #define SPIFFS_PAGES_PER_BLOCK(fs) \
  153. ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  154. // number of object lookup pages per block
  155. #define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
  156. (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
  157. // checks if page index belongs to object lookup
  158. #define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
  159. (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
  160. // number of object lookup entries in all object lookup pages
  161. #define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
  162. (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
  163. // converts a block to physical address
  164. #define SPIFFS_BLOCK_TO_PADDR(fs, block) \
  165. ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
  166. // converts a object lookup entry to page index
  167. #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
  168. ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
  169. // converts a object lookup entry to physical address of corresponding page
  170. #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
  171. (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  172. // converts a page to physical address
  173. #define SPIFFS_PAGE_TO_PADDR(fs, page) \
  174. ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  175. // converts a physical address to page
  176. #define SPIFFS_PADDR_TO_PAGE(fs, addr) \
  177. ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  178. // gives index in page for a physical address
  179. #define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
  180. ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  181. // returns containing block for given page
  182. #define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
  183. ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
  184. // returns starting page for block
  185. #define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
  186. ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
  187. // converts page to entry in object lookup page
  188. #define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
  189. ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
  190. // returns data size in a data page
  191. #define SPIFFS_DATA_PAGE_SIZE(fs) \
  192. ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
  193. // returns physical address for block's erase count,
  194. // always in the physical last entry of the last object lookup page
  195. #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
  196. ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
  197. // returns physical address for block's magic,
  198. // always in the physical second last entry of the last object lookup page
  199. #define SPIFFS_MAGIC_PADDR(fs, bix) \
  200. ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
  201. // checks if there is any room for magic in the object luts
  202. #define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
  203. ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
  204. <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
  205. // define helpers object
  206. // entries in an object header page index
  207. #define SPIFFS_OBJ_HDR_IX_LEN(fs) \
  208. ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
  209. // entries in an object page index
  210. #define SPIFFS_OBJ_IX_LEN(fs) \
  211. ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
  212. // object index entry for given data span index
  213. #define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
  214. ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
  215. // object index span index number for given data span index or entry
  216. #define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
  217. ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
  218. #define SPIFFS_OP_T_OBJ_LU (0<<0)
  219. #define SPIFFS_OP_T_OBJ_LU2 (1<<0)
  220. #define SPIFFS_OP_T_OBJ_IX (2<<0)
  221. #define SPIFFS_OP_T_OBJ_DA (3<<0)
  222. #define SPIFFS_OP_C_DELE (0<<2)
  223. #define SPIFFS_OP_C_UPDT (1<<2)
  224. #define SPIFFS_OP_C_MOVS (2<<2)
  225. #define SPIFFS_OP_C_MOVD (3<<2)
  226. #define SPIFFS_OP_C_FLSH (4<<2)
  227. #define SPIFFS_OP_C_READ (5<<2)
  228. #define SPIFFS_OP_C_WRTHRU (6<<2)
  229. #define SPIFFS_OP_TYPE_MASK (3<<0)
  230. #define SPIFFS_OP_COM_MASK (7<<2)
  231. // if 0, this page is written to, else clean
  232. #define SPIFFS_PH_FLAG_USED (1<<0)
  233. // if 0, writing is finalized, else under modification
  234. #define SPIFFS_PH_FLAG_FINAL (1<<1)
  235. // if 0, this is an index page, else a data page
  236. #define SPIFFS_PH_FLAG_INDEX (1<<2)
  237. // if 0, page is deleted, else valid
  238. #define SPIFFS_PH_FLAG_DELET (1<<7)
  239. // if 0, this index header is being deleted
  240. #define SPIFFS_PH_FLAG_IXDELE (1<<6)
  241. #define SPIFFS_CHECK_MOUNT(fs) \
  242. ((fs)->mounted != 0)
  243. #define SPIFFS_CHECK_CFG(fs) \
  244. ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
  245. #define SPIFFS_CHECK_RES(res) \
  246. do { \
  247. if ((res) < SPIFFS_OK) return (res); \
  248. } while (0);
  249. #define SPIFFS_API_CHECK_MOUNT(fs) \
  250. if (!SPIFFS_CHECK_MOUNT((fs))) { \
  251. (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
  252. return SPIFFS_ERR_NOT_MOUNTED; \
  253. }
  254. #define SPIFFS_API_CHECK_CFG(fs) \
  255. if (!SPIFFS_CHECK_CFG((fs))) { \
  256. (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
  257. return SPIFFS_ERR_NOT_CONFIGURED; \
  258. }
  259. #define SPIFFS_API_CHECK_RES(fs, res) \
  260. if ((res) < SPIFFS_OK) { \
  261. (fs)->err_code = (res); \
  262. return (res); \
  263. }
  264. #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
  265. if ((res) < SPIFFS_OK) { \
  266. (fs)->err_code = (res); \
  267. SPIFFS_UNLOCK(fs); \
  268. return (res); \
  269. }
  270. #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
  271. if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
  272. if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
  273. if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
  274. if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
  275. if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
  276. if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
  277. //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
  278. #define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
  279. if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
  280. if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
  281. if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
  282. if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
  283. if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
  284. if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
  285. // check id
  286. #define SPIFFS_VIS_CHECK_ID (1<<0)
  287. // report argument object id to visitor - else object lookup id is reported
  288. #define SPIFFS_VIS_CHECK_PH (1<<1)
  289. // stop searching at end of all look up pages
  290. #define SPIFFS_VIS_NO_WRAP (1<<2)
  291. #if SPIFFS_HAL_CALLBACK_EXTRA
  292. #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
  293. (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
  294. #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
  295. (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
  296. #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
  297. (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
  298. #else // SPIFFS_HAL_CALLBACK_EXTRA
  299. #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
  300. (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
  301. #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
  302. (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
  303. #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
  304. (_fs)->cfg.hal_erase_f((_paddr), (_len))
  305. #endif // SPIFFS_HAL_CALLBACK_EXTRA
  306. #if SPIFFS_CACHE
  307. #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
  308. #define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
  309. #define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
  310. #define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
  311. #define SPIFFS_CACHE_FLAG_DATA (1<<4)
  312. #define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
  313. #define SPIFFS_CACHE_PAGE_SIZE(fs) \
  314. (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
  315. #define spiffs_get_cache(fs) \
  316. ((spiffs_cache *)((fs)->cache))
  317. #define spiffs_get_cache_page_hdr(fs, c, ix) \
  318. ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
  319. #define spiffs_get_cache_page(fs, c, ix) \
  320. ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
  321. // cache page struct
  322. typedef struct {
  323. // cache flags
  324. u8_t flags;
  325. // cache page index
  326. u8_t ix;
  327. // last access of this cache page
  328. u32_t last_access;
  329. union {
  330. // type read cache
  331. struct {
  332. // read cache page index
  333. spiffs_page_ix pix;
  334. };
  335. #if SPIFFS_CACHE_WR
  336. // type write cache
  337. struct {
  338. // write cache
  339. spiffs_obj_id obj_id;
  340. // offset in cache page
  341. u32_t offset;
  342. // size of cache page
  343. u16_t size;
  344. };
  345. #endif
  346. };
  347. } spiffs_cache_page;
  348. // cache struct
  349. typedef struct {
  350. u8_t cpage_count;
  351. u32_t last_access;
  352. u32_t cpage_use_map;
  353. u32_t cpage_use_mask;
  354. u8_t *cpages;
  355. } spiffs_cache;
  356. #endif
  357. // spiffs nucleus file descriptor
  358. typedef struct {
  359. // the filesystem of this descriptor
  360. spiffs *fs;
  361. // number of file descriptor - if 0, the file descriptor is closed
  362. spiffs_file file_nbr;
  363. // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
  364. spiffs_obj_id obj_id;
  365. // size of the file
  366. u32_t size;
  367. // cached object index header page index
  368. spiffs_page_ix objix_hdr_pix;
  369. // cached offset object index page index
  370. spiffs_page_ix cursor_objix_pix;
  371. // cached offset object index span index
  372. spiffs_span_ix cursor_objix_spix;
  373. // current absolute offset
  374. u32_t offset;
  375. // current file descriptor offset
  376. u32_t fdoffset;
  377. // fd flags
  378. spiffs_flags flags;
  379. #if SPIFFS_CACHE_WR
  380. spiffs_cache_page *cache_page;
  381. #endif
  382. } spiffs_fd;
  383. // object structs
  384. // page header, part of each page except object lookup pages
  385. // NB: this is always aligned when the data page is an object index,
  386. // as in this case struct spiffs_page_object_ix is used
  387. typedef struct __attribute(( packed )) {
  388. // object id
  389. spiffs_obj_id obj_id;
  390. // object span index
  391. spiffs_span_ix span_ix;
  392. // flags
  393. u8_t flags;
  394. } spiffs_page_header;
  395. // object index header page header
  396. typedef struct __attribute(( packed ))
  397. #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
  398. __attribute(( aligned(sizeof(spiffs_page_ix)) ))
  399. #endif
  400. {
  401. // common page header
  402. spiffs_page_header p_hdr;
  403. // alignment
  404. u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
  405. // size of object
  406. u32_t size;
  407. // type of object
  408. spiffs_obj_type type;
  409. // name of object
  410. u8_t name[SPIFFS_OBJ_NAME_LEN];
  411. } spiffs_page_object_ix_header;
  412. // object index page header
  413. typedef struct __attribute(( packed )) {
  414. spiffs_page_header p_hdr;
  415. u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
  416. } spiffs_page_object_ix;
  417. // callback func for object lookup visitor
  418. typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
  419. const void *user_const_p, void *user_var_p);
  420. #if SPIFFS_CACHE
  421. #define _spiffs_rd(fs, op, fh, addr, len, dst) \
  422. spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
  423. #define _spiffs_wr(fs, op, fh, addr, len, src) \
  424. spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
  425. #else
  426. #define _spiffs_rd(fs, op, fh, addr, len, dst) \
  427. spiffs_phys_rd((fs), (addr), (len), (dst))
  428. #define _spiffs_wr(fs, op, fh, addr, len, src) \
  429. spiffs_phys_wr((fs), (addr), (len), (src))
  430. #endif
  431. #ifndef MIN
  432. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  433. #endif
  434. #ifndef MAX
  435. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  436. #endif
  437. // ---------------
  438. s32_t spiffs_phys_rd(
  439. spiffs *fs,
  440. #if SPIFFS_CACHE
  441. u8_t op,
  442. spiffs_file fh,
  443. #endif
  444. u32_t addr,
  445. u32_t len,
  446. u8_t *dst);
  447. s32_t spiffs_phys_wr(
  448. spiffs *fs,
  449. #if SPIFFS_CACHE
  450. u8_t op,
  451. spiffs_file fh,
  452. #endif
  453. u32_t addr,
  454. u32_t len,
  455. u8_t *src);
  456. s32_t spiffs_phys_cpy(
  457. spiffs *fs,
  458. spiffs_file fh,
  459. u32_t dst,
  460. u32_t src,
  461. u32_t len);
  462. s32_t spiffs_phys_count_free_blocks(
  463. spiffs *fs);
  464. s32_t spiffs_obj_lu_find_entry_visitor(
  465. spiffs *fs,
  466. spiffs_block_ix starting_block,
  467. int starting_lu_entry,
  468. u8_t flags,
  469. spiffs_obj_id obj_id,
  470. spiffs_visitor_f v,
  471. const void *user_const_p,
  472. void *user_var_p,
  473. spiffs_block_ix *block_ix,
  474. int *lu_entry);
  475. s32_t spiffs_erase_block(
  476. spiffs *fs,
  477. spiffs_block_ix bix);
  478. #if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
  479. s32_t spiffs_probe(
  480. spiffs_config *cfg);
  481. #endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
  482. // ---------------
  483. s32_t spiffs_obj_lu_scan(
  484. spiffs *fs);
  485. s32_t spiffs_obj_lu_find_free_obj_id(
  486. spiffs *fs,
  487. spiffs_obj_id *obj_id,
  488. const u8_t *conflicting_name);
  489. s32_t spiffs_obj_lu_find_free(
  490. spiffs *fs,
  491. spiffs_block_ix starting_block,
  492. int starting_lu_entry,
  493. spiffs_block_ix *block_ix,
  494. int *lu_entry);
  495. s32_t spiffs_obj_lu_find_id(
  496. spiffs *fs,
  497. spiffs_block_ix starting_block,
  498. int starting_lu_entry,
  499. spiffs_obj_id obj_id,
  500. spiffs_block_ix *block_ix,
  501. int *lu_entry);
  502. s32_t spiffs_obj_lu_find_id_and_span(
  503. spiffs *fs,
  504. spiffs_obj_id obj_id,
  505. spiffs_span_ix spix,
  506. spiffs_page_ix exclusion_pix,
  507. spiffs_page_ix *pix);
  508. s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
  509. spiffs *fs,
  510. spiffs_obj_id obj_id,
  511. spiffs_span_ix spix,
  512. spiffs_page_ix exclusion_pix,
  513. spiffs_page_ix *pix);
  514. // ---------------
  515. s32_t spiffs_page_allocate_data(
  516. spiffs *fs,
  517. spiffs_obj_id obj_id,
  518. spiffs_page_header *ph,
  519. u8_t *data,
  520. u32_t len,
  521. u32_t page_offs,
  522. u8_t finalize,
  523. spiffs_page_ix *pix);
  524. s32_t spiffs_page_move(
  525. spiffs *fs,
  526. spiffs_file fh,
  527. u8_t *page_data,
  528. spiffs_obj_id obj_id,
  529. spiffs_page_header *page_hdr,
  530. spiffs_page_ix src_pix,
  531. spiffs_page_ix *dst_pix);
  532. s32_t spiffs_page_delete(
  533. spiffs *fs,
  534. spiffs_page_ix pix);
  535. // ---------------
  536. s32_t spiffs_object_create(
  537. spiffs *fs,
  538. spiffs_obj_id obj_id,
  539. const u8_t name[SPIFFS_OBJ_NAME_LEN],
  540. spiffs_obj_type type,
  541. spiffs_page_ix *objix_hdr_pix);
  542. s32_t spiffs_object_update_index_hdr(
  543. spiffs *fs,
  544. spiffs_fd *fd,
  545. spiffs_obj_id obj_id,
  546. spiffs_page_ix objix_hdr_pix,
  547. u8_t *new_objix_hdr_data,
  548. const u8_t name[SPIFFS_OBJ_NAME_LEN],
  549. u32_t size,
  550. spiffs_page_ix *new_pix);
  551. void spiffs_cb_object_event(
  552. spiffs *fs,
  553. spiffs_fd *fd,
  554. int ev,
  555. spiffs_obj_id obj_id,
  556. spiffs_span_ix spix,
  557. spiffs_page_ix new_pix,
  558. u32_t new_size);
  559. s32_t spiffs_object_open_by_id(
  560. spiffs *fs,
  561. spiffs_obj_id obj_id,
  562. spiffs_fd *f,
  563. spiffs_flags flags,
  564. spiffs_mode mode);
  565. s32_t spiffs_object_open_by_page(
  566. spiffs *fs,
  567. spiffs_page_ix pix,
  568. spiffs_fd *f,
  569. spiffs_flags flags,
  570. spiffs_mode mode);
  571. s32_t spiffs_object_append(
  572. spiffs_fd *fd,
  573. u32_t offset,
  574. u8_t *data,
  575. u32_t len);
  576. s32_t spiffs_object_modify(
  577. spiffs_fd *fd,
  578. u32_t offset,
  579. u8_t *data,
  580. u32_t len);
  581. s32_t spiffs_object_read(
  582. spiffs_fd *fd,
  583. u32_t offset,
  584. u32_t len,
  585. u8_t *dst);
  586. s32_t spiffs_object_truncate(
  587. spiffs_fd *fd,
  588. u32_t new_len,
  589. u8_t remove_object);
  590. s32_t spiffs_object_find_object_index_header_by_name(
  591. spiffs *fs,
  592. const u8_t name[SPIFFS_OBJ_NAME_LEN],
  593. spiffs_page_ix *pix);
  594. // ---------------
  595. s32_t spiffs_gc_check(
  596. spiffs *fs,
  597. u32_t len);
  598. s32_t spiffs_gc_erase_page_stats(
  599. spiffs *fs,
  600. spiffs_block_ix bix);
  601. s32_t spiffs_gc_find_candidate(
  602. spiffs *fs,
  603. spiffs_block_ix **block_candidate,
  604. int *candidate_count,
  605. char fs_crammed);
  606. s32_t spiffs_gc_clean(
  607. spiffs *fs,
  608. spiffs_block_ix bix);
  609. s32_t spiffs_gc_quick(
  610. spiffs *fs, u16_t max_free_pages);
  611. // ---------------
  612. s32_t spiffs_fd_find_new(
  613. spiffs *fs,
  614. spiffs_fd **fd);
  615. s32_t spiffs_fd_return(
  616. spiffs *fs,
  617. spiffs_file f);
  618. s32_t spiffs_fd_get(
  619. spiffs *fs,
  620. spiffs_file f,
  621. spiffs_fd **fd);
  622. #if SPIFFS_CACHE
  623. void spiffs_cache_init(
  624. spiffs *fs);
  625. void spiffs_cache_drop_page(
  626. spiffs *fs,
  627. spiffs_page_ix pix);
  628. #if SPIFFS_CACHE_WR
  629. spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
  630. spiffs *fs,
  631. spiffs_fd *fd);
  632. void spiffs_cache_fd_release(
  633. spiffs *fs,
  634. spiffs_cache_page *cp);
  635. spiffs_cache_page *spiffs_cache_page_get_by_fd(
  636. spiffs *fs,
  637. spiffs_fd *fd);
  638. #endif
  639. #endif
  640. s32_t spiffs_lookup_consistency_check(
  641. spiffs *fs,
  642. u8_t check_all_objects);
  643. s32_t spiffs_page_consistency_check(
  644. spiffs *fs);
  645. s32_t spiffs_object_index_consistency_check(
  646. spiffs *fs);
  647. #endif /* SPIFFS_NUCLEUS_H_ */