diff --git a/nrf5/Makefile b/nrf5/Makefile index 984281e4b2..8b0a37b81b 100644 --- a/nrf5/Makefile +++ b/nrf5/Makefile @@ -43,7 +43,7 @@ FROZEN_DIR = freeze include ../py/py.mk -FATFS_DIR = lib/fatfs +FATFS_DIR = lib/oofatfs MPY_CROSS = ../mpy-cross/mpy-cross MPY_TOOL = ../tools/mpy-tool.py @@ -76,7 +76,7 @@ CFLAGS_MCU_m0 = $(CFLAGS_CORTEX_M) --short-enums -mtune=cortex-m0 -mcpu=cortex-m CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) -CFLAGS += $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(COPT) $(NRF_DEFINES) +CFLAGS += $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' @@ -102,8 +102,8 @@ SRC_LIB = $(addprefix lib/,\ mp-readline/readline.c \ utils/pyexec.c \ timeutils/timeutils.c \ - fatfs/ff.c \ - fatfs/option/ccsbcs.c \ + oofatfs/ff.c \ + oofatfs/option/unicode.c \ netutils/netutils.c \ ) @@ -133,7 +133,6 @@ SRC_C += \ gccollect.c \ pin_named_pins.c \ fatfs_port.c \ - builtin_open.c \ DRIVERS_SRC_C += $(addprefix modules/,\ display/moddisplay.c \ diff --git a/nrf5/fatfs_port.c b/nrf5/fatfs_port.c index c7b15a703c..4d44e2d1d5 100644 --- a/nrf5/fatfs_port.c +++ b/nrf5/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 "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 - */ -}; +#include "lib/oofatfs/ff.h" DWORD get_fattime(void) { + // TODO: Implement this function. For now, fake it. return ((2000 + 2016 - 1980) << 25) | ((12) << 21) | ((4) << 16) | ((00) << 11) | ((18) << 5) | (23 / 2); } diff --git a/nrf5/main.c b/nrf5/main.c index d7a0f813ef..b998e84e98 100644 --- a/nrf5/main.c +++ b/nrf5/main.c @@ -223,9 +223,6 @@ void HardFault_Handler(void) #endif } -mp_import_stat_t mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; -} void nlr_jump_fail(void *val) { } diff --git a/nrf5/modules/machine/modmachine.c b/nrf5/modules/machine/modmachine.c index 7b5b6f01b7..101123dcce 100644 --- a/nrf5/modules/machine/modmachine.c +++ b/nrf5/modules/machine/modmachine.c @@ -34,8 +34,8 @@ #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 "lib/oofatfs/diskio.h" #include "gccollect.h" #include "pin.h" #include "spi.h" diff --git a/nrf5/modules/uos/moduos.c b/nrf5/modules/uos/moduos.c index e3bf4c1ae1..35bc3f0e64 100644 --- a/nrf5/modules/uos/moduos.c +++ b/nrf5/modules/uos/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 "lib/timeutils/timeutils.h" +//#include "timeutils.h" //#include "rng.h" #include "uart.h" -#include "extmod/vfs_fat_file.h" -//#include "sdcard.h" -#include "extmod/fsusermount.h" //#include "portmodules.h" /// \module os - basic "operating system" services @@ -80,255 +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); - 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); @@ -376,16 +133,16 @@ 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_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 }, @@ -398,9 +155,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/nrf5/mpconfigport.h b/nrf5/mpconfigport.h index 9c3c29ad69..6e710c9553 100644 --- a/nrf5/mpconfigport.h +++ b/nrf5/mpconfigport.h @@ -36,6 +36,7 @@ #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (0) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) +#define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (0) @@ -48,16 +49,24 @@ #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_OPT_MPZ_BITWISE (0) -#define MICROPY_READER_FATFS (1) +#define MICROPY_VFS (1) +#define MICROPY_VFS_FAT (1) // fatfs configuration used in ffconf.h #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 #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1)