• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }