Building MicroPython Firmware for STM32: Nucleo L476RG and STM32F411CEU6 Boards

<rawat.s>
5 min readApr 28, 2020

--

‍‍‍‍‍‍ ‍‍ ‍‍‍‍‍‍

บทความนี้เป็นบันทึกช่วยจำ เพื่อลองทำขั้นตอนคอมไพล์ซอร์ซโค้ดของ 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.)

บอร์ด STM32 NUCLEO L476RG

อีกบอร์ดหนึ่งที่ได้เลือกมาทดลองใช้งาน และมีราคาถูกว่ามาก คือ บอร์ดที่ใช้ชิป STM32F411CEU6 (ARM Cortex M4, 512 KByte Flash, 128 KByte SRAM, 100MHz) แต่มีหน่วยความจำ Flash น้อยกว่า STM32L476RGT6

เนื่องจากมีราคาถูก เมื่อซื้อบอร์ดนี้มา จะต้องนำมาบัดกรีขา (Pin Headers มีแถมมาให้) จึงจะนำไปใช้งานได้ เช่น เสียบลงบนเบรดบอร์ด

บอร์ด STM32F411CEU6 (มุมมองจากด้านบน)
บอร์ด STM32F411CEU6 (มุมมองจากด้านล่าง)

ข้อสังเกต: มุมจากด้านล่างของ 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

  1. การคอมไพล์โค้ดสำหรับ 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
ตัวอย่างข้อความที่ปรากฏ เมื่อเริ่มขั้นตอน 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
ตัวอย่างการคลิกเลือกไฟล์ .bin แล้วลากไปใส่ลงในไดรฟ์ NUCLEO_L476RG

จากนั้นเมื่อบอร์ด NUCLEO ได้รีบูทตัวเองใหม่โดยอัตโนมัติ เราก็สามารถใช้โปรแกรมอย่างเช่น Thonny IDE เชื่อมต่อกับบอร์ดได้

Thonny IDE: เมนู Select Interpreter: MicroPython (generic) และ Serial Port
ตัวอย่างการเปิดไฟล์ใน MicroPython Flash File System ของบอร์ด โดยใช้ 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
ตัวอย่างข้อความที่ปรากฏเมื่อทำขั้นตอน 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 แล้ว

USB Driver Tool: เลือกรายการ STM Device in DFU Mode

สำหรับอุปกรณ์ (0483:df11) ให้เปลี่ยน USB Driver โดยกดปุ่ม Change driver type แล้วให้เลือกรายการ Driver Selection: WinUSB หรือ STM32 Bootloader (ถ้ามีให้เลือก)

เปลี่ยนไปใช้ 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
ตัวอย่างข้อความที่ปรากฏเมื่อทำคำสั่ง dfu-util

เมื่อทำขั้นตอนได้สำเร็จแล้ว ให้ถอดสายไฟที่เชื่อมต่อระหว่างขา A9 และ A10 แล้วกดปุ่ม RESET หลังจากนั้นจากนั้น ให้ลองใช้ Thonny IDE เชื่อมต่อกับบอร์ด

ตัวอย่างโค้ดทดสอบ: LED Blink

‍‍‍‍‍‍ ‍‍ ‍‍‍‍‍‍ ‍‍‍‍‍‍

ลองมาดูตัวอย่างโค้ด MicroPython สำหรับทดลองการทำงานเบื้องต้น โดยทำให้ LED ที่มีอยู่บนบอร์ด STM32F411CEU6 กระพริบได้ (ขา GPIO ของ On-board Blue LED ตรงกับ PC13)

import machine
import time
LED_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')
ทดลองเขียนและรันโค้ดใน Thonny IDE

หรือจะลองต่อวงจร 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

--

--

<rawat.s>
<rawat.s>

Written by <rawat.s>

I'm Thai and working in Bangkok/Thailand.

Responses (1)