From: p15692025051 <846603105@qq.com> Date: Tue, 11 Mar 2025 10:09:13 +0000 (+0800) Subject: 补充文件 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=c84ca28d79c0b1e0bf44c2653de67df1e05d5de4;p=mirrors%2FASR1603_G5.git 补充文件 --- 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 index 00000000..372cdcec --- /dev/null +++ b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.c @@ -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 +#include +#include + +#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 index 00000000..693eaf68 --- /dev/null +++ b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio.h @@ -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 index 00000000..e8de7455 --- /dev/null +++ b/2.sdk/Helios_SDK/services/microPython/extmod/vfs_fat_sdio_file.c @@ -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 +#include + +#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, "", 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