第六章 MicroPython固件编译
本章将向读者介绍MicroPython ESP32固件编译的详细步骤和过程。我们将从准备工作开始,逐步指导开发者完成固件编译的各个环节。通过阅读本章,开发者将了解MicroPython固件编译的基本原理、所需工具和文件,以及编译过程中的注意事项和技巧。
本章分为如下几个小节:
6.1 搭建编译环境
6.2 编译ESP32-S3固件
6.3 总结
6.1 搭建编译环境
自编译MicroPython ESP32-S3固件需要搭建两个开发环境,一个是Linux环境,另一个是ESP-IDF环境。这两个环境是必需的,因为MicroPython ESP32固件依赖于它们进行编译。下面是对这两个环境的搭建流程的介绍。
6.1.1 Linux环境搭建
Linux环境的搭建有三种方式。第一种是使用VMware虚拟机并安装Ubuntu系统来搭建,第二种是安装多个操作系统,每次重启电脑时根据需要进行选择进入,第三种是在Windows系统下安装WSL Ubuntu子系统。前两种方式属于比较完整的安装方式,都可以有图形用户界面,适合对图形界面有需求的同学。而最后一种Linux子系统的方式,安装和运行最快,但是只有命令行,适合Linux老手或者对图形界面需求不大的用户。
考虑到不需要安装VMware虚拟机且安装多个操作系统,本文介绍的是最后一种方式,如何在Windows上安装ubuntu linux子系统。本机是Windows10系统。
一、下载ubuntu子系统
进入Windows store 微软商城,输入关键词ubuntu,即可找到多个版本的ubuntu子系统,如下图所示。
图6.1.1.1 下载Ubuntu
这里作者选的是Ubuntu22.04.2 LTS版本。点进去下载安装。接着我们打开linux子系统功能,如下步骤所示:
打开电脑设置(快捷键为 WIN + i),如下图所示。
图6.1.1.2 Windown设置
在上图中,点击“应用”选项,进入应用和功能界面,如下图所示。
图6.1.1.3 应用和功能界面
在上图中,点击可选功能,进入可选功能界面,接着往下找到更多Windowns功能选项,并且点击进入,如下图所示。
图6.1.1.4 打开Windows功能
在此界面下找到“适用Linux的windown子系统”选项,我们必须勾选这个选项,否则无法启动子系统,最后重启系统即可。
重启完毕后,需要进行一下账户配置。我们还是从微软商城中进入,找到我们刚刚安装的Ubuntu22.04.2 LTS,点击“打开”。此时会提示正在安装,安装完毕后,会让您输入一个用户名,并配置密码,按照提示进行配置,最后进入Ubuntu22.04.2 LTS系统,如下图所示。
6.1.1.5 配置用户名称和密码
二、WSL子系统搬迁
Windows Store 微软商城安装的APP都默认被安装在C盘,然而C盘是我们电脑重要的磁盘,如果C盘空间满了,会影响电脑运行。因此,我们最好将子系统搬离C盘,也就是说,不使用C盘来存放文件。在这里,作者将子系统搬到D盘存储。
WSL子系统搬迁流程,如下所示:
1,查询WSL系统状态。使用管理员身份打开CMD命令行,并在命令行输入“wsl -l -v”查看wsl虚拟机的名称和状态,如下图所示。
图6.1.1.6 wsl虚拟机的名称与状态
从上图可知,作者安装了两个WSL Ubuntu子系统,它们分别为Ubuntu和Ubuntu-22.04,目前它们的状态分别为停止状态和运行状态。下面,作者将以Ubuntu-22.04为例,说明如何将其搬迁到D盘。
2,停止WSL子系统。输入wsl --shutdown使Ubuntu-22.04停止运行,再次使用wsl -l -v确保其处于stopped状态,如下图所示。
图6.1.1.7 Ubuntu-22.04停止运行
3,导出/恢复备份。在D盘创建一个文件夹用来存放新的WSL,比如作者创建了一个 D:\Ubuntu_WSL文件夹。
①:导出它的备份(比如命名为Ubuntu.tar)。在CMD命令行下输入“wsl --export Ubuntu-22.04 D:\Ubuntu_WSL\Ubuntu.tar”。
②:确定在D:\Ubuntu_WSL下是否可看见备份Ubuntu.tar文件,如下图所示那样,之后注销原有的WSL。在CMD命令行输入“wsl --unregister Ubuntu-22.04”注销原本的WSL。
图6.1.1.8 在D:\Ubuntu_WSL目录下生成Ubuntu.tar文件
③:将备份文件恢复到D:\Ubuntu_WSL中去。在CMD命令行下输入“wsl --import Ubuntu-22.04 D:\Ubuntu_WSL D:\Ubuntu_WSL\Ubuntu.tar”恢复备份文件,如下图所示。
图6.1.1.9 恢复WSL备份
这时候启动WSL,发现好像已经恢复正常了,但是用户变成了root,如下图所示。
图6.1.1.10 启动Ubuntu-22.04
在使用git工具进行代码版本管理时,特别是在克隆开源市场中的Github仓库时,可能会遇到超时或失败的问题。这主要是因为国内网络连接国外服务器可能会显得冗余。为了解决这个问题,作者介绍了一种加速方法,可以帮助大家更好地搭建MicroPython环境。这种方法的具体操作步骤如下:
①:在Ubuntu子系统上输入以下命令来解析github.com的IP地址。
nslookup github.com
解析完成之后,我们得到了Github仓库的IP地址,如下图所示。
图6.1.1.11 解析github仓库
②:修改hosts文件,该文件位于路径是:C:\Windows\System32\drivers\etc。添加内容如下。
# GitHub520 Host Start 140.82.112.4 alive.github.com 140.82.112.4 live.github.com 18.207.134.67 github.githubassets.com 140.82.112.4 central.github.com 3.220.169.176 desktop.githubusercontent.com 140.82.112.4 assets-cdn.github.com 3.238.132.1 camo.githubusercontent.com 151.101.1.6 github.map.fastly.net 151.101.1.6 github.global.ssl.fastly.net 140.82.112.4 gist.github.com 185.199.108.153 github.io 20.205.243.166 github.com 192.0.66.2 github.blog 140.82.112.4 api.github.com 18.212.214.173 raw.githubusercontent.com 44.204.227.149 user-images.githubusercontent.com 18.208.143.190 favicons.githubusercontent.com 3.227.11.2 avatars5.githubusercontent.com 44.192.25.139 avatars4.githubusercontent.com 54.197.35.64 avatars3.githubusercontent.com 44.211.83.233 avatars2.githubusercontent.com 3.238.132.1 avatars1.githubusercontent.com 3.238.199.124 avatars0.githubusercontent.com 44.210.19.120 avatars.githubusercontent.com 140.82.112.4 codeload.github.com 72.21.206.80 github-cloud.s3.amazonaws.com 72.21.206.80 github-com.s3.amazonaws.com 72.21.206.80 github-production-release-asset-2e65be.s3.amazonaws.com 72.21.206.80 github-production-user-asset-6210df.s3.amazonaws.com 72.21.206.80 github-production-repository-file-5c1aeb.s3.amazonaws.com 185.199.108.153 githubstatus.com 140.82.113.18 github.community 52.224.38.193 github.dev 140.82.112.4 collector.github.com 3.238.235.79 pipelines.actions.githubusercontent.com 18.207.249.155 media.githubusercontent.com 35.172.164.199 cloud.githubusercontent.com 54.198.215.57 objects.githubusercontent.com 13.107.219.40 vscode.dev
大部分情况下是直接生效,如未生效可尝试刷新 DNS,在 CMD 窗口输入“ipconfig /flushdns”命令。
6.1.2 安装工具链
到了这里,我们将开始在Ubuntu下工作。首先,我们需要安装Linux常用的工具链,例如gcc、cmake、python3、source、git等。为了安装这些工具链,我们首先需要打开Ubuntu-22.04子系统。然后,以命令的形式安装工具链,如下安装命令:
1,更新工具:sudo apt-get update 2,安装GCC:sudo apt-get install gcc 3,安装Cmake:sudo apt-get install cmake 4,安装python3.10:sudo apt-get install python3.10 5,安装python pip:sudo apt-get install python3-pip 6,安装子系统:sudo apt-get install source/ linux-source-5.7 7,安装virtualenv:sudo apt-get install virtualenv 8,安装git:sudo apt-get install git
一旦这些工具链成功安装,我们就可以开始搭建ESP-IDF环境并编译MicroPython固件。请注意,这些工具链的安装必须全部安装完成,否则在编译MicroPython时可能会出现问题。
6.1.3 ESP-IDF环境搭建
ESP-IDF(Espressif IoT Development Framework)是用于开发ESP系列芯片的官方开发环境,它支持Windows、Linux 和 macOS 操作系统,方便用户在不同系统下开发。在开发之前,我们先了解一下ESP-IDF和乐鑫芯片的版本关系,不同版本的IDF所支持的乐鑫芯片都不一样,下图总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中支持代表已支持,预览代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。
图6.1.3.1 不同版本的IDF支持乐鑫芯片关系表
从上图可以看到,ESP32-S3芯片只能在IDF v4.4版本及以上运行,因此我们在使用MicroPython搭建IDF开发环境时,需要选择IDF v4.4版本及以上。在这里,作者选择的是V5.0.4版本,因为MicroPython目前仅支持IDF v5.0.4和V5.1.2版本( MicroPython IDF版本要求 : MicroPython目前支持的IDF版本如下图所示)。然而,不排除以后可能会支持更高版本的可能性。
图6.1.3.2 MicroPython支持的IDF版本
到了这里,我们已经了解了MicroPython目前支持的IDF版本,下面作者来讲解Micropython ESP-IDF环境搭建的基本步骤:
1,克隆IDF库
首先打开ubuntu 22.04.2 LTS子系统,然后在命令行下输出“git clone -b v5.0.4 --recursive https://github.com/espressif/esp-idf.git(目前官方建议使用5.0.4 版本)”克隆Github仓库中的ESP-IDF源码库,如下图所示。
图6.1.3.3 克隆ESP32 IDF库
当读者成功克隆IDF库后,我们会在子系统(D:\Ubuntu_WSL\rootfs\root)根目录下找到一个名为“esp-idf”的文件夹。这个文件夹包含了ESP-IDF开发环境的相关文件和工具(相关文件的描述,请用户观看IDF版的教程)。
2,切换IDF 5.0.4版本
在root@DESKTOP-QH7611H:~/根目录下输入“cd esp-idf”进入esp-idf文件夹,然后在root@DESKTOP-QH7611H:~/esp-idf#目录下输入“git checkout v5.0.4”命令,切换IDF版本为v5.0.4。如下图所示。
图6.1.3.4 切换IDF版本
3,更新IDF版本子模块
在root@DESKTOP-QH7611H:~/esp-idf#目录下输入“git submodule update --init --recursive”更新子模块,如下图所示。
图6.1.3.5 更新子模块
一般来讲,在克隆IDF时会自动更新子模块,为了保险起见,最好重新更新子模块。
4,运行安装脚本和设置环境变量
root@DESKTOP-QH7611H:~/esp-idf#目录下输入两条命令“./install.sh”和“source export.sh”,它们分别是安装IDF环境和设置环境变量,设置成功之后系统提示“../export.sh”信息表示安装及设置环境变量成功如下图所示。
图6.1.3.6 IDF安装环境
上图提示“../export.sh”信息表示安装成功,此时我们在子系统目录下发现了.espressif隐藏文件夹,这是IDF环境搭建时生成的文件。
接着输入“source export.sh”设置环境变量,如下图所示。
图6.1.3.7 设置环境变量
上图提示“idf.py build”信息表示设置环境变量成功。请注意,每次进入Ubuntu 22.04.2 LTS子系统时,用户必须在root@DESKTOP-QH7611H:~/esp-idf#目录下输入“source export.sh”来操作环境变量,否则在生成固件时可能会报错。
为了解决上述的问题,作者在启动Ubuntu 22.04.2 LTS子系统时,在~/.bashrc直接执行export.sh文件,来设置ESP-IDF环境变量。
~/.bashrc 是一个在 Unix 和 Linux 系统中非常重要的 Shell 初始化文件。这个文件在 bash shell (Bourne Again SHell)启动时被读取(系统启动时),用户可以在这里定义别名、函数、环境变量、路径等,所有这些在以后启动的 bash shell 中都可用。
这个文件通常位于系统的 home 目录下(~/.bashrc),用户可以使用文本编辑器(如 vim、nano 或 emacs)来编辑它。在此文件最后一行命令下添加以下命令,如下所示:
source ./esp-idf/export.sh
这样我们在子系统启动时,就无需进去ESP-IDF源码库设置环境变量,启动时直接运行export.sh文件设置ESP-IDF的环境变量了。
到了这里,总共花费了作者一天的时间,因为Github是国外的服务器,国内的网路想要从Github下载资料,必须有更良好的网络才行,否则即使知道ESP-IDF搭建环境步骤,也未必能搭建成功。另外,作者还提供了第二种ESP-IDF环境搭建方法,请参考这个 博客的文章 ,他是从国内的gitee仓库克隆下来的,这样我们下载时就比较快速了。但在子模块更新时可能会遇到“gitee Username for 'https://gitee.com':”这样的提示信息,需要大家自行解决。
6.1.4 搭建MicroPython开发环境
在root@DESKTOP-QH7611H:~/目录下输入“git clone https://github.com/micropython/micropython.git”克隆MicroPython库,如下图所示。
图6.1.4.1 克隆MicroPython库
克隆成功之后,在此目录下输入“cd micropython”进入micropython库,然后输入“git submodule update --init --recursive”更新MicroPython子模块。
子模块更新成功之后,在root@DESKTOP-QH7611H:~/micropython#目录下输入“make -C mpy-cross”构建MicroPython交叉编译器,以便将一些内置脚本预编译为字节码,如下图所示。
图6.1.4.2 构建MicroPython交叉编译
构建MicroPython交叉编译器完成之后,就可以构建MicroPython ESP32固件了。首先在root@DESKTOP-QH7611H:~/micropython目录下输入“cd ports/esp32”进入MicroPython ESP32编译工程,在此目录下输入“make”构建ESP32 MicroPython固件,如下图所示。
图6.1.4.3 编译ESP32 MicroPython固件
根据上图所示,系统在esp32\build-ESP32_GENERIC文件夹下生成了三个bin文件,它们分别为bootloader.bin、partition-table.bin和micropython.bin。然后,我们使用flash_download_tool_3.9.5.exe工具将这三个bin文件烧录到ESP32芯片中,设置方法如下所示:
图6.1.4.4 烧录bin文件的地址设置
根据上图中的信息,我们可以得知烧录bin文件的地址是根据图5.1.4.4编译固件成功后的系统提示信息来进行的。根据提示信息,我们需要将生成的bin文件烧录到对应的地址中。另外,我们也可以使用esp32\build-ESP32_GENERIC文件夹下的firmware.bin文件,这个文件是bootloader.bin、partition-table.bin和micropython.bin三个文件的总bin文件:
图6.1.4.5 烧录总bin文件
注意:此固件虽然能满足ESP32在MicroPython下的运作,但它是有缺陷的。它并没有适配芯片的资源,如,是否挂载PSRAM、Flash/PSRAM的大小、时钟是否调节到240MHz等等。如果我们不去配置的话,系统可能选择默认的配置,如时钟只能达到160MHz、Flash大小为2MB等。这种默认的配置无法体现该芯片的价值,所以作者在后续的教程中,会详细讲解如何配置一个与手上芯片相匹配的固件。
6.1.5 MicroPython源文件结构分析
在上小节中,我们在子系统的Ubuntu下克隆了MicroPython源码包,并且在这个源码包下编译出了ESP32 MicroPython固件。下面,作者重点介绍这个源码包文件架构及文件功能说明。
MicroPython的基础源程序基本由C语言编写的,在编译过程中,使用了少量的Py脚本,用于在预编译过程中处理字符串。如下表中展示了MicroPython项目的源码文件结构。
表6.1.5.1 MicroPython项目的源文件结构
docs目录: 可生成MicroPython文档,可以在GitHub仓库中找到MicroPython/docs目录,并安装相关的工具来生成HTML,如下图所示。
图6.1.5.1 命令生成MicroPython文档
从上述可知,首先使用pip命令安装sphinx和sphinx_rtd_theme工具,然后在子系统上使用cd命令跳到micropython/docs目录下,最后在此目录下输入“make html”命令构建html文档。
py目录:在MicroPython的开发过程中,为了确保与Python标准库的一致性,我们不会修改py目录中的任何源代码。这是因为py目录存放着Python内核的全部源代码,是实现Python功能的重要基础。
lib目录和extmod目录:它们都包含了MicroPython扩展功能的组件,但它们的分工有所不同。lib目录中的内容是与MicroPython无关的,它们针对特定的微控制器平台,并可以独立地在这些平台上运行,以支持MicroPython功能的实现。它们位于MicroPython的下层,例如,包括各个微控制器平台的固件库、基本的文件系统协议栈和USB协议栈等。而extmod目录中实现的是扩展模块,这些模块都是基于MicroPython实现的,并在MicroPython内部实现扩展功能,例如,machine_spi模块就是在MicroPython的machine类中实现的SPI类模块。
对于微控制器开发者最有用也是最直接操作的目录是ports,里面存在了MicroPython支持的所有微控制器的移植代码,如下图所示。
图6.1.5.2 MicroPython已经支持的移植平台
在具体微控制器平台的目录下,存放了各自对MicroPython的底层移植源文件以及移植工程的Makefile文件。因此,在6.1.4小节编译固件时,作者只输入“make”命令即可完成ESP32 MicroPython固件的编译和构建。
6.2 编译ESP32-S3固件
上小节中,我们直接make就可以构建ESP32固件了,make 这是Make的基本命令,用于生成目标文件。执行make命令时,Make会自动查找当前目录下的Makefile文件(如果真的要细说make命令和Makefile,可能需要客户了解linux相关知识了)。
Makefile是用于自动编译和构建软件项目的工具。它使用简单的规则来告诉编译器如何构建软件。Makefile包含一组命令,这些命令用于编译、链接和构建源代码文件。
在ESP32-S3的固件编译过程中,可以在ports/esp32目录中找到一个Makefile文件。这个Makefile文件包含了编译ESP32-S3固件的规则和指令。通过编辑Makefile文件,可以设置要编译的型号,例如GENERIC_S3,然后保存文件后在终端使用make命令开始编译适用于对应板型的固件。
为了用户能够了解MicroPython固件编译,下面作者简单讲解一下ports/esp32目录Makefile文件到底有什么作用,该文件的部分内容如下所示:
ifdef BOARD_DIR # (1)自定义板路径 BOARD ?= $(notdir $(BOARD_DIR:/=)) else # (2)如果命令行中未给出,则默认为ESP32_GENERIC. BOARD ?= ESP32_GENERIC # (3)得到对应芯片的编译路径 BOARD_DIR ?= boards/$(BOARD) endif ifeq ($(wildcard $(BOARD_DIR)/.),) ifeq ($(findstring boards/GENERIC,$(BOARD_DIR)),boards/GENERIC) $(warning The GENERIC* boards have been renamed to ESP32_GENERIC*) endif $(error Invalid BOARD specified: $(BOARD_DIR)) endif # (5)如果没有给出构建目录,使用默认文件名 ifneq ($(BOARD_VARIANT),) BUILD ?= build-$(BOARD)-$(BOARD_VARIANT) else BUILD ?= build-$(BOARD) endif # (6)串口设备波特兰 PORT ?= /dev/ttyUSB0 BAUD ?= 460800 # Python3 PYTHON ?= python3 .PHONY: all clean deploy erase submodules FORCE CMAKE_ARGS = # (5)使用C模块,把自己的C驱动编译成MicroPython调用的API ifdef USER_C_MODULES CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} endif IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -D MICROPY_BOARD_DIR=$(abspath $(BOARD_DIR)) $(CMAKE_ARGS) ifdef FROZEN_MANIFEST IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST) endif # (6)设置PSRAM SPI模式、D2WD等 ifdef BOARD_VARIANT IDFPY_FLAGS += -D MICROPY_BOARD_VARIANT=$(BOARD_VARIANT) endif HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" define RUN_IDF_PY idf.py $(IDFPY_FLAGS) -B $(BUILD) -p $(PORT) -b $(BAUD) $(1) endef all: idf.py $(IDFPY_FLAGS) -B $(BUILD) build || (echo -e $(HELP_BUILD_ERROR); false) @$(PYTHON) makeimg.py \ $(BUILD)/sdkconfig \ $(BUILD)/bootloader/bootloader.bin \ $(BUILD)/partition_table/partition-table.bin \ $(BUILD)/micropython.bin \ $(BUILD)/firmware.bin \ $(BUILD)/micropython.uf2 $(BUILD)/bootloader/bootloader.bin $(BUILD)/partition_table/partition-table.bin $(BUILD)/micropython.bin: FORCE clean: $(call RUN_IDF_PY,fullclean) # 自动烧录 deploy: $(call RUN_IDF_PY,flash) # 擦除指令 erase: $(call RUN_IDF_PY,erase-flash) monitor: $(call RUN_IDF_PY,monitor) size: $(call RUN_IDF_PY,size) size-components: $(call RUN_IDF_PY,size-components) size-files: $(call RUN_IDF_PY,size-files) # 更新子模块 submodules: @GIT_SUBMODULES=$$(idf.py $(IDFPY_FLAGS) -B $(BUILD)/submodules -D ECHO_SUBMODULES=1 build 2>&1 | \ grep '^GIT_SUBMODULES=' | cut -d= -f2); \ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules
上述源码中的(1)表示要编译型号(如make BOARD=GENERIC_S3就是编译S3的MicroPython固件),如果在命令行中没有给出这个变量,则默认为ESP32_GENERIC(2),即编译ESP32这款芯片;(3)表示编译路径,也就是在这个路径下编译哪些文件,如果(1)中没有设置BOARD变量,则系统会编译boards/ESP32_GENERIC路径下的文件(如下图所示);(4)表示构建文件夹名称,这个文件夹包含系统编译产生的文件都会保存在这个文件夹中;(5)表示是否使用C模块,也就是说,使用C驱动编译成MicroPython可调用的API,这个方法我们到第六章时候讲解;(6)表示编译条件,如挂在PSRAM的SPI模式为SPIRAM_OCT。
图6.2.1 boards/ESP32_GENERIC路径下的文件
上图中的mpconfigboard.cmake文件用于指定编译哪些sdkconfig文件。sdkconfig文件决定了系统应该编译和构建哪些功能(即加载项目的具体变量,通过具体变量让系统执行相应的代码),而mpconfigboard.h文件则用于定义全局宏定义,系统在运行时会根据这些宏定义的数值来执行相应的条件判断。
打开mpconfigboard.cmake文件,如下:
# 需执行的文件 set(SDKCONFIG_DEFAULTS boards/sdkconfig.base boards/sdkconfig.ble ) # 判断是否开启D2WD if(MICROPY_BOARD_VARIANT STREQUAL "D2WD") set(SDKCONFIG_DEFAULTS ${SDKCONFIG_DEFAULTS} boards/ESP32_GENERIC/sdkconfig.d2wd ) list(APPEND MICROPY_DEF_BOARD MICROPY_HW_MCU_NAME="ESP32-D2WD" ) endif() # 省略以下代码
从上述内容可知,编译ESP32 MicroPython固件时,需要执行boards/路径下的sdkconfig.base和sdkconfig.ble文件以及条件判断下的sdkconfig.x文件。根据这些项目的具体变量,系统将有意识地编译哪些代码。下面,作者将以sdkconfig.spiram_sx为例来讲解这个文件的作用。
打开ports/esp32/boards/sdkconfig.spiram_sx文件,如下:
# PSRAM模式 CONFIG_SPIRAM_MODE_QUAD=y ...... # PSRAM 读取速率 CONFIG_SPIRAM_SPEED_80M=y # 使能PSRAM CONFIG_SPIRAM=y ......
此文件用于配置ESP32芯片是否挂载PSRAM,以及设置SPI模式、速率等相关项目的具体变量。例如,正点原子ESP32-S3开发板的主控使用的是ESP32-S3-WROOM-1-N16R8模组,根据《esp32-s3-wroom-1_wroom-1u_datasheet_cn.pdf》模组数据手册第三页表1所示,该模组的PSRAM使用Octal SPI模式,因此在本章节编译ESP32-S3固件时,需要开启PSRAM,并将SPI模式设置为Octal SPI。
ESP32-S3-WROOM-1-N16R8模组内置16MB Flash(Octal SPI)和8MB PSRAM(Octal SPI),可运行最高时钟频率为240MHz。这些信息来自《esp32-s3_datasheet_cn.pdf》和《esp32-s3-wroom-1_wroom-1u_datasheet_cn.pdf》这两份数据手册。
根据上述的要求,作者划分几个步骤来讲解。
1,修改sdkconfig.board文件
打开ports/esp32/borads/ESP32_GENERIC_S3路径下打开sdkconfig.board文件,此文件的内容如下:
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y CONFIG_ESPTOOLPY_AFTER_NORESET=y # Flash大小 CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y CONFIG_ESPTOOLPY_FLASHSIZE_16MB= CONFIG_PARTITION_TABLE_CUSTOM=y # 分区表名称 CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
此文件默认设置Flash大小为8MB,显然不符合ESP32-S3-WROOM-1-N16R8模组内置16MB Flash大小,因此,把CONFIG_ESPTOOLPY_FLASHSIZE_16MB配置为y,并且修改分区表名称为“partitions-16MiB.csv”,修改后如下:
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y CONFIG_ESPTOOLPY_AFTER_NORESET=y # Flash大小为16MB CONFIG_ESPTOOLPY_FLASHSIZE_4MB= CONFIG_ESPTOOLPY_FLASHSIZE_8MB= CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_PARTITION_TABLE_CUSTOM=y # 分区表名称 CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv"
2,修改partitions-16MiB.csv分区表
因为正点原子ESP32-S3 MicroPython固件使用了乐鑫AI库,因此这个AI库存储在Flash内需要大量的内存。因此,我们将分区表中的factory子分区(存储代码的区域)设置为6M。
修改前的分区表:
# Notes: the offset of the partition table itself is set in # $IDF_PATH/components/partition_table/Kconfig.projbuild. # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000 , phy_init, data, phy, 0xf000, 0x1000 , factory, app, factory, 0x10000, 0x1F0000, # 1M内存 vfs, data, fat, 0x200000, 0xE00000, # 14M内存
修改后的分区表
# Notes: the offset of the partition table itself is set in # $IDF_PATH/components/partition_table/Kconfig.projbuild. # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000 , phy_init, data, phy, 0xf000, 0x1000 , factory, app, factory, 0x10000, 0x600000, # 6M内存 vfs, data, fat, 0x700000, 0x900000, # 9M内存
到了这里,我们成功让MicroPython源代码适配了ESP32-S3-WROOM-1-N16R8模组。有小伙伴会问,为什么CONFIG_ESPTOOLPY_FLASHMODE_QIO还是为y呢?其实,在编译固件时,通过在make命令后面加上“BOARD_VARIANT= SPIRAM_OCT”命令就可以覆盖这个项目具体变量。大家可以打开ports/esp32/boards/ESP32_GENERIC_S3路径下的mpconfigboard.cmake文件,如下所示:
set(IDF_TARGET esp32s3) set(SDKCONFIG_DEFAULTS boards/sdkconfig.base boards/sdkconfig.usb boards/sdkconfig.ble boards/sdkconfig.spiram_sx boards/ESP32_GENERIC_S3/sdkconfig.board ) if(MICROPY_BOARD_VARIANT STREQUAL "SPIRAM_OCT") set(SDKCONFIG_DEFAULTS ${SDKCONFIG_DEFAULTS} boards/sdkconfig.240mhz boards/sdkconfig.spiram_oct ) list(APPEND MICROPY_DEF_BOARD MICROPY_HW_BOARD_NAME="Generic ESP32S3 module with Octal-SPIRAM" ) endif()
根据上述文件内容,当MICROPY_BOARD_VARIANT变量等于SPIRAM_OCT时,将编译sdkconfig.240mhz和sdkconfig.spiram_oct文件。sdkconfig.240mhz文件用于将芯片的时钟频率配置为240MHz,而sdkconfig.spiram_oct文件则用于将外挂PSRAM的SPI模式配置为Otcal SPI。因此,在系统编译sdkconfig.spiram_oct时,将禁用CONFIG_SPIRAM_MODE_QUAD这个项目具体变量,并将CONFIG_SPIRAM_MODE_OCT这个项目具体变量设置为y。以下是sdkconfig.spiram_oct文件的内容:
# MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support in Octal mode CONFIG_SPIRAM_MODE_QUAD= CONFIG_SPIRAM_MODE_OCT=y
至此,MicroPython源代码适配ESP32-S3-WROOM-1-N16R8模组完成,接下来,在ports/esp32/路径下输入“make BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT”命令构建ESP32-S3-WROOM-1-N16R8模组MicroPython固件,如下图所示。
图6.2.2 ESP32-S3-WROOM-1-N16R8模组MiroPython固件
根据上图所示,系统会在build-ESP32_GENERIC_S3-SPIRAM_OCT文件夹下生成四个bin文件,它们分别是bootloader.bin、partition-table.bin、micropython.bin和firmware.bin(总bin)。接着,我们使用flash_download_tool.exe工具将这三个bin文件烧录到ESP32-S3-WROOM-1-N16R8模组中。设置flash_download_tool的方法请参考图5.1.4.5所示。需要注意的是,bootloader.bin、partition-table.bin和micropython.bin设置的下载地址分别为0x0000、0x8000和0x10000。如果烧录的是firmware.bin(总bin),则将烧录地址设置为0x0000。当然,我们也可以借助Thonny软件来烧录这个固件,如下图所示。
图6.2.3 烧录ESP32-S3 MicroPython固件
烧录完成后,关闭烧录界面,切换Thonny软件的解释器。在Thonny软件的Shell下提示固件信息,如下图所示。
图6.2.4 固件提示信息
在Shell交互环境下输入以下代码,查看固件资源信息,如下图所示。
图6.2.5 提示固件资源信息
从上图中可知,这个固件的系统时钟被设置为240MHz,内部Flash大小为16MB,PSRAM经过申请和释放操作,最后打印剩余空间为7.930084MB约等于8MB。
6.3 总结
不妨读者思考一下MicroPython的ESP32-S3固件为什么能驱动ESP32-S3芯片,并且实现相关的应用。
在编译MicroPython的ESP32-S3固件之前,需要先搭建ESP-IDF环境。这是因为ESP-IDF库为开发者提供了一套完善的API,使得开发者可以使用高级语言(如C/C++)来操作硬件,而不需要直接对硬件寄存器进行操作。这一设计大大降低了开发的难度,使得开发者可以更加专注于实现应用功能,而不必花费大量时间在底层的硬件操作上。
MicroPython的ESP32-S3固件编译也是基于这一思想进行的。它在ESP-IDF库的基础上进行了Python的封装,使得用户可以使用Python的语法来实现对ESP32-S3芯片的控制。这种封装方式不仅使得使用MicroPython进行开发变得更加简单和方便,同时也提高了MicroPython的可读性和易用性。
总的来说,MicroPython的ESP32-S3固件编译是基于ESP-IDF库进行的,它为开发者提供了一种更加高级、更加方便的方式来控制ESP32-S3芯片,使得开发者可以更加专注于实现应用功能。