/** This file is part of the MicroPython project, http://micropython.org/** The MIT License (MIT)** Copyright (c) 2014 Damien P. George* Copyright (c) 2016 Paul Sokolovsky* Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.** 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/mpconfig.h"#if MICROPY_VFS_FAT#if !MICROPY_VFS#error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS"#endif#include <string.h>#include <stdio.h>#include "py/runtime.h"#include "py/mperrno.h"#include "ff.h"#include "extmod/vfs_fat.h"#include "lib/timeutils/timeutils.h"#if FF_MAX_SS == FF_MIN_SS#define SECSIZE(fs) (FF_MIN_SS)#else#define SECSIZE(fs) ((fs)->ssize)#endif#define mp_obj_fat_vfs_t fs_user_mount_tenum { FATFS_MAKE_ARG_spiport, FATFS_MAKE_ARG_spimode, FATFS_MAKE_ARG_spiclk, FATFS_MAKE_ARG_spics };const mp_arg_t fatfs_make_allowed_args[] = {{ MP_QSTR_spiport, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 32} },{ MP_QSTR_spimode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 32} },{ MP_QSTR_spiclk, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 32} },{ MP_QSTR_spics, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 32} },};STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) {fs_user_mount_t *vfs = vfs_in;FILINFO fno;char fat_path[258] = "0:";assert(vfs != NULL);sprintf(fat_path, "%s%s", "0:", path);FRESULT res = f_stat(fat_path, &fno);if (res == FR_OK) {if ((fno.fattrib & AM_DIR) != 0) {return MP_IMPORT_STAT_DIR;} else {return MP_IMPORT_STAT_FILE;}}return MP_IMPORT_STAT_NO_EXIST;}extern unsigned char SD_Init_Config(int spi_port, int spimode, unsigned int spiclk, int spics);STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {mp_arg_val_t args_parse[MP_ARRAY_SIZE(fatfs_make_allowed_args)];mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(fatfs_make_allowed_args), fatfs_make_allowed_args, args_parse);// create new objectfs_user_mount_t *vfs = m_new_obj(fs_user_mount_t);vfs->base.type = type;// Initialise underlying block devicevfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ;vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE//mp_vfs_blockdev_init(&vfs->blockdev, args[0]);SD_Init_Config(args_parse[FATFS_MAKE_ARG_spiport].u_int, args_parse[FATFS_MAKE_ARG_spimode].u_int, args_parse[FATFS_MAKE_ARG_spiclk].u_int, args_parse[FATFS_MAKE_ARG_spics].u_int);//forrest.liu@20210731 add for SPI SD card function// mount the block device so the VFS methods can be usedFRESULT res = f_mount(&vfs->fatfs, "0:", 1);if (res == FR_NO_FILESYSTEM) {// don't error out if no filesystem, to let mkfs()/mount() create one if wantedvfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM;} else if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}return MP_OBJ_FROM_PTR(vfs);}#if _FS_REENTRANTSTATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in);// f_umount only needs to be called to release the sync objectf_umount(&self->fatfs);return mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del);#endifSTATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {// create new objectfs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in));// make the filesystemuint8_t working_buf[FF_MAX_SS];MKFS_PARM opt = {.fmt = FM_FAT32,.n_fat = 2,.align = 4096,.n_root = 0, // use default.au_size = 0, // auto selection};//forrest.liu@20210731 modify for SPI SD card functionFRESULT res = f_mkfs("0:", &opt, working_buf, sizeof(working_buf));if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}return mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs);STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj));typedef struct _mp_vfs_fat_ilistdir_it_t {mp_obj_base_t base;mp_fun_1_t iternext;bool is_str;DIR dir;} mp_vfs_fat_ilistdir_it_t;STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);for (;;) {FILINFO fno;FRESULT res = f_readdir(&self->dir, &fno);char *fn = fno.fname;if (res != FR_OK || fn[0] == 0) {// stop on error or end of dirbreak;}// Note that FatFS already filters . and .., so we don't need to// make 4-tuple with info about this entrymp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));if (self->is_str) {t->items[0] = mp_obj_new_str(fn, strlen(fn));} else {t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));}if (fno.fattrib & AM_DIR) {// dirt->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);} else {// filet->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG);}t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode numbert->items[3] = mp_obj_new_int_from_uint(fno.fsize);return MP_OBJ_FROM_PTR(t);}// ignore error because we may be closing a second timef_closedir(&self->dir);return MP_OBJ_STOP_ITERATION;}STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);bool is_str_type = true;const char *path;char fat_path[258] = "0:";if (n_args == 2) {if (mp_obj_get_type(args[1]) == &mp_type_bytes) {is_str_type = false;}path = mp_obj_str_get_str(args[1]);} else {path = "";}sprintf(fat_path, "%s%s", "0:", path);// Create a new iterator object to list the dirmp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t);iter->base.type = &mp_type_polymorph_iter;iter->iternext = mp_vfs_fat_ilistdir_it_iternext;iter->is_str = is_str_type;FRESULT res = f_opendir(&iter->dir, fat_path);if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}return MP_OBJ_FROM_PTR(iter);}STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func);STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);const char *path = mp_obj_str_get_str(path_in);char fat_path[258] = "0:";sprintf(fat_path, "%s%s", "0:", path);FILINFO fno;FRESULT res = f_stat(fat_path, &fno);if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}// check if path is a file or directoryif ((fno.fattrib & AM_DIR) == attr) {res = f_unlink(fat_path);if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}return mp_const_none;} else {mp_raise_OSError(attr ? MP_ENOTDIR : MP_EISDIR);}}STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {return fat_vfs_remove_internal(vfs_in, path_in, 0); // 0 == file attribute}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) {return fat_vfs_remove_internal(vfs_in, path_in, AM_DIR);}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir);STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);const char *old_path = mp_obj_str_get_str(path_in);const char *new_path = mp_obj_str_get_str(path_out);char fat_old_path[258] = "0:";char fat_new_path[258] = "0:";sprintf(fat_old_path, "%s%s", "0:", old_path);sprintf(fat_new_path, "%s%s", "0:", new_path);FRESULT res = f_rename(fat_old_path, fat_new_path);if (res == FR_EXIST) {// if new_path exists then try removing it (but only if it's a file)fat_vfs_remove_internal(vfs_in, path_out, 0); // 0 == file attribute// try to rename againres = f_rename(fat_old_path, fat_new_path);}if (res == FR_OK) {return mp_const_none;} else {mp_raise_OSError(fresult_to_errno_table[res]);}}STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename);STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);const char *path = mp_obj_str_get_str(path_o);char fat_path[258] = "0:";sprintf(fat_path, "%s%s", "0:", path);FRESULT res = f_mkdir(fat_path);if (res == FR_OK) {return mp_const_none;} else {mp_raise_OSError(fresult_to_errno_table[res]);}}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);/// Change current directory.STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {#if FF_FS_RPATH >= 1mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);const char *path;path = mp_obj_str_get_str(path_in);char fat_path[258] = "0:";sprintf(fat_path, "%s%s", "0:", path);FRESULT res = f_chdir(fat_path);if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}#endifreturn mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);/// Get the current directory.STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);char buf[MICROPY_ALLOC_PATH_MAX + 1];#if FF_FS_RPATH >= 2FRESULT res = f_getcwd(buf, sizeof(buf));if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}#endifreturn mp_obj_new_str(buf, strlen(buf));}STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);/// \function stat(path)/// Get the status of a file or directory.STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);const char *path = mp_obj_str_get_str(path_in);char fat_path[258] = "0:";sprintf(fat_path, "%s%s", "0:", path);FILINFO fno;if (path[0] == 0 || (path[0] == '/' && path[1] == 0)) {// stat root directoryfno.fsize = 0;fno.fdate = 0x2821; // Jan 1, 2000fno.ftime = 0;fno.fattrib = AM_DIR;} else {FRESULT res = f_stat(fat_path, &fno);if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}}mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));mp_int_t mode = 0;if (fno.fattrib & AM_DIR) {mode |= MP_S_IFDIR;} else {mode |= MP_S_IFREG;}mp_int_t seconds = timeutils_seconds_since_epoch(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_modet->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_inot->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_devt->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlinkt->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uidt->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gidt->items[6] = mp_obj_new_int_from_uint(fno.fsize); // st_sizet->items[7] = mp_obj_new_int_from_uint(seconds); // st_atimet->items[8] = mp_obj_new_int_from_uint(seconds); // st_mtimet->items[9] = mp_obj_new_int_from_uint(seconds); // st_ctimereturn MP_OBJ_FROM_PTR(t);}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);// Get the status of a VFS.STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);(void)path_in;DWORD nclst;FATFS *fatfs;const char *path = mp_obj_str_get_str(path_in);char fat_path[258] = "0:";sprintf(fat_path, "%s%s", "0:", path);FRESULT res = f_getfree(fat_path, &nclst, &fatfs);if (FR_OK != res) {mp_raise_OSError(fresult_to_errno_table[res]);}mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * SECSIZE(fatfs)); // f_bsizet->items[1] = t->items[0]; // f_frsizet->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2)); // f_blockst->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfreet->items[4] = t->items[3]; // f_bavailt->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_filest->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffreet->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favailt->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flagst->items[9] = MP_OBJ_NEW_SMALL_INT(FF_MAX_LFN); // f_namemaxreturn MP_OBJ_FROM_PTR(t);}STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs);STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) {fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.// User can specify read-only device by:// 1. readonly=True keyword argument// 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already)if (mp_obj_is_true(readonly)) {self->blockdev.writeblocks[0] = MP_OBJ_NULL;}// check if we need to make the filesystemFRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) {uint8_t working_buf[FF_MAX_SS];MKFS_PARM opt = {.fmt = FM_FAT32,.n_fat = 2,.align = 4096,.n_root = 0, // use default.au_size = 0, // auto selection};res = f_mkfs("0:", &opt, working_buf, sizeof(working_buf));}if (res != FR_OK) {mp_raise_OSError(fresult_to_errno_table[res]);}self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM;return mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount);STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) {(void)self_in;// keep the FAT filesystem mounted internally so the VFS methods can still be usedreturn mp_const_none;}STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount);STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {#if _FS_REENTRANT{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) },#endif{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) },{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) },{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) },{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) },{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },};STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);STATIC const mp_vfs_proto_t fat_vfs_proto = {.import_stat = fat_vfs_import_stat,};const mp_obj_type_t mp_fat_vfs_type = {{ &mp_type_type },.name = MP_QSTR_VfsFat,.make_new = fat_vfs_make_new,.protocol = &fat_vfs_proto,.locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict,};#endif // MICROPY_VFS_FAT
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。