概述
总体的思路是:
自顶向下逐步启用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);
}