Skip to content

Commit f5f4cda

Browse files
committed
extmod/vfs_fat: Rework so it can optionally use OO version of FatFS.
If MICROPY_VFS_FAT is enabled by a port then the port must switch to using MICROPY_FATFS_OO. Otherwise a port can continue to use the FatFs code without any changes.
1 parent d4464b0 commit f5f4cda

File tree

8 files changed

+243
-65
lines changed

8 files changed

+243
-65
lines changed

extmod/fsusermount.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
#include "py/nlr.h"
3333
#include "py/runtime.h"
3434
#include "py/mperrno.h"
35+
#if MICROPY_FATFS_OO
36+
#include "lib/oofatfs/ff.h"
37+
#else
3538
#include "lib/fatfs/ff.h"
39+
#endif
3640
#include "extmod/fsusermount.h"
3741

3842
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs) {
@@ -57,7 +61,11 @@ fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp
5761
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
5862
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
5963
if (vfs != NULL && !memcmp(mnt_str, vfs->str, mnt_len + 1)) {
64+
#if MICROPY_FATFS_OO
65+
res = f_umount(&vfs->fatfs);
66+
#else
6067
res = f_mount(NULL, vfs->str, 0);
68+
#endif
6169
if (vfs->flags & FSUSER_FREE_OBJ) {
6270
m_del_obj(fs_user_mount_t, vfs);
6371
}
@@ -86,6 +94,9 @@ fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp
8694
vfs->str = mnt_str;
8795
vfs->len = mnt_len;
8896
vfs->flags = FSUSER_FREE_OBJ;
97+
#if MICROPY_FATFS_OO
98+
vfs->fatfs.drv = vfs;
99+
#endif
89100

90101
// load block protocol methods
91102
mp_load_method(device, MP_QSTR_readblocks, vfs->readblocks);
@@ -114,23 +125,42 @@ fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp
114125
MP_STATE_PORT(fs_user_mount)[i] = vfs;
115126

116127
// mount the block device (if mkfs, only pre-mount)
117-
FRESULT res = f_mount(&vfs->fatfs, vfs->str, !mkfs);
128+
FRESULT res;
129+
#if MICROPY_FATFS_OO
130+
if (mkfs) {
131+
res = FR_OK;
132+
} else {
133+
res = f_mount(&vfs->fatfs);
134+
}
135+
#else
136+
res = f_mount(&vfs->fatfs, vfs->str, !mkfs);
137+
#endif
138+
118139
// check the result
119140
if (res == FR_OK) {
120141
if (mkfs) {
121142
goto mkfs;
122143
}
123144
} else if (res == FR_NO_FILESYSTEM && args[1].u_bool) {
124-
mkfs:
145+
mkfs:;
146+
#if MICROPY_FATFS_OO
147+
uint8_t working_buf[_MAX_SS];
148+
res = f_mkfs(&vfs->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
149+
#else
125150
res = f_mkfs(vfs->str, 1, 0);
151+
#endif
126152
if (res != FR_OK) {
127153
mkfs_error:
128154
MP_STATE_PORT(fs_user_mount)[i] = NULL;
129155
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't mkfs"));
130156
}
131157
if (mkfs) {
132158
// If requested to only mkfs, unmount pre-mounted device
159+
#if MICROPY_FATFS_OO
160+
res = FR_OK;
161+
#else
133162
res = f_mount(NULL, vfs->str, 0);
163+
#endif
134164
if (res != FR_OK) {
135165
goto mkfs_error;
136166
}
@@ -188,7 +218,12 @@ mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
188218
}
189219

190220
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
191-
FRESULT res = f_mount(NULL, vfs->str, 0);
221+
FRESULT res;
222+
#if MICROPY_FATFS_OO
223+
res = f_umount(&vfs->fatfs);
224+
#else
225+
res = f_mount(NULL, vfs->str, 0);
226+
#endif
192227
if (vfs->flags & FSUSER_FREE_OBJ) {
193228
m_del_obj(fs_user_mount_t, vfs);
194229
}

extmod/vfs_fat.c

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@
2828
#include "py/mpconfig.h"
2929
#if MICROPY_VFS_FAT
3030

31+
#if !MICROPY_FATFS_OO
32+
#error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_FATFS_OO"
33+
#endif
34+
3135
#include <string.h>
3236
#include "py/nlr.h"
3337
#include "py/runtime.h"
3438
#include "py/mperrno.h"
35-
#include "lib/fatfs/ff.h"
36-
#include "lib/fatfs/diskio.h"
39+
#include "lib/oofatfs/ff.h"
3740
#include "extmod/vfs_fat_file.h"
3841
#include "extmod/fsusermount.h"
3942
#include "timeutils.h"
@@ -55,13 +58,10 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
5558
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs);
5659
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj));
5760

58-
STATIC mp_obj_t fat_vfs_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
59-
// Skip self
60-
return fatfs_builtin_open(n_args - 1, args + 1, kwargs);
61-
}
62-
MP_DEFINE_CONST_FUN_OBJ_KW(fat_vfs_open_obj, 2, fat_vfs_open);
61+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(fat_vfs_open_obj, 2, fatfs_builtin_open_self);
6362

6463
STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) {
64+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);
6565
bool is_str_type = true;
6666
const char *path;
6767
if (n_args == 2) {
@@ -73,27 +73,24 @@ STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) {
7373
path = "";
7474
}
7575

76-
return fat_vfs_listdir(path, is_str_type);
76+
return fat_vfs_listdir2(self, path, is_str_type);
7777
}
7878
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func);
7979

80-
STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t path_in, mp_int_t attr) {
80+
STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) {
81+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
8182
const char *path = mp_obj_str_get_str(path_in);
8283

8384
FILINFO fno;
84-
#if _USE_LFN
85-
fno.lfname = NULL;
86-
fno.lfsize = 0;
87-
#endif
88-
FRESULT res = f_stat(path, &fno);
85+
FRESULT res = f_stat(&self->fatfs, path, &fno);
8986

9087
if (res != FR_OK) {
9188
mp_raise_OSError(fresult_to_errno_table[res]);
9289
}
9390

9491
// check if path is a file or directory
9592
if ((fno.fattrib & AM_DIR) == attr) {
96-
res = f_unlink(path);
93+
res = f_unlink(&self->fatfs, path);
9794

9895
if (res != FR_OK) {
9996
mp_raise_OSError(fresult_to_errno_table[res]);
@@ -105,27 +102,25 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t path_in, mp_int_t attr) {
105102
}
106103

107104
STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
108-
(void)vfs_in;
109-
return fat_vfs_remove_internal(path_in, 0); // 0 == file attribute
105+
return fat_vfs_remove_internal(vfs_in, path_in, 0); // 0 == file attribute
110106
}
111107
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
112108

113109
STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) {
114-
(void) vfs_in;
115-
return fat_vfs_remove_internal(path_in, AM_DIR);
110+
return fat_vfs_remove_internal(vfs_in, path_in, AM_DIR);
116111
}
117112
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir);
118113

119114
STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) {
120-
(void)vfs_in;
115+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
121116
const char *old_path = mp_obj_str_get_str(path_in);
122117
const char *new_path = mp_obj_str_get_str(path_out);
123-
FRESULT res = f_rename(old_path, new_path);
118+
FRESULT res = f_rename(&self->fatfs, old_path, new_path);
124119
if (res == FR_EXIST) {
125120
// if new_path exists then try removing it (but only if it's a file)
126-
fat_vfs_remove_internal(path_out, 0); // 0 == file attribute
121+
fat_vfs_remove_internal(vfs_in, path_out, 0); // 0 == file attribute
127122
// try to rename again
128-
res = f_rename(old_path, new_path);
123+
res = f_rename(&self->fatfs, old_path, new_path);
129124
}
130125
if (res == FR_OK) {
131126
return mp_const_none;
@@ -137,9 +132,9 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
137132
STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename);
138133

139134
STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
140-
(void)vfs_in;
135+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
141136
const char *path = mp_obj_str_get_str(path_o);
142-
FRESULT res = f_mkdir(path);
137+
FRESULT res = f_mkdir(&self->fatfs, path);
143138
if (res == FR_OK) {
144139
return mp_const_none;
145140
} else {
@@ -150,15 +145,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
150145

151146
/// Change current directory.
152147
STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
153-
(void)vfs_in;
148+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
154149
const char *path;
155150
path = mp_obj_str_get_str(path_in);
156151

157-
FRESULT res = f_chdrive(path);
158-
159-
if (res == FR_OK) {
160-
res = f_chdir(path);
161-
}
152+
FRESULT res = f_chdir(&self->fatfs, path);
162153

163154
if (res != FR_OK) {
164155
mp_raise_OSError(fresult_to_errno_table[res]);
@@ -170,14 +161,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);
170161

171162
/// Get the current directory.
172163
STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
173-
(void)vfs_in;
164+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
174165
char buf[MICROPY_ALLOC_PATH_MAX + 1];
175-
FRESULT res = f_getcwd(buf, sizeof buf);
176-
166+
memcpy(buf, self->str, self->len);
167+
FRESULT res = f_getcwd(&self->fatfs, buf + self->len, sizeof(buf) - self->len);
177168
if (res != FR_OK) {
178169
mp_raise_OSError(fresult_to_errno_table[res]);
179170
}
180-
171+
// remove trailing / if in root dir, because we prepended the mount point
172+
size_t l = strlen(buf);
173+
if (res == FR_OK && buf[l - 1] == '/') {
174+
buf[l - 1] = 0;
175+
}
181176
return mp_obj_new_str(buf, strlen(buf), false);
182177
}
183178
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
@@ -202,14 +197,10 @@ STATIC bool path_equal(const char *path, const char *path_canonical) {
202197
/// \function stat(path)
203198
/// Get the status of a file or directory.
204199
STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
205-
(void)vfs_in;
200+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
206201
const char *path = mp_obj_str_get_str(path_in);
207202

208203
FILINFO fno;
209-
#if _USE_LFN
210-
fno.lfname = NULL;
211-
fno.lfsize = 0;
212-
#endif
213204
FRESULT res;
214205

215206
if (path_equal(path, "/")) {
@@ -233,7 +224,7 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
233224
}
234225
if (res == FR_NO_PATH) {
235226
// stat normal file
236-
res = f_stat(path, &fno);
227+
res = f_stat(&self->fatfs, path, &fno);
237228
}
238229
if (res != FR_OK) {
239230
mp_raise_OSError(fresult_to_errno_table[res]);
@@ -272,12 +263,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
272263

273264
// Get the status of a VFS.
274265
STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
275-
(void)vfs_in;
276-
const char *path = mp_obj_str_get_str(path_in);
266+
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
267+
(void)path_in;
277268

278-
FATFS *fatfs;
279269
DWORD nclst;
280-
FRESULT res = f_getfree(path, &nclst, &fatfs);
270+
FATFS *fatfs = &self->fatfs;
271+
FRESULT res = f_getfree(fatfs, &nclst);
281272
if (FR_OK != res) {
282273
mp_raise_OSError(fresult_to_errno_table[res]);
283274
}

0 commit comments

Comments
 (0)