Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

798 righe
24 KiB

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