4 * Created on: Jun 15, 2013
10 * spiffs is designed for following spi flash characteristics:
11 * - only big areas of data (blocks) can be erased
12 * - erasing resets all bits in a block to ones
13 * - writing pulls ones to zeroes
14 * - zeroes cannot be pulled to ones, without erase
17 * spiffs is also meant to be run on embedded, memory constraint devices.
19 * Entire area is divided in blocks. Entire area is also divided in pages.
20 * Each block contains same number of pages. A page cannot be erased, but a
21 * block can be erased.
23 * Entire area must be block_size * x
24 * page_size must be block_size / (2^y) where y > 2
26 * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
28 * BLOCK 0 PAGE 0 object lookup 1
29 * PAGE 1 object lookup 2
31 * PAGE n-1 object lookup n
32 * PAGE n object data 1
33 * PAGE n+1 object data 2
35 * PAGE n+m-1 object data m
37 * BLOCK 1 PAGE n+m object lookup 1
38 * PAGE n+m+1 object lookup 2
40 * PAGE 2n+m-1 object lookup n
41 * PAGE 2n+m object data 1
42 * PAGE 2n+m object data 2
44 * PAGE 2n+2m-1 object data m
47 * n is number of object lookup pages, which is number of pages needed to index all pages
48 * in a block by object id
49 * : block_size / page_size * sizeof(obj_id) / page_size
50 * m is number data pages, which is number of pages in block minus number of lookup pages
51 * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
52 * thus, n+m is total number of pages in a block
53 * : block_size / page_size
55 * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
57 * Object lookup pages contain object id entries. Each entry represent the corresponding
59 * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
60 * An object id being 0x0000 represents a deleted page.
62 * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
63 * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
64 * page 2 : data : data for object id 0008
65 * page 3 : data : data for object id 0001
66 * page 4 : data : data for object id 0aaa
70 * Object data pages can be either object index pages or object content.
71 * All object data pages contains a data page header, containing object id and span index.
72 * The span index denotes the object page ordering amongst data pages with same object id.
73 * This applies to both object index pages (when index spans more than one page of entries),
74 * and object data pages.
75 * An object index page contains page entries pointing to object content page. The entry index
76 * in a object index page correlates to the span index in the actual object data page.
77 * The first object index page (span index 0) is called object index header page, and also
78 * contains object flags (directory/file), size, object name etc.
82 * PAGE 256: objectl lookup page 1
83 * [*123] [ 123] [ 123] [ 123]
84 * [ 123] [*123] [ 123] [ 123]
85 * [free] [free] [free] [free] ...
86 * PAGE 257: objectl lookup page 2
87 * [free] [free] [free] [free] ...
88 * PAGE 258: object index page (header)
89 * obj.id:0123 span.ix:0000 flags:INDEX
90 * size:1600 name:ex.txt type:file
91 * [259] [260] [261] [262]
92 * PAGE 259: object data page
93 * obj.id:0123 span.ix:0000 flags:DATA
94 * PAGE 260: object data page
95 * obj.id:0123 span.ix:0001 flags:DATA
96 * PAGE 261: object data page
97 * obj.id:0123 span.ix:0002 flags:DATA
98 * PAGE 262: object data page
99 * obj.id:0123 span.ix:0003 flags:DATA
100 * PAGE 263: object index page
101 * obj.id:0123 span.ix:0001 flags:INDEX
102 * [264] [265] [fre] [fre]
103 * [fre] [fre] [fre] [fre]
104 * PAGE 264: object data page
105 * obj.id:0123 span.ix:0004 flags:DATA
106 * PAGE 265: object data page
107 * obj.id:0123 span.ix:0005 flags:DATA
110 #ifndef SPIFFS_NUCLEUS_H_
111 #define SPIFFS_NUCLEUS_H_
118 #define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
119 #define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
120 #define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
121 #define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
122 #define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
124 // visitor result, continue searching
125 #define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
126 // visitor result, continue searching after reloading lu buffer
127 #define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
128 // visitor result, stop searching
129 #define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
131 // updating an object index contents
132 #define SPIFFS_EV_IX_UPD (0)
133 // creating a new object index
134 #define SPIFFS_EV_IX_NEW (1)
135 // deleting an object index
136 #define SPIFFS_EV_IX_DEL (2)
137 // moving an object index without updating contents
138 #define SPIFFS_EV_IX_MOV (3)
139 // updating an object index header data only, not the table itself
140 #define SPIFFS_EV_IX_UPD_HDR (4)
142 #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
144 #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
146 #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
147 #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
151 #if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
152 /* For GCC, clang and TI compilers */
153 #define SPIFFS_PACKED __attribute__((packed))
154 #elif defined(__ICCARM__) || defined(__CC_ARM)
155 /* For IAR ARM and Keil MDK-ARM compilers */
156 #define SPIFFS_PACKED
159 /* Unknown compiler */
160 #define SPIFFS_PACKED
166 #if !SPIFFS_USE_MAGIC_LENGTH
167 #define SPIFFS_MAGIC(fs, bix) \
168 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
169 #else // SPIFFS_USE_MAGIC_LENGTH
170 #define SPIFFS_MAGIC(fs, bix) \
171 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
172 #endif // SPIFFS_USE_MAGIC_LENGTH
173 #endif // SPIFFS_USE_MAGIC
175 #define SPIFFS_CONFIG_MAGIC (0x20090315)
177 #if SPIFFS_SINGLETON == 0
178 #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
179 ((fs)->cfg.log_page_size)
180 #define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
181 ((fs)->cfg.log_block_size)
182 #define SPIFFS_CFG_PHYS_SZ(fs) \
183 ((fs)->cfg.phys_size)
184 #define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
185 ((fs)->cfg.phys_erase_block)
186 #define SPIFFS_CFG_PHYS_ADDR(fs) \
187 ((fs)->cfg.phys_addr)
190 // total number of pages
191 #define SPIFFS_MAX_PAGES(fs) \
192 ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
193 // total number of pages per block, including object lookup pages
194 #define SPIFFS_PAGES_PER_BLOCK(fs) \
195 ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
196 // number of object lookup pages per block
197 #define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
198 (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
199 // checks if page index belongs to object lookup
200 #define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
201 (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
202 // number of object lookup entries in all object lookup pages
203 #define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
204 (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
205 // converts a block to physical address
206 #define SPIFFS_BLOCK_TO_PADDR(fs, block) \
207 ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
208 // converts a object lookup entry to page index
209 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
210 ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
211 // converts a object lookup entry to physical address of corresponding page
212 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
213 (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
214 // converts a page to physical address
215 #define SPIFFS_PAGE_TO_PADDR(fs, page) \
216 ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
217 // converts a physical address to page
218 #define SPIFFS_PADDR_TO_PAGE(fs, addr) \
219 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
220 // gives index in page for a physical address
221 #define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
222 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
223 // returns containing block for given page
224 #define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
225 ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
226 // returns starting page for block
227 #define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
228 ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
229 // converts page to entry in object lookup page
230 #define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
231 ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
232 // returns data size in a data page
233 #define SPIFFS_DATA_PAGE_SIZE(fs) \
234 ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
235 // returns physical address for block's erase count,
236 // always in the physical last entry of the last object lookup page
237 #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
238 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
239 // returns physical address for block's magic,
240 // always in the physical second last entry of the last object lookup page
241 #define SPIFFS_MAGIC_PADDR(fs, bix) \
242 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
243 // checks if there is any room for magic in the object luts
244 #define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
245 ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
246 <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
248 // define helpers object
250 // entries in an object header page index
251 #define SPIFFS_OBJ_HDR_IX_LEN(fs) \
252 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
253 // entries in an object page index
254 #define SPIFFS_OBJ_IX_LEN(fs) \
255 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
256 // object index entry for given data span index
257 #define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
258 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
259 // object index span index number for given data span index or entry
260 #define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
261 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
262 // get data span index for object index span index
263 #define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \
264 ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) )
266 #if SPIFFS_FILEHDL_OFFSET
267 #define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
268 #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
270 #define SPIFFS_FH_OFFS(fs, fh) (fh)
271 #define SPIFFS_FH_UNOFFS(fs, fh) (fh)
275 #define SPIFFS_OP_T_OBJ_LU (0<<0)
276 #define SPIFFS_OP_T_OBJ_LU2 (1<<0)
277 #define SPIFFS_OP_T_OBJ_IX (2<<0)
278 #define SPIFFS_OP_T_OBJ_DA (3<<0)
279 #define SPIFFS_OP_C_DELE (0<<2)
280 #define SPIFFS_OP_C_UPDT (1<<2)
281 #define SPIFFS_OP_C_MOVS (2<<2)
282 #define SPIFFS_OP_C_MOVD (3<<2)
283 #define SPIFFS_OP_C_FLSH (4<<2)
284 #define SPIFFS_OP_C_READ (5<<2)
285 #define SPIFFS_OP_C_WRTHRU (6<<2)
287 #define SPIFFS_OP_TYPE_MASK (3<<0)
288 #define SPIFFS_OP_COM_MASK (7<<2)
291 // if 0, this page is written to, else clean
292 #define SPIFFS_PH_FLAG_USED (1<<0)
293 // if 0, writing is finalized, else under modification
294 #define SPIFFS_PH_FLAG_FINAL (1<<1)
295 // if 0, this is an index page, else a data page
296 #define SPIFFS_PH_FLAG_INDEX (1<<2)
297 // if 0, page is deleted, else valid
298 #define SPIFFS_PH_FLAG_DELET (1<<7)
299 // if 0, this index header is being deleted
300 #define SPIFFS_PH_FLAG_IXDELE (1<<6)
303 #define SPIFFS_CHECK_MOUNT(fs) \
306 #define SPIFFS_CHECK_CFG(fs) \
307 ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
309 #define SPIFFS_CHECK_RES(res) \
311 if ((res) < SPIFFS_OK) return (res); \
314 #define SPIFFS_API_CHECK_MOUNT(fs) \
315 if (!SPIFFS_CHECK_MOUNT((fs))) { \
316 (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
317 return SPIFFS_ERR_NOT_MOUNTED; \
320 #define SPIFFS_API_CHECK_CFG(fs) \
321 if (!SPIFFS_CHECK_CFG((fs))) { \
322 (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
323 return SPIFFS_ERR_NOT_CONFIGURED; \
326 #define SPIFFS_API_CHECK_RES(fs, res) \
327 if ((res) < SPIFFS_OK) { \
328 (fs)->err_code = (res); \
332 #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
333 if ((res) < SPIFFS_OK) { \
334 (fs)->err_code = (res); \
339 #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
340 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
341 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
342 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
343 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
344 if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
345 if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
346 //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
348 #define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
349 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
350 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
351 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
352 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
353 if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
354 if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
357 // check id, only visit matching objec ids
358 #define SPIFFS_VIS_CHECK_ID (1<<0)
359 // report argument object id to visitor - else object lookup id is reported
360 #define SPIFFS_VIS_CHECK_PH (1<<1)
361 // stop searching at end of all look up pages
362 #define SPIFFS_VIS_NO_WRAP (1<<2)
364 #if SPIFFS_HAL_CALLBACK_EXTRA
366 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
367 (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
368 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
369 (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
370 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
371 (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
373 #else // SPIFFS_HAL_CALLBACK_EXTRA
375 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
376 (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
377 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
378 (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
379 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
380 (_fs)->cfg.hal_erase_f((_paddr), (_len))
382 #endif // SPIFFS_HAL_CALLBACK_EXTRA
386 #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
387 #define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
388 #define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
389 #define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
390 #define SPIFFS_CACHE_FLAG_DATA (1<<4)
391 #define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
393 #define SPIFFS_CACHE_PAGE_SIZE(fs) \
394 (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
396 #define spiffs_get_cache(fs) \
397 ((spiffs_cache *)((fs)->cache))
399 #define spiffs_get_cache_page_hdr(fs, c, ix) \
400 ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
402 #define spiffs_get_cache_page(fs, c, ix) \
403 ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
411 // last access of this cache page
416 // read cache page index
423 spiffs_obj_id obj_id
;
424 // offset in cache page
426 // size of cache page
438 u32_t cpage_use_mask
;
445 // spiffs nucleus file descriptor
447 // the filesystem of this descriptor
449 // number of file descriptor - if 0, the file descriptor is closed
450 spiffs_file file_nbr
;
451 // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
452 spiffs_obj_id obj_id
;
455 // cached object index header page index
456 spiffs_page_ix objix_hdr_pix
;
457 // cached offset object index page index
458 spiffs_page_ix cursor_objix_pix
;
459 // cached offset object index span index
460 spiffs_span_ix cursor_objix_spix
;
461 // current absolute offset
463 // current file descriptor offset (cached)
468 spiffs_cache_page
*cache_page
;
470 #if SPIFFS_TEMPORAL_FD_CACHE
471 // djb2 hash of filename
473 // hit score (score == 0 indicates never used fd)
477 // spiffs index map, if 0 it means unmapped
478 spiffs_ix_map
*ix_map
;
485 // page header, part of each page except object lookup pages
486 // NB: this is always aligned when the data page is an object index,
487 // as in this case struct spiffs_page_object_ix is used
488 typedef struct SPIFFS_PACKED
{
490 spiffs_obj_id obj_id
;
492 spiffs_span_ix span_ix
;
495 } spiffs_page_header
;
497 // object index header page header
498 typedef struct SPIFFS_PACKED
499 #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
500 __attribute((aligned(sizeof(spiffs_page_ix
))))
503 // common page header
504 spiffs_page_header p_hdr
;
506 u8_t _align
[4 - ((sizeof(spiffs_page_header
) & 3) == 0 ? 4 : (sizeof(spiffs_page_header
) & 3))];
510 spiffs_obj_type type
;
512 u8_t name
[SPIFFS_OBJ_NAME_LEN
];
513 #if SPIFFS_OBJ_META_LEN
514 // metadata. not interpreted by SPIFFS in any way.
515 u8_t meta
[SPIFFS_OBJ_META_LEN
];
518 spiffs_page_object_ix_header
;
520 // object index page header
521 typedef struct SPIFFS_PACKED
{
522 spiffs_page_header p_hdr
;
523 u8_t _align
[4 - ((sizeof(spiffs_page_header
) & 3) == 0 ? 4 : (sizeof(spiffs_page_header
) & 3))];
524 } spiffs_page_object_ix
;
526 // callback func for object lookup visitor
527 typedef s32_t (*spiffs_visitor_f
)(spiffs
*fs
, spiffs_obj_id id
, spiffs_block_ix bix
, int ix_entry
,
528 const void *user_const_p
, void *user_var_p
);
532 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
533 spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
534 #define _spiffs_wr(fs, op, fh, addr, len, src) \
535 spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
537 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
538 spiffs_phys_rd((fs), (addr), (len), (dst))
539 #define _spiffs_wr(fs, op, fh, addr, len, src) \
540 spiffs_phys_wr((fs), (addr), (len), (src))
544 #define MIN(a,b) ((a) < (b) ? (a) : (b))
547 #define MAX(a,b) ((a) > (b) ? (a) : (b))
552 s32_t
spiffs_phys_rd(
562 s32_t
spiffs_phys_wr(
572 s32_t
spiffs_phys_cpy(
579 s32_t
spiffs_phys_count_free_blocks(
582 s32_t
spiffs_obj_lu_find_entry_visitor(
584 spiffs_block_ix starting_block
,
585 int starting_lu_entry
,
587 spiffs_obj_id obj_id
,
589 const void *user_const_p
,
591 spiffs_block_ix
*block_ix
,
594 s32_t
spiffs_erase_block(
596 spiffs_block_ix bix
);
598 #if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
601 #endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
605 s32_t
spiffs_obj_lu_scan(
608 s32_t
spiffs_obj_lu_find_free_obj_id(
610 spiffs_obj_id
*obj_id
,
611 const u8_t
*conflicting_name
);
613 s32_t
spiffs_obj_lu_find_free(
615 spiffs_block_ix starting_block
,
616 int starting_lu_entry
,
617 spiffs_block_ix
*block_ix
,
620 s32_t
spiffs_obj_lu_find_id(
622 spiffs_block_ix starting_block
,
623 int starting_lu_entry
,
624 spiffs_obj_id obj_id
,
625 spiffs_block_ix
*block_ix
,
628 s32_t
spiffs_obj_lu_find_id_and_span(
630 spiffs_obj_id obj_id
,
632 spiffs_page_ix exclusion_pix
,
633 spiffs_page_ix
*pix
);
635 s32_t
spiffs_obj_lu_find_id_and_span_by_phdr(
637 spiffs_obj_id obj_id
,
639 spiffs_page_ix exclusion_pix
,
640 spiffs_page_ix
*pix
);
644 s32_t
spiffs_page_allocate_data(
646 spiffs_obj_id obj_id
,
647 spiffs_page_header
*ph
,
652 spiffs_page_ix
*pix
);
654 s32_t
spiffs_page_move(
658 spiffs_obj_id obj_id
,
659 spiffs_page_header
*page_hdr
,
660 spiffs_page_ix src_pix
,
661 spiffs_page_ix
*dst_pix
);
663 s32_t
spiffs_page_delete(
669 s32_t
spiffs_object_create(
671 spiffs_obj_id obj_id
,
674 spiffs_obj_type type
,
675 spiffs_page_ix
*objix_hdr_pix
);
677 s32_t
spiffs_object_update_index_hdr(
680 spiffs_obj_id obj_id
,
681 spiffs_page_ix objix_hdr_pix
,
682 u8_t
*new_objix_hdr_data
,
686 spiffs_page_ix
*new_pix
);
690 s32_t
spiffs_populate_ix_map(
693 u32_t vec_entry_start
,
694 u32_t vec_entry_end
);
698 void spiffs_cb_object_event(
700 spiffs_page_object_ix
*objix
,
702 spiffs_obj_id obj_id_raw
,
704 spiffs_page_ix new_pix
,
707 s32_t
spiffs_object_open_by_id(
709 spiffs_obj_id obj_id
,
714 s32_t
spiffs_object_open_by_page(
721 s32_t
spiffs_object_append(
727 s32_t
spiffs_object_modify(
733 s32_t
spiffs_object_read(
739 s32_t
spiffs_object_truncate(
744 s32_t
spiffs_object_find_object_index_header_by_name(
746 const u8_t name
[SPIFFS_OBJ_NAME_LEN
],
747 spiffs_page_ix
*pix
);
751 s32_t
spiffs_gc_check(
755 s32_t
spiffs_gc_erase_page_stats(
757 spiffs_block_ix bix
);
759 s32_t
spiffs_gc_find_candidate(
761 spiffs_block_ix
**block_candidates
,
762 int *candidate_count
,
765 s32_t
spiffs_gc_clean(
767 spiffs_block_ix bix
);
769 s32_t
spiffs_gc_quick(
770 spiffs
*fs
, u16_t max_free_pages
);
774 s32_t
spiffs_fd_find_new(
779 s32_t
spiffs_fd_return(
788 #if SPIFFS_TEMPORAL_FD_CACHE
789 void spiffs_fd_temporal_cache_rehash(
791 const char *old_path
,
792 const char *new_path
);
796 void spiffs_cache_init(
799 void spiffs_cache_drop_page(
804 spiffs_cache_page
*spiffs_cache_page_allocate_by_fd(
808 void spiffs_cache_fd_release(
810 spiffs_cache_page
*cp
);
812 spiffs_cache_page
*spiffs_cache_page_get_by_fd(
818 s32_t
spiffs_lookup_consistency_check(
820 u8_t check_all_objects
);
822 s32_t
spiffs_page_consistency_check(
825 s32_t
spiffs_object_index_consistency_check(
829 // checked in test builds, otherwise plain memcpy (unless already defined)
831 #define _SPIFFS_MEMCPY(__d, __s, __l) do { \
832 intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \
833 intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \
834 intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \
835 intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \
836 if (__a1 <= __b2 && __b1 <= __a2) { \
837 printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \
840 memcpy((__d),(__s),(__l)); \
843 #ifndef _SPIFFS_MEMCPY
844 #define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0)
846 #endif //_SPIFFS_TEST
848 #endif /* SPIFFS_NUCLEUS_H_ */