mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	This provides a limited form of wear leveling. While wear is not actually balanced across blocks, the filesystem can recover from corrupted blocks and extend the lifetime of a device nearly as much as dynamic wear leveling. For use-cases where wear is important, it would be better to use a full form of dynamic wear-leveling at the block level. (or consider a logging filesystem). Corrupted block handling was simply added on top of the existing logic in place for the filesystem, so it's a bit more noodly than it may have to be, but it gets the work done.
		
			
				
	
	
		
			106 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /// AUTOGENERATED TEST ///
 | |
| #include "lfs.h"
 | |
| #include "emubd/lfs_emubd.h"
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| 
 | |
| // test stuff
 | |
| void test_log(const char *s, uintmax_t v) {{
 | |
|     printf("%s: %jd\n", s, v);
 | |
| }}
 | |
| 
 | |
| void test_assert(const char *file, unsigned line,
 | |
|         const char *s, uintmax_t v, uintmax_t e) {{
 | |
|     static const char *last[6] = {{0, 0}};
 | |
|     if (v != e || !(last[0] == s || last[1] == s ||
 | |
|             last[2] == s || last[3] == s ||
 | |
|             last[4] == s || last[5] == s)) {{
 | |
|         test_log(s, v);
 | |
|         last[0] = last[1];
 | |
|         last[1] = last[2];
 | |
|         last[2] = last[3];
 | |
|         last[3] = last[4];
 | |
|         last[4] = last[5];
 | |
|         last[5] = s;
 | |
|     }}
 | |
| 
 | |
|     if (v != e) {{
 | |
|         printf("\033[31m%s:%u: assert %s failed, expected %jd\033[0m\n",
 | |
|                 file, line, s, e);
 | |
|         exit(-2);
 | |
|     }}
 | |
| }}
 | |
| 
 | |
| #define test_assert(s, v, e) test_assert(__FILE__, __LINE__, s, v, e)
 | |
| 
 | |
| 
 | |
| // utility functions for traversals
 | |
| int test_count(void *p, lfs_block_t b) {{
 | |
|     unsigned *u = (unsigned*)p;
 | |
|     *u += 1;
 | |
|     return 0;
 | |
| }}
 | |
| 
 | |
| 
 | |
| // lfs declarations
 | |
| lfs_t lfs;
 | |
| lfs_emubd_t bd;
 | |
| lfs_file_t file[4];
 | |
| lfs_dir_t dir[4];
 | |
| struct lfs_info info;
 | |
| 
 | |
| uint8_t buffer[1024];
 | |
| uint8_t wbuffer[1024];
 | |
| uint8_t rbuffer[1024];
 | |
| lfs_size_t size;
 | |
| lfs_size_t wsize;
 | |
| lfs_size_t rsize;
 | |
| 
 | |
| uintmax_t res;
 | |
| 
 | |
| #ifndef LFS_READ_SIZE
 | |
| #define LFS_READ_SIZE 64
 | |
| #endif
 | |
| 
 | |
| #ifndef LFS_PROG_SIZE
 | |
| #define LFS_PROG_SIZE 64
 | |
| #endif
 | |
| 
 | |
| #ifndef LFS_BLOCK_SIZE
 | |
| #define LFS_BLOCK_SIZE 512
 | |
| #endif
 | |
| 
 | |
| #ifndef LFS_BLOCK_COUNT
 | |
| #define LFS_BLOCK_COUNT 1024
 | |
| #endif
 | |
| 
 | |
| #ifndef LFS_LOOKAHEAD
 | |
| #define LFS_LOOKAHEAD 128
 | |
| #endif
 | |
| 
 | |
| const struct lfs_config cfg = {{
 | |
|     .context = &bd,
 | |
|     .read  = &lfs_emubd_read,
 | |
|     .prog  = &lfs_emubd_prog,
 | |
|     .erase = &lfs_emubd_erase,
 | |
|     .sync  = &lfs_emubd_sync,
 | |
| 
 | |
|     .read_size   = LFS_READ_SIZE,
 | |
|     .prog_size   = LFS_PROG_SIZE,
 | |
|     .block_size  = LFS_BLOCK_SIZE,
 | |
|     .block_count = LFS_BLOCK_COUNT,
 | |
|     .lookahead   = LFS_LOOKAHEAD,
 | |
| }};
 | |
| 
 | |
| 
 | |
| // Entry point
 | |
| int main() {{
 | |
|     lfs_emubd_create(&cfg, "blocks");
 | |
| 
 | |
| {tests}
 | |
| 
 | |
|     lfs_emubd_destroy(&cfg);
 | |
| }}
 |