MicroPython 在 esp-idf (esp32) 上编译固件

esp32 编译 micropython 的固件相关的资料应该很多吧,我也会出一篇,但会额外讲一些 linux 的东西的。

资料将按照以下顺序进行说明。

  • 什么是 esp-idf ?
  • 配置 esp32 工具链
  • 准备 micropython 仓库
  • 建立 micropython for esp32 固件

注意,以下操作截图全部在 linux 下完成(but 我在虚拟机,方便截图),顺便一提,我写的资料,并不会考虑开发新手,如果有问题可以评论解答,但我是不会在写的内容中照顾他人的,随心所欲,但是有问题欢迎来提。

什么是 esp-idf ?

esp-idf 就是 esp32 的官方标准 SDK 支持,进入仓库看下 readme 即可,但在这里并非必要了解的知识。

往下看前请先准备 esp-idf 的官方文档,进入 快速开始 一章,按步骤开始部署开发环境。

配置 esp32 交叉编译工具链

因为在电脑上写的程序将要编译运行在 esp32 上,所以这必然就需要交叉编译工具链,所以写代码先需要先配置好编译环境。

值得一提的是官方的配置文档(/get-started/linux-setup)写的流程很好,所以照着做就行,但要注意的是,它们都是在 i686(i386) 或 ARM64 上的机器上跑的二进制(bin)文件,如果需要在类似树莓派的 arm linux 上编译,则需要重新编译工具链了。

请准备一台 linux 按上述官方配置文档配置完成后,在命令行下输入 xtensa-esp32-elf 然后按 tab 键补全系统命令,确认配置完成,如下图。

注意工具链相关的文件需要绑定到系统全局下,作为命令(符号)给 makefile 接入。

所以记得在 linux 环境变量里添加路径,例如配置文档里讲的,至此编译环境已经建立,注意,不同版本的 idf 可能会变更 工具链 ,所以编译出错的时候不妨检查检查 esp-idf 和 工具链 是否匹配。

export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH";

至于如果你想编译工具链,可以继续看官方文档 从零开始设置 Linux 环境下的工具链 ,可喜可贺的是如今都有中文了鸭,上述我们设置的是编译后的二进制版本,如果想学习工具链的本质,就要亲自试试编译工具链了。

交叉编译工具链源码仓库 在这里 ,是很值得学习的开源代码呢。

准备 micropython 仓库

看到这里,我希望你已经按上述的文档和步骤,成功搭建 esp32 的编译环境和获取 esp-idf 源码。

如果发现 git clone 很慢,记得在尾巴添加 --depth=1 的命令,让它不要获取历史提交(commit),这样下载就会快很多了。

  • 准备好工具链xtensa-esp32-elf
  • 准备好开发 SDK 的仓库 esp-idf 。
  • 看一眼 esp32 目录下的 readme.md 。

通过下述命令获取 micropython 的仓库。

$ git clone https://github.com/micropython/micropython --depth=1

接着编译一下 mpy-coress ,用来给 Python 文件预编译为 bytecode 到固件里的工具链。

$ make -C mpy-cross

然后初始化一下相关的子仓库。

$ git submodule init lib/berkeley-db-1.xx
$ git submodule update

最后在编译(make)一下。

$ cd ports/esp32
$ make

此时编译就开始了,会有如下滚动信息。

大致是这样的流程,但要注意的是我这里只是简化了操作,接着说一下下述几个注意点。

注意看 micropython/port/esp32 的 readme.md 。

有如下内容:

Setting up the toolchain and ESP-IDF
------------------------------------ There are two main components that are needed to build the firmware:
- the Xtensa cross-compiler that targets the CPU in the ESP32 (this is different to the compiler used by the ESP8266)
- the Espressif IDF (IoT development framework, aka SDK) The ESP-IDF changes quickly and MicroPython only supports a certain version. The
git hash of this version can be found by running `make` without a configured
`ESPIDF`. Then you can fetch only the given esp-idf using the following command: $ git clone https://github.com/espressif/esp-idf.git
$ git checkout <Current supported ESP-IDF commit hash>
$ git submodule update --init --recursive

所以没事多看 readme ,比看一般人的博客强多了,所以我这里主要是交待一些编译的方法和常见错误的坑。

上述的意思很简单,就是 micropython 依赖于 esp-idf ,但是需要切换 esp-idf 的版本,也就是说随着 micropython 不一定会支持最新的 esp-idf 代码,如果出现错误,你需要通过 git checkout 切换版本号。

命令格式示范:git checkout <Current supported ESP-IDF commit hash>

而尾巴的<hash> 存放在 Makefile 文件中的,如下内容。

# the git hash of the currently supported ESP IDF version
ESPIDF_SUPHASH := 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9

所以在 esp-idf 的目录下有如下操作(注意和 readme 有点点不同鸭)

$ cd esp-idf
$ git checkout 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9
$ git submodule update --init --recursive

那么现在就可以继续编译 esp32 的 micropython 了。

此时注意,虽然前面说过直接 make 是可以,但实际上官方的做法是额外在 ports/esp32 里准备一个 makefile ,并且区别于 Makefile 文件(Linux 文件区分大小写),按 readme 所述填下列内容即可。

ESPIDF = <path to root of esp-idf repository> # such as ESPIDF = /root/esp-idf
BOARD = GENERIC
# PORT = /dev/ttyUSB0
# FLASH_MODE = qio
# FLASH_SIZE = 4MB
# CROSS_COMPILE = xtensa-esp32-elf- include Makefile

注意这里可以指定填写你的 ESP-IDF 路径,这样做的好处就是不需要添加到系统环境变量中了,所以你可以同时拥有许多份不同工程用的 esp-idf 仓库,并且此时 make 命令调用的是 makefile ,接着 makefile 末尾将会调用 Makefile(即 include Makefile),其他内容可以选填(# 为注释),相当于预先为 Makefile 的执行载入环境变量。

此时就开始编译固件吧,编译成功如下图:

此时常用命令有如下(查阅 readme 可知):

  • 打开串口收发,组合 Ctrl + A 和 Ctrl + Q 退出串口(需要安装 picocom )
$ picocom -b 115200 /dev/ttyUSB0
  • 擦除 esp32 中 flash 。
$ make erase
  • 编译后烧录 micropython 固件。
$ make deploy
  • 清理编译结果。
$ make clean
  • 组合命令,烧录完固件后打开串口。
$ make deploy && picocom -b 115200 /dev/ttyUSB0

如下图运行结果:

顺手输入了 print('hello esp32') ,值得注意的是,这里也支持 tab 补全操作多多体验吧。

额外的信息

为什么固件只有一个 firmware.bin 文件?

固件编译后的 firmware.bin 文件产生在 port/esp32/build 文件夹,它是通过 makeimg.py 合成的,看一下就知道发生了什么。

import sys

OFFSET_BOOTLOADER = 0x1000
OFFSET_PARTITIONS = 0x8000
OFFSET_APPLICATION = 0x10000 files_in = [
('bootloader', OFFSET_BOOTLOADER, sys.argv[1]),
('partitions', OFFSET_PARTITIONS, sys.argv[2]),
('application', OFFSET_APPLICATION, sys.argv[3]),
]
file_out = sys.argv[4] cur_offset = OFFSET_BOOTLOADER
with open(file_out, 'wb') as fout:
for name, offset, file_in in files_in:
assert offset >= cur_offset
fout.write(b'\xff' * (offset - cur_offset))
cur_offset = offset
with open(file_in, 'rb') as fin:
data = fin.read()
fout.write(data)
cur_offset += len(data)
print('%-12s% 8d' % (name, len(data)))
print('%-12s% 8d' % ('total', cur_offset))

可以得知,firmware.bin 是由 bootloader + partitions + application 而来的一个单独的 bin ,即为固件,所以只需要在 0x1000 起始位置烧入 esp32 的 flash 里就可以运行 micropython 了。

如何编译 8M spiflash 的固件?

此外我们还需要知道如何编译带 SPIRAM 固件,通常来说,只需要修改 makefile 的 BOARD = GENERIC_SPIRAM

ESPIDF = <path to root of esp-idf repository> # such as ESPIDF = /root/esp-idf
BOARD = GENERIC_SPIRAM
include Makefile

不过你也可能会遇到一些问题,比如我修改了编译工具链里的一些头文件才编译通过的,所以得做好准备随时修改源码的准备趴。

至于我遇到了什么问题,唔,改一下编译中的文件之间的符号关系就好了。

编译后运行可以看到 Found 64MBit SPI RAM device ,然后查看 gc.mem_free() 可以看到 3997 * 4096 Byte,也就是 4M RAM ,如下图(带有 SPIRAM 的固件)。

下图就是对照的无 Flash 固件,可以看到 111 * 1024 的,用的是内部的 RAM (小于 384 KB)。

结语

最后,如果遇到在本文的流程下出现编译问题,可以留言,也可以直接问我。

如何为 esp32 编译和配置及烧写 MicroPython 固件。的更多相关文章

  1. esp32(M5STACK)程序烧写(Ubuntu)

    由于我们的开发环境在Ubuntu上,所以介绍一下如何在Ubuntu上烧写esp32的程序 首先下载esptools   pip install esptool           擦除 sudo es ...

  2. 在windows 下使用eclipse进行编译和烧写

    eclipse IDE是一款开源的前端编程软件,它提供了编写,编译和调试ESP-IDF项目的图形集成开发环境. 首先在https://www.obeo.fr/en/eclipse-download?I ...

  3. UBoot的编译与烧写

    每当我们学习任何编译语言之前,第一节课都是介绍我们要学习的是什么,以及编译语言和工具,最后写一个小程序编译并运行就算入门,也就是所谓的"Hello, world!".这里也不例外, ...

  4. 编译 Linux 3.5 内核烧写 Android 4.2.2 到 Tiny4412 开发板

    . . . . . 昨天已经编译了 Android 4.2.2 的源码,详见<Ubuntu 14.04 编译 Android 4.2.2 for Tiny4412>一文. 今天我们继续剩下 ...

  5. sd卡脱机烧写系统的方法(测试成功)

    一.sd卡烧写系统的基本思路: (1)把uboot.bin烧写到sd卡 (2)把image整个文件夹复制到sd卡 (3)开发板从sd卡启动,就开始自动烧写到nandflash中了. 二.烧写uboot ...

  6. 【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410

    作者 : 万境绝尘 转载请著名出处 终于拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...

  7. 烧写uboot和openwrt固件ARxx系列

      以AR9331为例. 1.用烧录器将uboot烧写到flash中 (AR9331_U-Boot_Oolite-v1-v20170713.bin) 2.登录:192.168.1.1网页烧写uboot ...

  8. 8元电调调参教程(使用Arduino Uno)| BLHeli无刷电调的固件烧写及调参

    前言 淘某上有款8元电调,性价比很高,但是需要简单设置一下 1.材料清单 (1)Arduino UNO开发板 (2)BLHeliSuite 16.7.14.9.0.1 调参软件及固件已上传Gitee: ...

  9. VS Code 与 ESP32 官方SDK配置

    开发基于 ESP XXX 微控制器应用,最简单的环境搭建方案是像 MicroPython.CircuitPython.NanoFramework 等,下载固件,直接开刷:或者基于 Arduino 的开 ...

随机推荐

  1. Python可变参数函数用法详解

    来自:http://c.biancheng.net/view/2257.html 很多编程语言都允许定义个数可变的参数,这样可以在调用函数时传入任意多个参数.Python 当然也不例外,Python ...

  2. RDS数据库全量恢复方案

    一.全量恢复 恢复最近的快照,将快找之前的数据全量恢复 二.增量恢复 下载对应的binlog日志导入到数据库 三.还没有备份的binlog日志获取方法 首先连接 RDS for MySQL 后查看当前 ...

  3. 【Taro全实践】6位验证码输入视觉分离(标准下划线分离)

    一.实现的效果图 二.实现思路 中间想过很多实现方法,但是因为input为原生组件的原因,很难适配所有手机直接. 所有如何实现适配所有手机的验证码分离输入呢?(思路如下) 1.input组件为原生组件 ...

  4. iOS UIBarButtonItem 固定尺寸

    自定义UIBarButtonItem的时候发现 有时候UIBarButtonItem尺寸会发生变化 通过以下方式可以很好的解决问题 [button.widthAnchor constraintEqua ...

  5. 成功解决Developer Express和Janus WinForms Controls中控件的冲突

    最新在做一套GIS系统的框架,其中用到了Janus WinForms Controls和Developer Express这两个插件. 我用DE的xtraTabbedMdiManager组件来管理我的 ...

  6. WPF学习笔记 - .Net Framework的分离存储技术

    写入: protected override void OnClosed(EventArgs e) { base.OnClosed(e); IsolatedStorageFile f = Isolat ...

  7. C# VS预生成事件命令行 和 生成后事件命令行

    宏 说明 $(ConfigurationName) 当前项目配置的名称(例如,“Debug|Any CPU”). $(OutDir) 输出文件目录的路径,相对于项目目录.这解析为“输出目录”属性的值. ...

  8. Scrapy框架——使用CrawlSpider爬取数据

    引言 本篇介绍Crawlspider,相比于Spider,Crawlspider更适用于批量爬取网页 Crawlspider Crawlspider适用于对网站爬取批量网页,相对比Spider类,Cr ...

  9. Go项目实战:打造高并发日志采集系统(五)

    前情回顾 前文我们完成了如下功能1 根据配置文件启动多个协程监控日志,并启动协程监听配置文件.2 根据配置文件热更新,动态协调日志监控.3 编写测试代码,向文件中不断写入日志并备份日志,验证系统健壮性 ...

  10. How to remove duplicate lines in a large text file?

    How would you remove duplicate lines from a file that is  much too large to fit in memory? The dupli ...