---
tags: MicroPython, ESP32, 測試報告
robots: ESP32, firmware, 韌體, 編譯, expressif, esp-idf, MicroPython
lang: zh-tw
---
編譯 ESP32 的 MicroPython 韌體
===
由於編譯 MicroPython 韌體用到的都是 Linux 下開源的工具鏈, 雖然在 Windows 以及 Mac 上都有移植跨平台的工具, 但最便利的環境還是 Linux, 以下說明均以在 Ubuntu 20.04 為例。
:::info
在 Windows 上也可用 [WSL (Windows Subsystem for Linux)](https://hackmd.io/@meebox/H1VHLqCgF)。
:::
以下假設以 ~/code 為主要的資料夾, 我們會將所有的工具、原始碼都放在這個資料夾下。
```bash
mkdir code
cd code
```
## 安裝所需的套件與 Python 環境
編譯 MicroPythonn 韌體需要使用到許多工具以及 Python2 與 Python3 執行環境, 以下一一安裝。
### 安裝套件
1. 編譯韌體的 esp-idf 工具需要先安裝以下套件:
```bash
sudo apt-get install git wget libncurses-dev flex bison gperf python3 python3-pip cmake ninja-build ccache libffi-dev libssl-dev libdb-dev python2
```
### 安裝 Python 模組
3. 安裝 Python2 的 pip 管理模組, 由於在 Ubuntu 上沒有可直安裝的 Python2-pip 套件, 這裡改採用下載並執行 get-pip.py 的方式安裝:
```bash
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
```
注意上述網址中的 2.7 是根據系統上 Python2 的版本而定, 若沒有指定, 會取得預設為 Python3 的 get-pip.py。取得安裝 pip 的 Python 程式後, 執行以下步驟安裝 pip:
```bash
sudo python2 get-pip.py
```
4. 安裝 ESP-IDF 工具鏈需要的 virtualenv 套件, 版本不能太新, 請安裝舊版本:
```bash
pip2 install virtualenv==16.7.9
```
1. 稍後的韌體建置會使用到 Python3 以及 Python3 下的 pyparsing 模組, 且 pyparsing 模組必須是 2.4 版以下:
```bash
pip3 install 'pyparsing<2.4'
```
### 設定 Python 環境
2. MicroPython 編譯時會以 Python2 為預設的 Python, 所以我們再安裝以下的套件設定 Python2 為預設的 Python:
```bash
sudo apt install python-is-python2
```
:::info
如果你不需要編譯 1.14 或更早的版本, 可以只使用 Python3, 可安裝以下的套件將你的 Python3 設定為預設的 python:
```bash
sudo apt install python-is-python3
```
:::
## 下載 MicroPython 原始碼
1. 首先回到 ~/code 資料夾下:
```bash
cd ~/code
```
1. 接著複製 MicroPython 的原始碼:
```bash
git clone https://github.com/micropython/micropython.git
cd micropython
```
### 切換 MicroPython 版本
1. 如果需要編譯特定版本的 MicroPython, 可以先切換到特定的版本或是提交:
```bash
git checkout v1.14
```
1. 在 1.14 或是更早的版本, 可以先查看編譯所需的 esp-idf 工具鏈版本, 這只要在還沒有設定好 esp-idf 工具前, 切換到 ports/esp32 下執行 make 就可以了, 以下以 v1.14 版本為例:
```bash
cd ports/esp32
$ make
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.
See README.md for installation instructions.
Supported git hash (v3.3): 9e70825d1e1cbf7988cf36981774300066580ea7
Supported git hash (v4.0) (experimental): 4c81978a3e2220674a432a588292a4c860eef27b
Makefile:74: *** ESPIDF not set. Stop.
```
可以看到倒數第三行說明可以採用 V3.3 版 的 esp-idf, 也是雜湊碼 9e70825 開頭的提交。
如果是 1.15 開始的 MicroPython 版本, 稍後就請直接使用 v4.0.2 版的 esp-idf 即可。
## 安裝 esp-idf 開發工具
MicroPython 韌體的編譯使用的是 esp-idf 工具鏈:
1. 從 github 上複製 esp-idf 開發工具, 首先切回 code 資料夾下:
```bash
cd ~/code
git clone https://github.com/espressif/esp-idf.git
```
1. 接著切換到該資料夾中:
```bash
cd esp-idf
```
### 切換 esp-idf 工具版本
1. 請依照前面下載 MicroPython 的步驟, 將 esp-idf 工具鏈檢出到對應標籤的版本, 以下以切換到 v4.0.2 版編譯 v1.16 版的 MicroPython 韌體為例:
```bash
git checkout v4.0.2
```
1. 此倉庫用到許多子模組, 所以要先更新子模組:
```bash
git submodule update --init --recursive
```
### 建置與設定環境變數
1. 接著執行 install.sh 建置完整的 esp-idf 工具:
```bash
./install.sh
```
1. 設定環境變數:
```bash
. ./export.sh
```
:::success
這裡的 `.` 可以換成 `source`, 表示在目前 shell 下執行 export.sh 腳本, 而不是另外啟動一個 shell 來執行腳本, 這樣腳本裡設定的環境變數才會在目前的 shell 中生效。
:::
這裡設置的環境變數只在目前的 shell 中有效, 如果關閉 shell 重新開啟, 就要再重新執行一次 export.sh。
這樣就完成 esp-idf 工具的建置。
## 編譯跨平台 Python 編譯器
1. MicroPython 中可以載入以 Python 撰寫的模組, 這需要可將 py 檔編譯為 mpy 的編譯器, 因此要先建置這個編譯器:
```bash
cd ~/code/micropython
make -C mpy-cross
```
## 編譯 MicroPython 韌體
1. 在 ports 資料夾下有各種控制板的 MicroPython 檔案, 我們先切換到 esp32 下:
```bash
cd ports/esp32
```
1. 首先要先建置使用到的子模組:
```bash
make submodules
```
1. 接著編譯韌體:
```bash
make
```
1. 最後會在 build-GENERIC 下產生 firmware.bin 韌體檔:
```bash
ls build-GENERIC/*.bin
build-GENERIC/firmware.bin
build-GENERIC/micropython.bin
```
## 加入以 C 撰寫的模組
這裡以 [ulab](https://github.com/v923z/micropython-ulab) 模組為例, 說明如何將以 C 開發的模組一起編譯到 MicroPython 韌體中。
### 下載模組原始碼
```bash
cd ~/code
git clone https://github.com/v923z/micropython-ulab.git ulab
```
如果需要的話, 也可以在這裡切換版本或是提交。
### 讓 MicroPython 啟用 ulab 模組
請檢查你下載的 ulab 下 code/micropython.mk 檔, 是否有以下這行:
```
override CFLAGS_EXTRA += -DMODULE_ULAB_ENABLED=1
```
如果沒有的話, 請自行加上。
:::info
或者也可以在 ports/esp32/mpconfigport.h 檔, 在最後加上啟用 ulab 的敘述:
```CPP
#define MODULE_ULAB_ENABLED (1)
```
:::
### 編譯包含 C 模組的韌體
由於 esp-idf 工具在 4.x 與 3.x 版本採用的建置工具不同, 所以加入外部 C 模組的編譯方式略有差異, 以下分別說明。
#### MicroPython v1.15 或更新版本
由於使用新版的 esp-idf, 採用 CMake, 要在 micpropython/ports/esp32 中新增一個 makefile 檔, 告訴 CMake 要連帶把剛剛下載的 ulab 模組一起編譯到 MicroPython 韌體中。
1. 切換到資料夾中:
```bash
cd micropython/ports/esp32
```
1. 新增如下內容的檔案, 命名為 makefile:
```makefile
BOARD = GENERIC
USER_C_MODULES = $(HOME)/code/ulab/code/micropython.cmake
include Makefile
```
1. 先把剛剛建置的結果清除後再重新建置:
```bash
make clean
make
```
#### MicroPython 1.4 或更舊的版本
1. 切換到資料夾中:
```bash
cd micropython/ports/esp32
```
1. 先把剛剛建置的結果清除:
```bash
make clean
```
1. 在 make 時從指令行參數指定加入 C 模組一起編譯:
```bash
make USER_C_MODULES=../../../ulab all
```
建置完成一樣在 buile_GENERIC 下的 firmware.bin 就包含了 ulab 模組了。
## 加入額外的 Python 模組
如果你有使用 Python 撰寫的模組想要加入 MicroPython 韌體中, 可以將模組檔案放入 ports/esp32/modules 下, 像是下載的 MicroPython 原始碼中並沒有 [umqtt](https://github.com/micropython/micropython-lib/tree/master/micropython/umqtt.robust) 模組, 下載放入後重新編譯就可以了:
```bash
ls modules
apa106.py flashbdev.py mpu6050.py urequests.py
BlynkLib.py inisetup.py neopixel.py
_boot.py keras_lite.py umqtt
```