diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c index 24e0ff88cf..513b521631 100644 --- a/ports/stm32/factoryreset.c +++ b/ports/stm32/factoryreset.c @@ -25,6 +25,11 @@ */ #include "py/runtime.h" +#include "py/mperrno.h" +#include "extmod/vfs_fat.h" +#include "systick.h" +#include "led.h" +#include "storage.h" #include "factoryreset.h" #if MICROPY_HW_ENABLE_STORAGE @@ -96,4 +101,31 @@ MP_WEAK void factory_reset_make_files(FATFS *fatfs) { } } +MP_WEAK int factory_reset_create_filesystem(void) { + // LED on to indicate creation of local filesystem + led_state(PYB_LED_GREEN, 1); + uint32_t start_tick = HAL_GetTick(); + + fs_user_mount_t vfs; + pyb_flash_init_vfs(&vfs); + uint8_t working_buf[FF_MAX_SS]; + FRESULT res = f_mkfs(&vfs.fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); + if (res != FR_OK) { + mp_printf(&mp_plat_print, "MPY: can't create flash filesystem\n"); + return -MP_ENODEV; + } + + // Set label + f_setlabel(&vfs.fatfs, MICROPY_HW_FLASH_FS_LABEL); + + // Populate the filesystem with factory files + factory_reset_make_files(&vfs.fatfs); + + // Keep LED on for at least 200ms + systick_wait_at_least(start_tick, 200); + led_state(PYB_LED_GREEN, 0); + + return 0; // success +} + #endif // MICROPY_HW_ENABLE_STORAGE diff --git a/ports/stm32/factoryreset.h b/ports/stm32/factoryreset.h index 85226f880b..1d1f4b8571 100644 --- a/ports/stm32/factoryreset.h +++ b/ports/stm32/factoryreset.h @@ -29,5 +29,6 @@ #include "lib/oofatfs/ff.h" void factory_reset_make_files(FATFS *fatfs); +int factory_reset_create_filesystem(void); #endif // MICROPY_INCLUDED_STM32_FACTORYRESET_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 3c6420d50d..707b1fc68e 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" +#include "py/mperrno.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" @@ -81,10 +82,6 @@ STATIC pyb_thread_t pyb_thread_main; #endif -#if MICROPY_HW_ENABLE_STORAGE -STATIC fs_user_mount_t fs_user_mount_flash; -#endif - #if defined(MICROPY_HW_UART_REPL) #ifndef MICROPY_HW_UART_REPL_RXBUF #define MICROPY_HW_UART_REPL_RXBUF (260) @@ -159,65 +156,51 @@ STATIC mp_obj_t pyb_main(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); #if MICROPY_HW_ENABLE_STORAGE +STATIC int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) { + nlr_buf_t nlr; + mp_int_t ret = -MP_EIO; + if (nlr_push(&nlr) == 0) { + mp_obj_t args[] = { bdev, mount_point }; + mp_vfs_mount(2, args, (mp_map_t*)&mp_const_empty_map); + mp_vfs_chdir(mount_point); + ret = 0; // success + nlr_pop(); + } else { + mp_obj_base_t *exc = nlr.ret_val; + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { + mp_obj_t v = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); + mp_obj_get_int_maybe(v, &ret); // get errno value + ret = -ret; + } + } + return ret; +} + // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { - // init the vfs object - fs_user_mount_t *vfs_fat = &fs_user_mount_flash; - vfs_fat->blockdev.flags = 0; - pyb_flash_init_vfs(vfs_fat); + if (reset_mode == 3) { + // Asked by user to reset filesystem + factory_reset_create_filesystem(); + } - // try to mount the flash - FRESULT res = f_mount(&vfs_fat->fatfs); + // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. + mp_obj_t bdev = MP_OBJ_FROM_PTR(&pyb_flash_obj); + mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash); + int ret = vfs_mount_and_chdir(bdev, mount_point); - if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { - // no filesystem, or asked to reset it, so create a fresh one - - // LED on to indicate creation of LFS - led_state(PYB_LED_GREEN, 1); - uint32_t start_tick = HAL_GetTick(); - - uint8_t working_buf[FF_MAX_SS]; - res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); - if (res == FR_OK) { - // success creating fresh LFS - } else { - printf("MPY: can't create flash filesystem\n"); - return false; + if (ret == -MP_ENODEV && reset_mode != 3) { + // No filesystem (and didn't already create one), try to create a fresh one + ret = factory_reset_create_filesystem(); + if (ret == 0) { + ret = vfs_mount_and_chdir(bdev, mount_point); } + } - // set label - f_setlabel(&vfs_fat->fatfs, MICROPY_HW_FLASH_FS_LABEL); - - // populate the filesystem with factory files - factory_reset_make_files(&vfs_fat->fatfs); - - // keep LED on for at least 200ms - systick_wait_at_least(start_tick, 200); - led_state(PYB_LED_GREEN, 0); - } else if (res == FR_OK) { - // mount sucessful - } else { - fail: + if (ret != 0) { printf("MPY: can't mount flash\n"); return false; } - // mount the flash device (there should be no other devices mounted at this point) - // we allocate this structure on the heap because vfs->next is a root pointer - mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); - if (vfs == NULL) { - goto fail; - } - vfs->str = "/flash"; - vfs->len = 6; - vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); - vfs->next = NULL; - MP_STATE_VM(vfs_mount_table) = vfs; - - // The current directory is used as the boot up directory. - // It is set to the internal flash filesystem by default. - MP_STATE_PORT(vfs_cur) = vfs; - return true; } #endif @@ -616,7 +599,7 @@ soft_reset: // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // if there is a file in the flash called "SKIPSD", then we don't mount the SD card - if (!mounted_flash || f_stat(&fs_user_mount_flash.fatfs, "/SKIPSD", NULL) != FR_OK) { + if (!mounted_flash || mp_vfs_import_stat("SKIPSD") == MP_IMPORT_STAT_FILE) { mounted_sdcard = init_sdcard_fs(); } } diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index d9d5464855..905d51f325 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -234,7 +234,7 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t // Expose the flash as an object with the block protocol. // there is a singleton Flash object -STATIC const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; +const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments diff --git a/ports/stm32/storage.h b/ports/stm32/storage.h index 826b465a66..0ba3497a17 100644 --- a/ports/stm32/storage.h +++ b/ports/stm32/storage.h @@ -63,6 +63,7 @@ int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uin int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks); extern const struct _mp_obj_type_t pyb_flash_type; +extern const struct _mp_obj_base_t pyb_flash_obj; struct _fs_user_mount_t; void pyb_flash_init_vfs(struct _fs_user_mount_t *vfs);