打印
[MM32软件]

在MicroPython中启用基于spiflash的LFS挂载文件系统

[复制链接]
1897|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aoyi|  楼主 | 2022-10-20 13:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
概述
总体的思路是:

自顶向下逐步启用mpy-cross编译,将Python程序集成到固件中
自底向上逐步添加sfud组件并启用lfs
合龙,创建mm32f3.flash模块,封装sfud,并由集成到固件中的Python程序调用mm32f3.flash模块。
启用frozen_module
MicroPython加载lfs使用了同之前加载fatfs不同的方式,通过向固件程序中集成Python语言编写的脚本来加载lfs文件系统。在C语言编写的MicroPython固件中加载Python语言程序的机制,就是所谓的“frozen”。在本节中,期望实现frozen机制,先引导一个普通的Python脚本文件,实现在启动REPL之前闪烁电路板小灯的功能。在后续准备好底层文件系统后,再将引导Python文件中的内容替换成加载文件系统的脚本。

新建manifest.py文件
在ports/mm32f3-lfs-spiflash/boards目录下创建manifest.py文件,指定编译工程的过程中,预先处理ports/mm32f3-lfs-spiflash/modules目录下的Python源文件。实际上,ports/mm32f3-lfs-spiflash/modules目录下已经创建了_boot.py文件。

编写manifest.py文件内容有:

freeze("$(PORT_DIR)/modules")


更新mpconfigboard.mk文件
在ports/mm32f3-lfs-spiflash/boards/plus-f3270/mpconfigboard.mk文件中,添加脚本,引用新建的manifest.py文件,将其集成在编译工程的过程中。

在已有mpconfigboard.mk文件中添加脚本:

FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py


更新mpconfigport.h文件
在现有移植项目的mpconfigport.h文件中,添加配置宏,启用MicroPython内核中的frozen机制:

#define MICROPY_MODULE_FROZEN          (1) /* enable pyexec_frozen_module() in pyexec.c */
#define MICROPY_MODULE_FROZEN_MPY      (1)


更新main.c文件
在现有移植项目中的main.c文件中,删除原有从sd卡加载文件系统相关的代码,在固件的执行过程中添加执行_boot.py脚本的语句:

#include "lib/mp-readline/readline.h"

...

int main(void)
{
...
    for (;;)
    {
        ...
        // Initialise sub-systems.
        readline_init0();
        // Execute _boot.py to set up the filesystem.
        pyexec_frozen_module("_boot.py");
        ...
    }
}



实验
试着编一下整个项目,应该是能编通的:

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython-su/micropython-1.16/ports/mm32f3-lfs-spiflash
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-plus-f3270/genhdr/qstrdefs.collected.h
QSTR not updated
mkdir -p build-plus-f3270/build-plus-f3270/
MPY _boot.py
GEN build-plus-f3270/frozen_content.c
CC build-plus-f3270/frozen_content.c
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
135084     860    3396  139340   2204c build-plus-f3270/firmware.elf




从输出的信息中可以看到,编译过程已经处理了_boot.py文件,生成并编译了fromzen_content.c文件。

再试着改写_boot.py文件,控制板子上的小灯闪烁,以验证frozen的功能已经启用。

改写_boot.py文件内容如下:

import time
from machine import Pin

led0 = Pin('PH2', mode=Pin.OUT_PUSHPULL, value=1)

for i in range(10):
    time.sleep_ms(100)
    led0(1-led0())




重新编译,下载,运行。实际可以看到板子上的LED灯闪了5次,之后进入REPL。验证frozen功能已经正常启用。

添加和移植sfud组件
sfud组件是一个开源的管理spiflash存储芯片的组件,面向市面上主流的spiflash存储芯片,提供一系列例如初始化、擦除块、读块、写块等标准操作接口。使用sfud访问spiflash存储芯片,而不是直接使用spiflash存储芯片的驱动程序,可以提高上层应用对底层设备的抽象程度,便于复用代码。在很多基于微控制器的SDK软件包中,都提供了sfud的移植样例工程,这就为在MicroPython中通过sfud使用spiflash存储芯片提供了便利。

添加sfud组件源码
在MicroPython代码包的\lib目录下创建sfud目录,将sfud组件的源码复制在其中:

sfud.c
sfud_sfdp.c
sfud.h
sfud_def.h
sfud_flash_def.h
添加移植sfud组件源码
另外,还需要在具体移植板子项目的目录\ports\mm32f3-lfs-spiflash\boards\plus-f3270下,添加sfud组件的移植源程序文件:

sfud_port.c
sfud_cfg.h
新添加的这两个文件在MindSDK中plus-f3270板子的spiflash_sfud_spi样例工程中都可以找到。

还有一个细节,需要更新\ports\mm32f3-lfs-spiflash\boards\plus-f3270目录下配置板子相关的文件。

board_init.h文件,定义SPI接口的映射:
/* SPI3. */
#define BOARD_FLASH_SPI_PORT          SPI2
#define BOARD_FLASH_SPI_BAUDRATE      400000u /* 400khz. */
#define BOARD_FLASH_SPI_FREQ          CLOCK_APB1_FREQ

#define BOARD_FLASH_CS_GPIO_PORT      GPIOE
#define BOARD_FLASH_CS_GPIO_PIN       GPIO_PIN_3


clock_init.c文件,启用总线访问SPI外设的时钟:
void BOARD_InitBootClocks(void)
{
    ...

    /* SPI2. */
    RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_SPI2, true);
    RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_SPI2);
}


pin_init.c文件,配置SPI外设引脚复用功能:
void BOARD_InitPins(void)
{
    ...
    /* PE3 - SPI_CS. */
    gpio_init.Pins  = GPIO_PIN_3;
    gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &gpio_init);
    GPIO_PinAFConf(GPIOE, gpio_init.Pins, GPIO_AF_15);
    GPIO_SetBits(GPIOE, gpio_init.Pins);

    /* PB10 - SPI_SCK. */
    gpio_init.Pins  = GPIO_PIN_10;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);

    /* PB14 - SPI_MISO. */
    gpio_init.Pins  = GPIO_PIN_14;
    gpio_init.PinMode  = GPIO_PinMode_In_PullUp;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);

    /* PB15 - SPI_MOSI. */
    gpio_init.Pins  = GPIO_PIN_15;
    gpio_init.PinMode  = GPIO_PinMode_AF_PushPull;
    gpio_init.Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_init);
    GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_5);
}


更新Makefile
将新增sfud组件及移植源程序的文件添加到Makefile文件中,进入编译过程。

# includepath.
...
INC += -I$(TOP)/lib/sfud
...

SRC_BRD_C += \
        ...
        $(BOARD_DIR)/sfud_port.c \
        ...
...

SRC_C += \
        ...
        lib/sfud/sfud.c \
        lib/sfud/sfud_sfdp.c \
        ...
...



实验
编译一下工程,确保当前添加到MicroPython中的代码不会产生编译错误。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython-su/micropython-1.16/ports/mm32f3-lfs-spiflash
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-plus-f3270/genhdr/qstrdefs.collected.h
QSTR not updated
CC boards/plus-f3270/sfud_port.c
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
135056     860    3396  139312   22030 build-plus-f3270/firmware.elf


启用lfs组件
MicroPython的lfs文件系统,实际上仅仅是一个文件系统框架,并没有像fatfs一样,通过源代码静态绑定。因此,可以独立启用lfs组件,而暂不实现具体的移植。

更新mpconfigboard.mk文件
lfs组件相关的源码,已经存放在MicroPython代码仓库的\extmod目录下。在现有工程的mpconfigboard.mk文件中,添加 配置开关,让编译过程能够编译lfs相关的源代码。

MICROPY_VFS_LFS2 ?= 1


更新mpconfigport.h文件
在现有移植项目的mpconfigport.h文件中,添加配置宏,启用MicroPython内核中的lfs组件,并添加部分映射对象:

// Use VfsLfs2's types for fileio/textio
#define mp_type_fileio mp_type_vfs_lfs2_fileio
#define mp_type_textio mp_type_vfs_lfs2_textio


这是为了在os类模块中,向vfs(虚拟文件系统,virtual file system)绑定io过程使用lfs相关的方法。

更新moduos.c文件
在后面集成实验时,发现os类模块的几个函数尚未实现,赶紧在这里补充说明。

在现有移植项目的moduos.c文件中,解锁os类模块中与vfs相关的属性方法,特别是mount()和VfsLfs2()。

...
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "extmod/vfs_lfs.h"
...

STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },

    //{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },

    { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
    { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
    { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
    { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
    { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
    { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
    { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj)},
    { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
    { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
    { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
    { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove

    { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) },

#if 1 /* unlock for vfs and lfs. */
    /// \constant sep - separation character used in paths
    { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },

    #if MICROPY_HW_ENABLE_RNG
    { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
    #endif

    // these are MicroPython extensions
    //{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&uos_dupterm_obj) },
    { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
    { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
#endif
    #if MICROPY_VFS_FAT
    { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
    #endif
    #if MICROPY_VFS_LFS1
    { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
    #endif
    #if MICROPY_VFS_LFS2
    { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
    #endif

};


实验
试着编译一下当前的移植工程,报错,说在lfs_get_mtime函数中引用的mp_hal_time_ns函数未被定义。

CC mphalport.c
CC ../../lib/mp-readline/readline.c
CC ../../lib/utils/gchelper_native.c
CC ../../lib/utils/pyexec.c
CC ../../lib/utils/stdout_helpers.c
CC ../../lib/timeutils/timeutils.c
CC fatfs_port.c
CC boards/plus-f3270/machine_pin_board_pins.c
CC ../../drivers/bus/softspi.c
LINK build-plus-f3270/firmware.elf
C:\msys64\usr\gcc-arm-none-eabi-10-2020-q4-major\bin\arm-none-eabi-ld.exe: build-plus-f3270/extmod/vfs_lfs.o: in function `lfs_get_mtime':
vfs_lfs.c:(.text.lfs_get_mtime+0x4): undefined reference to `mp_hal_time_ns'
make: *** [Makefile:213: build-plus-f3270/firmware.elf] Error 1


顾名思义,lfs_get_mtime函数是为lfs创建文件时提供时间戳信息的,对主要功能影响不大,所以可以用一个“假”的实现消除错误。在mphalport.h文件中定义mp_hal_time_ns函数:

/* return the current ns from very start. */
static inline uint64_t mp_hal_time_ns(void)
{
    return 0u;
}


再编译一次,就应该通过了。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython-su/micropython-1.16/ports/mm32f3-lfs-spiflash
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
CC ../../py/mpprint.c
CC ../../py/modmicropython.c
CC ../../extmod/moduasyncio.c
CC ../../extmod/machine_pulse.c
CC ../../extmod/machine_i2c.c
CC ../../extmod/machine_spi.c
CC ../../extmod/modbluetooth.c
CC ../../extmod/vfs_posix.c
CC ../../extmod/vfs_posix_file.c
CC ../../extmod/vfs_fat_diskio.c
CC ../../extmod/vfs_lfs.c
CC ../../extmod/utime_mphal.c
CC ../../lib/utils/printf.c
CC modmachine.c
CC machine_spi.c
CC machine_i2c.c
CC mphalport.c
CC ../../lib/mp-readline/readline.c
CC ../../lib/utils/pyexec.c
CC ../../lib/utils/stdout_helpers.c
CC boards/plus-f3270/machine_pin_board_pins.c
CC ../../drivers/bus/softspi.c
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
174792     988   10572  186352   2d7f0 build-plus-f3270/firmware.elf



创建flash类模块
这里需要创建一个同具体芯片平台相关的类模块,用以包含flash子类。实际上,这个flash可以是片内flash,也可以是片外flash。早期的MicroPython是运行在使用STM32F4微控制器作为主控芯片的PyBoard上,PyBoard板子没有搭载片外flash,就是用片内flash加载文件系统,因此,将flash作为芯片平台子类的做法就作为传统保留了下来。

创建mm32f3_flash.c文件
在\ports\mm32f3-lfs-spiflash目录下创建mm32f3_flash.c文件,用于实现flash子类。flash子类中必须要实现的几个函数,包括make_new()、readblocks()、writeblocks()和ioctl,内部都是通过调用sfud组件的接口访问底层的spiflash存储芯片。spiflash存储芯片的差异性已经被sfud覆盖掉了,所以实际上,当我从mm32f5移植项目(一个使用sfud组件访问qspiflash存储芯片的项目)中复制出mm32f5_flash.c文件时,只是将其中的mm32f5的字符串改成了mm32f3,并停用了其中一个激活4线SPI功能的sfud调用而已。

...
STATIC const mp_rom_map_elem_t mm32f3_flash_locals_dict_table[] = {
    { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&mm32f3_flash_readblocks_obj) },
    { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&mm32f3_flash_writeblocks_obj) },
    { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mm32f3_flash_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mm32f3_flash_locals_dict, mm32f3_flash_locals_dict_table);

const mp_obj_type_t mm32f3_flash_type = {
    { &mp_type_type },
    .name = MP_QSTR_Flash,
    .make_new = mm32f3_flash_make_new,
    .locals_dict = (mp_obj_dict_t *)&mm32f3_flash_locals_dict,
};


至于xxxx_flash.c文件中各个属性方法的实现方法和内容,可以参阅具体的代码。

创建modmm32f3.c/.h文件
前文提到,flash类模块需要作为同主控芯片相关的一个类的子类集成在MicroPython内核中。这里就创建一个仅包含flash类模块的mm32f3类模块。

创建modmm32f3.c文件,并编写代码:

#include "py/runtime.h"
#include "modmm32f3.h"

STATIC const mp_rom_map_elem_t mm32f3_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__),            MP_ROM_QSTR(MP_QSTR_mm32f3) },
    { MP_ROM_QSTR(MP_QSTR_Flash),               MP_ROM_PTR(&mm32f3_flash_type) },
};
STATIC MP_DEFINE_CONST_DICT(mm32f3_module_globals, mm32f3_module_globals_table);

const mp_obj_module_t mp_module_mm32f3 = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&mm32f3_module_globals,
};


创建modmm32f3.h文件,并编写代码:

#ifndef MICROPY_INCLUDED_MM32F3_MODMM32F3_H
#define MICROPY_INCLUDED_MM32F3_MODMM32F3_H

#include "py/obj.h"

extern const mp_obj_type_t mm32f3_flash_type;
extern const mp_obj_module_t mp_module_mm32f3;

#endif // MICROPY_INCLUDED_MM32F3_MODMM32F3_H


更新mpconfigport.h文件
将新建的mm32f3模块添加到MicroPython内核的内建模块当中。

在当前移植项目的mpconfigport.h文件中,添加源代码:

...
extern const struct _mp_obj_module_t mp_module_mm32f3;

#define MICROPY_PORT_BUILTIN_MODULES \
    ...
    { MP_ROM_QSTR(MP_QSTR_mm32f3), MP_ROM_PTR(&mp_module_mm32f3) }, \

...


更新Makefile文件
在当前移植项目的Makefile中,添加新建文件:

...
SRC_C += \
        ...
        modmm32f3.c \
        mm32f3_flash.c \
...

# list of sources for qstr extraction
SRC_QSTR += modmachine.c \
                        ...
                        modmm32f3.c \
                        mm32f3_flash.c \
                        ...



实验
试着编译一下当前的移植工程,应该是可以编通不报错的。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython-su/micropython-1.16/ports/mm32f3-lfs-spiflash
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-plus-f3270/genhdr/qstr.i.last
GEN build-plus-f3270/genhdr/qstr.split
GEN build-plus-f3270/genhdr/qstrdefs.collected.h
QSTR updated
...
CC mm32f3_flash.c
CC modmm32f3.c
...
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
141004     988    3916  145908   239f4 build-plus-f3270/firmware.elf



此时,可以将固件下载到板子上,然后试着手工在REPL中逐行输入脚本加载文件系统。在REPL中输入Python脚本进行单步调试,如下:

MicroPython v1.16 on 2022-07-30; PLUS-F3270 with MM32F3277G9P
Type "help()" for more information.
>>>
>>>
>>>
>>>
>>> import os
>>> dir(os)
['__name__', 'remove', 'sep', 'VfsFat', 'VfsLfs2', 'chdir', 'getcwd', 'ilistdir', 'listdir', 'mkdir', 'mount', 'rename', 'rmdir', 'stat', 'statvfs', 'sync', 'umount', 'unlink']
>>> import mm32f3
>>> dir(mm32f3)
['__name__', 'Flash']
>>> bdev=mm32f3.Flash()
[SFUD](../../lib/sfud/sfud.c:116) Start initialize Serial Flash Universal Driver(SFUD) V1.1.0.
[SFUD](../../lib/sfud/sfud.c:117) You can get the latest version on https://github.com/armink/SFUD .
[SFUD](../../lib/sfud/sfud.c:865) The flash device manufacturer ID is 0xFF, memory type ID is 0xFF, capacity ID is 0xFF.
[SFUD](../../lib/sfud/sfud_sfdp.c:131) Check SFDP header is OK. The reversion isV1.0, NPN is 0.
[SFUD](../../lib/sfud/sfud_sfdp.c:173) Check JEDEC basic flash parameter headeris OK. The table id is 0, reversion is V1.0, length is 9, parameter table pointer is 0x000080.
[SFUD](../../lib/sfud/sfud_sfdp.c:203) JEDEC basic flash parameter table info:
[SFUD](../../lib/sfud/sfud_sfdp.c:204) MSB-LSB  3    2    1    0
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0001] 0xFF 0xF1 0x20 0xE5
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0002] 0x07 0xFF 0xFF 0xFF
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0003] 0x6B 0x08 0xEB 0x44
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0004] 0xBB 0x42 0x3B 0x08
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0005] 0xFF 0xFF 0xFF 0xFE
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0006] 0x00 0x00 0xFF 0xFF
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0007] 0xEB 0x21 0xFF 0xFF
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0008] 0x52 0x0F 0x20 0x0C
[SFUD](../../lib/sfud/sfud_sfdp.c:206) [0009] 0x00 0x00 0xD8 0x10
[SFUD](../../lib/sfud/sfud_sfdp.c:215) 4 KB Erase is supported throughout the device. Command is 0x20.
[SFUD](../../lib/sfud/sfud_sfdp.c:234) Write granularity is 64 bytes or larger.
[SFUD](../../lib/sfud/sfud_sfdp.c:245) Target flash status register is non-volatile.
[SFUD](../../lib/sfud/sfud_sfdp.c:271) 3-Byte only addressing.
[SFUD](../../lib/sfud/sfud_sfdp.c:305) Capacity is 16777216 Bytes.
[SFUD](../../lib/sfud/sfud_sfdp.c:311) Flash device supports 4KB block erase. Command is 0x20.
[SFUD](../../lib/sfud/sfud_sfdp.c:311) Flash device supports 32KB block erase. Command is 0x52.
[SFUD](../../lib/sfud/sfud_sfdp.c:311) Flash device supports 64KB block erase. Command is 0xD8.
[SFUD]Find a flash chip. Size is 16777216 bytes.
[SFUD](../../lib/sfud/sfud.c:844) Flash device reset success.
[SFUD]SPI Flash flash device is initialize success.
>>> os.VfsLfs2.mkfs(bdev, progsize=256)
>>> vfs=os.VfsLfs2(bdev, progsize=256)
>>> os.mount(vfs,'/')
>>> os.listdir()
[]
>>> with open('hello', 'w') as f:
...   f.write('hello')
...
5
>>> os.listdir()
['hello']
>>> os.sync()
>>> os.listdir()
['hello']
>>>


看起来,文件系统已经准备好了。接下来就是让MicroPython启动的时候自动加载文件系统。

改写_boot.py文件加载lfs

将上述手动加载文件系统的脚本写到之前创建的_boot.py文件中:

import os
import mm32f3

bdev = mm32f3.Flash()

try:
    vfs = os.VfsLfs2(bdev, progsize=256)
except:
    os.VfsLfs2.mkfs(bdev, progsize=256)
    vfs = os.VfsLfs2(bdev, progsize=256)
os.mount(vfs, "/")


重新编译工程,正常情况下应该通过编译,无错误。

此时整个工程已经基本移植成功了,可以关掉sfud的调试选项。重新编译工程,下载固件到开发板,在REPL中可以看到,在欢迎信息之前没有报错信息,系统正常被加载。

$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-plus-f3270/genhdr/qstrdefs.collected.h
QSTR not updated
CC mm32f3_flash.c
CC ../../lib/sfud/sfud.c
CC ../../lib/sfud/sfud_sfdp.c
CC boards/plus-f3270/sfud_port.c
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
169528     988   10316  180832   2c260 build-plus-f3270/firmware.elf



下载代码运行。

使用Thonny IDE建立连接
尝试通过Thonny创建Python脚本文件,保存到MicroPython设备上。



图1 使用Thonny查看flash文件系统
如图1所示,当要使用Thonny保存Python脚本文件时,Thonny的文件浏览器已经可以看到之前实验中创建的hello文件了。尝试保存新脚本为main.py文件,是成功的。至此,说明移植成功。大功告成。

后记
启用文件系统之后,为了方便用户使用,还需要继续做两件事:

芯片上电之后,MicroPython能自动运行到main.py函数。
为了防止在main.py中进入无限循环后无法再同Thonny建立连接,需要在文件系统中创建boot.py文件,选择启动模式,在必要的情况下跳过main.py直接进入REPL。
改写main.c文件
在MicroPython的启动过程中,添加执行boot.py和main.py文件的流程,位于进入REPL之前:

        pyexec_file_if_exists("boot.py");


重新编译工程,并下载到开发板中。

MindMotion@PF2LD92H MSYS /d/_git_repos/micropython-su/micropython-1.16/ports/mm32f3-lfs-spiflash
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build-plus-f3270/genhdr/qstrdefs.collected.h
QSTR not updated
CC main.c
LINK build-plus-f3270/firmware.elf
   text    data     bss     dec     hex filename
169588     988   10316  180892   2c29c build-plus-f3270/firmware.elf



注意,这里不能在main.c中直接执行main.py文件,需要通过boot.py有条件地引导进入main.py。

创建boot.py文件
在Thonny IDE中新建boot.py文件,并保存到MicroPython设备中。boot.py文件源码如下:

from machine import Pin

btn = Pin('PG15', mode=Pin.IN_PULLUP)

if 0==btn():
    print('skip main.py')
else:
    if 'main.py' in os.listdir():
        import main
    else:
        print('no main.py in filesystem')




现在可以通过开发板上的拨码开关选择启动MicroPython之后,在进入REPL之前,是否跳过可能包含无限循环的main.py。



图2 PLUS-F3270开发板上的拨码开关
最后,附送预编译好的MicroPython可执行文件:https://download.csdn.net/download/suyong_yq/86267405

完整的项目源代码,见gitee.com上的开源代码库:https://gitee.com/suyong_yq/micropython-su,其中的ports/mm32f3-lfs-spiflash。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

3301

帖子

3

粉丝