为micropython启用文件系统(3)

为micropython启用文件系统(3)

启用oofatfs

oofatfs的代码已经存在于micropython的代码仓库中,但是需要在makefile中把相关的编译选项打开。extmod/extmod.mk文件中包含了extmod目录下很多组件的编译配置代码段,其中也包含了oofatfs的部分:

# VFS FAT FS

OOFATFS_DIR = lib/oofatfs

# this sets the config file for FatFs
CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"

ifeq ($(MICROPY_VFS_FAT),1)
CFLAGS_MOD += -DMICROPY_VFS_FAT=1
SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\
	ff.c \
	ffunicode.c \
	)
endif

extmod.mk已经包含在micropython的makefile中了。在 ports/mm32/Makefile 中,添加CFLAGS_MOD和SRC_MOD:

…
CFLAGS += $(CFLAGS_MOD)
…
SRC_HAL_MM32_C += \
	$(MCU_DIR)/devices/$(CMSIS_MCU)/system_$(CMSIS_MCU).c \
	$(MCU_DIR)/drivers/hal_rcc.c \
	$(MCU_DIR)/drivers/hal_gpio.c \
	$(MCU_DIR)/drivers/hal_uart.c \
	$(MCU_DIR)/drivers/hal_sdio.c \

SRC_BRD_MM32_C += \
	$(BOARD_DIR)/clock_init.c \
	$(BOARD_DIR)/pin_init.c \
	$(BOARD_DIR)/board_init.c \
	$(BOARD_DIR)/machine_pin_board_pins.c \
	$(BOARD_DIR)/sdcard_sdio.c \

SRC_C += \
	main.c \
	fatfs_port.c \
…
	$(SRC_MOD) \

这里还在SRC_C中手动补完了fatfs_port.c文件。

此时,需要指定“MICROPY_VFS_FAT”的配置值为1,才能解锁对oofatfs相关源文件的包含。参考nrf的port中的做法,在 ports\mm32\boards\MB_F3270\mpconfigboard.mk 中添加:

MCU_SERIES = mm32f3270
CMSIS_MCU = mm32f3277g7
LD_FILES = boards/mm32f3277g7_flash.ld

MICROPY_VFS_FAT ?= 1

此处特别注意,在makefile系统中的“MICROPY_VFS_FAT”和C预编译系统中的“MICROPY_VFS_FAT”是两个域的东西,在mk文件中直接定义“MICROPY_VFS_FAT ?= 1”仅作用于makefile系统,“CFLAGS_MOD += -DMICROPY_VFS_FAT=1”才是作用在C预编译系统中的,作用于C源代码的内容。

另外,还要在代码中添加FATFS和VFS的宏开关,在micropython内核中启用与文件系统相关的功能,在编译的过程中包含到最终的可执行文件中。在 ports\mm32\ mpconfigport.h 文件中添加如下宏定义开关:

// fatfs configuration used in ffconf.h
#define MICROPY_VFS                    (1)
//#define MICROPY_VFS_FAT              (1) /* already included in cflags. */
#define MICROPY_FATFS                  (1)
#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_MULTI_PARTITION  (1)

在mpconfigport.h中添加mp_import_stat、mp_builtin_open和mp_builtin_open_opj等函数到vfs组件中对应函数的映射,同时注销掉之正在main.c文件中的空实现。

// 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
#if 0
mp_import_stat_t mp_import_stat(const char *path) {
    return MP_IMPORT_STAT_NO_EXIST;
}

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);
#endif

一番折腾之后,终于在包含oofatfs的情况下通过了编译。

在这里插入图片描述

将sd卡访问函数框架注册到vfs

这一步还没有直接调用sdcard_sdio中的函数,但是要创建调用框架。

在 ports/mm32 目录下创建machine_sdcard.h/.c 文件。没错,除了系统默认的访问操作,sdcard模块将要挂在machine模块之下。

从网页上复制下来代码种子的代码到machien_sdcard源文件中,对象名字也要从“pyb_flash”改成“machine_sdcard”。

在使用代码注入种子的时候,还是遇到了很多问题。

需要在machine_sdcard.h中添加代码,包含必要的声明和引用:

/* machine_sdcard.h */

#ifndef __MACHINE_SDCARD_H__
#define __MACHINE_SDCARD_H__

#include "py/runtime.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"

extern const struct _mp_obj_type_t machine_sdcard_type;
extern const struct _mp_obj_base_t machine_sdcard_obj;

void machine_sdcard_init_vfs(fs_user_mount_t *vfs);

#endif /* __MACHINE_SDCARD_H__ */

在machine_sdcard.c中,需要删除 machine_sdcard_obj 声明之前的“STATIC”。

const mp_obj_base_t machine_sdcard_obj = { &machine_sdcard_type };

machine_sdcard_ioctl()函数中的命令宏,也要换成“MP_BLOCKDEV_IOCTL_XXX”(这些宏来自于extmod/vfs.h)。

STATIC mp_obj_t machine_sdcard_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 MP_BLOCKDEV_IOCTL_INIT: 
            machine_sdcard_init();
            if(b_machine_sdcard_is_initialised)
            {
                return MP_OBJ_NEW_SMALL_INT(0);
            }
            return MP_OBJ_NEW_SMALL_INT(1);
        
        case MP_BLOCKDEV_IOCTL_DEINIT: 
            machine_sdcard_flush(); 
            return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
        
        case MP_BLOCKDEV_IOCTL_SYNC: 
            machine_sdcard_flush(); 
            return MP_OBJ_NEW_SMALL_INT(0);
        
        case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: 
            return MP_OBJ_NEW_SMALL_INT(machine_sdcard_get_block_count());
            
        case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: 
            return MP_OBJ_NEW_SMALL_INT(machine_sdcard_get_block_size());
            
        default: 
            return mp_const_none;
    }
}

vfs->flags、vfs->readblocks[]、vfs->writeblocks[]等写法,也要插入blockdev:

void machine_sdcard_init_vfs(fs_user_mount_t *vfs)
{
    vfs->base.type      = &mp_fat_vfs_type;
    vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL;
    vfs->fatfs.drv      = vfs;
    vfs->blockdev.readblocks[0]  = MP_OBJ_FROM_PTR(&machine_sdcard_readblocks_obj);
    vfs->blockdev.readblocks[1]  = MP_OBJ_FROM_PTR(&machine_sdcard_obj);
    vfs->blockdev.readblocks[2]  = MP_OBJ_FROM_PTR(machine_sdcard_read_blocks); // native version
    vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&machine_sdcard_writeblocks_obj);
    vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&machine_sdcard_obj);
    vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(machine_sdcard_write_blocks); // native version
    vfs->blockdev.u.ioctl[0]     = MP_OBJ_FROM_PTR(&machine_sdcard_ioctl_obj);
    vfs->blockdev.u.ioctl[1]     = MP_OBJ_FROM_PTR(&machine_sdcard_obj);
}

此处参考了 ports\cc3200\mods\pybflash.c文件中的写法。

一顿操作猛如虎之后,确保编译无误。

在这里插入图片描述

在main.c中调用vfs

此处参考 nrf中main.c的写法

// create vfs object
        fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t);
        if (vfs == NULL) {
            goto no_mem_for_sd;
        }
        vfs->str = "/sd";
        vfs->len = 3;
        vfs->flags = MP_BLOCKDEV_FLAG_FREE_OBJ;
        sdcard_init_vfs(vfs);

        // put the sd device in slot 1 (it will be unused at this point)
        MP_STATE_PORT(fs_user_mount)[1] = vfs;

        FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1);
        if (res != FR_OK) {
            printf("MPY: can't mount SD card\n");
            MP_STATE_PORT(fs_user_mount)[1] = NULL;
            m_del_obj(fs_user_mount_t, vfs);
        } else {
            // TODO these should go before the /flash entries in the path
            mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd));
            mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib));

            // use SD card as current directory
            f_chdrive("/sd");
        }

对vfs初始化的代码要放在 mp_init()之后,repl之前。

    machine_init();

    gc_init(&_heap_start, &_heap_end);

    mp_init();
    mp_obj_list_init(mp_sys_path, 0);
    mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
    mp_obj_list_init(mp_sys_argv, 0);

    readline_init0();


。。。

之前在main函数中对vfs注册的代码有误,最后还是参考stm32的porting,勉强过了编译,但在linker环节出了问题。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython_su/micropython-1.16/ports/mm32
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-MB_F3270/genhdr/qstrdefs.collected.h
QSTR not updated
CC main.c
CC machine_sdcard.c
LINK build-MB_F3270/firmware.elf
C:\msys64\usr\gcc-arm-none-eabi-10-2020-q4-major\bin\arm-none-eabi-ld.exe: build-MB_F3270/extmod/vfs_fat.o: in function `fat_vfs_stat':
vfs_fat.c:(.text.fat_vfs_stat+0x70): undefined reference to `timeutils_seconds_since_2000'
make: *** [Makefile:131: build-MB_F3270/firmware.elf] Error 1

这个“timeutils_seconds_since_2000”是什么鬼?在lib\timeutils\timeutils.h 文件中找到的它的声明,在对应的c文件中找到了它的定义。也就是说,这个函数不需要我额外实现,只要想办法把它包到makefile里就好。先看看别家的的makefile怎么包timeutilis的。好吧,无论是在stm32、nrf还是mimxrt,都是直接在makefile里直接包含的,不像之前extmod可以“四两拨千斤”。那我也直接写到makefile里,在SRC_C中添加lib/timeutils/timeutils.c

SRC_C = \
	main.c \
	led.c \
	pin.c \
	ticks.c \
	tusb_port.c \
	board_init.c \
	$(BOARD_DIR)/flash_config.c \
	machine_adc.c \
	machine_led.c \
	machine_pin.c \
	machine_rtc.c \
	machine_timer.c \
	machine_uart.c \
	mimxrt_flash.c \
	modutime.c \
	modmachine.c \
	modmimxrt.c \
	moduos.c \
	mphalport.c \
	hal/flexspi_nor_flash.c \
	lib/mp-readline/readline.c \
	lib/libc/string0.c \
	lib/timeutils/timeutils.c \
	lib/utils/gchelper_native.c \
	lib/utils/mpirq.c \
	lib/utils/printf.c \
	lib/utils/pyexec.c \
	lib/utils/stdout_helpers.c \
	lib/utils/sys_stdio_mphal.c \
	drivers/bus/softspi.c \
	extmod/modonewire.c \
	$(SRC_TINYUSB_C) \
	$(SRC_HAL_IMX_C) \

日它先人板板,竟然通了。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython_su/micropython-1.16/ports/mm32
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-MB_F3270/genhdr/qstrdefs.collected.h
QSTR not updated
mkdir -p build-MB_F3270/lib/timeutils/
CC ../../lib/timeutils/timeutils.c
LINK build-MB_F3270/firmware.elf
   text    data     bss     dec     hex filename
 103928      16    2968  106912   1a1a0 build-MB_F3270/firmware.elf

这个时候下载代码肯定是不行的,因为在底层还没有跟真正的sdcard_sdio关联起来。

在这里插入图片描述
突然想到一点,可以在现在假的sdcard函数中“打桩”,看看哪些函数被调用了。

在machine_sdcard中调用sdcard_sdio

在machine_sdcard中调用sdcard_sdio中的函数,打通到硬件的访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值