补充文件
authorp15692025051 <846603105@qq.com>
Tue, 11 Mar 2025 10:09:13 +0000 (18:09 +0800)
committerp15692025051 <846603105@qq.com>
Tue, 11 Mar 2025 10:09:13 +0000 (18:09 +0800)
2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.c [new file with mode: 0644]
2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.h [new file with mode: 0644]
2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio_file.c [new file with mode: 0644]

diff --git a/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.c b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.c
new file mode 100644 (file)
index 0000000..372cdce
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+
+
+#include "py/runtime.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "py/mpthread.h"
+#include "py/objstr.h"
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat_sdio.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "helios_fs.h"
+#include "helios_pin.h"
+
+#if MICROPY_VFS_FAT_SDIO
+
+enum { SDIO_MAKE_ARG_pname};
+
+const mp_arg_t sdio_make_allowed_args[] = {   
+    { MP_QSTR_pname, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+};
+
+const char *mp_vfs_sdio_make_path(mp_obj_vfs_sdio_t *self, mp_obj_t path_in) {
+       const char *path = mp_obj_str_get_str(path_in);
+    if (path[0] != '/') {
+        size_t l = vstr_len(&self->cur_dir);
+        if (l > 0) {
+            vstr_add_str(&self->cur_dir, path);
+            path = vstr_null_terminated_str(&self->cur_dir);
+            self->cur_dir.len = l;
+        }
+    }
+
+    return path;
+}
+
+STATIC mp_import_stat_t mp_vfs_sdio_import_stat(void *self_in, const char *path) {
+       mp_obj_vfs_sdio_t *self = self_in;
+       unsigned char isdir = '\0';
+    unsigned int size = 0;
+
+
+       mp_obj_str_t path_obj = { { &mp_type_str }, 0, 0, (const byte *)path };
+    path = mp_vfs_sdio_make_path(self, MP_OBJ_FROM_PTR(&path_obj));
+       char f_path[64] = "";
+
+    sprintf(f_path, "%s%s", "C:", path);
+    QUEC_QPY_SDIO_LOG("FAT SDIO import stat:%s \r\n", f_path);
+
+       int ret = Helios_fat_getstat(f_path, &size, &isdir);
+       if (ret == 0) 
+       {
+           if ((uint8_t)isdir == 1) 
+               {
+                       return MP_IMPORT_STAT_DIR;
+           } 
+               else 
+               {
+               return MP_IMPORT_STAT_FILE;
+           }
+       }
+
+    return MP_IMPORT_STAT_NO_EXIST;
+}
+static c_callback_t *callback_sd_det = 0;
+
+STATIC mp_obj_t vfs_sdio_sdcard_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(sdio_make_allowed_args)];
+    mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(sdio_make_allowed_args), sdio_make_allowed_args, args_parse);
+       char *partition_name = (char *)mp_obj_str_get_str(args_parse[SDIO_MAKE_ARG_pname].u_obj);
+    Helios_sdio_device_type_e device_type = HELIOS_SDIO_SDCARD;
+
+    mp_obj_vfs_sdio_t *vfs = m_new_obj(mp_obj_vfs_sdio_t);
+    vfs->base.type = type;
+       vstr_init(&vfs->cur_dir, 16);
+    vstr_add_byte(&vfs->cur_dir, '/');
+
+    if(Helios_fat_device_type_switch(device_type) != 0)
+    {
+        mp_raise_OSError(19);
+    }
+
+    memset(vfs->data, '\0', sizeof(vfs->data));
+       strcpy(vfs->data,partition_name);
+       
+    return MP_OBJ_FROM_PTR(vfs);
+}
+
+STATIC mp_obj_t vfs_sdio_emmc_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(sdio_make_allowed_args)];
+    mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(sdio_make_allowed_args), sdio_make_allowed_args, args_parse);
+       char *partition_name = (char *)mp_obj_str_get_str(args_parse[SDIO_MAKE_ARG_pname].u_obj);
+
+    Helios_sdio_device_type_e device_type = HELIOS_SDIO_EMMC;
+
+    mp_obj_vfs_sdio_t *vfs = m_new_obj(mp_obj_vfs_sdio_t);
+    vfs->base.type = type;
+       vstr_init(&vfs->cur_dir, 16);
+    vstr_add_byte(&vfs->cur_dir, '/');
+
+    if(Helios_fat_device_type_switch(device_type) != 0)
+    {
+        mp_raise_OSError(19);
+    }
+
+    memset(vfs->data, '\0', sizeof(vfs->data));
+       strcpy(vfs->data,partition_name);
+       
+    return MP_OBJ_FROM_PTR(vfs);
+}
+
+STATIC mp_obj_t vfs_sdio_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) {
+    /*mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
+    if (mp_obj_is_true(readonly)) {
+        self->readonly = true;
+    }*/
+    if (mp_obj_is_true(mkfs)) {
+               uint8_t ret =0;
+       ret = Helios_fat_format(ASR_SDIO_SD_VOLUME);
+        if(ret!=0)
+        {
+            mp_raise_ValueError("format fail");
+        }
+    }
+
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_sdio_mount_obj, vfs_sdio_mount);
+
+STATIC mp_obj_t vfs_sdio_umount(mp_obj_t self_in) {
+    (void)self_in;
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_sdio_umount_obj, vfs_sdio_umount);
+
+STATIC mp_obj_t vfs_sdio_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *mode = mp_obj_str_get_str(mode_in);
+       const char *path = mp_obj_str_get_str(path_in);
+
+       
+       mp_obj_str_t path_obj = { { &mp_type_str }, 0, 0, (const byte *)path };
+    path = mp_vfs_sdio_make_path(self, MP_OBJ_FROM_PTR(&path_obj));
+       path_obj.data = (const byte *)path;
+
+    return mp_vfs_sdio_file_open(self_in, &mp_type_vfs_sdio_textio, MP_OBJ_FROM_PTR(&path_obj), mode_in);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_sdio_open_obj, vfs_sdio_open);
+
+STATIC mp_obj_t vfs_sdio_chdir(mp_obj_t self_in, mp_obj_t path_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+
+    // Check path exists
+    const char *path = mp_vfs_sdio_make_path(self, path_in);
+    if (path[1] != '\0') {
+        // Not at root, check it exists
+               unsigned char isdir = '\0';
+        unsigned int size = 0;
+               char f_path[64] = "";
+
+        sprintf(f_path, "%s%s", "C:", path);
+               
+               int ret = Helios_fat_getstat(f_path, &size, &isdir);
+               if ((ret != 0) || (uint8_t)isdir == 0) {
+               mp_raise_OSError(-MP_ENOENT);
+           }
+    }
+
+    // Update cur_dir with new path
+    if (path == vstr_str(&self->cur_dir)) {
+        self->cur_dir.len = strlen(path);
+    } else {
+        vstr_reset(&self->cur_dir);
+        vstr_add_str(&self->cur_dir, path);
+    }
+
+    // If not at root add trailing / to make it easy to build paths
+    // and then normalise the path
+    if (vstr_len(&self->cur_dir) != 1) {
+        vstr_add_byte(&self->cur_dir, '/');
+
+       #define CWD_LEN (vstr_len(&self->cur_dir))
+        size_t to = 1;
+        size_t from = 1;
+        char *cwd = vstr_str(&self->cur_dir);
+        while (from < CWD_LEN) {
+            for (; cwd[from] == '/' && from < CWD_LEN; ++from) {
+                // Scan for the start
+            }
+            if (from > to) {
+                // Found excessive slash chars, squeeze them out
+                vstr_cut_out_bytes(&self->cur_dir, to, from - to);
+                from = to;
+            }
+            for (; cwd[from] != '/' && from < CWD_LEN; ++from) {
+                // Scan for the next /
+            }
+            if ((from - to) == 1 && cwd[to] == '.') {
+                // './', ignore
+                vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
+                from = to;
+            } else if ((from - to) == 2 && cwd[to] == '.' && cwd[to + 1] == '.') {
+                // '../', skip back
+                if (to > 1) {
+                    // Only skip back if not at the tip
+                    for (--to; to > 1 && cwd[to - 1] != '/'; --to) {
+                        // Skip back
+                    }
+                }
+                vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
+                from = to;
+            } else {
+                // Normal element, keep it and just move the offset
+                to = ++from;
+            }
+        }
+    }
+
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_chdir_obj, vfs_sdio_chdir);
+
+STATIC mp_obj_t vfs_sdio_getcwd(mp_obj_t self_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    if (vstr_len(&self->cur_dir) == 1) {
+        return MP_OBJ_NEW_QSTR(MP_QSTR__slash_);
+    } else {
+        // don't include trailing /
+        return mp_obj_new_str(self->cur_dir.buf, self->cur_dir.len - 1);
+    }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_sdio_getcwd_obj, vfs_sdio_getcwd);
+
+typedef struct _mp_vfs_sdio_ilistdir_it_t {
+    mp_obj_base_t base;
+    mp_fun_1_t iternext;
+    bool is_str;
+    SDIO_DIR dir;
+} mp_vfs_sdio_ilistdir_it_t;
+
+STATIC mp_obj_t vfs_sdio_ilistdir_it_iternext(mp_obj_t self_in) {
+  mp_vfs_sdio_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+
+    for (;;) {
+        SDIO_FILINFO fno;
+        int res = Helios_fat_dirread(&self->dir, &fno);
+        char *fn = fno.fname;
+        if (res != 0 || fn[0] == 0) {
+            // stop on error or end of dir
+            break;
+        }
+
+        // Note that FatFS already filters . and .., so we don't need to
+
+        // make 4-tuple with info about this entry
+        mp_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) {
+            // dir
+            t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
+        } else {
+            // file
+            t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG);
+        }
+        t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
+        t->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 time
+    Helios_fat_dirclose(&self->dir);
+
+    return MP_OBJ_STOP_ITERATION;
+}
+
+STATIC mp_obj_t vfs_sdio_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
+       mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_vfs_sdio_ilistdir_it_t *iter = m_new_obj(mp_vfs_sdio_ilistdir_it_t);
+
+    iter->base.type = &mp_type_polymorph_iter;
+    iter->iternext = vfs_sdio_ilistdir_it_iternext;
+    iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
+    const char *path = mp_obj_str_get_str(path_in);
+       char f_path[64] = "";
+       int len = 0;
+       
+    if (path[0] == '\0') {
+        path = ".";
+    }
+
+    sprintf(f_path, "%s%s", "C:", path);
+       
+    //iter->dir = Helios_fat_diropen(f_path);
+    int ret = Helios_fat_diropen(&iter->dir, f_path);
+    if (ret != 0) {
+        mp_raise_OSError(-1);
+    }
+    return MP_OBJ_FROM_PTR(iter);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_ilistdir_obj, vfs_sdio_ilistdir);
+
+STATIC mp_obj_t vfs_sdio_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
+       mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *path = mp_vfs_sdio_make_path(self, path_in);
+    char f_path[64] = "";
+    sprintf(f_path, "%s%s", "C:", path);
+
+       int ret = Helios_fat_makedir(f_path, 0777);
+       if (ret != 0) {
+        mp_raise_OSError(ret);
+    }
+       
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_mkdir_obj, vfs_sdio_mkdir);
+
+STATIC mp_obj_t vfs_sdio_remove(mp_obj_t self_in, mp_obj_t path_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *path = mp_vfs_sdio_make_path(self, path_in);
+       char f_path[64] = "";
+
+    sprintf(f_path, "%s%s", "C:", path);
+       
+    int ret = Helios_fat_remove(f_path);
+       if (ret != 0) {
+        mp_raise_OSError(ret);
+    }
+       return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_remove_obj, vfs_sdio_remove);
+
+STATIC mp_obj_t vfs_sdio_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *old_path = mp_vfs_sdio_make_path(self, old_path_in);
+    const char *new_path = mp_obj_str_get_str(new_path_in);
+    vstr_t path_new;
+    vstr_init(&path_new, vstr_len(&self->cur_dir));
+    if (new_path[0] != '/') {
+        vstr_add_strn(&path_new, vstr_str(&self->cur_dir), vstr_len(&self->cur_dir));
+    }
+    vstr_add_str(&path_new, new_path);
+       char o_path[64] = "";
+       char n_path[64] = "";
+
+    sprintf(o_path, "%s%s", "C:", old_path);
+    sprintf(n_path, "%s%s", "C:", vstr_null_terminated_str(&path_new));
+
+    int ret = Helios_fat_rename(o_path, n_path);
+    vstr_clear(&path_new);
+    if (ret != 0) {
+        mp_raise_OSError(ret);
+    }
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_sdio_rename_obj, vfs_sdio_rename);
+
+STATIC mp_obj_t vfs_sdio_rmdir(mp_obj_t self_in, mp_obj_t path_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *path = mp_vfs_sdio_make_path(self, path_in);
+    char f_path[64] = "";
+
+    sprintf(f_path, "%s%s", "C:", path);
+
+    QUEC_QPY_SDIO_LOG("remove dir %s", f_path);
+       
+       int ret = Helios_fat_removedir(f_path);
+       if (ret != 0) {
+        mp_raise_OSError(ret);
+    }
+       
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_rmdir_obj, vfs_sdio_rmdir);
+
+STATIC mp_obj_t vfs_sdio_stat(mp_obj_t self_in, mp_obj_t path_in) {
+    int ret;
+       unsigned char isdir = '\0';
+    unsigned int size = 0;
+       mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+    const char *path = mp_vfs_sdio_make_path(self, path_in);
+       char f_path[64] = "";
+       
+    sprintf(f_path, "%s%s", "C:", path);
+       
+       ret = Helios_fat_getstat(f_path, &size, &isdir);
+       if (ret != 1) {
+        mp_raise_OSError(ret);
+    }
+       
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
+    t->items[0] = MP_OBJ_NEW_SMALL_INT((uint8_t)isdir == 1 ? MP_S_IFDIR : MP_S_IFREG);// st_mode
+    t->items[1] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_ino);// st_ino
+    t->items[2] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_dev);// st_dev
+    t->items[3] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_nlink);// st_nlink
+    t->items[4] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_uid);// st_uid
+    t->items[5] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_gid);// st_gid
+    t->items[6] = mp_obj_new_int_from_uint(size);// st_size
+    t->items[7] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_atime);// st_atime
+    t->items[8] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_mtime);// st_mtime
+    t->items[9] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_ctime);// st_ctime
+    return MP_OBJ_FROM_PTR(t);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_stat_obj, vfs_sdio_stat);
+
+
+STATIC mp_obj_t vfs_sdio_statvfs(mp_obj_t self_in, mp_obj_t path_in) {
+       mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+       int ret;
+    unsigned int fat_total_block = (Helios_fat_gettotal("C:") / 4096);
+       unsigned int fat_free_block = (Helios_fat_getfree("C:") / 4096);
+    const char *path = mp_obj_str_get_str(path_in);
+       char f_path[64] = "";
+       
+    sprintf(f_path, "%s%s", "C:", path);
+
+       // if (ret != 0) {
+    //     mp_raise_OSError(ret);
+    // }
+       
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
+    t->items[0] = MP_OBJ_NEW_SMALL_INT(4096);// f_bsize
+    t->items[1] = t->items[0];// f_frsize
+    t->items[2] = MP_OBJ_NEW_SMALL_INT(fat_total_block);//MP_OBJ_NEW_SMALL_INT(256);// f_blocks
+    t->items[3] = MP_OBJ_NEW_SMALL_INT(fat_free_block);// f_bfree
+    t->items[4] = t->items[3];// f_bavail
+    t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files
+    t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree
+    t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail
+    t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags
+    t->items[9] = MP_OBJ_NEW_SMALL_INT(0);
+    return MP_OBJ_FROM_PTR(t);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_sdio_statvfs_obj, vfs_sdio_statvfs);
+
+STATIC const mp_rom_map_elem_t vfs_sdio_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_sdio_mount_obj) },
+    { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_sdio_umount_obj) },
+    { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&vfs_sdio_open_obj) },
+
+    { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&vfs_sdio_chdir_obj) },
+    { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&vfs_sdio_getcwd_obj) },
+    { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&vfs_sdio_ilistdir_obj) },
+    { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&vfs_sdio_mkdir_obj) },
+    { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&vfs_sdio_remove_obj) },
+    { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_sdio_rename_obj) },
+    { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_sdio_rmdir_obj) },
+    { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_sdio_stat_obj) },
+    { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_sdio_statvfs_obj) },
+    // { MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&vfs_sdio_sd_set_callback_obj) },
+    // { MP_ROM_QSTR(MP_QSTR_set_det), MP_ROM_PTR(&vfs_sdio_sd_set_det_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(vfs_sdio_locals_dict, vfs_sdio_locals_dict_table);
+
+STATIC const mp_vfs_proto_t vfs_sdio_proto = {
+    .import_stat = mp_vfs_sdio_import_stat,
+};
+
+const mp_obj_type_t mp_type_vfs_sdio_sd = {
+    { &mp_type_type },
+    .name = MP_QSTR_VfsSd,
+    .make_new = vfs_sdio_sdcard_make_new,
+    .protocol = &vfs_sdio_proto,
+    .locals_dict = (mp_obj_dict_t *)&vfs_sdio_locals_dict,
+};
+
+const mp_obj_type_t mp_type_vfs_sdio_emmc = {
+    { &mp_type_type },
+    .name = MP_QSTR_VfsEmmc,
+    .make_new = vfs_sdio_emmc_make_new,
+    .protocol = &vfs_sdio_proto,
+    .locals_dict = (mp_obj_dict_t *)&vfs_sdio_locals_dict,
+};
+
+#endif // PLAT_ASR_1803s || PLAT_ASR_1803sc
diff --git a/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.h b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.h
new file mode 100644 (file)
index 0000000..693eaf6
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _VFS_SDIO_H_
+#define _VFS_SDIO_H_
+
+
+#include "py/lexer.h"
+#include "py/obj.h"
+#include "helios_debug.h"
+
+#if MICROPY_VFS_FAT_SDIO
+
+#if 1
+#define QUEC_QPY_SDIO_LOG(msg, ...)  custom_log(QPY_FS_SDIO, msg, ##__VA_ARGS__)
+#else
+#define QUEC_QPY_SDIO_LOG(msg, ...)
+#endif
+
+extern const mp_obj_type_t mp_type_vfs_sdio_emmc;
+extern const mp_obj_type_t mp_type_vfs_sdio_sd;
+extern const mp_obj_type_t mp_type_vfs_sdio_fileio;
+extern const mp_obj_type_t mp_type_vfs_sdio_textio;
+
+
+#define            S_IFMT        (0170000)     /* type of file */
+#define                S_IFDIR   (0040000)     /* directory */
+#define                S_IFCHR   (0020000)     /* character special */
+#define                S_IFBLK   (0060000)     /* block special */
+#define                S_IFREG   (0100000)     /* regular */
+#define                S_IFLNK   (0120000)     /* symbolic link */
+#define                S_IFSOCK  (0140000)     /* socket */
+#define                S_IFIFO   (0010000)     /* fifo */
+
+#define        FA_WRITE                        0x02
+#define        FA_OPEN_EXISTING        0x00
+#define        FA_CREATE_NEW           0x04
+#define        FA_CREATE_ALWAYS        0x08
+#define        FA_OPEN_ALWAYS          0x10
+#define        FA_OPEN_APPEND          0x30
+
+/* Fast seek controls (2nd argument of f_lseek) */
+#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
+
+/* Format options (2nd argument of f_mkfs) */
+#define FM_FAT         0x01
+#define FM_FAT32       0x02
+#define FM_EXFAT       0x04
+#define FM_ANY         0x07
+#define FM_SFD         0x08
+
+/* Filesystem type (FATFS.fs_type) */
+#define FS_FAT12       1
+#define FS_FAT16       2
+#define FS_FAT32       3
+#define FS_EXFAT       4
+
+/* File attribute bits for directory entry (FILINFO.fattrib) */
+#define        AM_RDO  0x01    /* Read only */
+#define        AM_HID  0x02    /* Hidden */
+#define        AM_SYS  0x04    /* System */
+#define AM_DIR 0x10    /* Directory */
+#define AM_ARC 0x20    /* Archive */
+
+
+typedef struct
+{
+    unsigned long f_bsize;   /* file system block size */
+    unsigned long f_frsize;  /* fragment size */
+    unsigned long f_blocks;  /* size of fs in f_frsize units */
+    unsigned long f_bfree;   /* free blocks in fs */
+    unsigned long f_bavail;  /* free blocks avail to non-superuser */
+    unsigned long f_files;   /* total file nodes in file system */
+    unsigned long f_ffree;   /* free file nodes in fs */
+    unsigned long f_favail;  /* avail file nodes in fs */
+    unsigned long f_fsid;    /* file system id */
+    unsigned long f_flag;    /* mount flags */
+    unsigned long f_namemax; /* maximum length of filenames */
+}qstat_vfs;
+
+typedef struct
+{
+    int d_ino;            ///< inode number, file system implementation can use it for any purpose
+    unsigned char d_type;                ///< type of file
+    char d_name[256];     ///< file name
+}qdirent;
+
+typedef unsigned char BYTE;
+typedef char TCHAR;
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+typedef unsigned long long QWORD;
+typedef DWORD LBA_t;
+typedef QWORD FSIZE_t;
+
+typedef struct {
+       void*   fs;                             /* Pointer to the hosting volume of this object */
+       WORD    id;                             /* Hosting volume mount ID */
+       BYTE    attr;                   /* Object attribute */
+       BYTE    stat;                   /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
+       DWORD   sclust;                 /* Object data start cluster (0:no cluster or root directory) */
+       FSIZE_t objsize;                /* Object size (valid when sclust != 0) */
+       DWORD   n_cont;                 /* Size of first fragment - 1 (valid when stat == 3) */
+       DWORD   n_frag;                 /* Size of last fragment needs to be written to FAT (valid when not zero) */
+       DWORD   c_scl;                  /* Containing directory start cluster (valid when sclust != 0) */
+       DWORD   c_size;                 /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
+       DWORD   c_ofs;                  /* Offset in the containing directory (valid when file object and sclust != 0) */
+} FFOBJID;
+
+typedef struct {
+       FFOBJID obj;                    /* Object identifier */
+       DWORD   dptr;                   /* Current read/write offset */
+       DWORD   clust;                  /* Current cluster */
+       LBA_t   sect;                   /* Current sector (0:Read operation has terminated) */
+       BYTE*   dir;                    /* Pointer to the directory item in the win[] */
+       BYTE    fn[12];                 /* SFN (in/out) {body[8],ext[3],status[1]} */
+       DWORD   blk_ofs;                /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
+       const TCHAR* pat;               /* Pointer to the name matching pattern */
+} SDIO_DIR;
+
+#define SDIO_FF_LFN_BUF                255
+#define SDIO_FF_SFN_BUF                12
+
+typedef struct {
+       FSIZE_t fsize;                  /* File size */
+       WORD    fdate;                  /* Modified date */
+       WORD    ftime;                  /* Modified time */
+       BYTE    fattrib;                /* File attribute */
+       TCHAR   altname[SDIO_FF_SFN_BUF + 1];/* Altenative file name */
+       TCHAR   fname[SDIO_FF_LFN_BUF + 1];     /* Primary file name */
+} SDIO_FILINFO;
+
+typedef struct _mp_obj_vfs_sdio_t {
+    mp_obj_base_t base;
+       vstr_t cur_dir;
+    vstr_t root;
+    size_t root_len;
+    bool readonly;
+    char data[64];
+} mp_obj_vfs_sdio_t;
+
+mp_obj_t mp_vfs_sdio_file_open(mp_obj_t self_in, const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in);
+
+#endif // PLAT_ASR1803S
+
+#endif // _VFS_SDIO_H_
\ No newline at end of file
diff --git a/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio_file.c b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio_file.c
new file mode 100644 (file)
index 0000000..e8de745
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include "py/mphal.h"
+#include "py/mpthread.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/objstr.h"
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat_sdio.h"
+
+#include "helios_fs.h"
+
+#if MICROPY_VFS_FAT_SDIO
+
+#if MICROPY_VFS_FAT
+#include "ff.h"
+#else
+#define FA_READ             0x01
+#define FA_WRITE            0x02
+#define FA_OPEN_EXISTING    0x00
+#define FA_CREATE_NEW       0x04
+#define FA_CREATE_ALWAYS    0x08
+#define FA_OPEN_ALWAYS      0x10
+#define FA_OPEN_APPEND      0x30
+#endif
+
+typedef struct _mp_obj_vfs_sdio_file_t {
+    mp_obj_base_t base;
+    HeliosFILE * fd;
+} mp_obj_vfs_sdio_file_t;
+
+#ifdef MICROPY_CPYTHON_COMPAT
+STATIC void check_fd_is_open(const mp_obj_vfs_sdio_file_t *o) {
+    if (0 >= (unsigned int)o->fd) {
+        mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file"));
+    }
+}
+#else
+#define check_fd_is_open(o)
+#endif
+
+STATIC void vfs_sdio_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+    (void)kind;
+    mp_obj_vfs_sdio_file_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self_in), self->fd);
+}
+
+STATIC mp_obj_t vfs_sdio_file_fileno(mp_obj_t self_in) {
+    mp_obj_vfs_sdio_file_t *self = MP_OBJ_TO_PTR(self_in);
+    check_fd_is_open(self);
+    return MP_OBJ_NEW_SMALL_INT(self->fd);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_sdio_file_fileno_obj, vfs_sdio_file_fileno);
+
+STATIC mp_obj_t vfs_sdio_file___exit__(size_t n_args, const mp_obj_t *args) {
+    (void)n_args;
+    return mp_stream_close(args[0]);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_sdio_file___exit___obj, 4, 4, vfs_sdio_file___exit__);
+
+STATIC mp_uint_t vfs_sdio_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
+    mp_obj_vfs_sdio_file_t *o = MP_OBJ_TO_PTR(o_in);
+    check_fd_is_open(o);
+    int r;
+       
+    QUEC_QPY_SDIO_LOG("SDIO read %d with size:%d", o->fd, size);
+       r = Helios_fat_fread(buf, size, 1, o->fd);
+       if(r < 0)
+       {
+               *errcode = -r;
+               return MP_STREAM_ERROR;
+       }
+
+    return (mp_uint_t)r;
+}
+
+STATIC mp_uint_t vfs_sdio_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
+    mp_obj_vfs_sdio_file_t *o = MP_OBJ_TO_PTR(o_in);
+    check_fd_is_open(o);
+    #if MICROPY_PY_OS_DUPTERM
+    if (o->fd <= STDERR_FILENO) {
+        mp_hal_stdout_tx_strn(buf, size);
+        return size;
+    }
+    #endif
+    int r;
+       
+    QUEC_QPY_SDIO_LOG("SDIO write %d with size:%d", o->fd, size);
+       r = Helios_fat_fwrite((void *)buf, size, 1, o->fd);
+       if(r < 0)
+       {
+               *errcode = -r;
+               return MP_STREAM_ERROR;
+       }
+
+    return (mp_uint_t)r;
+}
+
+STATIC mp_uint_t vfs_sdio_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+    mp_obj_vfs_sdio_file_t *o = MP_OBJ_TO_PTR(o_in);
+    check_fd_is_open(o);
+    switch (request) {
+        case MP_STREAM_FLUSH: {
+            int res = Helios_fat_fsync((unsigned int)(o->fd));
+
+            if (res != 0) {
+                *errcode = -res;
+                return MP_STREAM_ERROR;
+            }
+
+            return 0;
+            }
+        case MP_STREAM_SEEK: {
+            struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg;
+                       int res = Helios_fat_fseek(o->fd, s->offset, s->whence);
+            if (res < 0) {
+                *errcode = -res;
+                return MP_STREAM_ERROR;
+            }
+
+            s->offset = res;
+            return 0;
+        }
+        case MP_STREAM_CLOSE:
+                       Helios_fat_fclose(o->fd);
+            #ifdef MICROPY_CPYTHON_COMPAT
+            o->fd = NULL;
+            #endif
+            return 0;
+        case MP_STREAM_GET_FILENO:
+            return 0;
+        default:
+            *errcode = 0;
+            return MP_STREAM_ERROR;
+    }
+}
+
+
+mp_obj_t mp_vfs_sdio_file_open(mp_obj_t self_in, const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) {
+    mp_obj_vfs_sdio_t *self = MP_OBJ_TO_PTR(self_in);
+       mp_obj_vfs_sdio_file_t *o = m_new_obj(mp_obj_vfs_sdio_file_t);
+    const char *mode_s = mp_obj_str_get_str(mode_in);
+    const char *fname = mp_obj_str_get_str(file_in);
+    HeliosFILE * fd;
+       char f_path[64] = "";
+    int mode = 0;
+
+    sprintf(f_path, "%s%s", "C:", fname);
+    QUEC_QPY_SDIO_LOG("FAT SDIO import open:%s \r\n", f_path);
+
+       o->base.type = type;
+    while (*mode_s) {
+        switch (*mode_s++) {
+            case 'r':
+                mode |= FA_READ;
+                break;
+            case 'w':
+                mode |= FA_WRITE | FA_CREATE_ALWAYS;
+                break;
+            case 'x':
+                mode |= FA_WRITE | FA_CREATE_NEW;
+                break;
+            case 'a':
+                mode |= FA_WRITE | FA_OPEN_ALWAYS;
+                break;
+            case '+':
+                mode |= FA_READ | FA_WRITE;
+                break;
+            #if MICROPY_PY_IO_FILEIO
+            case 'b':
+                type = &mp_type_vfs_sdio_fileio;
+                break;
+            #endif
+            case 't':
+                type = &mp_type_vfs_sdio_textio;
+                break;
+        }
+    }
+       fd = Helios_fat_fopen(f_path, mode);
+       
+       if(0 >= (unsigned int)fd)
+       {
+               mp_raise_OSError(-1);
+        QUEC_QPY_SDIO_LOG("FAT SDIO OPEN ERROR");
+               return mp_const_none;
+       }
+    o->fd = fd;
+       
+    return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t vfs_sdio_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+    enum { ARG_file, ARG_mode };
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
+        { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} },
+    };
+
+    mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)];
+    mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals);
+
+    const char *fname = mp_obj_str_get_str(arg_vals[ARG_file].u_obj);
+    const char *p_out;
+    const char *mode_s = mp_obj_str_get_str(arg_vals[ARG_mode].u_obj);
+    mp_vfs_mount_t *vfs = mp_vfs_lookup_path(fname, &p_out);
+    if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) {
+        arg_vals[ARG_file].u_obj = mp_obj_new_str_of_type(mp_obj_get_type(arg_vals[ARG_file].u_obj),
+            (const byte *)p_out, strlen(p_out));
+    }
+    
+    if((vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) && vfs->readonly == MP_VFS_READONIY_ENABLE && vfs_readonly_mode)
+       {
+               if(strcmp(mode_s, "r") && strcmp(mode_s, "rt") && strcmp(mode_s, "rb"))
+               {
+                       return mp_obj_new_int(-1);
+               }
+       }
+
+    return mp_vfs_sdio_file_open(vfs->obj, type, arg_vals[ARG_file].u_obj, arg_vals[ARG_mode].u_obj);
+}
+
+
+STATIC const mp_rom_map_elem_t vfs_sdio_rawfile_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_sdio_file_fileno_obj) },
+    { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
+    { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+    { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
+    { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
+    { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+    { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+    { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
+    { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_sdio_file___exit___obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(vfs_sdio_rawfile_locals_dict, vfs_sdio_rawfile_locals_dict_table);
+
+#if MICROPY_PY_IO_FILEIO
+STATIC const mp_stream_p_t vfs_sdio_fileio_stream_p = {
+    .read = vfs_sdio_file_read,
+    .write = vfs_sdio_file_write,
+    .ioctl = vfs_sdio_file_ioctl,
+};
+
+const mp_obj_type_t mp_type_vfs_sdio_fileio = {
+    { &mp_type_type },
+    .name = MP_QSTR_FileIO,
+    .print = vfs_sdio_file_print,
+    .make_new = vfs_sdio_file_make_new,
+    .getiter = mp_identity_getiter,
+    .iternext = mp_stream_unbuffered_iter,
+    .protocol = &vfs_sdio_fileio_stream_p,
+    .locals_dict = (mp_obj_dict_t *)&vfs_sdio_rawfile_locals_dict,
+};
+#endif
+
+STATIC const mp_stream_p_t vfs_sdio_textio_stream_p = {
+    .read = vfs_sdio_file_read,
+    .write = vfs_sdio_file_write,
+    .ioctl = vfs_sdio_file_ioctl,
+    .is_text = true,
+};
+
+const mp_obj_type_t mp_type_vfs_sdio_textio = {
+    { &mp_type_type },
+    .name = MP_QSTR_TextIOWrapper,
+    .print = vfs_sdio_file_print,
+    .make_new = vfs_sdio_file_make_new,
+    .getiter = mp_identity_getiter,
+    .iternext = mp_stream_unbuffered_iter,
+    .protocol = &vfs_sdio_textio_stream_p,
+    .locals_dict = (mp_obj_dict_t *)&vfs_sdio_rawfile_locals_dict,
+};
+
+/*const mp_obj_vfs_efs_file_t mp_sys_stdin_obj = {{&mp_type_vfs_efs_textio}, STDIN_FILENO};
+const mp_obj_vfs_efs_file_t mp_sys_stdout_obj = {{&mp_type_vfs_efs_textio}, STDOUT_FILENO};
+const mp_obj_vfs_efs_file_t mp_sys_stderr_obj = {{&mp_type_vfs_efs_textio}, STDERR_FILENO};
+*/
+
+#endif // PLAT_ASR_1803s || PLAT_ASR_1803sc
\ No newline at end of file