Building MicroPython Firmware for STM32: Nucleo L476RG and STM32F411CEU6 Boards
บทความนี้เป็นบันทึกช่วยจำ เพื่อลองทำขั้นตอนคอมไพล์ซอร์ซโค้ดของ MicroPython โดยใช้ WSL Ubuntu สำหรับ Windows 10 เพื่อให้ได้ไฟล์เฟิร์มแวร์ (Firmware) และนำไปทดสอบกับบอร์ดไมโครคอนโทรลเลอร์ STM32 เช่น บอร์ด STM32 NUCLEOo L476RG และบอร์ด STM32F411CEU6
MicroPython สำหรับบอร์ด STM32
เนื่องจากบอร์ด STM32 NUCLEO มีให้เลือกใช้งานหลายชนิด แตกต่างกันไปตามชิปไมโครคอนโทรลเลอร์ ที่มีอยู่บนบอร์ด ในบทความนี้ เราจะเลือกใช้บอร์ด Nucleo L476RG ซึ่งใช้ชิปไมโครคอนโทรลเลอร์ STM32L476RGT6 (ARM 32-bit Cortex-M4 CPU, 1 MB Flash, 128 KB SRAM, 80 MHz max.)
อีกบอร์ดหนึ่งที่ได้เลือกมาทดลองใช้งาน และมีราคาถูกว่ามาก คือ บอร์ดที่ใช้ชิป STM32F411CEU6 (ARM Cortex M4, 512 KByte Flash, 128 KByte SRAM, 100MHz) แต่มีหน่วยความจำ Flash น้อยกว่า STM32L476RGT6
เนื่องจากมีราคาถูก เมื่อซื้อบอร์ดนี้มา จะต้องนำมาบัดกรีขา (Pin Headers มีแถมมาให้) จึงจะนำไปใช้งานได้ เช่น เสียบลงบนเบรดบอร์ด
ข้อสังเกต: มุมจากด้านล่างของ PCB บริเวณ U3 มีไว้สำหรับบัดกรีชิป SPI Flash แต่ไม่ได้ใส่มาให้ ถ้าต้องการเพิ่มความจุของ Flash ซึ่งหมายถึง ขนาดของ Flash File System ก็สามารถบัดกรีไอซีเพิ่มได้ เช่น Winbond W25Qxx ขนาด 4MB / 8MB / 16MB เป็นต้น
ขั้นตอนการสร้างไฟล์เฟิร์มแวร์ MicroPython สำหรับบอร์ด NUCLEO
ในบทความนี้ เราจะทำคำสั่งต่าง ๆ โดยใช้ WSL Ubuntu สำหรับ Windows 10 ดังนั้น ถ้ายังไม่เคยใช้งาน ให้ติดตั้ง WSL ก่อน (ทำตามขั้นตอน Guideline ของ Microsoft และเลือกใช้ Ubuntu 18.04 LTS) หรือถ้าใช้งานระบบปฏิบัติการ Ubuntu โดยตรง ก็มีขั้นตอนไม่แตกต่างกัน
ขั้นตอนการติดตั้ง MicroPython for STM32 อ้างอิงตามเอกสารออนไลน์ดังนี้
https://github.com/micropython/micropython/wiki/Getting-Started-STM
- การคอมไพล์โค้ดสำหรับ STM32 จำเป็นต้องใช้ GNU ARM Embedded Toolchain ให้ดาวน์โหลดไฟล์ ติดตั้งตามเวอร์ชันและระบบปฏิบัติการที่ต้องการใช้ได้ ในตัวอย่างนี้เราได้เลือกใช้เวอร์ชัน “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. ดาวน์โหลดซอร์ซโค้ดของ MicroPython จาก Github
$ git clone https://github.com/micropython/micropython.git
$ cd micropython
$ git submodule update --init --recursive
3. คอมไพล์โค้ดสำหรับ MicroPython Cross Compiler (mpy-cross
)
$ sudo apt-get install build-essential libffi-dev pkg-config
ทำคำสั่ง make
ในไดเรกทอรีชื่อ mpy-cross
$ make -C mpy-cross
4. คอมไพล์โค้ดสำหรับ 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
ถ้าใช้บอร์ด STM32 NUCLEO ซึ่งมีวงจร ST-Link รวมไว้บนบอร์ดแล้ว เมื่อนำไปเชื่อมต่อด้วยสาย USB กับคอมพิวเตอร์ Windows จะมองเห็นไดเรกทอรี (USB Flash Drive) ปรากฏชื่อเป็น NUCLEO_L476RG การโปรแกรมไฟล์ .bin
ก็ทำได้ง่าย โดยการลากไฟล์ไปยังยูเอสบีไดรฟ์
ถ้าใช้ WSL Ubuntu จะไม่สามารถมองเห็นพอร์ต USB (และไม่สามารถใช้คำสั่ง make deploy
ได้) ดังนั้นจึงใช้วิธีสำเนาไฟล์จาก Ubuntu File System ไปยังไดเรกทอรีของ Windows 10 ตัวอย่างเช่น
$ cp build-NUCLEO_L476RG/firmware.bin /mnt/c/Work/Micropython_STM32
จากนั้นเมื่อบอร์ด NUCLEO ได้รีบูทตัวเองใหม่โดยอัตโนมัติ เราก็สามารถใช้โปรแกรมอย่างเช่น Thonny IDE เชื่อมต่อกับบอร์ดได้
ขั้นตอนการสร้างไฟล์เฟิร์มแวร์ MicroPython สำหรับบอร์ด STM32F411CEU6
ถ้าจะใช้บอร์ด STM32F411CEU6 Development Board (WeAct) จะต้องดาวน์โหลดไฟล์สำหรับบอร์ดนี้ (Board Definition Files) ซึ่งมีนักพัฒนาได้ทำแล้ว (Thank to Mr. Mike Causer, Australia) แชร์ไว้ใน Github โดยทำคำสั่งดังนี้ แล้วทำคำสั่ง make
โดยเลือกบอร์ดชื่อ WEACT_F411CEU6
ข้อสังเกต: ถ้ามีการเพิ่มไอซี SPI Flash จะต้องแก้ไขไฟล์ mpconfigboard.h
ก่อนทำขั้นตอนคอมไพล์ แตถ้าไม่ได้ใช้ SPI Flash ภายนอก ก็ให้ใช้ Internal Flash 512KB (default)
$ cd micropython/ports/stm32/boards
$ git clone https://github.com/mcauser/WEACT_F411CEU6.git
$ cd ..
$ make BOARD=WEACT_F411CEU6
การอัปโหลดเฟิร์มแวร์ในโหมด DFU
เมื่อได้ไฟล์ firmware.dfu
ถัดไปจะมาลองใช้คำสั่ง dfu-util
สำหรับ Windows
ให้ดาวน์โหลดไฟล์ dfu-util-0.9-win64.zip และแตกไฟล์ในไดเรกทอรีใหม่ ภายในมีคำสั่ง .exe ที่เรียกใช้งานได้
ข้อสังเกต: ถ้าไม่ต้องการใช้ DFU ก็ให้ใช้ ST-Link แทน ถ้ามีอุปกรณ์ ST-Link V2 Programmer
การใช้คำสั่ง dfu-util
สำหรับ Windows จะต้องมีการเลือกใช้ USB Driver ให้ถูกต้องก่อน โดยจะต้องเปลี่ยนไปใช้ WinUSB Driver และเราสามารถใช้โปรแกรมอย่างเช่น UsbDriverTool.exe
การทำให้บอร์ด STM32F411CEU6 รีบูทใหม่ แล้วเข้าสู่โหมด DFU มีดังนี้
- เชื่อมต่อขา A10 (PA10/USB_FS_ID) ด้วยตัวต้านทาน Pullup เช่น 10k ไปยัง VCC (3.3V) และเสียบสายไฟเชื่อมต่อระหว่างขา A9 และ A10
- เสียบสาย USB-C เชื่อมต่อบอร์ดไมโครคอนโทรลเลอร์กับคอมพิวเตอร์
- กดปุ่ม BOOT0 ก่อน โดยกดค้างไว้ แล้วจึงกดปุ่ม RESET
- ปล่อยปุ่ม RESET และ BOOT0 ตามลำดับ
เปิดโปรแกรม USB Driver Tool แล้วมองหารายการ STM Device in DFU Mode (0483:df11) ถ้ามีรายชื่อปรากฏ แสดงว่าบอร์ดนั้นอยู่ในโหมด DFU แล้ว
สำหรับอุปกรณ์ (0483:df11) ให้เปลี่ยน USB Driver โดยกดปุ่ม Change driver type แล้วให้เลือกรายการ Driver Selection: WinUSB หรือ STM32 Bootloader (ถ้ามีให้เลือก)
ลองทำคำสั่ง dfu-util.exe
สามารถสื่อสารกับบอร์ด STM32 ในโหมด DFU ได้หรือไม่
dfu-util.exe -d 0483:df11 -l
ตัวอย่างข้อความเอาต์พุตที่ปรากฏ
Found DFU: [0483:df11] ver=2200, devnum=4, cfg=1, intf=0, path="1-1.2.4", alt=3, name="@Device Feature/0xFFFF0000/01*004 e", serial="336A338C3337"Found DFU: [0483:df11] ver=2200, devnum=4, cfg=1, intf=0, path="1-1.2.4", alt=2, name="@OTP Memory /0x1FFF7800/01*512 e,01*016 e", serial="336A338C3337"Found DFU: [0483:df11] ver=2200, devnum=4, cfg=1, intf=0, path="1-1.2.4", alt=1, name="@Option Bytes /0x1FFFC000/01*016 e", serial="336A338C3337"Found DFU: [0483:df11] ver=2200, devnum=4, cfg=1, intf=0, path="1-1.2.4", alt=0, name="@Internal Flash /0x08000000/04*016Kg,01*064Kg,03*128Kg", serial="336A338C3337"
เมื่อมองเห็นอุปกรณ์แล้ว ก็ทำคำสั่งเพื่ออัปโหลดไฟล์ .dfu
ไปยังหน่วยความจำ Internal Flash ภายในชิป STM32
dfu-util -a 0 -D ../firmware.dfu
เมื่อทำขั้นตอนได้สำเร็จแล้ว ให้ถอดสายไฟที่เชื่อมต่อระหว่างขา A9 และ A10 แล้วกดปุ่ม RESET หลังจากนั้นจากนั้น ให้ลองใช้ Thonny IDE เชื่อมต่อกับบอร์ด
ตัวอย่างโค้ดทดสอบ: LED Blink
ลองมาดูตัวอย่างโค้ด MicroPython สำหรับทดลองการทำงานเบื้องต้น โดยทำให้ LED ที่มีอยู่บนบอร์ด STM32F411CEU6 กระพริบได้ (ขา GPIO ของ On-board Blue LED ตรงกับ PC13)
import machine
import timeLED_OFF = 1
# use the onboard Blue LED
led = machine.Pin('PC13', machine.Pin.OUT)try:
while True:
led.value( not led.value() )
time.sleep_ms(100)
except KeyboardInterrupt:
pass
finally:
led.value( LED_OFF )
print('Done')
หรือจะลองต่อวงจร LEDs ภายนอก เช่น RGB LED (ขา GPIO ที่ B7, B8, B9) ตามโค้ดตัวอย่างนี้
from machine import Pin
import time# on board push button (active-low)
btn = Pin('A0', Pin.IN, Pin.PULL_UP )led_pins = ['B7','B8','B9'] # pins for RGB LED
leds = [Pin(pin, Pin.OUT) for pin in led_pins ]
try:
while btn.value():
for led in leds:
led.low()
time.sleep_ms(200)
led.high()
time.sleep_ms(200)
except KeyboardInterrupt:
pass
finally:
for led in leds:
led.value( 1 )
print('Done')
ลองเขียนโค้ดเพื่อตรวจสอบขนาดของ Flash File System
import uos as osstat = os.statvfs('/flash')
print(stat)block_size = stat[0]
total_blocks = stat[2]
free_blocks = stat[3]print( 'Total space (bytes):', total_blocks * block_size )
print( 'Free space (bytes):', free_blocks * block_size )
ตัวอย่างเอาต์พุต ซึ่งแสดงให้เห็นว่า ความจุ (Total space) มีประมาณ 47 KB
(512, 512, 94, 80, 80, 0, 0, 0, 0, 255)
Total space (bytes): 48128
Free space (bytes): 40960
โดยสรุป เราได้เห็นขั้นตอนการติดตั้งโปรแกรมและการทำคำสั่งต่าง ๆ เพื่อคอมไพล์ซอร์ซโค้ด และติดตั้งใช้งานเฟิร์มแวร์ของ MicroPython สำหรับบอร์ด STM32