spiffs_nucleus.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  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. // visitor result, continue searching
  117. #define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
  118. // visitor result, continue searching after reloading lu buffer
  119. #define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
  120. // visitor result, stop searching
  121. #define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
  122. // updating an object index contents
  123. #define SPIFFS_EV_IX_UPD (0)
  124. // creating a new object index
  125. #define SPIFFS_EV_IX_NEW (1)
  126. // deleting an object index
  127. #define SPIFFS_EV_IX_DEL (2)
  128. // moving an object index without updating contents
  129. #define SPIFFS_EV_IX_MOV (3)
  130. // updating an object index header data only, not the table itself
  131. #define SPIFFS_EV_IX_UPD_HDR (4)
  132. #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
  133. #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
  134. #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
  135. #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
  136. #if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
  137. /* For GCC, clang and TI compilers */
  138. #define SPIFFS_PACKED __attribute__((packed))
  139. #elif defined(__ICCARM__) || defined(__CC_ARM)
  140. /* For IAR ARM and Keil MDK-ARM compilers */
  141. #define SPIFFS_PACKED
  142. #else
  143. /* Unknown compiler */
  144. #define SPIFFS_PACKED
  145. #endif
  146. #if SPIFFS_USE_MAGIC
  147. #if !SPIFFS_USE_MAGIC_LENGTH
  148. #define SPIFFS_MAGIC(fs, bix) \
  149. ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
  150. #else // SPIFFS_USE_MAGIC_LENGTH
  151. #define SPIFFS_MAGIC(fs, bix) \
  152. ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
  153. #endif // SPIFFS_USE_MAGIC_LENGTH
  154. #endif // SPIFFS_USE_MAGIC
  155. #define SPIFFS_CONFIG_MAGIC (0x20090315)
  156. #if SPIFFS_SINGLETON == 0
  157. #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
  158. ((fs)->cfg.log_page_size)
  159. #define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
  160. ((fs)->cfg.log_block_size)
  161. #define SPIFFS_CFG_PHYS_SZ(fs) \
  162. ((fs)->cfg.phys_size)
  163. #define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
  164. ((fs)->cfg.phys_erase_block)
  165. #define SPIFFS_CFG_PHYS_ADDR(fs) \
  166. ((fs)->cfg.phys_addr)
  167. #endif
  168. // total number of pages
  169. #define SPIFFS_MAX_PAGES(fs) \
  170. ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  171. // total number of pages per block, including object lookup pages
  172. #define SPIFFS_PAGES_PER_BLOCK(fs) \
  173. ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  174. // number of object lookup pages per block
  175. #define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
  176. (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
  177. // checks if page index belongs to object lookup
  178. #define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
  179. (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
  180. // number of object lookup entries in all object lookup pages
  181. #define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
  182. (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
  183. // converts a block to physical address
  184. #define SPIFFS_BLOCK_TO_PADDR(fs, block) \
  185. ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
  186. // converts a object lookup entry to page index
  187. #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
  188. ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
  189. // converts a object lookup entry to physical address of corresponding page
  190. #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
  191. (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  192. // converts a page to physical address
  193. #define SPIFFS_PAGE_TO_PADDR(fs, page) \
  194. ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  195. // converts a physical address to page
  196. #define SPIFFS_PADDR_TO_PAGE(fs, addr) \
  197. ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  198. // gives index in page for a physical address
  199. #define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
  200. ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
  201. // returns containing block for given page
  202. #define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
  203. ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
  204. // returns starting page for block
  205. #define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
  206. ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
  207. // converts page to entry in object lookup page
  208. #define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
  209. ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
  210. // returns data size in a data page
  211. #define SPIFFS_DATA_PAGE_SIZE(fs) \
  212. ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
  213. // returns physical address for block's erase count,
  214. // always in the physical last entry of the last object lookup page
  215. #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
  216. ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
  217. // returns physical address for block's magic,
  218. // always in the physical second last entry of the last object lookup page
  219. #define SPIFFS_MAGIC_PADDR(fs, bix) \
  220. ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
  221. // checks if there is any room for magic in the object luts
  222. #define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
  223. ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
  224. <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
  225. // define helpers object
  226. // entries in an object header page index
  227. #define SPIFFS_OBJ_HDR_IX_LEN(fs) \
  228. ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
  229. // entries in an object page index
  230. #define SPIFFS_OBJ_IX_LEN(fs) \
  231. ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
  232. // object index entry for given data span index
  233. #define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
  234. ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
  235. // object index span index number for given data span index or entry
  236. #define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
  237. ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
  238. // get data span index for object index span index
  239. #define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \
  240. ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) )
  241. #if SPIFFS_FILEHDL_OFFSET
  242. #define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
  243. #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
  244. #else
  245. #define SPIFFS_FH_OFFS(fs, fh) ((spiffs_file)(fh))
  246. #define SPIFFS_FH_UNOFFS(fs, fh) ((spiffs_file)(fh))
  247. #endif
  248. #define SPIFFS_OP_T_OBJ_LU (0<<0)
  249. #define SPIFFS_OP_T_OBJ_LU2 (1<<0)
  250. #define SPIFFS_OP_T_OBJ_IX (2<<0)
  251. #define SPIFFS_OP_T_OBJ_DA (3<<0)
  252. #define SPIFFS_OP_C_DELE (0<<2)
  253. #define SPIFFS_OP_C_UPDT (1<<2)
  254. #define SPIFFS_OP_C_MOVS (2<<2)
  255. #define SPIFFS_OP_C_MOVD (3<<2)
  256. #define SPIFFS_OP_C_FLSH (4<<2)
  257. #define SPIFFS_OP_C_READ (5<<2)
  258. #define SPIFFS_OP_C_WRTHRU (6<<2)
  259. #define SPIFFS_OP_TYPE_MASK (3<<0)
  260. #define SPIFFS_OP_COM_MASK (7<<2)
  261. // if 0, this page is written to, else clean
  262. #define SPIFFS_PH_FLAG_USED (1<<0)
  263. // if 0, writing is finalized, else under modification
  264. #define SPIFFS_PH_FLAG_FINAL (1<<1)
  265. // if 0, this is an index page, else a data page
  266. #define SPIFFS_PH_FLAG_INDEX (1<<2)
  267. // if 0, page is deleted, else valid
  268. #define SPIFFS_PH_FLAG_DELET (1<<7)
  269. // if 0, this index header is being deleted
  270. #define SPIFFS_PH_FLAG_IXDELE (1<<6)
  271. #define SPIFFS_CHECK_MOUNT(fs) \
  272. ((fs)->mounted != 0)
  273. #define SPIFFS_CHECK_CFG(fs) \
  274. ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
  275. #define SPIFFS_CHECK_RES(res) \
  276. do { \
  277. if ((res) < SPIFFS_OK) return (res); \
  278. } while (0);
  279. #define SPIFFS_API_CHECK_MOUNT(fs) \
  280. if (!SPIFFS_CHECK_MOUNT((fs))) { \
  281. (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
  282. return SPIFFS_ERR_NOT_MOUNTED; \
  283. }
  284. #define SPIFFS_API_CHECK_CFG(fs) \
  285. if (!SPIFFS_CHECK_CFG((fs))) { \
  286. (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
  287. return SPIFFS_ERR_NOT_CONFIGURED; \
  288. }
  289. #define SPIFFS_API_CHECK_RES(fs, res) \
  290. if ((res) < SPIFFS_OK) { \
  291. (fs)->err_code = (res); \
  292. return (res); \
  293. }
  294. #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
  295. if ((res) < SPIFFS_OK) { \
  296. (fs)->err_code = (res); \
  297. SPIFFS_UNLOCK(fs); \
  298. return (res); \
  299. }
  300. #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
  301. if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
  302. if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
  303. if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
  304. if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
  305. if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
  306. if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
  307. //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
  308. #define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
  309. if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
  310. if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
  311. if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
  312. if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
  313. if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
  314. if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
  315. // check id, only visit matching objec ids
  316. #define SPIFFS_VIS_CHECK_ID (1<<0)
  317. // report argument object id to visitor - else object lookup id is reported
  318. #define SPIFFS_VIS_CHECK_PH (1<<1)
  319. // stop searching at end of all look up pages
  320. #define SPIFFS_VIS_NO_WRAP (1<<2)
  321. #if SPIFFS_HAL_CALLBACK_EXTRA
  322. #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
  323. (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
  324. #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
  325. (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
  326. #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
  327. (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
  328. #else // SPIFFS_HAL_CALLBACK_EXTRA
  329. #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
  330. (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
  331. #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
  332. (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
  333. #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
  334. (_fs)->cfg.hal_erase_f((_paddr), (_len))
  335. #endif // SPIFFS_HAL_CALLBACK_EXTRA
  336. #if SPIFFS_CACHE
  337. #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
  338. #define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
  339. #define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
  340. #define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
  341. #define SPIFFS_CACHE_FLAG_DATA (1<<4)
  342. #define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
  343. #define SPIFFS_CACHE_PAGE_SIZE(fs) \
  344. (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
  345. #define spiffs_get_cache(fs) \
  346. ((spiffs_cache *)((fs)->cache))
  347. #define spiffs_get_cache_page_hdr(fs, c, ix) \
  348. ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
  349. #define spiffs_get_cache_page(fs, c, ix) \
  350. ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
  351. // cache page struct
  352. typedef struct {
  353. // cache flags
  354. u8_t flags;
  355. // cache page index
  356. u8_t ix;
  357. // last access of this cache page
  358. u32_t last_access;
  359. union {
  360. // type read cache
  361. struct {
  362. // read cache page index
  363. spiffs_page_ix pix;
  364. };
  365. #if SPIFFS_CACHE_WR
  366. // type write cache
  367. struct {
  368. // write cache
  369. spiffs_obj_id obj_id;
  370. // offset in cache page
  371. u32_t offset;
  372. // size of cache page
  373. u16_t size;
  374. };
  375. #endif
  376. };
  377. } spiffs_cache_page;
  378. // cache struct
  379. typedef struct {
  380. u8_t cpage_count;
  381. u32_t last_access;
  382. u32_t cpage_use_map;
  383. u32_t cpage_use_mask;
  384. u8_t *cpages;
  385. } spiffs_cache;
  386. #endif
  387. // spiffs nucleus file descriptor
  388. typedef struct {
  389. // the filesystem of this descriptor
  390. spiffs *fs;
  391. // number of file descriptor - if 0, the file descriptor is closed
  392. spiffs_file file_nbr;
  393. // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
  394. spiffs_obj_id obj_id;
  395. // size of the file
  396. u32_t size;
  397. // cached object index header page index
  398. spiffs_page_ix objix_hdr_pix;
  399. // cached offset object index page index
  400. spiffs_page_ix cursor_objix_pix;
  401. // cached offset object index span index
  402. spiffs_span_ix cursor_objix_spix;
  403. // current absolute offset
  404. u32_t offset;
  405. // current file descriptor offset (cached)
  406. u32_t fdoffset;
  407. // fd flags
  408. spiffs_flags flags;
  409. #if SPIFFS_CACHE_WR
  410. spiffs_cache_page *cache_page;
  411. #endif
  412. #if SPIFFS_TEMPORAL_FD_CACHE
  413. // djb2 hash of filename
  414. u32_t name_hash;
  415. // hit score (score == 0 indicates never used fd)
  416. u16_t score;
  417. #endif
  418. #if SPIFFS_IX_MAP
  419. // spiffs index map, if 0 it means unmapped
  420. spiffs_ix_map *ix_map;
  421. #endif
  422. } spiffs_fd;
  423. // object structs
  424. // page header, part of each page except object lookup pages
  425. // NB: this is always aligned when the data page is an object index,
  426. // as in this case struct spiffs_page_object_ix is used
  427. typedef struct SPIFFS_PACKED {
  428. // object id
  429. spiffs_obj_id obj_id;
  430. // object span index
  431. spiffs_span_ix span_ix;
  432. // flags
  433. u8_t flags;
  434. } spiffs_page_header;
  435. // object index header page header
  436. typedef struct SPIFFS_PACKED
  437. #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
  438. #ifdef _MSC_VER
  439. __declspec( align( 2 ) ) // must track sizeof(spiffs_page_ix) in spiffs_config.h
  440. #else
  441. __attribute(( aligned(sizeof(spiffs_page_ix)) ))
  442. #endif
  443. #endif
  444. {
  445. // common page header
  446. spiffs_page_header p_hdr;
  447. // alignment
  448. u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
  449. // size of object
  450. u32_t size;
  451. // type of object
  452. spiffs_obj_type type;
  453. // name of object
  454. u8_t name[SPIFFS_OBJ_NAME_LEN];
  455. #if SPIFFS_OBJ_META_LEN
  456. // metadata. not interpreted by SPIFFS in any way.
  457. u8_t meta[SPIFFS_OBJ_META_LEN];
  458. #endif
  459. } spiffs_page_object_ix_header;
  460. // object index page header
  461. typedef struct SPIFFS_PACKED {
  462. spiffs_page_header p_hdr;
  463. u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
  464. } spiffs_page_object_ix;
  465. // callback func for object lookup visitor
  466. typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
  467. const void *user_const_p, void *user_var_p);
  468. #if SPIFFS_CACHE
  469. #define _spiffs_rd(fs, op, fh, addr, len, dst) \
  470. spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
  471. #define _spiffs_wr(fs, op, fh, addr, len, src) \
  472. spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
  473. #else
  474. #define _spiffs_rd(fs, op, fh, addr, len, dst) \
  475. spiffs_phys_rd((fs), (addr), (len), (dst))
  476. #define _spiffs_wr(fs, op, fh, addr, len, src) \
  477. spiffs_phys_wr((fs), (addr), (len), (src))
  478. #endif
  479. #ifndef MIN
  480. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  481. #endif
  482. #ifndef MAX
  483. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  484. #endif
  485. // ---------------
  486. s32_t spiffs_phys_rd(
  487. spiffs *fs,
  488. #if SPIFFS_CACHE
  489. u8_t op,
  490. spiffs_file fh,
  491. #endif
  492. u32_t addr,
  493. u32_t len,
  494. u8_t *dst);
  495. s32_t spiffs_phys_wr(
  496. spiffs *fs,
  497. #if SPIFFS_CACHE
  498. u8_t op,
  499. spiffs_file fh,
  500. #endif
  501. u32_t addr,
  502. u32_t len,
  503. u8_t *src);
  504. s32_t spiffs_phys_cpy(
  505. spiffs *fs,
  506. spiffs_file fh,
  507. u32_t dst,
  508. u32_t src,
  509. u32_t len);
  510. s32_t spiffs_phys_count_free_blocks(
  511. spiffs *fs);
  512. s32_t spiffs_obj_lu_find_entry_visitor(
  513. spiffs *fs,
  514. spiffs_block_ix starting_block,
  515. int starting_lu_entry,
  516. u8_t flags,
  517. spiffs_obj_id obj_id,
  518. spiffs_visitor_f v,
  519. const void *user_const_p,
  520. void *user_var_p,
  521. spiffs_block_ix *block_ix,
  522. int *lu_entry);
  523. s32_t spiffs_erase_block(
  524. spiffs *fs,
  525. spiffs_block_ix bix);
  526. #if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
  527. s32_t spiffs_probe(
  528. spiffs_config *cfg);
  529. #endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
  530. // ---------------
  531. s32_t spiffs_obj_lu_scan(
  532. spiffs *fs);
  533. s32_t spiffs_obj_lu_find_free_obj_id(
  534. spiffs *fs,
  535. spiffs_obj_id *obj_id,
  536. const u8_t *conflicting_name);
  537. s32_t spiffs_obj_lu_find_free(
  538. spiffs *fs,
  539. spiffs_block_ix starting_block,
  540. int starting_lu_entry,
  541. spiffs_block_ix *block_ix,
  542. int *lu_entry);
  543. s32_t spiffs_obj_lu_find_id(
  544. spiffs *fs,
  545. spiffs_block_ix starting_block,
  546. int starting_lu_entry,
  547. spiffs_obj_id obj_id,
  548. spiffs_block_ix *block_ix,
  549. int *lu_entry);
  550. s32_t spiffs_obj_lu_find_id_and_span(
  551. spiffs *fs,
  552. spiffs_obj_id obj_id,
  553. spiffs_span_ix spix,
  554. spiffs_page_ix exclusion_pix,
  555. spiffs_page_ix *pix);
  556. s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
  557. spiffs *fs,
  558. spiffs_obj_id obj_id,
  559. spiffs_span_ix spix,
  560. spiffs_page_ix exclusion_pix,
  561. spiffs_page_ix *pix);
  562. // ---------------
  563. s32_t spiffs_page_allocate_data(
  564. spiffs *fs,
  565. spiffs_obj_id obj_id,
  566. spiffs_page_header *ph,
  567. u8_t *data,
  568. u32_t len,
  569. u32_t page_offs,
  570. u8_t finalize,
  571. spiffs_page_ix *pix);
  572. s32_t spiffs_page_move(
  573. spiffs *fs,
  574. spiffs_file fh,
  575. u8_t *page_data,
  576. spiffs_obj_id obj_id,
  577. spiffs_page_header *page_hdr,
  578. spiffs_page_ix src_pix,
  579. spiffs_page_ix *dst_pix);
  580. s32_t spiffs_page_delete(
  581. spiffs *fs,
  582. spiffs_page_ix pix);
  583. // ---------------
  584. s32_t spiffs_object_create(
  585. spiffs *fs,
  586. spiffs_obj_id obj_id,
  587. const u8_t name[],
  588. const u8_t meta[],
  589. spiffs_obj_type type,
  590. spiffs_page_ix *objix_hdr_pix);
  591. s32_t spiffs_object_update_index_hdr(
  592. spiffs *fs,
  593. spiffs_fd *fd,
  594. spiffs_obj_id obj_id,
  595. spiffs_page_ix objix_hdr_pix,
  596. u8_t *new_objix_hdr_data,
  597. const u8_t name[],
  598. const u8_t meta[],
  599. u32_t size,
  600. spiffs_page_ix *new_pix);
  601. #if SPIFFS_IX_MAP
  602. s32_t spiffs_populate_ix_map(
  603. spiffs *fs,
  604. spiffs_fd *fd,
  605. u32_t vec_entry_start,
  606. u32_t vec_entry_end);
  607. #endif
  608. void spiffs_cb_object_event(
  609. spiffs *fs,
  610. spiffs_page_object_ix *objix,
  611. int ev,
  612. spiffs_obj_id obj_id,
  613. spiffs_span_ix spix,
  614. spiffs_page_ix new_pix,
  615. u32_t new_size);
  616. s32_t spiffs_object_open_by_id(
  617. spiffs *fs,
  618. spiffs_obj_id obj_id,
  619. spiffs_fd *f,
  620. spiffs_flags flags,
  621. spiffs_mode mode);
  622. s32_t spiffs_object_open_by_page(
  623. spiffs *fs,
  624. spiffs_page_ix pix,
  625. spiffs_fd *f,
  626. spiffs_flags flags,
  627. spiffs_mode mode);
  628. s32_t spiffs_object_append(
  629. spiffs_fd *fd,
  630. u32_t offset,
  631. u8_t *data,
  632. u32_t len);
  633. s32_t spiffs_object_modify(
  634. spiffs_fd *fd,
  635. u32_t offset,
  636. u8_t *data,
  637. u32_t len);
  638. s32_t spiffs_object_read(
  639. spiffs_fd *fd,
  640. u32_t offset,
  641. u32_t len,
  642. u8_t *dst);
  643. s32_t spiffs_object_truncate(
  644. spiffs_fd *fd,
  645. u32_t new_len,
  646. u8_t remove_object);
  647. s32_t spiffs_object_find_object_index_header_by_name(
  648. spiffs *fs,
  649. const u8_t name[SPIFFS_OBJ_NAME_LEN],
  650. spiffs_page_ix *pix);
  651. // ---------------
  652. s32_t spiffs_gc_check(
  653. spiffs *fs,
  654. u32_t len);
  655. s32_t spiffs_gc_erase_page_stats(
  656. spiffs *fs,
  657. spiffs_block_ix bix);
  658. s32_t spiffs_gc_find_candidate(
  659. spiffs *fs,
  660. spiffs_block_ix **block_candidate,
  661. int *candidate_count,
  662. char fs_crammed);
  663. s32_t spiffs_gc_clean(
  664. spiffs *fs,
  665. spiffs_block_ix bix);
  666. s32_t spiffs_gc_quick(
  667. spiffs *fs, u16_t max_free_pages);
  668. // ---------------
  669. s32_t spiffs_fd_find_new(
  670. spiffs *fs,
  671. spiffs_fd **fd,
  672. const char *name);
  673. s32_t spiffs_fd_return(
  674. spiffs *fs,
  675. spiffs_file f);
  676. s32_t spiffs_fd_get(
  677. spiffs *fs,
  678. spiffs_file f,
  679. spiffs_fd **fd);
  680. #if SPIFFS_TEMPORAL_FD_CACHE
  681. void spiffs_fd_temporal_cache_rehash(
  682. spiffs *fs,
  683. const char *old_path,
  684. const char *new_path);
  685. #endif
  686. #if SPIFFS_CACHE
  687. void spiffs_cache_init(
  688. spiffs *fs);
  689. void spiffs_cache_drop_page(
  690. spiffs *fs,
  691. spiffs_page_ix pix);
  692. #if SPIFFS_CACHE_WR
  693. spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
  694. spiffs *fs,
  695. spiffs_fd *fd);
  696. void spiffs_cache_fd_release(
  697. spiffs *fs,
  698. spiffs_cache_page *cp);
  699. spiffs_cache_page *spiffs_cache_page_get_by_fd(
  700. spiffs *fs,
  701. spiffs_fd *fd);
  702. #endif
  703. #endif
  704. s32_t spiffs_lookup_consistency_check(
  705. spiffs *fs,
  706. u8_t check_all_objects);
  707. s32_t spiffs_page_consistency_check(
  708. spiffs *fs);
  709. s32_t spiffs_object_index_consistency_check(
  710. spiffs *fs);
  711. // memcpy macro,
  712. // checked in test builds, otherwise plain memcpy (unless already defined)
  713. #ifdef _SPIFFS_TEST
  714. #define _SPIFFS_MEMCPY(__d, __s, __l) do { \
  715. intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \
  716. intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \
  717. intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \
  718. intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \
  719. if (__a1 <= __b2 && __b1 <= __a2) { \
  720. printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \
  721. ERREXIT(); \
  722. } \
  723. memcpy((__d),(__s),(__l)); \
  724. } while (0)
  725. #else
  726. #ifndef _SPIFFS_MEMCPY
  727. #define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0)
  728. #endif
  729. #endif //_SPIFFS_TEST
  730. #endif /* SPIFFS_NUCLEUS_H_ */