1、文件类型
// File types
enum lfs_type {
// file types
LFS_TYPE_REG = 0x001,
LFS_TYPE_DIR = 0x002,
// internally used types
LFS_TYPE_SPLICE = 0x400,
LFS_TYPE_NAME = 0x000,
LFS_TYPE_STRUCT = 0x200,
LFS_TYPE_USERATTR = 0x300,
LFS_TYPE_FROM = 0x100,
LFS_TYPE_TAIL = 0x600,
LFS_TYPE_GLOBALS = 0x700,
LFS_TYPE_CRC = 0x500,
// internally used type specializations
LFS_TYPE_CREATE = 0x401,
LFS_TYPE_DELETE = 0x4ff,
LFS_TYPE_SUPERBLOCK = 0x0ff,
LFS_TYPE_DIRSTRUCT = 0x200,
LFS_TYPE_CTZSTRUCT = 0x202,
LFS_TYPE_INLINESTRUCT = 0x201,
LFS_TYPE_SOFTTAIL = 0x600,
LFS_TYPE_HARDTAIL = 0x601,
LFS_TYPE_MOVESTATE = 0x7ff,
// internal chip sources
LFS_FROM_NOOP = 0x000,
LFS_FROM_MOVE = 0x101,
LFS_FROM_USERATTRS = 0x102,
};
2、文件打开时的标志
// File open flags
enum lfs_open_flags {
// open flags
LFS_O_RDONLY = 1, // Open a file as read only
LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
// internally used flags
LFS_F_DIRTY = 0x010000, // File does not match storage
LFS_F_WRITING = 0x020000, // File has been written since last flush
LFS_F_READING = 0x040000, // File has been read since last flush
LFS_F_ERRED = 0x080000, // An error occured during write
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
LFS_F_OPENED = 0x200000, // File has been opened
};
3、文件seek时的标志
// File seek flags
enum lfs_whence_flags {
LFS_SEEK_SET = 0, // Seek relative to an absolute position
LFS_SEEK_CUR = 1, // Seek relative to the current file position
LFS_SEEK_END = 2, // Seek relative to the end of the file
};
4、lfs的配置参数
// Configuration provided during initialization of the littlefs
struct lfs_config {
// Opaque user provided context that can be used to pass
// information to the block device operations
/* 这个参数主要是传递给block驱动代码 */
void *context;
/* 从设备读数据 */
int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);
/* 向设备写入数据,block设备在写入前必须已经erase了 */
int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
/* 擦除block */
int (*erase)(const struct lfs_config *c, lfs_block_t block);
/* sync块设备的状态 */
int (*sync)(const struct lfs_config *c);
/* 最小的读取单元大小 */
lfs_size_t read_size;
/* 最小的写入数据单元大小,也是数据metadata pair中tag的对齐尺寸 */
lfs_size_t prog_size;
/* 最小的擦除单元大小。可以比flash的实际block尺寸大。但是对于ctz类型的文件,block size是最小的分配单元。同时block size必须是
read size和program size的倍数,block size会存储在superblock中 */
lfs_size_t block_size;
/* 属于文件系统的block数量,block count会存储在superblock中 */
lfs_size_t block_count;
/* 文件系统进行垃圾回收时的block的擦除次数,推荐取值100-1000.值越大垃圾回收的次数越少,性能越好 */
int32_t block_cycles;
/* littlefs需要一个read cache,一个program cache,每个文件也需要一个cache。cache越大性能越好,会减少会flash的访问次数,
cache必须是block的read size和program size的倍数,同时是block size的因数 */
lfs_size_t cache_size;
/* lookahead buffer的尺寸。lookahead buffer主要是block alloctor在分配块的时候用到。lookahead size必须是8的倍数,
因为它是采用bitmap的形式存储的 */
lfs_size_t lookahead_size;
/* cache size大小的read buffer,可以静态分配也可以动态分配 */
void *read_buffer;
/* cache size大小的program buffer,可以静态分配也可以动态分配 */
void *prog_buffer;
/* lookahead_size大小的lookahead buffer,且是32-bit对齐的,即可以静态分配也可以动态分配 */
void *lookahead_buffer;
/* 文件名的最大长度,这个值会存储在superblock中 */
lfs_size_t name_max;
/* 文件的最大长度,存储在superblock中 */
lfs_size_t file_max;
/* 用户属性的最大长度 */
lfs_size_t attr_max;
};
5、文件信息
// File info structure
struct lfs_info {
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR 普通文件或者目录
uint8_t type;
// Size of the file, only valid for REG files. Limited to 32-bits. 对于普通文件才有意义
lfs_size_t size;
// Name of the file stored as a null-terminated string. Limited to
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
// respected by other littlefs drivers.
/* 字符串形式的文件名 */
char name[LFS_NAME_MAX+1];
};
6、用户属性
struct lfs_attr {
/* 属性类型 */
uint8_t type;
/* 存储属性的buffer */
void *buffer;
/* 属性的长度,最大值为LFS_ATTR_MAX */
lfs_size_t size;
};
7、文件open时的配置
struct lfs_file_config {
/* cache size长度的buffer,可以静态分配也可以动态分配 */
void *buffer;
/* 用户属性,读文件时,attr存储从flash上读取的文件用户属性,写入文件时,attr存放用户指定的文件属性并会写入到flash中 */
struct lfs_attr *attrs;
/* 用户属性的长度 */
lfs_size_t attr_count;
};
8、lfs_cache结构
typedef struct lfs_cache {
lfs_block_t block; // cache中的数据属于的block
lfs_off_t off; // cache中的数据在block上的偏移地址
lfs_size_t size; // cache的大小
uint8_t *buffer; // cache数据的存放地址
} lfs_cache_t;
9、lfs_mdir结构,代表metadata pair,dir本身所在的block
typedef struct lfs_mdir {
lfs_block_t pair[2]; // dir的metadata pair所在的block
uint32_t rev; // metadata pair的revision
lfs_off_t off; // tag的偏移地址
uint32_t etag;
uint16_t count;
bool erased;
bool split; // metadata pair是否是链表
lfs_block_t tail[2]; // 用于metadata pair链表
} lfs_mdir_t;
10、lfs目录结构
// littlefs directory type
typedef struct lfs_dir {
struct lfs_dir *next; // 指向子目录
uint16_t id;
uint8_t type; // LFS_TYPE_DIR
lfs_mdir_t m; // 代表dir的metadata pair
lfs_off_t pos; // 在目录中的当前位置,主要用在seek,tell和rewind操作中
lfs_block_t head[2];
} lfs_dir_t;
11、lfs文件类型
// littlefs file type
typedef struct lfs_file {
struct lfs_file *next;
uint16_t id; // metadata tag中的id,在文件open时获取
uint8_t type; // LFS_TYPE_REG 或者 LFS_TYPE_DIR
lfs_mdir_t m; // 文件所在的目录的metadata pair
struct lfs_ctz {
lfs_block_t head;
lfs_size_t size;
} ctz; // 指向大文件的CTZ skip-list。对于小文件则直接inline了,无需CTZ skip-list
uint32_t flags; // lfs_open_flags中的值
lfs_off_t pos; // 文件访问时的偏移
lfs_block_t block; // file当前的block
lfs_off_t off; // 在block内的offset
lfs_cache_t cache; // 文件访问时的cache
const struct lfs_file_config *cfg; // 文件open时的配置参数,包含一个buffer以及用户属性
} lfs_file_t;
12、lfs superblock结构
typedef struct lfs_superblock {
uint32_t version; // 文件系统的版本号
lfs_size_t block_size; // 文件系统的block size,和flash的block size不一定相同
lfs_size_t block_count; // 文件系统包含的block数量,每个block的大小等于上面的block size
lfs_size_t name_max; // 文件名的最大长度
lfs_size_t file_max; // 文件的最大长度
lfs_size_t attr_max; // 用户属性的最大长度
} lfs_superblock_t;
13、lfs文件系统类型结构
// The littlefs filesystem type
typedef struct lfs {
lfs_cache_t rcache; // read cache
lfs_cache_t pcache; // program cache
lfs_block_t root[2]; // 根目录所在的block
struct lfs_mlist {
struct lfs_mlist *next; // 指向下一个节点
uint16_t id; // metadata pair的id
uint8_t type; // metadata pair的类型
lfs_mdir_t m; // metadata pair
} *mlist; // metadata pair list
uint32_t seed; // block alloctor的随机数生成的seed
struct lfs_gstate {
uint32_t tag;
lfs_block_t pair[2];
} gstate, gpending, gdelta; // 用于目录操作sync的global state,
struct lfs_free {
lfs_block_t off; // 记录lookahead buffer中起始block的偏移
lfs_block_t size; // lookahead buffer中block的数量,注意lookahead采用的是bitmap的形式,因此size=8*lookahead_size
lfs_block_t i; // lookahead buffer内部的偏移地址
lfs_block_t ack; // 剩余block的数量,初始值为block count,如果该值为0,表示已经没有free block了
uint32_t *buffer; // buffer的长度为lookahead size
} free; // lookahead buffer,用于分配free block
const struct lfs_config *cfg; // 文件系统的配置参数
lfs_size_t name_max; // 文件名的最大长度,和superblock中的name_max值相同
lfs_size_t file_max; // 文件的最大长度,和superblock中的file_max值相同
lfs_size_t attr_max; // 用户属性的最大长度,和superblock中的attr_max值相同
} lfs_t;