# littlefs使用说明 # 简述 LittleFS主要用在微控制器和flash上,是一种嵌入式文件系统,具有如下3个特点: 1. 掉电恢复 在写入时即使复位或者掉电也可以恢复到上一个正确的状态。 2. 擦写均衡 有效延长flash的使用寿命。 3. 有限的RAM/ROM 节省ROM和RAM空间。 niobe407模组外接16M flash,在外挂flash的后8M挂载littlefs文件系统,默认挂载点为talkweb,默认创建存储数据的目录data,目录如下: ``` OHOS # ls Directory /talkweb: . .. data talkweb0 8 talkweb1 7 wifi.cfg 28 ``` # littlefs使用说明 littlefs需要通过内核配置进行选配,操作如下: 1. 切换到kernel/liteos_m/目录 ``` cd kernel/liteos_m/ ``` 2. 输入make menuconfig 打开内核配置界面 ``` make menuconfig ``` 3. 选择FileSystem,选上littlefs ![image-20220215153205796](figures/1.png) OpenHarmony已经实现了vfs,注册了littlefs的相关接口,vfs向标准文件操作提供对应的接口,因此应用可以调用的newlibc标准文件操作接口进行测试。 涉及的部分文件操作接口如下: | 接口名 | 描述 | | -------- | ---------------- | | _open | 打开文件 | | _close | 关闭文件 | | _write | 写文件 | | _read | 读文件 | | _lseek | 设置文件偏移位置 | | mkdir | 创建目录 | | opendir | 打开目录 | | closedir | 关闭目录 | | rmdir | 删除目录 | | mount | 分区挂载 | | unmount | 分区卸载 | ## 测试 niobe407的littlefs的测试可以通过内核核配置打开,操作如下: 1. 切换到kernel/liteos_m/目录 ``` cd kernel/liteos_m/ ``` 2. 输入make menuconfig 打开内核配置界面 ``` make menuconfig ``` 弹出配置界面,选择Platform下的select board niobe407。 ![image-20220216150938794](figures/2.png) 3. 选配application中的fs store。 ![image-20220217141103858](figures/3.png) 测例: ``` static void dir_test(const char *path) { DIR *dir; int ret ; struct dirent *dp; /*文件夹打开关闭测试*/ if ((dir = opendir(path)) == NULL) { printf("opendir %s failed \n", path); return; } while ((dp = readdir(dir)) != NULL) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { continue; } struct stat st_buf = {0}; char realpath[260]; snprintf_s(realpath, sizeof(realpath), "%s/%s", path, dp->d_name); if (stat(realpath, &st_buf) != 0) { printf("can not access %s\n", realpath); closedir(dir); return; } if ((st_buf.st_mode & S_IFMT) == S_IFDIR) { printf("DIR %s\n", realpath); } else { printf("FILE %s, %ld bytes\n", realpath, st_buf.st_size); } } closedir(dir); /*文件夹创建删除测试*/ ret = mkdir("/talkweb/fstestdir",S_IRUSR | S_IWUSR); if(ret){ printf("mkdir failed \n"); return; } ret = rmdir("/talkweb/fstestdir"); if(ret){ printf("rmdir failed \n"); return; } printf("%s ok \n",__func__); } ``` 该接口测试目录的开启和关闭,如果目录不存在直接返回。 ``` static void write_test(const char *file, const char *data) { int fd = _open(file, O_RDWR | O_CREAT); if (fd < 0) { printf("open file '%s' failed \r\n", file); return; } int bytes = _write(fd,data,strlen(data)); _close(fd); printf("write file '%s' total bytes: %d, %s\r\n", file, bytes, data); } ``` 上述接口测试文件的写操作。 ``` static void read_test(const char *file, bool print_str) { int fd = _open(file, O_RDWR | O_CREAT); if (fd < 0) { printf("open file '%s' failed, \r\n", file); return; } int bytes = 0; char buf[513]; while (1) { memset_s(buf, sizeof(buf), 0, sizeof(buf)); int rc = _read(fd, buf, sizeof(buf) - 1); if (rc > 0) bytes += rc; if (print_str) { buf[rc] = '\0'; printf("%s\r\n", buf); } if (rc < sizeof(buf) - 1) break; } _close(fd); printf("read file '%s' total bytes: %d\r\n", file, bytes); } ``` 上述接口测试文件的读操作。 注意:littlefs挂载的根目录为talkweb,所有创建的目录都应该是talkweb的子目录,例如/talkweb/data等。 测试主程序: ``` void fs_test(void) { /*文件夹打开创建测试*/ dir_test("/talkweb"); /*文件读写测试*/ read_test("/talkweb/wifi.cfg", true); write_test("/talkweb/wifi.cfg", "ssid:talkweb password:123456"); read_test("/talkweb/wifi.cfg", true); } ``` BUILD.gn ``` import("//kernel/liteos_m/liteos.gni") module_name = get_path_info(rebase_path("."), "name") kernel_module(module_name) { sources = [ "fs_test.c", ] } ``` 测试结果: ``` hiview init success. Initialize 0littlefs_test DIR /talkweb/data dir_test ok read file '/talkweb/wifi.cfg' total bytes: 0 read_test ok write file '/talkweb/wifi.cfg' total bytes: 28, ssid:talkweb password:123456 write_test ok ssid:talkweb password:123456 read file '/talkweb/wifi.cfg' total bytes: 28 read_test ok ```