1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong 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 <securec.h>
17 #include <stdbool.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <utils_file.h>
23 #include <sys/types.h>
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include <dirent.h>
27 #include <hal_file.h>
28 #include "los_fs.h"
29 #include "errno.h"
30 #include "lfs.h"
31 #include "los_task.h"
32 #include "fmc_operation.h"
33 #include "exmc_sdram.h"
34 #include "utils_file.h"
35
36 #define GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR 0x08200000
37 #ifndef GD32F450ZIT6_FLASH_SECTOR_SIZE
38 #define GD32F450ZIT6_FLASH_SECTOR_SIZE (4 * 1024)
39 #endif
40
41 #define SLOT_AVAILABLE (-1)
42 #define HAL_ERROR (-1)
43
44 #define RD_WR_FIELD_MASK 0x000f
45 #define CREAT_EXCL_FIELD_MASK 0x00f0
46 #define TRUNC_FILED_MASK 0x0f00
47
48 #define ADDITIONAL_LEN 2
49 #define MAX_PATH_LEN 40
50 #define MAX_OPEN_FILE_NUM 32
51 #define FLASH_ROOT_PATH "/data"
52 #define DIR_SEPARATOR "/"
53 #define RAM_ROOT_PATH "/ram"
54
55 #define FLASH_READ_SIZE 1 // 128 /* 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) */
56 #define FLASH_PROG_SIZE 1 // 128 /* 最小写入字节数,所有的写入操作字节数必须是它的倍数(影响内存消耗) */
57 #define FLASH_BLOCK_SIZE \
58 GD32F450ZIT6_FLASH_SECTOR_SIZE /* 擦除块字节数,不会影响内存消耗,每个文件至少占用一个块,必须是READ_SIZE/PROG_SIZE的倍数 \
59 */
60 #define FLASH_CACHE_SIZE \
61 128 /* 块缓存的大小,缓存越大磁盘访问越小,性能越高,必须是READ_SIZE/PROG_SIZE的倍数,且是BLOCK_SIZE的因数 */
62 #define FLASH_LOOKAHEAD_SIZE 16 /* 块分配预测深度,分配块时每次步进多少个块,必须为8的整数倍,对于内存消耗影响不大 */
63 #define FLASH_BLOCK_CYCLES \
64 500 /* 逐出元数据日志并将元数据移动到另一个块之前的擦除周期数,值越大性能越好,但磨损越不均匀,-1将禁用块级磨损均衡 \
65 */
66 #define FLASH_BLOCK_COUNT (1024 * 1024 / FLASH_BLOCK_SIZE)
67
68 #define DEVICE_SDRAM_NAME EXMC_SDRAM_DEVICE0
69 #define SDRAM_OFFSET_ADDRESS 0x01000000
70 #define SDRAM_BLOCK_ADDRESS 0xC0000000
71 #define SDRAM_READ_SIZE 1 // 128 /* 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗)*/
72 #define SDRAM_PROG_SIZE 1 // 128 /* 最小写入字节数,所有的写入操作字节数必须是它的倍数(影响内存消耗)*/
73 #define SDRAM_BLOCK_COUNT 2048
74 #define SDRAM_BLOCK_SIZE 256 /* 擦除块字节数,不会影响内存消耗,每个文件至少占用一个块,必须是READ_SIZE/PROG_SIZE的倍数 */
75 #define SDRAM_CACHE_SIZE 128 /* 块缓存的大小,缓存越大磁盘访问越小,性能越高,必须是READ_SIZE/PROG_SIZE的倍数,且是BLOCK_SIZE的因数 */
76 #define SDRAM_LOOKAHEAD_SIZE 64 /* 块分配预测深度,分配块时每次步进多少个块,必须为8的整数倍,对于内存消耗影响不大 */
77 #define SDRAM_BLOCK_CYCLES 500 /* 逐出元数据日志并将元数据移动到另一个块之前的擦除周期数,值越大性能越好,但磨损越不均匀,-1将禁用块级磨损均衡 */
78
79 #define MAX_PATH_LEN 40
80
81 int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
82 int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer,
83 lfs_size_t size);
84 int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block);
85 int littlefs_block_sync(const struct lfs_config *c);
86
87 struct fs_cfg {
88 char *mount_point;
89 struct lfs_config lfs_cfg;
90 };
91 static struct fs_cfg fs[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0};
92
93 static struct PartitionCfg part_cfg[LOSCFG_LFS_MAX_MOUNT_SIZE] = {
94 {
95 .readFunc = NULL,
96 .writeFunc = NULL,
97 .eraseFunc = NULL,
98 .readSize = FLASH_READ_SIZE, // 读闪存 以字节为单位读取的块的最小大小。所有读操作都是该值的倍数。
99 .writeSize = FLASH_PROG_SIZE, // 写闪存 以字节为单位的块程序的最小大小。所有程序操作都是该值的倍数。
100 .blockSize = GD32F450ZIT6_FLASH_SECTOR_SIZE, // 块大小 可擦块的大小(以字节为单位),必须是读取大小和程序大小的倍数。
101 .blockCount = FLASH_BLOCK_COUNT, // 块个数 设备上可擦的块数。
102 .cacheSize = FLASH_CACHE_SIZE, // 系统缓存必须是读写缓存的倍数 块大小的因数
103 .lookaheadSize = FLASH_LOOKAHEAD_SIZE, // 类似目录缓存 必须是8的倍数
104 .blockCycles = FLASH_BLOCK_CYCLES, // 每500次磨损来一次均衡
105 .partNo = 1, // 用来判断底层操作函数的标志num
106 },
107 {
108 .readFunc = NULL,
109 .writeFunc = NULL,
110 .eraseFunc = NULL,
111 .readSize = SDRAM_READ_SIZE, // 读闪存 以字节为单位读取的块的最小大小。所有读操作都是该值的倍数。
112 .writeSize = SDRAM_PROG_SIZE, // 写闪存 以字节为单位的块程序的最小大小。所有程序操作都是该值的倍数。
113 .blockSize = SDRAM_BLOCK_SIZE, // 块大小 可擦块的大小(以字节为单位),必须是读取大小和程序大小的倍数。
114 .blockCount = SDRAM_BLOCK_COUNT, // 块个数 设备上可擦的块数。
115 .cacheSize = SDRAM_CACHE_SIZE, // 系统缓存必须是读写缓存的倍数 块大小的因数
116 .lookaheadSize = SDRAM_LOOKAHEAD_SIZE, // 类似目录缓存 必须是8的倍数
117 .blockCycles = SDRAM_BLOCK_CYCLES, // 每500次磨损来一次均衡
118 .partNo = 2, // 用来判断底层操作函数的标志num
119 }
120 };
121
lfs_init(void)122 int lfs_init(void)
123 {
124 DIR *dir = NULL;
125 fs[0].mount_point = FLASH_ROOT_PATH;
126 fs[1].mount_point = RAM_ROOT_PATH;
127 for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
128 if (fs[i].mount_point == NULL) {
129 continue;
130 }
131
132 int ret = mount(NULL, fs[i].mount_point, "littlefs", 0, &part_cfg[i]);
133 printf("%s: mount fs on '%s' %s\n", __func__, fs[i].mount_point, (ret == 0) ? "succeed" : "failed");
134 if ((dir = opendir(fs[i].mount_point)) == NULL) {
135 printf("first time create file %s\n", fs[i].mount_point);
136 ret = mkdir(fs[i].mount_point, S_IRUSR | S_IWUSR);
137 if (ret != LOS_OK) {
138 printf("Mkdir failed %d[%d]\n", ret, errno);
139 return ret;
140 } else {
141 printf("mkdir success %d\n", ret);
142 }
143 } else {
144 printf("open dir success!\n");
145 closedir(dir);
146 }
147 }
148 return LFS_ERR_OK;
149 }
150
littlefs_block_read(const struct lfs_config * c,lfs_block_t block,lfs_off_t off,void * buffer,lfs_size_t size)151 int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
152 {
153 uint32_t intlock;
154 intlock = LOS_IntLock();
155 uint32_t addr;
156 int partNum = (int) c->context;
157 switch (partNum) {
158 case 1:
159 addr =
160 (uint32_t)((uint32_t)block * GD32F450ZIT6_FLASH_SECTOR_SIZE)
161 + GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + off;
162 fmc_read_8bit_data(addr, size, buffer);
163 break;
164 case 2:
165 addr =
166 ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + off + SDRAM_BLOCK_ADDRESS);
167 int ret = memcpy_s(buffer, size, (void*)addr, size);
168 if (ret != 0) {
169 printf("The read sdram address 0x%x is failed ret = %d",addr,ret);
170 LOS_IntRestore(intlock);
171 return LOS_NOK;
172 }
173 break;
174 default:
175 printf("partNum(%d) is out of range \n", partNum);
176 LOS_IntRestore(intlock);
177 return LOS_NOK;
178 }
179 LOS_IntRestore(intlock);
180 return LFS_ERR_OK;
181 }
182
littlefs_block_write(const struct lfs_config * c,lfs_block_t block,lfs_off_t off,const void * buffer,lfs_size_t size)183 int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer,
184 lfs_size_t size)
185 {
186 uint32_t intlock;
187 intlock = LOS_IntLock();
188 uint32_t addr;
189 int partNum = (int) c->context;
190 switch (partNum) {
191 case 1:
192 addr =
193 (uint32_t)((uint32_t)block * GD32F450ZIT6_FLASH_SECTOR_SIZE)
194 + GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + off;
195 fmc_write_8bit_data(addr, size, buffer);
196 break;
197 case 2:
198 addr =
199 ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + off + SDRAM_BLOCK_ADDRESS);
200 int ret = memcpy_s((void*)addr, size, buffer, size);
201 if (ret != 0) {
202 printf("The write sdram address 0x%x is failed ret = %d",addr,ret);
203 LOS_IntRestore(intlock);
204 return LOS_NOK;
205 }
206 break;
207 default:
208 printf("partNum(%d) is out of range \n", partNum);
209 LOS_IntRestore(intlock);
210 return LOS_NOK;
211 }
212 LOS_IntRestore(intlock);
213 return LFS_ERR_OK;
214 }
215
littlefs_block_erase(const struct lfs_config * c,lfs_block_t block)216 int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block)
217 {
218 uint32_t intlock;
219 intlock = LOS_IntLock();
220 uint32_t addr;
221 int partNum = (int) c->context;
222 switch (partNum) {
223 case 1:
224 addr =
225 (uint32_t)(GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + (block * GD32F450ZIT6_FLASH_SECTOR_SIZE));
226 fmc_erase_sector_by_address(addr);
227 break;
228 case 2:
229 addr =
230 ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + SDRAM_BLOCK_ADDRESS);
231 int ret = memset_s((void *)addr,SDRAM_BLOCK_SIZE, 0xff, SDRAM_BLOCK_SIZE);
232 if (ret != 0) {
233 printf("The earse sdram address 0x%x is failed ret = %d",addr,ret);
234 LOS_IntRestore(intlock);
235 return LOS_NOK;
236 }
237 break;
238 default:
239 printf("partNum(%d) is out of range \n", partNum);
240 LOS_IntRestore(intlock);
241 return LOS_NOK;
242 }
243 LOS_IntRestore(intlock);
244 return LFS_ERR_OK;
245 }
246
littlefs_block_sync(const struct lfs_config * c)247 int littlefs_block_sync(const struct lfs_config *c)
248 {
249 return LFS_ERR_OK;
250 }
251
252 static int g_FileHandlerArray[MAX_OPEN_FILE_NUM] = {
253 SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
254 SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
255 SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
256 SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE,
257 SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE
258 };
259
GetAvailableFileHandlerIndex(void)260 static int GetAvailableFileHandlerIndex(void)
261 {
262 int i = MAX_OPEN_FILE_NUM;
263
264 for (; i > 0; i--) {
265 if (g_FileHandlerArray[i - 1] == SLOT_AVAILABLE) {
266 break;
267 }
268 }
269
270 return i;
271 }
ConvertFlags(int oflag)272 static int ConvertFlags(int oflag)
273 {
274 int ret = 0;
275 int buffer = 0;
276
277 buffer = (oflag & RD_WR_FIELD_MASK);
278 if (buffer == O_RDONLY_FS) {
279 ret = O_RDONLY;
280 } else if (buffer == O_WRONLY_FS) {
281 ret = O_WRONLY;
282 } else if (buffer == O_RDWR_FS) {
283 ret = O_RDWR;
284 }
285
286 buffer = (oflag & CREAT_EXCL_FIELD_MASK);
287 if ((buffer & O_CREAT_FS) != 0) {
288 ret |= O_CREAT;
289 }
290
291 if ((buffer & O_EXCL_FS) != 0) {
292 ret |= O_EXCL;
293 }
294
295 buffer = (oflag & TRUNC_FILED_MASK);
296 if ((buffer & O_TRUNC_FS) != 0) {
297 ret |= O_TRUNC;
298 }
299
300 if ((buffer & O_APPEND_FS) != 0) {
301 ret |= O_APPEND;
302 }
303
304 return ret;
305 }
306
GetActualFilePath(const char * path)307 static char *GetActualFilePath(const char *path)
308 {
309 int len;
310 char *file_path = NULL;
311
312 len = strnlen(path, MAX_PATH_LEN);
313 if (len >= MAX_PATH_LEN) {
314 printf("path is too long!\r\n");
315 return NULL;
316 }
317
318 len += (strlen(RAM_ROOT_PATH) + ADDITIONAL_LEN);
319 file_path = (char *)malloc(len);
320 if (file_path == NULL) {
321 printf("malloc failed!\r\n");
322 return NULL;
323 }
324
325 strcpy_s(file_path, len, RAM_ROOT_PATH);
326 strcat_s(file_path, len, DIR_SEPARATOR);
327 strcat_s(file_path, len, path);
328
329 return file_path;
330 }
331
HalFileOpen(const char * path,int oflag,int mode)332 int HalFileOpen(const char *path, int oflag, int mode)
333 {
334 int index;
335 int fd;
336 char *file_path;
337
338 index = GetAvailableFileHandlerIndex();
339 if (index == 0) {
340 printf("error: can not find index available!\n");
341 return HAL_ERROR;
342 }
343
344 file_path = GetActualFilePath(path);
345 if (file_path == NULL) {
346 return HAL_ERROR;
347 }
348
349 fd = open(file_path, ConvertFlags(oflag));
350 if (fd < 0) {
351 printf("error:failed to open file : errno = %d\n", errno);
352 free(file_path);
353 return HAL_ERROR;
354 }
355
356 g_FileHandlerArray[index - 1] = fd;
357 free(file_path);
358
359 return index;
360 }
361
HalFileClose(int fd)362 int HalFileClose(int fd)
363 {
364 int ret;
365
366 /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
367 if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
368 printf("error: close: fd(%d) is out of range!\n", fd);
369 return HAL_ERROR;
370 }
371
372 ret = close(g_FileHandlerArray[fd - 1]);
373 if (ret != 0) {
374 printf("error: failed to close ret = %d!\n", ret);
375 return HAL_ERROR;
376 }
377 LOS_MDelay(0x0A);
378
379 g_FileHandlerArray[fd - 1] = SLOT_AVAILABLE;
380
381 return ret;
382 }
383
HalFileRead(int fd,char * buf,unsigned int len)384 int HalFileRead(int fd, char *buf, unsigned int len)
385 {
386 /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
387 if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
388 printf("error: read: fd(%d) is out of range!\n", fd);
389 return HAL_ERROR;
390 }
391
392 return read(g_FileHandlerArray[fd - 1], buf, len);
393 }
394
HalFileWrite(int fd,const char * buf,unsigned int len)395 int HalFileWrite(int fd, const char *buf, unsigned int len)
396 {
397 /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
398 if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
399 printf("error: write: fd(%d) is out of range!\n", fd);
400 return HAL_ERROR;
401 }
402
403 return write(g_FileHandlerArray[fd - 1], buf, len);
404 }
405
HalFileDelete(const char * path)406 int HalFileDelete(const char *path)
407 {
408 char *file_path;
409 int ret;
410
411 file_path = GetActualFilePath(path);
412 if (file_path == NULL) {
413 printf("error: delete: file_path == NULL\n");
414 return HAL_ERROR;
415 }
416
417 ret = unlink(file_path);
418 free(file_path);
419 LOS_MDelay(0x0A);
420 return ret;
421 }
422
HalFileStat(const char * path,unsigned int * fileSize)423 int HalFileStat(const char *path, unsigned int *fileSize)
424 {
425 char *file_path;
426 struct stat f_info;
427 int ret;
428
429 file_path = GetActualFilePath(path);
430 if (file_path == NULL) {
431 printf("error: stat: file_path == NULL\n");
432 return HAL_ERROR;
433 }
434
435 ret = stat(file_path, &f_info);
436 *fileSize = f_info.st_size;
437 free(file_path);
438
439 return ret;
440 }
441
HalFileSeek(int fd,int offset,unsigned int whence)442 int HalFileSeek(int fd, int offset, unsigned int whence)
443 {
444 int ret = 0;
445 struct stat f_info;
446
447 /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */
448 if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) {
449 printf("error: seek: fd(%d) is out of range!\n", fd);
450 return HAL_ERROR;
451 }
452
453 ret = fstat(g_FileHandlerArray[fd - 1], &f_info);
454 if (ret != 0) {
455 printf("error: fail to fstat!\n");
456 return HAL_ERROR;
457 }
458
459 if (whence == SEEK_SET_FS) {
460 if (offset > f_info.st_size) {
461 printf("error: seek offset is more than st_size %d vs %d!\n", offset, f_info.st_size);
462 ret = HAL_ERROR;
463 }
464 }
465
466 ret = lseek(g_FileHandlerArray[fd - 1], offset, whence);
467 if ((ret > f_info.st_size) || (ret < 0)) {
468 printf("error: lseek ret:f_info.st_size %d vs %d\n", ret, f_info.st_size);
469 return HAL_ERROR;
470 }
471
472 return ret;
473 }