LittleFS是ARM mbedOS的官方推荐文件系统,具有轻量级、掉电安全的特性。
本着不吐不快的原则,先就个人对LittleFS的使用及移植进行单方面的吐槽,不喜请跳过。
示例如下:
/**
* @brief Mount LFS
*/
static int my_lfs_mount(void)
{
int err = 0;
// Check if block device available
if (hal_blk_probe() < 0) {
LFS_ERROR("ERROR: %s, %d\r\n", __func__, __LINE__);
err = -1;
goto ERR_EXIT;
}
memset(&config, 0, sizeof(config));
config.read = blk_device_read;
config.prog = blk_device_prog;
config.erase = blk_device_erase;
config.sync = blk_device_sync;
config.read_size = hal_blk_get_readsize();
config.prog_size = hal_blk_get_progsize();
config.block_size = hal_blk_get_erasesize();
config.block_count = hal_blk_get_blockcnt();
config.lookahead = ROUND_UP(config.block_count, 32);
// 需要使用的内存数量 = lookahead/8;
// 因此,此处需要限制最大数量,避免消耗过多内存
if (config.lookahead > MAX_LFS_LOOKAHEAD) {
config.lookahead = MAX_LFS_LOOKAHEAD;
}
LFS_PRINTF("block_count -> %d\r\n", config.block_count);
LFS_PRINTF("lookahead -> %d\r\n", config.lookahead);
memset(&the_lfs, 0, sizeof(the_lfs));
err = lfs_mount(&the_lfs, &config);
LFS_PRINTF("mount -> %d\r\n", err);
ERR_EXIT:
return err;
}
实际移植的时候,会发现最核心的就是对块设备的接口封装。
关键是LittleFS对这个部分的说明及注释实际上并不十分详细,这里加以补充说明。
int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);
参数
返回值
int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
参数
返回值
int (*erase)(const struct lfs_config *c, lfs_block_t block);
参数
返回值
由于嵌入式系统并不一定都支持heap,LittleFS提供了一个编译开关用于不支持heap的系统:
LFS_NO_MALLOC
如果系统的HEAP是自己实现的而不是使用标准库的malloc/free实现,则需要自己封装动态内存接口,参考lfs_util.h中的如下代码:
// Allocate memory, only used if buffers are not provided to littlefs
static inline void *lfs_malloc(size_t size) {
#ifndef LFS_NO_MALLOC
return sys_malloc(size);
#else
(void)size;
return NULL;
#endif
}
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p) {
#ifndef LFS_NO_MALLOC
sys_free(p);
#else
(void)p;
#endif
}
对于不支持HEAP的系统,除了需要定义LFS_NO_MALLOC外,还必须在lfs_mount前将lfs_config参数中的read_buffer/prog_buffer/lookahead_buffer/file_buffer设置为静态内存。并且存在只能同时打开一个文件的限制(单实例)。
若要支持同时打开多个文件,则动态内存(HEAP)是必须的。