> For the complete documentation index, see [llms.txt](https://think-embedded.gitbook.io/micropython/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://think-embedded.gitbook.io/micropython/building-micropython-firmware.md).

# Building MicroPython Firmware

## MicroPython-ESP32 Firmware&#x20;

โดยปรกติแล้ว ถ้าต้องการใช้งานไมโครไพธอนกับบอร์ดไมโครคอนโทรลเลอร์ เช่น **ESP32** หรือบอร์ดอื่น ๆ ก็มีไฟล์ **.bin** ที่ทางผู้พัฒนาได้จัดทำไว้แล้ว เพื่อนำไปใช้ติดตั้งเป็นเฟิร์มแวร์ (**Firmware**) ลงในหน่วยความจำ **Flash** ของบอร์ดไมโครคอนโทรลเลอร์ เช่น สำหรับ **ESP32** ก็สามารถดาวน์โหลดได้จาก <https://micropython.org/download/esp32/>

ในบางกรณี ถ้าเราต้องการลองดัดแปลงแก้ไข หรือลองทำขั้นตอน **Build Firmware** จากซอร์ซโค้ด (**Source Code**) ของ [**MicroPython**](https://github.com/micropython/micropython) ที่ดาวน์โหลดมาจาก **Github** ก็ต้องติดตั้งเครื่องมือหรือโปรแกรมที่จำเป็น โดยจำแนกตามระบบปฏิบัติการที่เลือกใช้ได้ เช่น **Windows**, **Linux**, **Mac OS**

{% hint style="info" %}
ในการคอมไพล์ซอร์ซโค้ดของไมโครไพธอน เช่น สำหรับ **ESP32** หรือ **STM32** แนะนำให้ใช้ **Linux** เช่น **Ubuntu** สำหรับคอมพิวเตอร์ **x86\_64** หรือ **Raspbian OS** สำหรับบอร์ด **Raspberry Pi** ในกรณีที่ใช้ระบบปฏิบัติการ **Windows 10** ก็แนะนำให้ใช้  **WSL  / WSL2** ที่รองรับการใช้งาน **Ubuntu 18.04 LTS** หรือใหม่ (ทำตามขั้นตอน [**Guideline ของ Microsoft**](https://docs.microsoft.com/en-us/windows/wsl/install-win10))&#x20;
{% endhint %}

ถัดไปเป็นขั้นตอนสำหรับ **Ubuntu** ที่อ้างอิงจาก:\
<https://github.com/micropython/micropython/tree/master/ports/esp32>

เครื่องคอมพิวเตอร์ที่ได้ลองใช้งานคือ คอมพิวเตอร์บอร์ดเดี่ยว **Raspberry Pi 4 Model B** ติดตั้งระบบปฏิบัติการ **Raspbian OS Buster (32-bit)** แต่ก็เราก็สามารถใช้คอมพิวเตอร์ **Ubuntu** หรือใช้งานผ่าน **WSL2** สำหรับ **Windows 10** ได้เช่นกัน

ตัวอย่างการทำคำสั่ง เพื่อดูเวอร์ชันของระบบปฏิบัติการ **Linux** ที่ได้นำมาใช้งาน

```
$ cat /etc/os-release 

PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
...
```

**ขั้นตอนแรก** ให้ติดตั้งโปรแกรมคำสั่งต่าง ๆ ที่จำเป็นต้องใช้ในขั้นตอนถัดไปลงในเครื่องคอมพิวเตอร์ **Linux** ของผู้ใช้ ดังนี้

```
$ sudo apt-get install python3 python3-pip python3-setuptools \
    git wget libncurses-dev flex bison gperf \
    cmake ninja-build ccache libffi-dev libssl-dev
```

**ขั้นตอนที่ 2** กำหนดไดเรกทอรี เพื่อทำคำสั่งดาวน์โหลด **Repository** ของไมโครไพธอน จาก **Github** มายังคอมพิวเตอร์ของผู้ใช้ (ในตัวอย่างนี้ เลือกเป็น `$HOME/MicroPython`)

```
$ export MPY=$HOME/MicroPython
$ mkdir -p $MPY && cd $MPY
$ git clone https://github.com/micropython/micropython.git
```

**ขั้นตอนที่ 3** เป็นการติดตั้งเครื่องมือต่าง ๆ เช่น **ESP-IDF** สำหรับ **ESP32**

ทำคำสั่งเพื่อย้ายไปยังไดเรกทอรีสำหรับ **`ports/esp32`** แล้วทำคำสั่ง `make` ดังนี้

```
$ cd $MPY/micropython/ports/esp32
$ make ESPIDF=
```

ให้สังเกตข้อความเอาต์พุตจากการทำคำสั่งดังกล่าว ดูตรงข้อความที่มีคำว่า **git hash** เช่น

`Supported git hash (v3.3):`` `***`9e70825d1e1cbf7988cf36981774300066580ea7`***`Supported git hash (v4.0) (experimental):`` `***`4c81978a3e2220674a432a588292a4c860eef27b`***

ในการคอมไพล์โค้ดสำหรับ **ESP32** จะต้องใช้โปรแกรมที่เรียกว่า **ESP-IDF** ของบริษัท **Espressif** ซึ่งในขณะนี้มีให้เลือกใช้สองเวอร์ชัน คือ **v3.3** และ **v4.0** ตามข้อความข้างบน

เราจะเลือกใช้ **ESP-IDF v4.0** และทำคำสั่งต่อไปนี้เพื่อติดตั้งโปรแกรมต่าง ๆ ที่เกี่ยวข้อง โดยต้องระบุ **git commit ID**  (ค่า **hash** ในเลขฐานสิบหก) ที่ปรากฏในข้อความเอาต์พุตข้างบน เพื่อใช้กับคำสั่ง `git checkout`&#x20;

```
# set the ESPIDF path
$ export ESPIDF=$HOME/esp/esp-idf
$ mkdir -p $ESPIDF && cd $ESPIDF

# clone the ESP-IDF 4.x repository from github
$ git clone https://github.com/espressif/esp-idf.git $ESPIDF

# checkout the version that matches the specified commit-hash
$ git checkout 4c81978a3e2220674a432a588292a4c860eef27b
$ git submodule update --init --recursive

# install ESP-IDF toolchain by Espressif 
# (e.g. xtensa cross compilers) and Python packages 
# as required in $ESPIDF/requirements.txt
$ ./install.sh

# export the tools path
$ source $ESPIDF/export.sh
```

**ขั้นตอนที่ 4** ให้ย้ายไปยังไดเรกทอรีของไมโครไพธอนสำหรับ **ESP32**  แล้วเริ่มใช้งาน **Python Virtual Environment** พร้อมติดตั้งซอฟต์แวร์ที่เกี่ยวข้อง

```
# change to the Micropython's esp32 port
$ cd $MPY/micropython/ports/esp32
$ PYTHON=python3

# update the virtualenv package
$ sudo python3 -m pip install -U virtualenv

# install Python 3 virtual environment tool
$ python3 -m venv build-venv

# activate Python3 virtual environment
$ source build-venv/bin/activate

# install required Python packages
$ pip3 install -r $ESPIDF/requirements.txt
```

**ขั้นตอนที่ 5** ทำคำสั่งต่อไปนี้ เพื่อเริ่มขั้นตอนคอมไพล์โค้ด ซึ่งอาจใช้เวลาหลายนาที

```
# make the mpy cross compiler
$ cd $MPY/micropython/mpy-cross
$ make

$ cd $MPY/micropython/ports/esp32
$ make clean 
$ make submodules

# build the MicroPython firmware for ESP32 boards
$ make BOARD=GENERIC
$ make BOARD=GENERIC_SPIRAM 
```

**ข้อสังเกต**: สำหรับบอร์ด **ESP32** โดยทั่วไป จะมีสองประเภทคือ บอร์ด **ESP32** ที่ไม่มีชิปหน่วยความจำภายนอกประเภท **SPIRAM** (เรียกว่า **`GENERIC`**) และบอร์ดที่มี **SPIRAM** อย่างน้อย **4MB** (เรียกว่า **`GENERIC_SPIRAM`**) และเมื่อคอมไพล์โค้ดแล้ว จะได้ไฟล์เฟิร์มแวร์ (**.bin**) แยกกัน ต้องเลือกให้ถูกต้อง เมื่อจะนำไปใช้งาน

![รูปภาพ: ข้อความเอาต์พุตเมื่อคอมไพล์ firmware.bin (ESP32 GENERIC) ได้สำเร็จ](/files/-MN7amauSqbHT79RWE0P)

![รูปภาพ: เมื่อคอมไพล์ firmware.bin (ESP32 GENERIC\_SPIRAM) ได้สำเร็จ](/files/-MN7auCnh57a63EVNpMW)

**ขั้นตอนที่ 6** (สุดท้าย) เป็นการเขียนไฟล์ `firmware.bin` ไปยังบอร์ดเป้าหมาย

เมื่อได้ไฟล์ `firmware.bin` แล้ว ก็สามารถนำไปเขียนลงให้หน่วยความจำ **Flash** ของบอร์ด **ESP32** ได้ โดยใช้โปรแกรมแบบ **Command Line** เช่น `esptool.py`

เสียบสาย **USB** เชื่อมต่อระหว่างคอมพิวเตอร์ผู้ใช้กับบอร์ด **ESP32** แล้วลองทำคำสั่งดังนี้

```
$ esptool.py flash_id
```

![รูปภาพ: ตัวอย่างข้อความเมื่อทำคำสั่ง esptool.py flash\_id](/files/-MN7fW6VfDy0HQaDLG-l)

ถ้าสามารถเชื่อมต่อและอ่านค่าจากบอร์ด **ESP32** ก็ให้ทำคำสั่งเขียนข้อมูลจากไฟล์ `firmware.bin` ไปยังบอร์ดเป้าหมาย

```
# erash the whole flash memory
$ esptool.py --chip esp32 --baud 460800 erase_flash

# write firmware.bin (ESP32 GENERIC_SPIRAM) to flash
$ esptool.py --chip esp32 --baud 460800 write_flash -z 0x1000 \
 ./build-GENERIC_SPIRAM/firmware.bin
```

เมื่อทำได้แล้ว ให้ลองเชื่อมต่อกับบอร์ด **ESP32** ผ่านทาง **Serial REPL** จะเห็นข้อความเริ่มต้นหลังจากรีเซตการทำงานของบอร์ด เช่น

`MicroPython v1.13-189-g76a2dff61 on 2020-11-27; ESP32 module (spiram) with ESP32 Type "help()" for more information.`

ซึ่งแสดงว่า เราสามารถใช้งานไมโครไพธอนได้แล้ว

## Micropython-STM32 Firmware

ขั้นตอนการติดตั้ง **MicroPython for STM32** อ้างอิงตามเอกสารออนไลน์ดังนี้\
<https://github.com/micropython/micropython/wiki/Getting-Started-STM>

1\) การคอมไพล์โค้ดสำหรับ **STM32** จำเป็นต้องใช้ [**GNU ARM Embedded Toolchain**](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) ให้ดาวน์โหลดไฟล์ ติดตั้งตามเวอร์ชันและระบบปฏิบัติการที่ต้องการใช้ได้ ในตัวอย่างนี้เราได้เลือกใช้เวอร์ชัน “**GNU Tools for Arm Embedded Processors 8–2019q4-major”**

```
$ tar -xjvf gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2

$ sudo mv gcc-arm-none-eabi-8-2018-q4-major /opt

$ cd /opt

$ sudo chown -R $USER:$USER /opt/gcc-arm-none-eabi-8-2018-q4-major

$ export PATH="${PATH}:/opt/gcc-arm-none-eabi-8-2018-q4-major/bin"

$ arm-none-eabi-gcc --version
```

2\) ติดตั้งโปรแกรมสำหรับการคอมไพล์โค้ดใน **Ubuntu**

```
$ sudo apt-get install build-essential libffi-dev pkg-config
```

3\) ดาวน์โหลดซอร์ซโค้ดของ **MicroPython** จาก **Github**

```
$ git clone 
https://github.com/micropython/micropython.git

$ cd micropython
$ git submodule update --init --recursive
```

4\) คอมไพล์โค้ดสำหรับ **MicroPython Cross Compiler** (`mpy-cross`)

```
$ make -C mpy-cross
```

5\) คอมไพล์โค้ดสำหรับ **MicroPython-STM32 Port** เช่น บอร์ดเป้าหมายเป็น **NUCLEO\_L476RG**

```
$ cd ../ports/stm32
$ make submodules
$ make clean
$ make BOARD=NUCLEO_L476RG
```

เมื่อทำขั้นตอนคอมไพล์ซอร์ซโค้ดให้ได้ไฟล์เฟิร์มแวร์ ซึ่งจะอยู่ในไดเรกทอรี `build-NUCLEO_L476RG` และเป็นไฟล์ `.dfu` และ `.hex`

* ไฟล์ `.hex` จะใช้สำหรับการอัปโหลดด้วยอุปกรณ์ **ST-Link V2** และใช้ร่วมกับโปรแกรมเช่น **OpenOCD** หรือ **ST-Link Utility**
* ไฟล์ `.dfu` จะใช้วิธีการทำให้ **STM32** อยู่ในโหมด **DFU (Device Firmware Upgrade Mode**) แล้วสามารถใช้โปรแกรมอย่างเช่น `dfu-util` อัปโหลดไฟล์ไปยังบอร์ดโดยใช้เพียงสาย **USB**

ถ้าต้องการได้ไฟล์ **.bin** ก็ทำคำสั่งดังนี้

```
$ arm-none-eabi-objcopy -O binary \
  build-NUCLEO_L476RG/firmware.elf \
  build-NUCLEO_L476RG/firmware.bin
```

ถ้าใช้บอร์ด **NUCLEO** เมื่อเสียบสาย **USB** กับคอมพิวเตอร์ จะมองเห็นไดรฟ์ปรากฎขึ้นมา เราสามารถลากไฟล์ **.bin** ไปใส่ลงในไดรฟ์ดังกล่าว เพื่อทำการโปรแกรมไฟล์เฟิร์มแวร์สำหรับไมโครไพธอนได้

**ข้อสังเกต:** ถ้าใช้ **WSL Ubuntu** จะไม่สามารถมองเห็นพอร์ต **USB** และไม่สามารถใช้คำสั่ง `make deploy` ได้ ดังนั้นจึงใช้วิธีสำเนาไฟล์จาก **Ubuntu File System** ไปยังไดเรกทอรีของ **Windows 10** เช่น ไดรฟ์ **C** คือ `/mnt/c` แล้วใช้โปรแกรมสำหรับ **Windows** ทำการอัปโหลดไฟล์ เช่น โปรแกรม **STM32CubeProgrammer** ที่ใช้สามารถใช้ร่วมกับอุปกรณ์ **ST-Link Programmer** เป็นต้น
