1 /*
2 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "prt_fs.h"
32 #include "prt_sem.h"
33 #include "pthread.h"
34
35 struct fs_cfg {
36 char *mount_point;
37 struct PartitionCfg partCfg;
38 };
39
PRT_CurTaskIDGet()40 U32 PRT_CurTaskIDGet()
41 {
42 return 0; /* 0, return success */
43 }
44
pthread_mutex_lock(pthread_mutex_t * mutex)45 int pthread_mutex_lock(pthread_mutex_t *mutex)
46 {
47 return 0; /* 0, return success */
48 }
49
pthread_mutex_unlock(pthread_mutex_t * mutex)50 int pthread_mutex_unlock(pthread_mutex_t *mutex)
51 {
52 return 0; /* 0, return success */
53 }
54
55 #define FLASH_PARTITION_DATA0 0
56
57 typedef struct {
58 const char *partitionDescription;
59 U32 partitionStartAddr;
60 U32 partitionLength;
61 U32 partitionOptions;
62 } HalLogicPartition;
63
64 HalLogicPartition g_halPartitions[] = {
65 [FLASH_PARTITION_DATA0] = {
66 .partitionDescription = "littlefs",
67 .partitionStartAddr = 0,
68 .partitionLength = 0x800000, // size is 8M
69 },
70 };
71
72 #define FLASH_SECTOR_SIZE 512
73
VirtFlashErase(int pdrv,U32 offSet,U32 size)74 S32 VirtFlashErase(int pdrv, U32 offSet, U32 size)
75 {
76 U32 startAddr = offSet;
77 U32 partitionEnd;
78
79 partitionEnd = g_halPartitions[pdrv].partitionStartAddr + g_halPartitions[pdrv].partitionLength;
80 if (startAddr >= partitionEnd) {
81 printf("flash over erase, 0x%x, 0x%x\r\n", startAddr, partitionEnd);
82 printf("flash over write\r\n");
83 return -1; /* -1, return failure */
84 }
85 if ((startAddr + size) > partitionEnd) {
86 printf("flash over write, new len is %d\r\n", size);
87 return -1; /* -1, return failure */
88 }
89
90 int count = size / FLASH_SECTOR_SIZE;
91 U32 p = offSet;
92
93 for (int i = 0; i < count; i++) {
94 W25qxxEraseSector(p);
95 p += FLASH_SECTOR_SIZE;
96 }
97
98 return 0; /* 0, return success */
99 }
100
VirtFlashWrite(int pdrv,U32 offSet,const void * buf,U32 bufLen)101 S32 VirtFlashWrite(int pdrv, U32 offSet, const void *buf, U32 bufLen)
102 {
103 U32 startAddr = offSet;
104 U32 partitionEnd;
105
106 partitionEnd = g_halPartitions[pdrv].partitionStartAddr + g_halPartitions[pdrv].partitionLength;
107 if (startAddr >= partitionEnd) {
108 printf("flash over write, 0x%x, 0x%x\r\n", startAddr, partitionEnd);
109 return -1; /* -1, return failure */
110 }
111 if ((startAddr + bufLen) > partitionEnd) {
112 printf("flash over write, new len is %d\r\n", bufLen);
113 return -1; /* -1, return failure */
114 }
115
116 W25qxxWrite(buf, startAddr, bufLen);
117
118 return 0; /* -1, return success */
119 }
120
VirtFlashRead(int pdrv,U32 offSet,void * buf,U32 bufLen)121 S32 VirtFlashRead(int pdrv, U32 offSet, void *buf, U32 bufLen)
122 {
123 U32 startAddr = offSet;
124 U32 partitionEnd;
125
126 partitionEnd = g_halPartitions[pdrv].partitionStartAddr + g_halPartitions[pdrv].partitionLength;
127 if (startAddr >= partitionEnd) {
128 printf("flash over read, 0x%x, 0x%x\r\n", startAddr, partitionEnd);
129 return -1; /* -1, return failure */
130 }
131 if ((startAddr + bufLen) > partitionEnd) {
132 printf("flash over read, new len is %d\r\n", bufLen);
133 return -1; /* -1, return failure */
134 }
135
136 W25qxxRead(buf, startAddr, bufLen);
137 return 0; /* -1, return success */
138 }
139
LfsLowLevelInit(void)140 static S32 LfsLowLevelInit(void)
141 {
142 S32 ret;
143 struct fs_cfg fs[OS_LFS_MAX_MOUNT_SIZE] = {0};
144
145 S32 lengthArray = g_halPartitions[FLASH_PARTITION_DATA0].partitionLength;
146 S32 addrArray = g_halPartitions[FLASH_PARTITION_DATA0].partitionStartAddr;
147 ret = PRT_DiskPartition("flash0", "littlefs", &lengthArray, &addrArray, 1);
148 printf("%s: DiskPartition %s\n", __func__, (ret == 0) ? "succeed" : "failed");
149 if (ret != 0) {
150 return -1; /* -1, return failure */
151 }
152
153 fs[0].mount_point = "/data";
154 fs[0].partCfg.partNo = FLASH_PARTITION_DATA0;
155 fs[0].partCfg.blockSize = 4096; /* 4096, lfs block size */
156 fs[0].partCfg.blockCount = 2048; /* 2048, lfs block count */
157 fs[0].partCfg.readFunc = VirtFlashRead;
158 fs[0].partCfg.writeFunc = VirtFlashWrite;
159 fs[0].partCfg.eraseFunc = VirtFlashErase;
160
161 fs[0].partCfg.readSize = 256; /* 256, lfs read size */
162 fs[0].partCfg.writeSize = 256; /* 256, lfs prog size */
163 fs[0].partCfg.cacheSize = 256; /* 256, lfs cache size */
164 fs[0].partCfg.lookaheadSize = 16; /* 16, lfs lookahead size */
165 fs[0].partCfg.blockCycles = 1000; /* 1000, lfs block cycles */
166
167 ret = PRT_PartitionFormat("flash0", "littlefs", &fs[0].partCfg);
168 printf("%s: PartitionFormat %s\n", __func__, (ret == 0) ? "succeed" : "failed");
169 if (ret != 0) {
170 return -1; /* -1, return failure */
171 }
172
173 ret = mount(NULL, fs[0].mount_point, "littlefs", 0, &fs[0].partCfg);
174 printf("%s: mount fs on '%s' %s\n", __func__, fs[0].mount_point, (ret == 0) ? "succeed" : "failed");
175 if (ret != 0) {
176 return -1; /* -1, return failure */
177 }
178
179 ret = mkdir(fs[0].mount_point, 0777); /* 0777, set dir permissions */
180 printf("%s: mkdir '%s' %s\n", __func__, fs[0].mount_point, (ret == 0) ? "succeed" : "failed");
181 if (ret != 0) {
182 return -1; /* -1, return failure */
183 }
184
185 #if (defined(OSCFG_TEST))
186 LfsTest();
187 #endif
188 return 0; /* -1, return success */
189 }
190
FsInit(void)191 int FsInit(void)
192 {
193 W25qxxInit();
194
195 S32 ret = PRT_VfsInit();
196 if (ret < 0) {
197 printf("VfsInit failed!\n");
198 return ret;
199 }
200
201 return LfsLowLevelInit();
202 }
203