diff --git a/main.c b/main.c index 0ad0506082..b88fd735ba 100644 --- a/main.c +++ b/main.c @@ -245,7 +245,7 @@ int __attribute__((used)) main(void) { // Create a new filesystem only if we're not in a safe mode. // A power brownout here could make it appear as if there's // no SPI flash filesystem, and we might erase the existing one. - filesystem_init(safe_mode == NO_SAFE_MODE); + filesystem_init(safe_mode == NO_SAFE_MODE, false); // Reset everything and prep MicroPython to run boot.py. reset_port(); diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c index bff78a41c2..a165d8887d 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/ports/atmel-samd/supervisor/filesystem.c @@ -50,7 +50,7 @@ static void make_empty_file(FATFS *fatfs, const char *path) { // we don't make this function static because it needs a lot of stack and we // want it to be executed without using stack within main() function -void filesystem_init(bool create_allowed) { +void filesystem_init(bool create_allowed, bool create_force) { // init the vfs object fs_user_mount_t *vfs_fat = &fs_user_mount_flash; vfs_fat->flags = 0; @@ -59,11 +59,11 @@ void filesystem_init(bool create_allowed) { // try to mount the flash FRESULT res = f_mount(&vfs_fat->fatfs); - if (res == FR_NO_FILESYSTEM && create_allowed) { - // no filesystem so create a fresh one + if ((res == FR_NO_FILESYSTEM && create_allowed) || create_force) { + // No filesystem so create a fresh one, or reformat has been requested. uint8_t working_buf[_MAX_SS]; res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); - // Flush the new file system to make sure its repaired immediately. + // Flush the new file system to make sure it's repaired immediately. flash_flush(); if (res != FR_OK) { return; diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 734cabcc1c..2195d22423 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -131,6 +131,24 @@ mp_obj_t storage_getmount(const mp_obj_t mnt_in) { } MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); +//| .. function:: erase_filesystem() +//| +//| Erase and re-create the ``CIRCUITPY`` filesystem. Then call +//| `microcontroller.reset()` to restart CircuitPython and have the +//| host computer remount CIRCUITPY. +//| +//| This function can be called from the REPL when ``CIRCUITPY`` +//| has become corrupted. +//| +//| .. warning:: All the data on ``CIRCUITPY`` will be lost, and +//| CircuitPython will restart. + +mp_obj_t storage_erase_filesystem(void) { + common_hal_storage_erase_filesystem(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(storage_erase_filesystem_obj, storage_erase_filesystem); + STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) }, @@ -138,6 +156,7 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&storage_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) }, { MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) }, + { MP_ROM_QSTR(MP_QSTR_erase_filesystem), MP_ROM_PTR(&storage_erase_filesystem_obj) }, //| .. class:: VfsFat(block_device) //| diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index 76b9ae854f..6a0cb9fc71 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -35,5 +35,6 @@ void common_hal_storage_umount_path(const char* path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char* path, bool readonly); mp_obj_t common_hal_storage_getmount(const char* path); +void common_hal_storage_erase_filesystem(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 5b0bbe01ec..f1fa74990a 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -32,7 +32,9 @@ #include "py/mperrno.h" #include "py/obj.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/storage/__init__.h" +#include "supervisor/filesystem.h" STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { if (vfs == MP_VFS_NONE) { @@ -125,3 +127,9 @@ void common_hal_storage_umount_path(const char* mount_path) { mp_obj_t common_hal_storage_getmount(const char *mount_path) { return storage_object_from_path(mount_path); } + +void common_hal_storage_erase_filesystem(void) { + filesystem_init(false, true); // Force a re-format. + common_hal_mcu_reset(); + // We won't actually get here, since we're resetting. +} diff --git a/supervisor/filesystem.h b/supervisor/filesystem.h index cfd1ed0273..63da0bcab5 100644 --- a/supervisor/filesystem.h +++ b/supervisor/filesystem.h @@ -29,7 +29,7 @@ #include -void filesystem_init(bool create_allowed); +void filesystem_init(bool create_allowed, bool create_force); void filesystem_flush(void); void filesystem_writable_by_python(bool writable); bool filesystem_present(void);