MicroCLI: Befehlsinterpreter auf einem STM32F0-Discovery + WLAN + Handy-App
Überblick
Abstract
Ziel ist die Kommunikation zwischen einer Mikrocontroller-Platine und einer Handy-App über WLAN/Bluetooth zum Steuern von Ein- und Ausgängen.
Der Name MicroCLI setzt sich dabei aus Micro für Microcontroller (µC, uC, MCU) und CLI für Command Line Interface (Command Line Interpreter, Befehlsinterpreter) zusammen.
Ein paar Informationen zur WLAN Platine gibt es in diesem Blogpost.
Was macht ein richtiges Kommunikationsprotokoll aus?
A well-designed communications protocol has a number of characteristics.
Everything is sent in well defined packets with a header and an optional body or data payload. In each packet’s header a type and or command specified. Each packet has a definite length.
In addition to these characteristics, protocols have varying degrees of statefulness, inter-packet independence, human readability, and the ability to reestablish a disconnected session.
Paket Format (packet header):
- Start Markierung mit packet length, Typ z.B. <start:0x00DF:0x01>
- Endmarkierung <end>
Weiterhin könnte man noch eine Checksumme am Ende hinzufügen um zu erkennen, ob es zu Übertragungsfehlern gekommen ist, einen Zähler der mit jedem Paket nach oben gezählt wird, oder eine Antwort ID, damit der Empfänger eine Antwort genau einer Frage zuordnen kann.
<start:length:type:responseid:counter> packet data <checksum:end>
Die Länge am Anfang ist nützlich falls wir dynamisch Speicher für das Paket anfordern und keinen festen Buffer haben und um fest zu stellen ob Bytes verlorengegangen sind, falls die Endmarkierung nicht dort ist wo sie sein sollte.
Andere Idee: Ein kleiner Befehlsinterpreter
Da die Menge der übermittelten Daten eher gering ist reicht auch eine einfache zeilenbasierte Kommunikation über Befehle aus. Jeder Befehl wird durch ein Newline-Symbol '\n' abgeschlossen und die Daten müssen nicht in Pakete gekapselt werden. Das Handy sendet die Befehle zum Bluetooth-/WLAN-Modul, diese werden an den Serial Port des Mikrocontrollers weitergeleitet, dieser interpretiert dann die Befehle und sendet das Ergebnis zurück. Der Benutzer der Handy App bekommt gar nicht mit, was im Hintergrund ausgeführt wird, man kann sich aber auch ohne Handyapp mit jedem Bluetooth/WLAN fähigen Laptop via Hyperterminal/Telnet verbinden und Daten auslesen oder Parameter setzen.
Der Befehlsinterpreter
Hier sind ein paar interaktive Script Interpreter die klein genug sind um auf Mikrocontrollern zu laufen:
PyMite:
http://deanandara.com/PyMite/docs/PyMiteOverview.html
PyMite is a flyweight Python interpreter written from scratch to execute on 8-bit and larger microcontrollers with resources as limited as 64 KiB of program memory (flash) and 4 KiB of RAM. PyMite supports a subset of the Python syntax and can execute a subset of its bytecodes. PyMite can also be compiled, tested and executed on a desktop computer.
GNU GENERAL PUBLIC LICENSE
picol:
- http://oldblog.antirez.com/page/picol.html
- A 556 lines of human readable C code Tcl interpreter with an interactive shell.
- BSD Lizenz
Weitere:
- Sammelthread bei Stackoverflow: http://stackoverflow.com/questions/1082751/what-are-the-available-interactive-languages-that-run-in-tiny-memory
- embedded Command Line Interpreter (eCLI): http://sourceforge.net/projects/ecli/
- Fort Interpreter for AVR ATmega: http://sourceforge.net/projects/amforth/
- AVR Shell: http://www.battledroids.net/downloads/avrsh.html
- Python-on-a-Chip (p14p): https://code.google.com/p/python-on-a-chip/
- picol, a Tcl interpreter in 550 lines of C code: http://oldblog.antirez.com/page/picol.html
- LPC2148 command-line interface (“Monitor”): http://www.microbuilder.eu/projects/LPC2148ReferenceDesign/LPC2148CodeBase.aspx
- Jcwren ARM CLI: http://www.jcwren.com/arm/#cli
- PicoC - a very small C interpreter for scripting: https://code.google.com/p/picoc/
- Ethersex Command (ECMD): http://www.ethersex.de/index.php/ECMD, https://github.com/ethersex/ethersex/tree/master/protocols/ecmd
- Bitlash: a programmable command shell for arduino: http://bitlash.net
- Wren: https://github.com/darius/wren
- A Scheme Interpreter for ARM Microcontrollers: http://armpit.sourceforge.net/
- libshell (part of libemb) provides the environment needed to build interactive (remote-) shells: https://github.com/wendlers/libemb
Ein kleiner Python Interpreter wäre am interessantesten, aber auf dem STM32F0-Mikrocontroller ist einfach nicht genug Platz.
Deshalb habe ich mich dann für die libshell aus dem libemb-Projekt entschieden, mit der sich ein ressourcensparender Interpreter realisieren ließ, bei dem der Quelltext trotzdem leicht verständlich und übersichtlich ist.
Durch den Verzicht auf printf aus der Newlib und stattdessen der Verwendung von libconio konnte ich noch mal 30KB Programmspeicher einsparen.
- 48,1 KiB mit picol
- 40 KiB ohne picol
- 5,6 KiB mit libconio cio_printf
- 6,3 KiB mit libshell und 2 Befehlen
- 6,8 KiB Nicht blockierendes Command Prompt mit Zeileneditor (Backspace Taste funktioniert unter anderem in der Eingabezeile microcli>)
- 8,2 KiB mit WLAN-Initialisierung und Befehlsinterpreter über Telnet
- 11,6 KiB mit allen momentanen Funktionen, die auf den Screenshots der Handy Apps weiter unten zu sehen sind
Wenn in der Datei conf.h die Zeile #define WIFI_CONNECTED einkommentiert ist, wird das WLAN Modul automatisch initialisiert und bis zu 16 Personen sollten gleichzeitig per WLAN über Telnetverbindungen auf den Befehlsinterpreter zugreifen können:

Telnet Verbindung mit PuTTY unter Windows.
Das STM32F0-Discovery Board
Das ganze läuft momentan auf einem STM32F0-Discovery Entwicklungsboard von STM:
- Eingebauter USB-Programmer/Debugger
- STM32F051R8T6 Cortex-M0 Mikrocontroller
- 64 KB Flash
- 8 KB RAM
- 9,69 € bei Farnell
Die Mikrocontroller Entwicklungsumgebung
Software unter Windows
- Programmer’s Notepad, Notepad++ oder anderer Editor/IDE
- GCC ARM Embedded Toolchain
- https://launchpad.net/gcc-arm-embedded/+download
- https://launchpad.net/gcc-arm-embedded/4.6/4.6-2012-q2-update/+download/gcc-arm-none-eabi-4_6-2012q2-20120614.exe
- Installation unter C:\arm-none-eabi-gcc-4.6-2012-q2, keine Lehrzeichen im Pfad
- STM32 ST-LINK Utility
- Zum Flashen des Mikrocontrollers
- Enthält auch die USB Treiber für das Discovery Board
- http://www.st.com/internet/com/SOFTWARE_RESOURCES/TOOL/DEVICE_PROGRAMMER/stm32_st-link_utility.zip installieren
- YAGARTO Tools
- make Programm für Windows
- http://www.yagarto.de/#download
- http://www.yagarto.de/download/yagarto/yagarto-tools-20100703-setup.exe (2 MB)
Software unter Linux
- Ein Editor oder eine IDE: QtCreator, Eclipse, Kate, vim, Netbeans, etc.
- GCC ARM Embedded Toolchain
- Flashen und Debuggen:
- https://github.com/texane/stlink
- sudo cp 49-stlinkv* /etc/udev/rules.d
- sudo udevadm control --reload-rules
- OpenOCD (Aus dem Git Repository git://git.code.sf.net/p/openocd/code, https://github.com/christianjann/microcli-stm32f0-discovery#loading-the-image-on-the-board)
- Nemiver: http://projects.gnome.org/nemiver/
- https://github.com/texane/stlink
Das Mikrocontroller Programm kann dann mit dem beiliegenden Makefile unter Windows und Linux compiliert werden. Zusätzlich befinden sich im Projektverzeichnis noch 2 Batchdateien, eine zum Compilieren und eine zum Flashen unter Windows.
Das Mikrocontroller Programm
Basiert auf dem Template: https://github.com/szczys/stm32f0-discovery-basic-template
Application Notes, Manuals and Firmware Package:
- STM32F0DISCOVERY: http://www.st.com/internet/evalboard/product/253215.jsp
- STM32 F0 http://www.st.com/internet/mcu/subclass/1588.jsp
Die Links zum Download des Source Code von GitHub befinden sich unten.
Compilieren und Flashen unter Windows
Wenn die oben genannten Programme installiert sind kann das Mikrocontroller Programm durch doppeltes klicken auf compile_with_gcc.bat compiliert werden:
Zum flashen muss das Discovery Board über USB mit dem PC verbunden werden, dann kann das Programm über die STLINK GUI auf den Mikrocontroller geflashd werden:
Das Flashen ist auch über die Batchdatei flash_with_st-link.bat möglich:
Compilieren und Flashen unter Linux
Zum Compilieren wird in das Verzeichnis mit dem Source Code gewechselt und make aufrufen:
[chris@thinkpad microcli-stm32f0-discovery]$ make clean
find . \( -name "*.orig" -or -name "*~" \) -exec rm -v "{}" \;
removed `./README.md~'
rm -f *.o
rm -f main.elf
rm -f main.hex
rm -f main.bin
rm -f main.map
rm -f main.lst
[chris@thinkpad microcli-stm32f0-discovery]$ make
make -C Libraries
make[1]: Entering directory `/mnt/data/Elektrotechnik/ARM/Projekte/MicroCLI/microcli-stm32f0-discovery/Libraries'
arm-none-eabi-ar -r libstm32f0.a stm32f0xx_adc.o stm32f0xx_cec.o stm32f0xx_comp.o stm32f0xx_crc.o stm32f0xx_dac.o stm32f0xx_dbgmcu.o stm32f0xx_dma.o stm32f0xx_exti.o stm32f0xx_flash.o stm32f0xx_gpio.o stm32f0xx_i2c.o stm32f0xx_iwdg.o stm32f0xx_misc.o stm32f0xx_pwr.o stm32f0xx_rcc.o stm32f0xx_rtc.o stm32f0xx_spi.o stm32f0xx_syscfg.o stm32f0xx_tim.o stm32f0xx_usart.o stm32f0xx_wwdg.o
make[1]: Leaving directory `/mnt/data/Elektrotechnik/ARM/Projekte/MicroCLI/microcli-stm32f0-discovery/Libraries'
arm-none-eabi-gcc -Wall -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m0 -march=armv6-m -mthumb -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,-Map=main.map -I inc -I Libraries -I Libraries/CMSIS/Device/ST/STM32F0xx/Include -I Libraries/CMSIS/Include -I Libraries/STM32F0xx_StdPeriph_Driver/inc -include Libraries/stm32f0xx_conf.h -I Libraries/libemb/libserial/src/include -I Libraries/libemb/libconio/src/include -I Libraries/libemb/libshell/src/include src/cli.c src/stm32f0xx_it.c src/main.c src/wifi.c src/system_stm32f0xx.c src/usart.c src/stm32f0_discovery.c Libraries/libemb/libconio/src/conio_serial.c Libraries/libemb/libconio/src/conio.c Libraries/libemb/libserial/src/serial_rb.c Libraries/libemb/libshell/src/shell.c Device/startup_stm32f0xx.s -o main.elf -LLibraries -lstm32f0 -LDevice/ldscripts -Tstm32f0.ld
arm-none-eabi-objcopy -O ihex main.elf main.hex
arm-none-eabi-objcopy -O binary main.elf main.bin
arm-none-eabi-objdump -St main.elf >main.lst
arm-none-eabi-size main.elf
text data bss dec hex filename
11484 364 2920 14768 39b0 main.elf
[chris@thinkpad microcli-stm32f0-discovery]$
Flashen unter Linux funktioniert über den Aufruf von make program:
[chris@thinkpad microcli-stm32f0-discovery]$ make program
openocd -f /usr/share/openocd/scripts/board/stm32f0discovery.cfg -f extra/stm32f0-openocd.cfg -c "stm_flash `pwd`/main.bin" -c shutdown
Open On-Chip Debugger 0.6.0-rc1-dev-00002-g66b9bff (2012-08-13-17:17)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
1000 kHz
srst_only separate srst_nogate srst_open_drain
Info : clock speed 1000 kHz
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints
stm_erase
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x08002320 msp: 0x20002000
auto erase enabled
Info : device id = 0x20006440
Info : flash size = 64kbytes
target state: halted
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20002000
wrote 12288 bytes from file /home/chris/data/Elektrotechnik/ARM/Projekte/MicroCLI/microcli-stm32f0-discovery/main.bin in 0.763440s (15.718 KiB/s)
target state: halted
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0x20002000
verified 11848 bytes in 0.159326s (72.620 KiB/s)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x08002320 msp: 0x20002000
shutdown command invoked
[chris@thinkpad microcli-stm32f0-discovery]$
Debuggen unter Linux
Wenn Nemiver und xterm installiert sind geht das über den Aufruf von make debug, siehe hier.
Die Handy Apps
Bei den Apps gibt es sicher noch Verbesserungspotential, sie sollten als eher Proof of Concept verstanden werden.
Die Apps wurden unter Android 1.6, im Emulator unter Android 2.2 und unter Android 4.1 getestet.
Auf GitHub gibt einen extra Branch der eine angepasste Version für Android 1.6 enthält, da bei der API unter Android 1.6 noch ein paar Funktionen fehlen und einen extra Branch für Android 4.1 da inzwischen einige ältere Funktionen aus der Android API entfernt wurden.
Entwicklungsumgebung:
- Download des Android SDK: https://developer.android.com/sdk/index.html
- Folgen der Anleitung: https://developer.android.com/sdk/installing/index.html
- Debuggen auf der richtigen Hardware: https://developer.android.com/tools/device.html
MicroCLI Android Console
- Minimal Programm zu Testzwecken
- Bei drücken der Menü-Taste öffnet sich kleines Menü mit 3 Funktionen: toggle LED3, disable TOGGLE_LEDS, enable TOGGLE_LEDS. Damit kann man das Blinken der LEDs aus-/einschalten oder LED3 umschalten.
- Eingabefeld um einzelne Befehle an das Mikrocontroller Board zu senden.
- Vor dem Starten der App sollte man sich über die WLAN Einstellungen des Handys mit dem MicroCLI_WiFi-Netzwerk verbinden.
MicroCLI Android Control
Viele Funktionen haben extra Menüs und Buttons.
Um die App im Emulator zu testen müssen die Variablen USE_BLUETOOTH und RUN_IN_EMULATOR in MicrodroidActivity.java folgende Werte haben:
private static final boolean USE_BLUETOOTH = false; private static final boolean RUN_IN_EMULATOR = true;
Hier ein paar Screenshots von der App, die Outputs und Optionen kann man durch antippen mit dem Finger umschalten:









Der Source Code
MicroCLI: https://github.com/christianjann/microcli-stm32f0-discovery
MicroCLI Android Console: https://github.com/christianjann/microcli-android-console
MicroCLI Android Control: https://github.com/christianjann/microcli-android-control