15
15
#include "supervisor/flash.h"
16
16
#include "supervisor/linker.h"
17
17
18
- static mp_vfs_mount_t _mp_vfs ;
19
- static fs_user_mount_t _internal_vfs ;
18
+ static mp_vfs_mount_t _circuitpy_vfs ;
19
+ static fs_user_mount_t _circuitpy_usermount ;
20
+
21
+ #if CIRCUITPY_SAVES_PARTITION_SIZE > 0
22
+ static mp_vfs_mount_t _saves_vfs ;
23
+ static fs_user_mount_t _saves_usermount ;
24
+ #endif
20
25
21
26
static volatile uint32_t filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS ;
22
27
volatile bool filesystem_flush_requested = false;
@@ -73,23 +78,37 @@ static void make_file_with_contents(FATFS *fatfs, const char *filename, const by
73
78
// want it to be executed without using stack within main() function
74
79
bool filesystem_init (bool create_allowed , bool force_create ) {
75
80
// init the vfs object
76
- fs_user_mount_t * vfs_fat = & _internal_vfs ;
77
- vfs_fat -> blockdev .flags = 0 ;
78
- supervisor_flash_init_vfs (vfs_fat );
81
+ fs_user_mount_t * circuitpy = & _circuitpy_usermount ;
82
+ circuitpy -> blockdev .flags = 0 ;
83
+ supervisor_flash_init_vfs (circuitpy );
84
+
85
+ #if CIRCUITPY_SAVES_PARTITION_SIZE > 0
86
+ // SAVES is placed before CIRCUITPY so that CIRCUITPY takes up the remaining space.
87
+ circuitpy -> blockdev .offset = CIRCUITPY_SAVES_PARTITION_SIZE ;
88
+ circuitpy -> blockdev .size = -1 ;
89
+
90
+ fs_user_mount_t * saves = & _saves_usermount ;
91
+ saves -> blockdev .flags = 0 ;
92
+ saves -> blockdev .offset = 0 ;
93
+ saves -> blockdev .size = CIRCUITPY_SAVES_PARTITION_SIZE ;
94
+ supervisor_flash_init_vfs (saves );
95
+ filesystem_set_concurrent_write_protection (saves , true);
96
+ filesystem_set_writable_by_usb (saves , false);
97
+ #endif
79
98
80
- mp_vfs_mount_t * vfs = & _mp_vfs ;
81
- vfs -> len = 0 ;
99
+ mp_vfs_mount_t * circuitpy_vfs = & _circuitpy_vfs ;
100
+ circuitpy_vfs -> len = 0 ;
82
101
83
102
// try to mount the flash
84
- FRESULT res = f_mount (& vfs_fat -> fatfs );
103
+ FRESULT res = f_mount (& circuitpy -> fatfs );
85
104
if ((res == FR_NO_FILESYSTEM && create_allowed ) || force_create ) {
86
105
// No filesystem so create a fresh one, or reformat has been requested.
87
106
uint8_t working_buf [FF_MAX_SS ];
88
107
BYTE formats = FM_FAT ;
89
108
#if FF_FS_EXFAT
90
109
formats |= FM_EXFAT | FM_FAT32 ;
91
110
#endif
92
- res = f_mkfs (& vfs_fat -> fatfs , formats , 0 , working_buf , sizeof (working_buf ));
111
+ res = f_mkfs (& circuitpy -> fatfs , formats , 0 , working_buf , sizeof (working_buf ));
93
112
if (res != FR_OK ) {
94
113
return false;
95
114
}
@@ -98,46 +117,66 @@ bool filesystem_init(bool create_allowed, bool force_create) {
98
117
99
118
// set label
100
119
#ifdef CIRCUITPY_DRIVE_LABEL
101
- res = f_setlabel (& vfs_fat -> fatfs , CIRCUITPY_DRIVE_LABEL );
120
+ res = f_setlabel (& circuitpy -> fatfs , CIRCUITPY_DRIVE_LABEL );
102
121
#else
103
- res = f_setlabel (& vfs_fat -> fatfs , "CIRCUITPY" );
122
+ res = f_setlabel (& circuitpy -> fatfs , "CIRCUITPY" );
104
123
#endif
105
124
if (res != FR_OK ) {
106
125
return false;
107
126
}
108
127
109
128
#if CIRCUITPY_USB_DEVICE
110
129
// inhibit file indexing on MacOS
111
- res = f_mkdir (& vfs_fat -> fatfs , "/.fseventsd" );
130
+ res = f_mkdir (& circuitpy -> fatfs , "/.fseventsd" );
112
131
if (res != FR_OK ) {
113
132
return false;
114
133
}
115
- make_empty_file (& vfs_fat -> fatfs , "/.fseventsd/no_log" );
116
- make_empty_file (& vfs_fat -> fatfs , "/.metadata_never_index" );
134
+ make_empty_file (& circuitpy -> fatfs , "/.fseventsd/no_log" );
135
+ make_empty_file (& circuitpy -> fatfs , "/.metadata_never_index" );
117
136
118
137
// Prevent storing trash on all OSes.
119
- make_empty_file (& vfs_fat -> fatfs , "/.Trashes" ); // MacOS
120
- make_empty_file (& vfs_fat -> fatfs , "/.Trash-1000" ); // Linux, XDG trash spec:
138
+ make_empty_file (& circuitpy -> fatfs , "/.Trashes" ); // MacOS
139
+ make_empty_file (& circuitpy -> fatfs , "/.Trash-1000" ); // Linux, XDG trash spec:
121
140
// https://specifications.freedesktop.org/trash-spec/trashspec-latest.html
122
141
#endif
123
142
124
143
#if CIRCUITPY_SDCARDIO || CIRCUITPY_SDIOIO
125
- res = f_mkdir (& vfs_fat -> fatfs , "/sd" );
144
+ res = f_mkdir (& circuitpy -> fatfs , "/sd" );
126
145
#if CIRCUITPY_FULL_BUILD
127
- MAKE_FILE_WITH_OPTIONAL_CONTENTS (& vfs_fat -> fatfs , "/sd/placeholder.txt" ,
146
+ MAKE_FILE_WITH_OPTIONAL_CONTENTS (& circuitpy -> fatfs , "/sd/placeholder.txt" ,
128
147
"SD cards mounted at /sd will hide this file from Python."
129
148
" SD cards are not visible via USB CIRCUITPY.\n" );
130
149
#endif
131
150
#endif
132
151
152
+ #if CIRCUITPY_SAVES_PARTITION_SIZE > 0
153
+ res = f_mkfs (& saves -> fatfs , formats , 0 , working_buf , sizeof (working_buf ));
154
+ if (res == FR_OK ) {
155
+ // Flush the new file system to make sure it's repaired immediately.
156
+ supervisor_flash_flush ();
157
+ res = f_setlabel (& saves -> fatfs , "CPSAVES" );
158
+ }
159
+
160
+ if (res == FR_OK ) {
161
+ res = f_mkdir (& circuitpy -> fatfs , "/saves" );
162
+ }
163
+ #if CIRCUITPY_FULL_BUILD
164
+ if (res == FR_OK ) {
165
+ MAKE_FILE_WITH_OPTIONAL_CONTENTS (& circuitpy -> fatfs , "/saves/placeholder.txt" ,
166
+ "A separate filesystem mounted at /saves will hide this file from Python."
167
+ " Saves are visible via USB CPSAVES.\n" );
168
+ }
169
+ #endif
170
+ #endif
171
+
133
172
#if CIRCUITPY_OS_GETENV
134
- make_empty_file (& vfs_fat -> fatfs , "/settings.toml" );
173
+ make_empty_file (& circuitpy -> fatfs , "/settings.toml" );
135
174
#endif
136
175
// make a sample code.py file
137
- MAKE_FILE_WITH_OPTIONAL_CONTENTS (& vfs_fat -> fatfs , "/code.py" , "print(\"Hello World!\")\n" );
176
+ MAKE_FILE_WITH_OPTIONAL_CONTENTS (& circuitpy -> fatfs , "/code.py" , "print(\"Hello World!\")\n" );
138
177
139
178
// create empty lib directory
140
- res = f_mkdir (& vfs_fat -> fatfs , "/lib" );
179
+ res = f_mkdir (& circuitpy -> fatfs , "/lib" );
141
180
if (res != FR_OK ) {
142
181
return false;
143
182
}
@@ -148,16 +187,28 @@ bool filesystem_init(bool create_allowed, bool force_create) {
148
187
return false;
149
188
}
150
189
151
- vfs -> str = "/" ;
152
- vfs -> len = 1 ;
153
- vfs -> obj = MP_OBJ_FROM_PTR (vfs_fat );
154
- vfs -> next = NULL ;
155
-
156
- MP_STATE_VM (vfs_mount_table ) = vfs ;
190
+ circuitpy_vfs -> str = "/" ;
191
+ circuitpy_vfs -> len = 1 ;
192
+ circuitpy_vfs -> obj = MP_OBJ_FROM_PTR (circuitpy );
193
+ circuitpy_vfs -> next = NULL ;
194
+
195
+ MP_STATE_VM (vfs_mount_table ) = circuitpy_vfs ;
196
+
197
+ #if CIRCUITPY_SAVES_PARTITION_SIZE > 0
198
+ res = f_mount (& saves -> fatfs );
199
+ if (res == FR_OK ) {
200
+ mp_vfs_mount_t * saves_vfs = & _saves_vfs ;
201
+ saves_vfs -> str = "/saves" ;
202
+ saves_vfs -> len = 6 ;
203
+ saves_vfs -> obj = MP_OBJ_FROM_PTR (& _saves_usermount );
204
+ saves_vfs -> next = MP_STATE_VM (vfs_mount_table );
205
+ MP_STATE_VM (vfs_mount_table ) = saves_vfs ;
206
+ }
207
+ #endif
157
208
158
209
// The current directory is used as the boot up directory.
159
210
// It is set to the internal flash filesystem by default.
160
- MP_STATE_PORT (vfs_cur ) = vfs ;
211
+ MP_STATE_PORT (vfs_cur ) = circuitpy_vfs ;
161
212
162
213
#if CIRCUITPY_STORAGE_EXTEND
163
214
supervisor_flash_update_extended ();
@@ -175,7 +226,7 @@ void PLACE_IN_ITCM(filesystem_flush)(void) {
175
226
}
176
227
177
228
void filesystem_set_internal_writable_by_usb (bool writable ) {
178
- fs_user_mount_t * vfs = & _internal_vfs ;
229
+ fs_user_mount_t * vfs = & _circuitpy_usermount ;
179
230
180
231
filesystem_set_writable_by_usb (vfs , writable );
181
232
}
@@ -199,7 +250,7 @@ bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) {
199
250
}
200
251
201
252
void filesystem_set_internal_concurrent_write_protection (bool concurrent_write_protection ) {
202
- filesystem_set_concurrent_write_protection (& _internal_vfs , concurrent_write_protection );
253
+ filesystem_set_concurrent_write_protection (& _circuitpy_usermount , concurrent_write_protection );
203
254
}
204
255
205
256
void filesystem_set_concurrent_write_protection (fs_user_mount_t * vfs , bool concurrent_write_protection ) {
@@ -211,14 +262,14 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu
211
262
}
212
263
213
264
bool filesystem_present (void ) {
214
- return _mp_vfs .len > 0 ;
265
+ return _circuitpy_vfs .len > 0 ;
215
266
}
216
267
217
268
fs_user_mount_t * filesystem_circuitpy (void ) {
218
269
if (!filesystem_present ()) {
219
270
return NULL ;
220
271
}
221
- return & _internal_vfs ;
272
+ return & _circuitpy_usermount ;
222
273
}
223
274
224
275
fs_user_mount_t * filesystem_for_path (const char * path_in , const char * * path_under_mount ) {
0 commit comments