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