mpy的文件系统为vfs(虚拟文件系统), vfs基于oofatfs库实现, 而oofatfs又是源自开源的fatfs文件系统,即整个vfs是基于fatfs扩展而来. fatfs文件系统原本需要用户移植的文件diskio.c , mpy重新封装了一层vfs_fat*, 一方面为MicroPython 的python module提供实现支持,另一方面也为用户进行porting(hal)层的实现提供了统一的实现入口.用户实现自己的文件系统需要:
#ifndef MICROPY_VFS
#define MICROPY_VFS (1)
#endif
#define MICROPY_VFS_FAT (MICROPY_VFS)
#if MICROPY_VFS
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_ENABLE_LFN (1)
#endif
static bool b_pyb_flash_is_initialised = false;
void pyb_flash_init(void) {
//ignore
b_pyb_flash_is_initialised = true;
}
uint32_t pyb_flash_get_block_size(void) {
return XFLASH_BLOCK_SIZE;
}
uint32_t pyb_flash_get_block_count(void) {
return XFLASH_SIZE/XFLASH_BLOCK_SIZE;
}
void pyb_flash_flush(void) {
//nothing to do
}
/*
* dest : buffer ptr to save read data
* block_num : the start number of block to read ,scope :[0 ~ 1023]
*/
bool pyb_flash_read_block(uint8_t *dest, uint32_t block_num) {
//ignore
}
/*
* dest : buffer ptr to save read data
* block_num : the start number of block to read ,scope :[0 ~ 1023]
* num_blocks : how many blocks to read
*/
mp_uint_t pyb_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
uint32_t i = 0;
mp_uint_t ret = 0;
for (i = 0; i < num_blocks; i++) {
if (!pyb_flash_read_block(dest + i * XFLASH_BLOCK_SIZE, block_num + i)) {
ret = 1; // error
break;
}
}
return ret; // success
}
/*
* src : buffer ptr to program data
* block_num : the start number of block to write ,scope :[0 ~ 1023]
*/
bool pyb_flash_write_block(const uint8_t *src, uint32_t block_num) {
//ignore
}
/*
* src : buffer ptr to program data
* block_num : the start number of block to write ,scope :[0 ~ 1023]
* num_blocks : how many blocks to write
*/
mp_uint_t pyb_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
for (size_t i = 0; i < num_blocks; i++) {
if (!pyb_flash_write_block(src + i * XFLASH_BLOCK_SIZE, block_num + i)) {
return 1; // error
}
}
return 0; // success
}
/******************************************************************************/
// MicroPython bindings
STATIC const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type};
STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return singleton object
return MP_OBJ_FROM_PTR(&pyb_flash_obj);
}
STATIC mp_obj_t pyb_flash_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
mp_uint_t ret = pyb_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / XFLASH_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_readblocks_obj, pyb_flash_readblocks);
STATIC mp_obj_t pyb_flash_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
mp_uint_t ret = pyb_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / XFLASH_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblocks);
STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
case BP_IOCTL_INIT:
pyb_flash_init();
if(b_pyb_flash_is_initialised){
return MP_OBJ_NEW_SMALL_INT(0);
}
return MP_OBJ_NEW_SMALL_INT(1);
case BP_IOCTL_DEINIT:
pyb_flash_flush();
return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
case BP_IOCTL_SYNC:
pyb_flash_flush();
return MP_OBJ_NEW_SMALL_INT(0);
case BP_IOCTL_SEC_COUNT:
return MP_OBJ_NEW_SMALL_INT(pyb_flash_get_block_count());
case BP_IOCTL_SEC_SIZE:
return MP_OBJ_NEW_SMALL_INT(pyb_flash_get_block_size());
default:
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_ioctl_obj, pyb_flash_ioctl);
STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_flash_readblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_flash_writeblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_flash_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
const mp_obj_type_t pyb_flash_type = {
{ &mp_type_type },
.name = MP_QSTR_Flash,
.make_new = pyb_flash_make_new,
.locals_dict = (mp_obj_dict_t*)&pyb_flash_locals_dict,
};
//vfs init func
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
vfs->fatfs.drv = vfs;
vfs->readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj);
vfs->readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj);
vfs->readblocks[2] = MP_OBJ_FROM_PTR(pyb_flash_read_blocks); // native version
vfs->writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj);
vfs->writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj);
vfs->writeblocks[2] = MP_OBJ_FROM_PTR(pyb_flash_write_blocks); // native version
vfs->u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj);
vfs->u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj);
}
根据实际需要,进行fatfs 的各项功能配置 (ffconf.h)
根据需要开启并实现依赖于文件系统的一些内建方法和module
系统初始化时候, 注意进行vfs的挂载
注意事项:
注意配置存储外设的block大小和ff的FATFS_MAX_SS/FATFS_MIN_SS 一直
#define MICROPY_FATFS_MAX_SS (4096)
STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
{ MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) },
{ MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) },
{ MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) },
#if MICROPY_PY_IO
{ MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) },
#endif
....
}
除了标准提供的__ main __ , builtins, micropython 外, 其余对象均使用宏控制,用户根据移植需要进行打开或者关闭即可
实现 内建的open/stat 方法
open 方法是micropython 重要的内建方法之一, 在提供的移植模板中, open 方法进行了空实现
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
如果移植实现了 vfs 文件系统的移植, 就可以将内建的open方法和vfs 提供的文件系统open方法绑定起来, 以实现使用内建的open方法直接进行文件操作, 与文件系统的open方法绑定后,需要注释掉模板的空实现,避免编译重定义错误。
内建的stat方法也可以直接和vfs的stat方法绑定
// 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
系统开始执行py,需要启用宏控MICROPY_READER_VFS, 使用系统实现的mp_lexer_new_from_file方法
#define MICROPY_READER_VFS 1
安装ampy
pip3(pip) install adafruit-ampy
pip3 install pserial # 依赖这个包
ampy 支持的功能
ampy --help
Usage: ampy [OPTIONS] COMMAND [ARGS]...
ampy - Adafruit MicroPython Tool
Ampy is a tool to control MicroPython boards over a serial connection.
Using ampy you can manipulate files on the board's internal filesystem and
even run scripts.
Options:
-p, --port PORT Name of serial port for connected board. Can optionally
specify with AMPY_PORT environment variable. [required]
-b, --baud BAUD Baud rate for the serial connection (default 115200).
Can optionally specify with AMPY_BAUD environment
variable.
-d, --delay DELAY Delay in seconds before entering RAW MODE (default 0).
Can optionally specify with AMPY_DELAY environment
variable.
--version Show the version and exit.
--help Show this message and exit.
Commands:
get Retrieve a file from the board.
ls List contents of a directory on the board.
mkdir Create a directory on the board.
put Put a file or folder and its contents on the board.
reset Perform soft reset/reboot of the board.
rm Remove a file from the board.
rmdir Forcefully remove a folder and all its children from the board.
run Run a script and print its output.
ampy使用举例
# 使用ls
>ampy --port COM8 ls /flash
/flash/3456
/flash/test.txt
# 传输文件到board
>ampy --port COM8 put main.py
# 使用ls
>ampy --port COM8 ls /flash
/flash/3456
/flash/main.py
/flash/test.txt
# 运行板载文件
>ampy --port COM8 run main.py
Hello word! # 从main.py 打印而来
dir() : 查看所有已导入的module、对象
import X : 导入module
dir(module): 查看module的方法、对象
import builtins: 导入 所有内建的方法和对象
其他常用module : uos, uio, uio.FileIO (文件对象)
创建和删除文件
f=open('file.txt', 'wr')
import uos
uos.remove('file.txt')
文件操作方法
dir(uio.FileIO)
['__class__', '__enter__', '__exit__', '__name__', 'close', 'read', 'readinto', 'readline', 'write', '__del__', 'flush', 'readlines', 'seek', 'tell']
其他,还可以根据应用需要与MCU的能力, 开启 float,longlong以及数学库等