1 /*
2 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <string.h>
17 #include <dirent.h>
18 #include <sys/mount.h>
19 #include "sys/stat.h"
20 #include "fcntl.h"
21 #include "littlefs.h"
22 #include "lfs.h"
23 #include "los_memory.h"
24 #include "los_task.h"
25 #include "los_compiler.h"
26 #include "los_fs.h"
27 #include "ohos_init.h"
28 #include "ohos_types.h"
29
30
31 const char LITTLEFS_MOUNT_POINT[] = { "/Openvalley" };
32 static const char TAG[] = { "Littlefs" };
33
34 #define LFS_LOG printf
35 #define RAM_BUF_SIZE (22*1024) /* 可以被擦除的块数量,实际大小=BLOCK_SIZE*BLOCK_COUNT字节 */
36 #define READ_SIZE 32 /* 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) */
37 #define PROG_SIZE READ_SIZE /* 最小写入字节数,所有的写入操作字节数必须是它的倍数(影响内存消耗) */
38 #define BLOCK_SIZE 128 /* 擦除块字节数,不会影响内存消耗,每个文件至少占用一个块,必须是READ_SIZE/PROG_SIZE的倍数 */
39 #define CACHE_SIZE READ_SIZE /* 块缓存的大小,缓存越大磁盘访问越小,性能越高,必须是READ_SIZE/PROG_SIZE的倍数,且是BLOCK_SIZE的因数 */
40 #define LOOKAHEAD_SIZE 16 /* 块分配预测深度,分配块时每次步进多少个块,必须为8的整数倍,对于内存消耗影响不大 */
41 #define BLOCK_CYCLES (-1) /* 逐出元数据日志并将元数据移动到另一个块之前的擦除周期数,值越大性能越好,但磨损越不均匀,-1将禁用块级磨损均衡 */
42
43
44 /* lfs配置变量,必须是全局内存或静态内存 */
45 static char LittlefsRamBuf[RAM_BUF_SIZE];
46
47 /* lfs读接口 */
littlefs_block_read(const struct lfs_config * cfg,lfs_block_t block,lfs_off_t off,char * buffer,lfs_size_t size)48 int littlefs_block_read(const struct lfs_config *cfg, lfs_block_t block,
49 lfs_off_t off, char *buffer, lfs_size_t size)
50 {
51 int ret;
52 off = cfg->block_size * block + off;
53 if ((off + size) > RAM_BUF_SIZE) {
54 return LOS_NOK;
55 }
56 ret = memcpy_s(buffer, size, (char*)cfg->context + off, size);
57 if (ret != 0) {
58 return LOS_NOK;
59 }
60 return LOS_OK;
61 }
62
63 /* lfs写接口 */
littlefs_block_write(const struct lfs_config * cfg,lfs_block_t block,lfs_off_t off,const void * buffer,lfs_size_t size)64 int littlefs_block_write(const struct lfs_config *cfg, lfs_block_t block,
65 lfs_off_t off, const void *buffer, lfs_size_t size)
66 {
67 int ret;
68 off = cfg->block_size * block + off;
69 if ((off + size) > RAM_BUF_SIZE) {
70 return LOS_NOK;
71 }
72 ret = memcpy_s((char*)cfg->context + off, size, buffer, size);
73 if (ret != 0) {
74 return LOS_NOK;
75 }
76 return LOS_OK;
77 }
78
79 /* lfs擦除接口 */
littlefs_block_erase(const struct lfs_config * cfg,lfs_block_t block)80 int littlefs_block_erase(const struct lfs_config *cfg, lfs_block_t block)
81 {
82 lfs_off_t off = cfg->block_size * block;
83 if ((off + cfg->block_size) > RAM_BUF_SIZE) {
84 return LOS_NOK;
85 }
86 int ret = memset_s((char*)cfg->context + off, cfg->block_size, 0xFF, cfg->block_size);
87 if (ret != 0) {
88 return LOS_NOK;
89 }
90 return LOS_OK;
91 }
92
93 // /* lfs同步接口 */
littlefs_block_sync(const struct lfs_config * c)94 int littlefs_block_sync(const struct lfs_config *c)
95 {
96 (void)c;
97 return 0;
98 }
99
GetLittlefsMountPoint(void)100 const char *GetLittlefsMountPoint(void)
101 {
102 return LITTLEFS_MOUNT_POINT;
103 }
104
littlefs_config(struct PartitionCfg * pCfg)105 static int littlefs_config(struct PartitionCfg *pCfg)
106 {
107 int ret;
108 pCfg->partNo = (void*)LittlefsRamBuf;
109 ret = memset_s(LittlefsRamBuf, RAM_BUF_SIZE, 0xFF, RAM_BUF_SIZE);
110 if (ret != 0) {
111 return LOS_NOK;
112 }
113 pCfg->blockCount = RAM_BUF_SIZE / BLOCK_SIZE;
114 pCfg->readSize = READ_SIZE;
115 pCfg->writeSize = PROG_SIZE;
116 pCfg->cacheSize = CACHE_SIZE;
117 pCfg->blockCycles = BLOCK_CYCLES;
118 pCfg->lookaheadSize = LOOKAHEAD_SIZE;
119 pCfg->blockSize = BLOCK_SIZE;
120 pCfg->readFunc = NULL;
121 pCfg->writeFunc = NULL;
122 pCfg->eraseFunc = NULL;
123 return LOS_OK;
124 }
125 // /* lfs初始化 */
LittlefsInit(void)126 static INT32 LittlefsInit(void)
127 {
128 int err, ret;
129 DIR* dir;
130 struct PartitionCfg cfg = {0};
131 if (littlefs_config(&cfg) == LOS_NOK) {
132 return LOS_NOK;
133 }
134 /* 设置挂载Littlefs */
135 err = mount(NULL, LITTLEFS_MOUNT_POINT, "littlefs", 0, &cfg);
136 if (err != LOS_OK) {
137 LFS_LOG("Error %s.mount=0x%X\n", TAG, err);
138 return LOS_NOK;
139 }
140 mkdir(LITTLEFS_MOUNT_POINT, S_IRUSR | S_IWUSR);
141 return LOS_OK;
142 }
143
144 SYS_FEATURE_INIT(LittlefsInit);
145