diff options
-rw-r--r-- | stmhal/Makefile | 8 | ||||
-rw-r--r-- | stmhal/builtin_open.c | 30 | ||||
-rw-r--r-- | stmhal/fatfs_port.c | 15 | ||||
-rw-r--r-- | stmhal/import.c | 35 | ||||
-rw-r--r-- | stmhal/main.c | 99 | ||||
-rw-r--r-- | stmhal/modmachine.c | 20 | ||||
-rw-r--r-- | stmhal/modpyb.c | 8 | ||||
-rw-r--r-- | stmhal/moduos.c | 294 | ||||
-rw-r--r-- | stmhal/mpconfigport.h | 16 | ||||
-rw-r--r-- | stmhal/sdcard.c | 5 | ||||
-rw-r--r-- | stmhal/storage.c | 5 |
11 files changed, 114 insertions, 421 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile index 87236068ba..3431c31050 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -26,7 +26,7 @@ CMSIS_DIR=cmsis HAL_DIR=hal/$(MCU_SERIES) USBDEV_DIR=usbdev #USBHOST_DIR=usbhost -FATFS_DIR=lib/fatfs +FATFS_DIR=lib/oofatfs DFU=../tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 @@ -109,8 +109,8 @@ SRC_LIB = $(addprefix lib/,\ libm/sf_erf.c \ libm/wf_lgamma.c \ libm/wf_tgamma.c \ - fatfs/ff.c \ - fatfs/option/ccsbcs.c \ + oofatfs/ff.c \ + oofatfs/option/unicode.c \ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ @@ -159,14 +159,12 @@ SRC_C = \ modutime.c \ modusocket.c \ modnetwork.c \ - import.c \ extint.c \ usrsw.c \ rng.c \ rtc.c \ flash.c \ storage.c \ - builtin_open.c \ sdcard.c \ fatfs_port.c \ lcd.c \ diff --git a/stmhal/builtin_open.c b/stmhal/builtin_open.c deleted file mode 100644 index 56b98ea61c..0000000000 --- a/stmhal/builtin_open.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/runtime.h" -#include "extmod/vfs_fat.h" - -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, fatfs_builtin_open); diff --git a/stmhal/fatfs_port.c b/stmhal/fatfs_port.c index 421ceddbaf..17ec3f7266 100644 --- a/stmhal/fatfs_port.c +++ b/stmhal/fatfs_port.c @@ -24,23 +24,10 @@ * THE SOFTWARE. */ -#include "py/mphal.h" #include "py/runtime.h" -#include "lib/fatfs/ff.h" /* FatFs lower layer API */ -#include "lib/fatfs/diskio.h" /* FatFs lower layer API */ +#include "lib/oofatfs/ff.h" #include "rtc.h" -const PARTITION VolToPart[MICROPY_FATFS_VOLUMES] = { - {0, 1}, // Logical drive 0 ==> Physical drive 0, 1st partition - {1, 0}, // Logical drive 1 ==> Physical drive 1 (auto detection) - {2, 0}, // Logical drive 2 ==> Physical drive 2 (auto detection) - {3, 0}, // Logical drive 3 ==> Physical drive 3 (auto detection) - /* - {0, 2}, // Logical drive 2 ==> Physical drive 0, 2nd partition - {0, 3}, // Logical drive 3 ==> Physical drive 0, 3rd partition - */ -}; - DWORD get_fattime(void) { rtc_init_finalise(); RTC_TimeTypeDef time; diff --git a/stmhal/import.c b/stmhal/import.c deleted file mode 100644 index 2bc282e7b7..0000000000 --- a/stmhal/import.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <stdio.h> - -#include "py/lexer.h" -#include "lib/fatfs/ff.h" -#include "extmod/vfs_fat.h" - -mp_import_stat_t mp_import_stat(const char *path) { - return fat_vfs_import_stat(NULL, path); -} diff --git a/stmhal/main.c b/stmhal/main.c index 78afe54ef6..1918658b7b 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -37,7 +37,8 @@ #include "py/mphal.h" #include "lib/utils/pyexec.h" -#include "lib/fatfs/ff.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs.h" #include "extmod/fsusermount.h" #include "systick.h" @@ -67,6 +68,7 @@ void SystemClock_Config(void); fs_user_mount_t fs_user_mount_flash; +mp_vfs_mount_t mp_vfs_mount_flash; void flash_error(int n) { for (int i = 0; i < n; i++) { @@ -168,17 +170,14 @@ static const char fresh_readme_txt[] = // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // init the vfs object - fs_user_mount_t *vfs = &fs_user_mount_flash; - vfs->str = "/flash"; - vfs->len = 6; - vfs->flags = 0; - pyb_flash_init_vfs(vfs); - - // put the flash device in slot 0 (it will be unused at this point) - MP_STATE_PORT(fs_user_mount)[0] = vfs; + fs_user_mount_t *vfs_fat = &fs_user_mount_flash; + vfs_fat->str = NULL; + vfs_fat->len = 0; + vfs_fat->flags = 0; + pyb_flash_init_vfs(vfs_fat); // try to mount the flash - FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); + FRESULT res = f_mount(&vfs_fat->fatfs); if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { // no filesystem, or asked to reset it, so create a fresh one @@ -187,33 +186,33 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); - res = f_mkfs("/flash", 0, 0); + uint8_t working_buf[_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("PYB: can't create flash filesystem\n"); - MP_STATE_PORT(fs_user_mount)[0] = NULL; return; } // set label - f_setlabel("/flash/pybflash"); + f_setlabel(&vfs_fat->fatfs, "pybflash"); // create empty main.py FIL fp; - f_open(&fp, "/flash/main.py", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/main.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // create .inf driver file - f_open(&fp, "/flash/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n); f_close(&fp); // create readme file - f_open(&fp, "/flash/README.txt", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/README.txt", FA_WRITE | FA_CREATE_ALWAYS); f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n); f_close(&fp); @@ -224,30 +223,25 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // mount sucessful } else { printf("PYB: can't mount flash\n"); - MP_STATE_PORT(fs_user_mount)[0] = NULL; return; } + // mount the flash device (there should be no other devices mounted at this point) + mp_vfs_mount_t *vfs = &mp_vfs_mount_flash; + 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. - f_chdrive("/flash"); + MP_STATE_PORT(vfs_cur) = vfs; // Make sure we have a /flash/boot.py. Create it if needed. FILINFO fno; -#if _USE_LFN - fno.lfname = NULL; - fno.lfsize = 0; -#endif - res = f_stat("/flash/boot.py", &fno); - if (res == FR_OK) { - if (fno.fattrib & AM_DIR) { - // exists as a directory - // TODO handle this case - // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation - } else { - // exists as a file, good! - } - } else { + res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno); + if (res != FR_OK) { // doesn't exist, create fresh file // LED on to indicate creation of boot.py @@ -255,7 +249,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { uint32_t start_tick = HAL_GetTick(); FIL fp; - f_open(&fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes @@ -485,24 +479,29 @@ soft_reset: // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // create vfs object - fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t); - if (vfs == NULL) { + fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); + mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); + if (vfs == NULL || vfs_fat == NULL) { goto no_mem_for_sd; } - vfs->str = "/sd"; - vfs->len = 3; - vfs->flags = FSUSER_FREE_OBJ; - sdcard_init_vfs(vfs); - - // put the sd device in slot 1 (it will be unused at this point) - MP_STATE_PORT(fs_user_mount)[1] = vfs; + vfs_fat->str = NULL; + vfs_fat->len = 0; + vfs_fat->flags = FSUSER_FREE_OBJ; + sdcard_init_vfs(vfs_fat); - FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); + FRESULT res = f_mount(&vfs_fat->fatfs); if (res != FR_OK) { printf("PYB: can't mount SD card\n"); - MP_STATE_PORT(fs_user_mount)[1] = NULL; - m_del_obj(fs_user_mount_t, vfs); + m_del_obj(fs_user_mount_t, vfs_fat); + m_del_obj(mp_vfs_mount_t, vfs); } else { + // mount the sd device after the internal flash + vfs->str = "/sd"; + vfs->len = 3; + vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); + vfs->next = NULL; + MP_STATE_VM(vfs_mount_table)->next = vfs; + // TODO these should go before the /flash entries in the path mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); @@ -520,7 +519,7 @@ soft_reset: #endif { // use SD card as current directory - f_chdrive("/sd"); + MP_STATE_PORT(vfs_cur) = vfs; } } no_mem_for_sd:; @@ -534,8 +533,8 @@ soft_reset: // TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py if (reset_mode == 1 || reset_mode == 3) { const char *boot_py = "boot.py"; - FRESULT res = f_stat(boot_py, NULL); - if (res == FR_OK) { + mp_import_stat_t stat = mp_import_stat(boot_py); + if (stat == MP_IMPORT_STAT_FILE) { int ret = pyexec_file(boot_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; @@ -597,8 +596,8 @@ soft_reset: } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } - FRESULT res = f_stat(main_py, NULL); - if (res == FR_OK) { + mp_import_stat_t stat = mp_import_stat(main_py); + if (stat == MP_IMPORT_STAT_FILE) { int ret = pyexec_file(main_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 7a337adb69..aec8e29c51 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -25,6 +25,7 @@ */ #include <stdio.h> +#include <string.h> #include "modmachine.h" #include "py/gc.h" @@ -34,8 +35,9 @@ #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" #include "lib/utils/pyexec.h" -#include "lib/fatfs/ff.h" -#include "lib/fatfs/diskio.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs.h" +#include "extmod/fsusermount.h" #include "gccollect.h" #include "irq.h" #include "rng.h" @@ -144,10 +146,16 @@ STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) { // free space on flash { - DWORD nclst; - FATFS *fatfs; - f_getfree("/flash", &nclst, &fatfs); - printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); + for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { + if (strncmp("/flash", vfs->str, vfs->len) == 0) { + // assumes that it's a FatFs filesystem + fs_user_mount_t *vfs_fat = MP_OBJ_TO_PTR(vfs->obj); + DWORD nclst; + f_getfree(&vfs_fat->fatfs, &nclst); + printf("LFS free: %u bytes\n", (uint)(nclst * vfs_fat->fatfs.csize * 512)); + break; + } + } } if (n_args == 1) { diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index e602234fc6..53b4335e79 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -35,8 +35,8 @@ #include "py/gc.h" #include "py/builtin.h" #include "lib/utils/pyexec.h" -#include "lib/fatfs/ff.h" -#include "lib/fatfs/diskio.h" +#include "lib/oofatfs/ff.h" +#include "lib/oofatfs/diskio.h" #include "gccollect.h" #include "irq.h" #include "systick.h" @@ -61,7 +61,7 @@ #include "usb.h" #include "portmodules.h" #include "modmachine.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs.h" #include "extmod/utime_mphal.h" /// \function millis() @@ -166,7 +166,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&mp_utime_sleep_ms_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&mp_utime_sleep_us_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&fsuser_mount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&mp_vfs_mount_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type }, diff --git a/stmhal/moduos.c b/stmhal/moduos.c index 158e530ff4..976d7f089d 100644 --- a/stmhal/moduos.c +++ b/stmhal/moduos.c @@ -31,15 +31,14 @@ #include "py/runtime.h" #include "py/objtuple.h" #include "py/objstr.h" +#include "lib/oofatfs/ff.h" +#include "lib/oofatfs/diskio.h" +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" #include "genhdr/mpversion.h" -#include "lib/fatfs/ff.h" -#include "lib/fatfs/diskio.h" #include "timeutils.h" #include "rng.h" #include "uart.h" -#include "extmod/vfs_fat.h" -#include "sdcard.h" -#include "extmod/fsusermount.h" #include "portmodules.h" /// \module os - basic "operating system" services @@ -80,263 +79,13 @@ STATIC mp_obj_t os_uname(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); -/// \function chdir(path) -/// Change current directory. -STATIC mp_obj_t os_chdir(mp_obj_t path_in) { - const char *path; - path = mp_obj_str_get_str(path_in); - - FRESULT res = f_chdrive(path); - - if (res == FR_OK) { - res = f_chdir(path); - } - - if (res != FR_OK) { - // TODO should be mp_type_FileNotFoundError - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path)); - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); - -/// \function getcwd() -/// Get the current directory. -STATIC mp_obj_t os_getcwd(void) { - char buf[MICROPY_ALLOC_PATH_MAX + 1]; - FRESULT res = f_getcwd(buf, sizeof buf); - - if (res != FR_OK) { - mp_raise_OSError(fresult_to_errno_table[res]); - } - - return mp_obj_new_str(buf, strlen(buf), false); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); - -/// \function listdir([dir]) -/// With no argument, list the current directory. Otherwise list the given directory. -STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) { - bool is_str_type = true; - const char *path; - if (n_args == 1) { - if (mp_obj_get_type(args[0]) == &mp_type_bytes) { - is_str_type = false; - } - path = mp_obj_str_get_str(args[0]); - } else { - path = ""; - } - - // "hack" to list root directory - if (path[0] == '/' && path[1] == '\0') { - mp_obj_t dir_list = mp_obj_new_list(0, NULL); - for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) { - fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i]; - if (vfs != NULL) { - mp_obj_list_append(dir_list, mp_obj_new_str(vfs->str + 1, vfs->len - 1, false)); - } - } - return dir_list; - } - - return fat_vfs_listdir(path, is_str_type); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir); - -/// \function mkdir(path) -/// Create a new directory. -STATIC mp_obj_t os_mkdir(mp_obj_t path_o) { - const char *path = mp_obj_str_get_str(path_o); - FRESULT res = f_mkdir(path); - switch (res) { - case FR_OK: - return mp_const_none; - case FR_EXIST: - // TODO should be FileExistsError - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path)); - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir); - -/// \function remove(path) -/// Remove a file. -STATIC mp_obj_t os_remove(mp_obj_t path_o) { - const char *path = mp_obj_str_get_str(path_o); - // TODO check that path is actually a file before trying to unlink it - FRESULT res = f_unlink(path); - switch (res) { - case FR_OK: - return mp_const_none; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove); - -/// \function rename(old_path, new_path) -/// Rename a file -STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) { - const char *old_path = mp_obj_str_get_str(path_in); - const char *new_path = mp_obj_str_get_str(path_out); - FRESULT res = f_rename(old_path, new_path); - if (res == FR_EXIST) { - // if new_path exists then try removing it - res = f_unlink(new_path); - if (res == FR_OK) { - // try to rename again - res = f_rename(old_path, new_path); - } - } - switch (res) { - case FR_OK: - return mp_const_none; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", old_path, new_path)); - } - -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename); - -/// \function rmdir(path) -/// Remove a directory. -STATIC mp_obj_t os_rmdir(mp_obj_t path_o) { - const char *path = mp_obj_str_get_str(path_o); - // TODO check that path is actually a directory before trying to unlink it - FRESULT res = f_unlink(path); - switch (res) { - case FR_OK: - return mp_const_none; - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir); - -// Checks for path equality, ignoring trailing slashes: -// path_equal(/, /) -> true -// path_equal(/flash//, /flash) -> true -// second argument must be in canonical form (meaning no trailing slash, unless it's just /) -STATIC bool path_equal(const char *path, const char *path_canonical) { - for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) { - } - if (*path_canonical != '\0') { - return false; - } - for (; *path == '/'; ++path) { - } - return *path == '\0'; -} - -/// \function stat(path) -/// Get the status of a file or directory. -STATIC mp_obj_t os_stat(mp_obj_t path_in) { - const char *path = mp_obj_str_get_str(path_in); - - FILINFO fno; -#if _USE_LFN - fno.lfname = NULL; - fno.lfsize = 0; -#endif - - FRESULT res; - if (path_equal(path, "/")) { - // stat root directory - fno.fsize = 0; - fno.fdate = 0; - fno.ftime = 0; - fno.fattrib = AM_DIR; - } else { - res = FR_NO_PATH; - for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) { - fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i]; - if (vfs != NULL && path_equal(path, vfs->str)) { - // stat mounted device directory - fno.fsize = 0; - fno.fdate = 0; - fno.ftime = 0; - fno.fattrib = AM_DIR; - res = FR_OK; - } - } - if (res == FR_NO_PATH) { - // stat normal file - res = f_stat(path, &fno); - } - if (res != FR_OK) { - mp_raise_OSError(fresult_to_errno_table[res]); - } - } - - mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); - mp_int_t mode = 0; - if (fno.fattrib & AM_DIR) { - mode |= 0x4000; // stat.S_IFDIR - } else { - mode |= 0x8000; // stat.S_IFREG - } - mp_int_t seconds = timeutils_seconds_since_2000( - 1980 + ((fno.fdate >> 9) & 0x7f), - (fno.fdate >> 5) & 0x0f, - fno.fdate & 0x1f, - (fno.ftime >> 11) & 0x1f, - (fno.ftime >> 5) & 0x3f, - 2 * (fno.ftime & 0x1f) - ); - t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode - t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino - t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev - t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink - t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid - t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid - t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size - t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime - t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime - t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime - - return t; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat); - -STATIC mp_obj_t os_statvfs(mp_obj_t path_in) { - const char *path = mp_obj_str_get_str(path_in); - - DWORD nclst; - FATFS *fatfs; - FRESULT res = f_getfree(path, &nclst, &fatfs); - if (res != FR_OK) { - goto error; - } - - mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); - - t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * 512); // f_bsize - block size - t->items[1] = t->items[0]; // f_frsize - fragment size - t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks - total number of blocks - t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree - number of free blocks - t->items[4] = t->items[3]; // f_bavail - free blocks avail to unpriviledged users - t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files - # inodes - t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree - # free inodes - t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail - # free inodes avail to unpriviledges users - t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags - t->items[9] = MP_OBJ_NEW_SMALL_INT(_MAX_LFN); // f_namemax - - return t; - -error: - mp_raise_OSError(fresult_to_errno_table[res]); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_statvfs_obj, os_statvfs); - /// \function sync() /// Sync all filesystems. STATIC mp_obj_t os_sync(void) { - disk_ioctl(0, CTRL_SYNC, NULL); - disk_ioctl(1, CTRL_SYNC, NULL); - disk_ioctl(2, CTRL_SYNC, NULL); + for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { + // this assumes that vfs->obj is fs_user_mount_t with block device functions + disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL); + } return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync); @@ -384,16 +133,17 @@ STATIC const mp_map_elem_t os_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_rename),(mp_obj_t)&os_rename_obj}, - { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_rmdir_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&os_stat_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_statvfs), (mp_obj_t)&os_statvfs_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove + { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&mp_vfs_chdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&mp_vfs_chdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&mp_vfs_getcwd_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&mp_vfs_listdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&mp_vfs_mkdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&mp_vfs_remove_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_rename),(mp_obj_t)&mp_vfs_rename_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&mp_vfs_rmdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&mp_vfs_stat_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_statvfs), (mp_obj_t)&mp_vfs_statvfs_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&mp_vfs_remove_obj }, // unlink aliases to remove { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj }, @@ -406,9 +156,9 @@ STATIC const mp_map_elem_t os_module_globals_table[] = { // these are MicroPython extensions { MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&mod_os_dupterm_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&fsuser_mount_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&fsuser_umount_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_mkfs), (mp_obj_t)&fsuser_mkfs_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&mp_vfs_mount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&mp_vfs_umount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_VfsFat), (mp_obj_t)&mp_fat_vfs_type }, }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 80cc1014bd..53369a1827 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -52,7 +52,7 @@ #define MICROPY_OPT_MPZ_BITWISE (1) // Python internal features -#define MICROPY_READER_FATFS (1) +#define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) @@ -69,6 +69,8 @@ #define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_VFS (1) +#define MICROPY_VFS_FAT (1) // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) @@ -133,13 +135,21 @@ #endif // fatfs configuration used in ffconf.h +#define MICROPY_FATFS_OO (1) #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_VOLUMES (4) #define MICROPY_FATFS_MULTI_PARTITION (1) -#define MICROPY_FSUSERMOUNT (1) + +// TODO these should be generic, not bound to fatfs +#define mp_type_fileio fatfs_type_fileio +#define mp_type_textio fatfs_type_textio + +// use vfs's functions for import stat and builtin open +#define mp_import_stat mp_vfs_import_stat +#define mp_builtin_open mp_vfs_open +#define mp_builtin_open_obj mp_vfs_open_obj // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c index a93b2b056d..52ede492bb 100644 --- a/stmhal/sdcard.c +++ b/stmhal/sdcard.c @@ -28,7 +28,8 @@ #include "py/nlr.h" #include "py/runtime.h" -#include "lib/fatfs/ff.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs_fat.h" #include "extmod/fsusermount.h" #include "mphalport.h" @@ -444,7 +445,9 @@ const mp_obj_type_t pyb_sdcard_type = { }; void sdcard_init_vfs(fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; vfs->readblocks[0] = (mp_obj_t)&pyb_sdcard_readblocks_obj; vfs->readblocks[1] = (mp_obj_t)&pyb_sdcard_obj; vfs->readblocks[2] = (mp_obj_t)sdcard_read_blocks; // native version diff --git a/stmhal/storage.c b/stmhal/storage.c index 60a7e9f480..6130d6fb8e 100644 --- a/stmhal/storage.c +++ b/stmhal/storage.c @@ -29,7 +29,8 @@ #include "py/obj.h" #include "py/runtime.h" -#include "lib/fatfs/ff.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs_fat.h" #include "extmod/fsusermount.h" #include "systick.h" @@ -504,7 +505,9 @@ const mp_obj_type_t pyb_flash_type = { }; void pyb_flash_init_vfs(fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; vfs->readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; vfs->readblocks[1] = (mp_obj_t)&pyb_flash_obj; vfs->readblocks[2] = (mp_obj_t)storage_read_blocks; // native version |