stm32: Generalise flash mounting code so it supports arbitrary FS.
This commit refactors and generalises the boot-mount routine on stm32 so that it can mount filesystems of arbitrary type. That is, it no longer assumes that the filesystem is FAT. It does this by using mp_vfs_mount() which does auto-detection of the filesystem type.
This commit is contained in:
parent
0527baf7fa
commit
7723dac337
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user