Skip to content

Commit b33a770

Browse files
committed
extmod/fsusermount: Support mounting of multiple block devices.
This patch adds support to fsusermount for multiple block devices (instead of just one). The maximum allowed is fixed at compile time by the size of the fs_user_mount array accessed via MP_STATE_PORT, which in turn is set by MICROPY_FATFS_VOLUMES. With this patch, stmhal (which is still tightly coupled to fsusermount) is also modified to support mounting multiple devices And the flash and SD card are now just two block devices that are mounted at start up if they exist (and they have special native code to make them more efficient).
1 parent 34023eb commit b33a770

12 files changed

Lines changed: 289 additions & 278 deletions

File tree

extmod/fsusermount.c

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,33 +53,46 @@ STATIC mp_obj_t fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
5353
if (device == mp_const_none) {
5454
// umount
5555
FRESULT res = FR_NO_FILESYSTEM;
56-
if (MP_STATE_PORT(fs_user_mount) != NULL) {
57-
res = f_mount(NULL, MP_STATE_PORT(fs_user_mount)->str, 0);
58-
m_del_obj(fs_user_mount_t, MP_STATE_PORT(fs_user_mount));
59-
MP_STATE_PORT(fs_user_mount) = NULL;
56+
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
57+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
58+
if (vfs != NULL && !memcmp(mnt_str, vfs->str, mnt_len + 1)) {
59+
res = f_mount(NULL, vfs->str, 0);
60+
if (vfs->flags & FSUSER_FREE_OBJ) {
61+
m_del_obj(fs_user_mount_t, vfs);
62+
}
63+
MP_STATE_PORT(fs_user_mount)[i] = NULL;
64+
break;
65+
}
6066
}
6167
if (res != FR_OK) {
6268
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't umount"));
6369
}
6470
} else {
6571
// mount
66-
if (MP_STATE_PORT(fs_user_mount) != NULL) {
67-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "device already mounted"));
72+
size_t i = 0;
73+
for (; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
74+
if (MP_STATE_PORT(fs_user_mount)[i] == NULL) {
75+
break;
76+
}
77+
}
78+
if (i == MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
79+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "too many devices mounted"));
6880
}
6981

7082
// create new object
7183
fs_user_mount_t *vfs;
72-
MP_STATE_PORT(fs_user_mount) = vfs = m_new_obj(fs_user_mount_t);
84+
MP_STATE_PORT(fs_user_mount)[i] = vfs = m_new_obj(fs_user_mount_t);
7385
vfs->str = mnt_str;
7486
vfs->len = mnt_len;
87+
vfs->flags = FSUSER_FREE_OBJ;
7588

7689
// load block protocol methods
7790
mp_load_method(device, MP_QSTR_readblocks, vfs->readblocks);
7891
mp_load_method_maybe(device, MP_QSTR_writeblocks, vfs->writeblocks);
7992
mp_load_method_maybe(device, MP_QSTR_ioctl, vfs->u.ioctl);
8093
if (vfs->u.ioctl[0] != MP_OBJ_NULL) {
8194
// device supports new block protocol, so indicate it
82-
vfs->u.old.count[1] = MP_OBJ_SENTINEL;
95+
vfs->flags |= FSUSER_HAVE_IOCTL;
8396
} else {
8497
// no ioctl method, so assume the device uses the old block protocol
8598
mp_load_method_maybe(device, MP_QSTR_sync, vfs->u.old.sync);
@@ -114,7 +127,7 @@ STATIC mp_obj_t fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
114127
if (res != FR_OK) {
115128
goto mkfs_error;
116129
}
117-
MP_STATE_PORT(fs_user_mount) = NULL;
130+
MP_STATE_PORT(fs_user_mount)[i] = NULL;
118131
}
119132
} else {
120133
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't mount"));
@@ -141,30 +154,39 @@ STATIC mp_obj_t fatfs_mount(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
141154
MP_DEFINE_CONST_FUN_OBJ_KW(fsuser_mount_obj, 2, fatfs_mount);
142155

143156
STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
144-
if (MP_STATE_PORT(fs_user_mount) == NULL) {
145-
goto einval;
146-
}
147-
157+
size_t i = 0;
148158
if (MP_OBJ_IS_STR(bdev_or_path_in)) {
149159
mp_uint_t mnt_len;
150160
const char *mnt_str = mp_obj_str_get_data(bdev_or_path_in, &mnt_len);
151-
if (memcmp(mnt_str, MP_STATE_PORT(fs_user_mount)->str, mnt_len + 1)) {
152-
goto einval;
161+
for (; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
162+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
163+
if (!memcmp(mnt_str, vfs->str, mnt_len + 1)) {
164+
break;
165+
}
153166
}
154-
} else if (bdev_or_path_in != MP_STATE_PORT(fs_user_mount)->readblocks[1]) {
155-
goto einval;
167+
} else {
168+
for (; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
169+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
170+
if (bdev_or_path_in == vfs->readblocks[1]) {
171+
break;
172+
}
173+
}
174+
}
175+
176+
if (i == MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
177+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
156178
}
157179

158-
FRESULT res = f_mount(NULL, MP_STATE_PORT(fs_user_mount)->str, 0);
159-
m_del_obj(fs_user_mount_t, MP_STATE_PORT(fs_user_mount));
160-
MP_STATE_PORT(fs_user_mount) = NULL;
180+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
181+
FRESULT res = f_mount(NULL, vfs->str, 0);
182+
if (vfs->flags & FSUSER_FREE_OBJ) {
183+
m_del_obj(fs_user_mount_t, vfs);
184+
}
185+
MP_STATE_PORT(fs_user_mount)[i] = NULL;
161186
if (res != FR_OK) {
162187
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't umount"));
163188
}
164189
return mp_const_none;
165-
166-
einval:
167-
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
168190
}
169191
MP_DEFINE_CONST_FUN_OBJ_1(fsuser_umount_obj, fatfs_umount);
170192

extmod/fsusermount.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
// these are the values for fs_user_mount_t.flags
28+
#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func
29+
#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount
30+
#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl
31+
2732
typedef struct _fs_user_mount_t {
2833
const char *str;
29-
mp_uint_t len;
34+
uint16_t len; // length of str
35+
uint16_t flags;
3036
mp_obj_t readblocks[4];
3137
mp_obj_t writeblocks[4];
3238
// new protocol uses just ioctl, old uses sync (optional) and count
33-
// if ioctl[3]=count[1]=MP_OBJ_SENTINEL then we have the new protocol, else old
3439
union {
3540
mp_obj_t ioctl[4];
3641
struct {

0 commit comments

Comments
 (0)