Embedded System II Tool (ESTOOL)

H. Högl, 2016, 2017, 2018, 2019 <Hubert.Hoegl@hs-augsburg.de>

Der ESTOOL Quelltext liegt auf Gitlab: https://r-n-d.informatik.hs-augsburg.de:8080/hubert.hoegl/estool

Inhalt

1   ESTOOL

1.1   Motivation

Wenn man Mikrocontroller mit elementaren Werkzeugen auf der Kommandozeile in einem Terminalfenster programmieren möchte, dann muss man eine Sammlung an Kommandozeilenaufrufen parat haben. Das ESTOOL konzentriert einige diese Kommandos in dem Aufruf estool. Typische Aufgaben sind Starten/Stoppen des OpenOCD Servers, Flashen und die Generierung von Tags zur Navigation im Editor. Ausserdem kann auch eine tmux Session gestartet werden. Tmux ist ein terminal multiplexer, der ein Terminalfenster in beliebige virtuelle Fenster unterteilen kann. Das estool ist in Python 3 geschrieben und läuft nur unter Linux. Hier sind ein paar Eigenschaften in Stichpunkten:

  • Klein und überschaubar.
  • Baut auf bewährten, schon lange verfügbaren Werkzeugen auf.
  • In Python 3 geschrieben.
  • Quelltext kann angepasst/erweitert werden (Open-Source Software unter MIT Lizenz)
  • Nicht-grafisch, das heisst alles findet in einem grösseren Terminal Fenster statt, das optional durch den Terminal Multiplexer tmux in mehrere windows und jedes window in mehrere panes geteilt werden kann.
  • Der Anwender soll durch ESTOOL lediglich unterstützt werden, die technischen Zusammenhänge sollen immer noch verstanden werden (und nicht verschleiert, wie das meist bei IDEs der Fall ist).

Die wesentlichen "Technologien", die in ESTOOL drin stecken, sind:

  • Python 3 (libtmux, executor, kaptan)
  • Shell (bash)
  • Terminal Multiplexer (tmux)
  • Session Manager für tmux (tmuxp)

Externe Abhängigkeiten sind:

  • Ein beliebiger Editor (Vim, Emacs, Atom, Sublime, VSC, ...)
  • Excuberant ctags
  • GNU C/C++ Crosscompiler für ARM
  • GNU Debugger (oder das grafische GDBGUI Werkzeug)
  • Open On-Chip Debugger OpenOCD
  • GNU make
  • Die Cube Bibliothek von ST Micro für den jeweiligen Mikrocontroller, z.B. CubeF1, CubeL4.

1.2   Rechner vorbereiten

Hinweis

Die im Text beschriebenen Konfigurationsdateien für tmux, vim, openocd und udev findet man unter [2].

Die Vorbereitung des Rechners umfasst ein paar allgemeine Schritte und ein paar Schritte, die vom verwendeten ARM Board abhängen:

Allgemeines:

  • GCC und GDB installieren
  • OpenOCD installieren
  • Hilfsprogramme installieren
    • make, picocom, splint, tmux, exuberant-ctags, ...
  • udev Regeln

Board-spezifisches:

  • udev Regeln für den USB-Zugang auf das Board (Debug-Adapter, serielle Schnittstelle)
  • Eventuell modprobe Regeln für bestimmte Boards, z.B. STM32 VL Discovery

1.2.1   GCC und GDB installieren

Man nimmt am besten das aktuelle Binärpaket von

https://launchpad.net/gcc-arm-embedded

Ich empfehle, die Dateien unter /opt zu installieren. Mein aktueller Pfad lautet:

/opt/gcc-arm-none-eabi-8-2019-q3-update/

Insgesamt umfassen die GNU Tools folgende Programme:

arm-none-eabi-addr2line  arm-none-eabi-gcc-ar     arm-none-eabi-ld.bfd
arm-none-eabi-ar         arm-none-eabi-gcc-nm     arm-none-eabi-nm
arm-none-eabi-as         arm-none-eabi-gcc-ranlib  arm-none-eabi-objcopy
arm-none-eabi-c++        arm-none-eabi-gcov       arm-none-eabi-objdump
arm-none-eabi-c++filt    arm-none-eabi-gcov-dump  arm-none-eabi-ranlib
arm-none-eabi-cpp        arm-none-eabi-gcov-tool  arm-none-eabi-readelf
arm-none-eabi-elfedit    arm-none-eabi-gdb        arm-none-eabi-size
arm-none-eabi-g++        arm-none-eabi-gdb-py     arm-none-eabi-strings
arm-none-eabi-gcc        arm-none-eabi-gprof      arm-none-eabi-strip
arm-none-eabi-gcc-7.3.1  arm-none-eabi-ld

Der GNU Debugger ist in zwei Varianten dabei, erstens arm-none-eabi-gdb (ohne Python) und zweitens arm-none-eabi-gdb-py (mit Python). Wir verwenden die zweite Variante.

Die Dokumentation findet man in den Formaten pdf, html, info und man unter

/opt/gcc-arm-none-eabi-8-2019-q3-update/share/doc/gcc-arm-none-eabi

1.2.2   OpenOCD installieren

Hinweis

(2018-10-16) Wer auf einem Ubuntu 18.04 arbeitet, der hat die gcc Version 7.3.0. Beim Kompilieren mit dieser neuen Compilerversion tritt ein Fehler beim Kompilieren von OpenOCD 0.10.0 auf, der ungefähr so aussieht:

src/svf/svf.c:663:7: error: this statement may fall through
[-Werror=implicit-fallthrough=]
...

Der Fehler lässt sich umgehen, wenn man die Option -Werror aus dem Makefile löscht.

  1. Hole OpenOCD Quelltextarchiv von http://www.openocd.org. Ich empfehle mit der aktuellen stabilen Version zu arbeiten, zur Zeit ist das die Version 0.10.0.

    Das Archiv kann man auch von meinem Server holen:

    wget http://hhoegl.informatik.hs-augsburg.de/es2/tools/openocd-0.10.0.tar.bz2
    
  2. Quelltext entpacken und konfigurieren.

    Hinweis: Bei manchen Linux Distribution ist es notwendig, vorher das noch fehlende Paket pkg-config zu installieren (z.B. bei Xubuntu). Sonst klappt der Konfigurationsprozess nicht. Weitere gelegentlich vorher nachzuinstallierende Pakete sind: libtool, autoconf, automake, libusb-1.0 (der genaue Paketname kann variieren, bei mir heisst er z.B. libusb-1.0-0-dev. Nachdem diese Pakete eventuell nachinstalliert wurden lauten die Kommandos zum Konfigurieren von OpenOCD:

    tar jxvf openocd-0.10.0.tar.bz2
    cd openocd-0.10.0
    ./configure --enable-stlink --prefix=/opt/openocd-0.10.0/
    

    Das Installationsverzeichnis ist damit auf /opt/openocd-0.10.0/ gesetzt.

  3. Bauen mit "make"

  4. Installieren (siehe prefix) als Superuser mit make install bzw. bei Ubuntu mit sudo make install.

    Man sollte die PATH Variable erweitern, so dass which openocd folgendes berichtet:

    hhoegl@e11:~$ which openocd
    /opt/openocd-0.10.0/bin/openocd
    

Wenn man nun openocd in einem beliebigen Verzeichnis startet, wird die Ausgabe sein:

hhoegl@e11:~$ openocd
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
     http://openocd.org/doc/doxygen/bugs.html
embedded:startup.tcl:60: Error: Can't find openocd.cfg
in procedure 'script'
at file "embedded:startup.tcl", line 60
Error: couldn't bind tcl to socket: Address already in use

Dies kommt durch die fehlende Konfigurationsdatei openocd.cfg. Der Inhalt dieser Datei sagt OpenOCD unter anderem, welches Board und welcher Debug-Adapter mit dem Rechner verbunden ist.

In jedem Projektverzeichnis sollte es das Unterverzeichnis .estool geben und darin die Datei openocd.cfg. Wenn man OpenOCD nun so startet:

openocd -f .estool/openocd.cfg

dann sollte die Ausgabe wie folgt sein, vorausgesetzt, alle udev Regeln (siehe unten) wurden richtig installiert:

hhoegl@e11 ~/es2-nucl476/starter $ openocd -f .estool/openocd.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 500 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : Unable to match requested speed 500 kHz, using 480 kHz
Info : clock speed 480 kHz
Info : STLINK v2 JTAG v28 API v2 SWIM v17 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 3.242772
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints

Das ESTOOL kann den OpenOCD Server über die Argumente --start-oocd und --stop-oocd im Hintergrund starten und stoppen.

1.2.3   Hilfsprogramme installieren

Nun sollte man noch ein paar Hilfsprogramme mit dem Linux Paketmanager installieren, die Paketnamen lauten wie folgt:

  • make

    Ein UNIX Klassiker. Steuert die Kompilierung mit sogenannten "Makefiles", die in einer regelbasierten Sprache geschrieben sind.

  • splint

    Die Linux-Variante des klassischen LINT Programmes, das C Programme statisch auf Programmierfehler prüfen kann.

  • picocom

    Ein Terminal Emulator.

    Mit picocom kann man ASCII Zeichen über einen USB-zu-UART Adapter an den Mikrocontroller schicken und von ihm empfangen. In der folgenden Abbildung sieht man links den USB-zu-UART Adapter der Firma Pololu (mit CP2101 Controller), rechts ist der von der Firma In-Circuit (mit CP2102 Controller). Beide Controller sind von https://www.silabs.com.

    bild1 bild2

    Der Debug-Adapter "STLINK-V2.1", der sich auf den ST Nucleo Boards befindet, hat bereits eine serielle Schnittstelle eingebaut. Über das angesteckte USB Kabel werden die Stromversorgung, das Debuggen und die serielle Schnittstelle gleichzeitig abgedeckt. Zusätzlich realisiert die USB Verbindung auch noch ein Massenspeicherinterface.

    In der udev Konfigurationsdatei 81-usb-to-serial.rules werden die Zugriffsrechte und die Gerätedateien für serielle Adapter (und andere) eingestellt.

    Ein Alternative zu picocom ist ckermit. Das Paket heisst ckermit, das Programm kermit. Die Homepage ist http://www.columbia.edu/kermit/ck90.html.

  • tmux

    Terminal Multiplexer. Beachte: Im Homeverzeichnis des Anwenders muss es eine Konfigurationsdatei ~/.tmux.config für tmux geben. Im etc/ Verzeichnis des ESTOOL gibt es Vorlagen für tmux Version 1.x bis 2.0 (_tmux.conf-1.x-2.0) und tmux Version >= 2.1 (_tmux.conf-2.1+). Mit tmux -V bekommt man heraus, welche tmux Version man hat.

    Den bei tmux voreingestellten Prefix-Wert C-b habe ich auf C-z geändert! Siehe dazu ~/.tmux.conf.

  • exuberant-ctags

    Erzeugt tags Files aus Quelltext. Dient zum Navigieren im Editor, z.B. im Vim. Viele Editoren können mit tags Dateien umgehen.

    Eine Fortführung von exuberant-ctags ist "universal ctags", siehe https://ctags.io. Alle modernen Linux Distributionen kennen diese ctags Variante. Man überzeuge sich mit ctags --version.

  • Geeigneten Programmier-Editor, ich verwende vim. Alternativen sind gedit, Emacs, Atom, Visual Studio Code, es gibt viele weitere. Der Editor sollte unbedingt mit den "tags" umgehen können, damit man im Quelltext navigieren kann.

  • netcat bzw. nc (optional)

    Programm zum Scripten von Netzwerkverbindungen, z.B. dem telnet Port von OpenOCD.

  • Saleae Logikanalysator

    Diese Gerät ist optional.

    Für den Saleae Logikanalysator gibt es ein kostenloses grafisches Bedienprogramm für Linux, Windows und MAC OS-X, man findet es auf der Homepage https://www.saleae.com.

    Man sollte das Programm in das Home-Verzeichnis /home/<user> installieren, danach heisst das neue Verzeichnis in etwa so:

    /home/user/Logic 1.2.14 (64-bit)/
    

    Die folgende Abbildung zeigt den Logikanalysator Saleae Logic4. Er wird über ein USB Kabel an den Entwicklungsrechner angeschlossen.

    img/saleae-logic4-red.jpg

    Saleae Logic4

  • Bus Pirate (http://dangerousprototypes.com/docs/Bus_Pirate)

    Dieses Gerät ist optional.

    Der "Bus Pirate" ist ein kleines Hardware-Modul, das an den PC über USB angeschlossen wird. Man kann damit vom PC aus fast alle in der Mikrocontrollertechnik verwendeten Schnittstellen ansteuern, z.B. GPIO, I2C, SPI, UART, PWM, ADC, DAC und viele weitere. Es ist daher eine sehr praktische Ergänzung, um digitale und analoge Signale an einen Mikrocontroller anzulegen und zu messen. Zum Beispiel kann man mit dem Bus Pirate einen Eingangspin am Mikrocontroller ansteuern, und im gdb Debugger feststellen, ob dadurch z.B. eine Interrupt-Routine ausgeführt wird.

    img/bus-pirate-3.6.jpg

    Bus Pirate v3.6.

1.2.4   Udev Regeln

Bei GNU/Linux regeln Dateien unter /etc/udev/rules.d/ unter anderem die Berechtigung beim Zugriff auf USB Geräte. Das sind die sogenannten udev rules. Bei der Mikrocontroller Entwicklung haben wir meist sogar mehrere angeschlossene USB Geräte, die spezielle Regeln erfordern:

  • Den Debug-Anschluss des Entwicklungsboards. Darüber steuert OpenOCD den Debug Vorgang. Ein einzelner USB Anschluss kann jedoch mehrere logische Verbindungen beinhalten. Zum Beispiel werden beim STM32L476 Nucleo über eine USB Verbindung drei Funktionen bereitgestellt: (a) die Debug Verbindung für OpenOCD, (b) ein USB Massenspeicher und (c) eine serielle Schnittstelle (UART).

    Manche Entwicklungsboards haben keinen integrierten Debug-Adapter. Dann benötigt OpenOCD einen externen Debug-Adapter.

    Die Regeldateien heissen:

    49-stlinkv2-1.rules    <== Nucleo STM32L476 Debug Adapter ("STLINK-V2.1")
    49-stlinkv2.rules      <== Externer STLINK Adapter ("STLINK-V2")
    49-stlinkv1.rules      <== STM32VLDiscovery Debug Adapter ("STLINK-V1")
    99-openocd.rules       <== Verschiedene Debug Adapter fuer OpenOCD
    
  • Ein oder mehrere USB-zu-UART Adapter:

    81-usb-to-serial.rules
    
  • Ein USB Logikanalysator, z.B. von http://www.saleae.com:

    100-saleae-logic.rules
    

Man kopiert die udev Regeln einfach in /etc/udev/rules.d/ und führt die folgenden Kommandos aus, damit die Regeln wirksam werden:

udevadm control --reload-rules
udevadm trigger

Oder man startet den Rechner neu. Die Regeln sind im ESTOOL vorhanden. Wenn man estool -l eingibt, werden die nötigen Kopierbefehle angezeigt.

Die Dateien der udev Regeln findet man im estool Repository an dieser Stelle:

https://r-n-d.informatik.hs-augsburg.de:8080/hubert.hoegl/estool/tree/master/estool/etc

Die udev Dateien sind auch in der ESTOOL Installation enthalten. Mit dem Kommando estool -p findet man das Installationsverzeichnis auf seinem Rechner. Wenn man an den ausgegebenen Pfad noch etc/ anhängt, dann hat man den Pfad, unter dem die udev Regeln sind.

1.2.5   Voraussetzungen prüfen

Die ESTOOL Option -c (für "check") hilft beim Prüfen der Voraussetzungen auf dem Hostrechner:

hhoegl@e11 $ estool -c
ESTOOL version 0.13 (2017-09-19)
Using board: stm32l476-nucleo
Checking platform
   Linux-4.4.0-53-generic-x86_64-with-debian-stretch-sid
Checking host python version
   found 3.6.0 final
TERM is set to screen-256color. Good.
Checking GDB
   Note: You need Python 2 support for the gdbmemview.py extension!
   Checking arm-none-eabi-gdb
      found /usr/bin/arm-none-eabi-gdb
      has Python 2 support
   Checking arm-none-eabi-gdb-py
      not found
   Checking /usr/bin/arm-none-eabi-gdb
      found /usr/bin/arm-none-eabi-gdb
      has Python 2 support
Checking GNU ARM cross compiler
   found /usr/bin/arm-none-eabi-gcc
Checking OpenOCD
   found /opt/openocd-0.10.0/bin/openocd
   version: b'Open On-Chip Debugger 0.10.0'
   found udev rules /etc/udev/rules.d/99-openocd.rules
   test openocd server with following command (as non-root):
      openocd -s /opt/openocd-0.10.0/share/openocd/scripts -f /home/hhoegl/anaconda3/lib/python3.6/site-packages/estool/etc/openocd-nucleo.cfg
Checking Tmux
   found /usr/bin/tmux
   version: b'tmux 2.1'
   found tmux startup file /home/hhoegl/.tmux.conf
   no local ESTOOL config file ./.estool/estool.yaml
   using global ESTOOL config file /home/hhoegl/anaconda3/lib/python3.6/site-packages/estool/etc/_estool/estool.yaml
   tmux server already running
Checking ST Link v2-1 debug adaptor connected to USB
   found ST Link adaptor 2-2.2.3
      device not bound to usb-storage
Checking udev rules /etc/udev/rules.d/49-stlinkv2-1.rules
   found udev rules /etc/udev/rules.d/49-stlinkv2-1.rules
Checking UART
    UART is on STLINK v2-1.  Try the command
        picocom -b 9600 /dev/ttyACM0
Checking Vim
   found vim startup file /home/hhoegl/.vimrc.
   you should compare it against the default file
   /home/hhoegl/anaconda3/lib/python3.6/site-packages/estool/etc/_vimrc.

1.3   ESTOOL Installation

Es kann sein, dass man vorher noch ein paar Pakete in Linux nachinstallieren muss. Bei mir waren das z.B. python3-pip, python3-setuptools, python3-wheel.

Danach kann man dann die ESTOOL so installieren:

git clone https://r-n-d.informatik.hs-augsburg.de:8080/hubert.hoegl/estool.git
cd estool
sudo python -m pip install --upgrade .

Das sudo vor python braucht man nur, wenn man in schreibgeschützte Bereiche installieren möchte. Manche Python 3 Installationen, z.B. Anaconda, sind im Homeverzeichnis installiert, da kann man sudo weglassen.

Die Angabe python in der Installations-Zeile kann man noch genauer spezifizieren, z.B. würde

sudo python3.6 -m pip install --upgrade .

das ESTOOL genau unter dem Python 3.6 Interpreter installieren.

Nach der Installation gibt es das estool Kommando, das folgende Optionen kennt:

::

Usage: estool [opts] [args]

Options:
-L, --list-boards
 list supported boards
-B BOARD, --board=BOARD
 select a board if .estool/estool.yaml does not contain a board (default 'stm32l476-nucleo')
-h, --help this help
-d, --doc show docs
-q show quickref
-c, --check run all checks (short version)
-C, --check-long
 run all checks (long version) - XXX needs some more work
-f FLASHFILE, --flash=FLASHFILE
 write a .bin file to FLASH memory using OpenOCD
-r BINFILE, --ram=BINFILE
 loads a .bin file to RAM with OpenOCD and starts it (sets initial SP and PC from vectors at start of .bin file)
-u, --unbind unbind STLINK v1 adaptor from usb-storage (sudo)
-b, --bind bind STLINK v1 adaptor to usb-storage (sudo)
--start-tmux start tmuxp session. See .estool/estool.yaml for window layout.
--stop-tmux stop tmuxp session
-v, --version get version info
-l, --linuxconf
 show how to copy linux configuration files
-p print the installation path
-t build tags for editor navigation from .estool/tagsconf.py config
-g get 'cube_dir' directory from .estool/estool.yaml
--start-oocd start OpenOCD in background
--ask-oocd is OpenOCD running?
--stop-oocd stop background OpenOCD process

Send comments to <Hubert.Hoegl@hs-augsburg.de> Sources are on gitlab: https://r-n-d.informatik.hs-augsburg.de:8080/hubert.hoegl/estool

1.4   Projekte mit ESTOOL

Der Aufbau der Dateien unserer STM32 Programmierprojekte sieht immer ähnlich aus. Man sollte sich eines der Projekte ansehen, siehe dazu den Abschnitt Beispielprogramme. Nehmen wir das "starter" Beispiel:

https://r-n-d.informatik.hs-augsburg.de:8080/es2-nucl476/starter

Das Projekt-Verzeichnis enthält den C Quelltext in Src/. Zur Steuerung der Kompilierung gibt es ein Makefile. Das Linkerskript ist in STM32L476RG_FLASH.ld. Damit ist das Projekt bereits benutzbar.

Projekt/
    .estool/
        estool.yaml     <-- Fensterkonfiguration
        gdbinit        <-- Debuggerkonfiguration
        tagsconf.py    <-- Konfiguration zur Tags-Generierung
    Makefile
    Src/
        main.c
        startup_stm32l476xx.s
        stm32l4xx_it.c
        system_stm32l4xx.c
    STM32L476RG_FLASH.ld

Das .estool Verzeichnis enthält nun die Dateien, die von der ESTOOL gebraucht werden (Achtung: mit ls sieht man keine versteckten Dateien und Verzeichnisse, die mit einem Punkt beginnen. Verwende ls -a). Am besten, man sieht sich nun die Dateien in einem Projekt an, siehe Abschnitt Beispielprogramme.

  • estool.yaml

    Die "yaml" Datei (yaml = yet another markup language) enthält die Anordnung der Fenster und die Programme, die in den Fenstern ausgeführt werden. Die Verwaltung der Fenster wird mit dem tmuxp Session Manager für tmux gemacht.

    Ausserdem enthält estool.yaml noch ein paar andere Einträge, die sich nicht an tmuxp richten, z.B. den Namen des Board auf dem das Projekt läuft und das Wurzelverzeichnis der Cube Bibliothek (falls benötigt).

  • gdbinit

    Konfigurationsdatei für den GDB Debugger.

  • tagsconf.py

    Konfigurationsdatei für die Erzeugung der tags Datei.

Regeln für das Makefile

  • Mit make wird das Projekt gebaut. Das Programm, das in den Flash geladen wird ("geflash"), heisst main.bin. Das vom GCC erzeugte ausführbare Programm ist in main.elf (im ELF Format). Es kann nicht direkt geflasht werden, sondern muss erst mit arm-none-eabi-objcopy in die Binärdatei main.bin umgewandelt werden.
  • Mit make clean kann wieder alles, was gebaut wurde, gelöscht werden.
  • Es muss ein Target gdb geben, das in etwa so aussieht:

    gdb: main.elf
         $(GDB) --tui -silent -x .estool/gdbinit -iex "set auto-load safe-path /"
    

Die Cube-Bibliothek

Manche Projekte benötigen die STM32 Cube Bibliothek, die separat installiert werden muss. Es gibt dazu ein eigenes gitlab Repository unter dem Link

https://r-n-d.informatik.hs-augsburg.de:8080/EmbSys2/stm32cubel4

Zum Bauen der Cube Bibliothek muss man im Verzeichnis stm32cubel4 lediglich das Kommando make install eingeben. Dazu wird am Anfang eine verkleinerte Version der Cube-Bibliothek geholt (siehe das Makefile-Target "download").

Die kompilierte Bibliothek befindet sich nach dem Bauen im Verzeichnis L476xx/libstml476.a.

Im Makefile der Projekte muss man oben die Variable CUBEL4_DIR definieren. In folgendem Auszug wird das über die Umgebungsvariable CUBE_HOME gemacht. Anschliessend wird makefile.base aus CUBE_HOME inkludiert. Darin werden z.B. die Pfade auf einige Verzeichnisse mit Header-Dateien gesetzt.

# Beginn des Projekt-Makefile
CUBEL4_DIR = $(CUBE_HOME)
include $(CUBEL4_DIR)/makefile.base
...

Auch in .estool/estool.yaml muss man den Pfad zur Cube Bibliothek einstellen, zum Beispiel so:

cube_dir: /path/to/stm32cubel4
...

Es ist auch möglich, statt des absoluten Pfades einen relativen Pfad oder die Umgebungsvariable CUBE_HOME zu verwenden. Ähnlich wie im Makefile schreibt man dann in estool.yaml:

cube_dir: $(CUBE_HOME)

Es gibt auch einen Trick, wie man im Projekt-Makefile den Pfad auf das Cube Verzeichnis aus estool.yaml holen kann. Dazu startet man im Makefile das ESTOOL mit der -g Option und weist das Resultat der Variable CUBEL4_DIR zu:

# Makefile
CUBEL4_DIR = $(shell estool -g)
...

Auf der Shell setzt man die Umgebungsvariable mit

$ export CUBE_HOME=/path/to/stm32cubel4

Die Homepage der Cube Bibliothek für die STM32 Microcontroller ist hier:

http://www.st.com/en/embedded-software/stm32cube-embedded-software.html

1.5   ESTOOL mit tmux Fenstern starten

Zum Starten der IDE wird das Kommando estool --tmux aufgerufen. Danach sieht man das folgende Hauptfenster.

img/estool-1.png

Die Aufteilung der Fenster in sog. panes ist durch das Programm tmux [5] bzw. tmuxp gemacht worden, das von ESTOOL gesteuert wird. Der linke Bereich ist zur Arbeit mit GDB vorgesehen, rechts oben läuft das picocom Terminalprogrammm, und rechts unten kann man Aufrufe des make Programms vornehmen. Man kann alle Trennlinien mit der Maus anklicken und verschieben.

Wenn man mit der Maus auf das untere Feld 2:Editor klickt, dann öffnet sich das Editor Fenster.

Alle Fenster und die darin verwendeten Kommandos werden in .estool/estool.yaml konfiguriert.

img/estool-2.png
img/estool-3.png

Hinweis

Sollte der OpenOCD Server bereits laufen, kann man nicht mehr mit einer anderen Programmiersoftware, z.B. st-flash auf den STLINK Adapter zugreifen.

Man kann die Fenster auch mit der Tastatur auswählen. Dazu gibt man die Tastenkombination C-z <nr> ein, also wählt z.B. C-z 2 das Editor Fenster aus.

Anmerkungen:

  • Den voreingestellten tmux Kommando-Präfix (C-b) habe ich geändert auf C-z. Der Grund ist, dass C-b mit der GNU Kommandozeilensteuerung und mit dem Emacs Texteditor kollidiert.
  • Das ESTOOL wird in einer neuen tmux Session "ESTOOL" gestartet. Falls man vor dem Start von ESTOOL schon in tmux gearbeitet hat, gibt es danach also mehrere Sessions. Man kann zu einer anderen Session schalten mit C-z s.

1.6   Optionen

-L, --list-boards

Damit werden alle Board-Typen ausgegeben, die ESTOOL kennt.

-B BOARD, --board=BOARD

Auswahl eines Boards, wenn es in .estool/estool.yaml keine Board Definition gibt. Der voreingestellte Wert ist 'stm32l476-nucleo'.

-h, --help

Ausgabe aller Optionen.

-d, --doc

Die ESTOOL Dokumentation wird im Restructed-Text Format über einen Pager auf der Kommandozeile ausgegeben. Die Datei ist in estool/doc/README.rst gespeichert.

-q

Die ES2 "Quickref" wird über einen Pager ausgegeben. Die Datei ist in der ESTOOL Distribution in estool/doc/quickref.txt gespeichert.

-c, --check

Damit prüft ESTOOL, ob die Vorbedingungen (siehe Abschnitt Rechner vorbereiten) erfüllt sind.

-f FLASHFILE, --flash=FLASHFILE

Die angegebene .bin Datei wird über OpenOCD auf den Mikrocontroller geflasht. Der Flash-Speicher beginnt ab 0x08000000. Das funktioniert sowohl mit als auch ohne laufenden OpenOCD Server.

-r BINFILE, --ram=BINFILE

Schreibt eine .bin Datei mit OpenOCD in das SRAM des Mikrocontrollers ab Adresse 0x20000000. Die ersten beiden Einträge in die Vektortabelle am Anfang der .bin Datei werden gelesen (initiale Werte von SP und PC) und in das OpenOCD Kommando übertragen, so dass das Programm im SRAM an der richtigen Stelle startet. Es ist nicht notwendig, dass der Mikrocontroller vom SRAM bootet. Allerdings startet das Programm dann auch nicht nach Drücken des Reset-Knopfes.

Die -r Option funktioniert mit als auch ohne laufenden OpenOCD Server.

-u, --unbind -b, --bind

Diese Optionen betreffen nur den STLINK v1 Adapter auf dem STM32VLDiscovery. OpenOCD funktioniert bei diesem Board nur, wenn der "usb-storage" des V1 Adapters abgeschaltet wird (-u). Man kann "usb-storage" wieder aktivieren durch -b.

--tmux

Startet die tmuxp Session. Den Aufbau der Fenster findet man in .estool/estool.yaml.

--tmux-kill

Beendet die tmuxp Session.

-v, --version

Zeigt die Versionsinformation an.

-l, --linuxconf

Zeigt, wie die eventuell fehlenden Konfigurationsdateien auf dem Rechner kopiert werden können (siehe Abschnitt Rechner vorbereiten).

hhoegl@e11 ~ $ estool -l
Run the following commands as root:
cp /home/hhoegl/Embedded-Systems/estool/estool/etc/stlink_v1.conf /etc/modprobe.d/
cp /home/hhoegl/Embedded-Systems/estool/estool/etc/49-stlinkv1.rules /etc/udev/rules.d/
...

-p

Gibt den Installationspfad von ESTOOL aus. Zum Beispiel könnte der Pfad so aussehen:

hhoegl@e11 $ estool -p
/home/hhoegl/anaconda3/lib/python3.6/site-packages/estool

-t

Generiert eine Tags Datei aus der Konfiguration in .estool/tagsconf.py.

-g

Die .estool/estool.yaml Datei definiert optional auch ein Verzeichnis, in dem die STM32 Cube Bibliothek installiert ist. Mit der -g Option wird dieser Pfad ausgegeben. Falls die Cube Bibliothek nicht installiert ist, wird no cube_dir ausgegeben.

1.7   Konfiguration

1.7.1   Fenster

Die Konfiguration von ESTOOL wird über den tmuxp [3] session manager ermöglicht. Dieser baut wiederum auf der libtmux [4] Python Bibliothek auf. Beide sind in ESTOOL integriert.

Falls das Projektverzeichnis auf der obersten Ebene eine Datei .estool/estool.yaml beinhaltet, dann liest ESTOOL diese beim Start und konfiguriert die Fenster entsprechend. Falls diese Datei nicht gefunden wurde, wird die Default-Konfiguration etc/estool.yaml aus dem ESTOOL Installationsverzeichnis genommen.

Allgemein gilt für .estool/estool.yaml:

  • Der Session-Name muss immer ESTOOL sein.
  • Die Fenster und Panes können nach dem eigenen Geschmack eingeteilt werden. Auch weitere Fenster/Panes können konfiguriert werden.
  • Über die shell_command Anweisungen kann man Kommandos in .estool/estool.yaml aufnehmen, die beim Starten von ESTOOL ausgeführt werden. Eine Ausnahme ist das Starten des OpenOCD Servers (siehe vorherigen Punkt).

Hier ist nun der typische Inhalt der .estool/estool.yaml Datei:

cube_dir: /home/hhoegl/Embedded-Systems/cubel4-build
board: stm32l476-nucleo

session_name: ESTOOL
windows:
- window_name: ESTOOL
  layout: main-vertical
  focus: true
  options:
    main-pane-width: 80
  panes:
    - shell_command:
        -
    - shell_command:
        - picocom -b 9600 /dev/stm32lab_uart
    - shell_command:
        -
- window_name: Editor
  layout: main-vertical
  panes:
    - shell_command:
       - vim -p *.c *.h    # choose an editor you like

1.7.2   Tags

Die Konfigurationsdatei .estool/tagsconf.py enthält eine Liste INCLUDE aus Pfaden und Verzeichnissen.

Beispiel:

INCLUDE = [
    "src/Drivers/BSP/STM32L4xx_Nucleo/",              # (1)
    "src/Drivers/CMSIS/Include/arm_common_tables.h",  # (2)
    "./Src/",     # (3)
]

Folgende Regeln gelten:

  • Unter allen Pfaden wird nach Dateien mit Endung .c, .h und .s gesucht.
  • Pfad: Wird vorne um Cube-Dir erweitert.
  • Pfad beginnt mit ./: Pfad wird nicht um Cube-Dir erweitert.
  • Dateiname: Genau diese Datei wird zur Tags-Erzeugung verwendet. Kann vorne auch wieder mit und ohne ./ geschrieben werden.

Es gibt ausserdem eine Liste IGNORE in der Dateinamen stehen, die von der Tags-Erzeugung ausgenommen werden.

1.8   Flashen

Es gibt mehrere Möglichkeiten.

Flashen auf der Shell

  1. estool -f main.bin

    Bei dieser Methode findet ESTOOL heraus, ob der OpenOCD im Hintergrund läuft oder nicht.

    Falls ja, wird eine telnet Verbindung aufgebaut worüber die Flash Kommandos geschickt werden.

    Falls nein, wird der OpenOCD Server mit einer Reihe von -c Optionen gestartet und nach dem Flashen wieder beendet. Die Kommandozeile im Hintergrund könnte ungefähr so aussehen:

    openocd -f .estool/openocd.cfg -c "init" -c "reset halt" -c "flash probe 0" \
    -c "flash write_image erase main.bin 0x08000000" -c "reset run" \
    -c "shutdown"
    

    Mit der -f Option kann also ausserhalb und innerhalb von ESTOOL geflasht werden.

    Man kann auch ein make Target flash anlegen, das die Aktion estool -f main.bin ausführt.

  2. telnet (dazu muss der OpenOCD im Hintergrund laufen):

    $ telnet localhost 4444
    > reset halt
    > flash probe 0
    > flash write_image erase main.bin 0x08000000
    > reset run
    > exit
    

    Man kann die Folge der Kommandos auch in eine Textdatei schreiben (z.B. oocd-flash.cmd) und diese mit netcat (nc) zum OpenOCD Server übertragen:

    cat oocd-flash.cmd | nc localhost 4444
    

Flashen auf dem GDB Prompt

(arm-gdb) load

Das load Kommando flasht die Datei die in .estool/gdbinit als Argument von file angegeben ist, üblicherweise main.elf. Das Kommando funktioniert, egal ob das zu ladende Programm im Flash oder im SRAM liegt!

Üblicherweise arbeitet der Mikrocontroller im "Flash" Boot-Modus. Nach dem Flashen kann man die Reset-Taste drücken und das Programm läuft los.

1.9   Laden in das SRAM

Laden mit 'estool -r'

Das Kommando estool -r main.bin erledigt das Laden in das SRAM. Aus der .bin Datei werden die Werte für den initial SP und PC entnommen und beim Aufruf von OpenOCD eingesetzt. Das Programm startet sofort an der Stelle des initialen PC.

Das Kommando arbeitet sowohl mit als auch ohne laufenden OpenOCD Server.

Laden mit dem Debugger

Wenn man das Programm mit dem GDB Kommando load in das SRAM lädt und der Boot-Modus weiterhin auf "Flash" steht, dann muss man das Programm auch explizit im Debugger starten. Dazu holt man sich die zum Starten wichtigen beiden ersten Einträge in die Vektor-Tabelle. Das sind die initialen Werte von SP und PC:

(arm-gdb) x/2xw 0x20000000
0x20000000 <Interrupt_Vec>:     0x20018000      0x200000d1

(die angezeigten Werte können bei Ihnen anders sein)

Dann setzt man die Werte mit:

(arm-gdb) set $sp = 0x20018000
(arm-gdb) set $pc = 0x200000d1

Nun kann man das Programm starten mit:

(arm-gdb) continue

1.10   Zyklus: Editieren / Kompilieren / Flashen / Debuggen

  • Editieren / Kompilieren in Vim

    • Editieren
    • Make anstossen
    • Fehler von gcc/gas parsen
    • Fehler korrigieren
  • Flashen

    estool -f ... oder (gdb) load

    Hinweis: Mit estool -r gibt es auch eine Option um in das SRAM zu laden.

  • Debuggen

    • im separaten GDB
    • im Vim
    • im Emacs mit GDB mode

2   Boards

2.1   STM32L476RG Nucleo

Das STM32L476 Nucleo hat einen Mikrocontroller mit Cortex M4 Kern, der auch über einen numerischen Koprozessor (FPU = floating point unit) verfügt. Er hat 1 MByte Flash Speicher und ca. 100 Kbyte SRAM. Der Debug Adapter hat die Version "STLINK V2-1". Besonders praktisch ist, dass der Debug Adapter auch eine serielle Schnittstelle (UART) hat. Nach dem Einstecken des Boards öffnet sich auf dem Hostrechner auch ein USB Massenspeicher. Wenn man Programme auf diesen Speicher kopiert, dann werden sie durch den Debug Adapter auf das Nucleo Board geflasht. Das Board ist auch kompatibel zum Mbed Projekt von ARM (https://www.mbed.com).

Weiterführende Dokumentation findet man auf der Homepage des Herstellers ST-Micro unter diesem Link:

http://www.st.com/en/evaluation-tools/nucleo-l476rg.html
img/host-with-nucleo-l476.png

Das STM32L476 Nucleo Board. Es kostet etwa 12 Euro.

2.2   STM32VLDiscovery

Das STM32 VL Discovery Board (VL = value line) war eines der ersten Discovery Boards von ST Micro. Auf dem Board ist ein "STLINK v1" Adapter, der die Verbindung zwischen dem PC und dem Mikrocontroller STM32F100 herstellt (siehe folgende Abbildung).

img/host-with-vldiscovery.png

Der STM32F100 besitzt 128 KByte Flash Speicher für Programme und 8 KByte SRAM für Daten. Er hat eine Cortex-M3 CPU (auch Core/Kern genannt) von ARM.

Es ist wichtig, dass das Massenspeicher-Interface abgeschaltet wird. Genau dies macht das estool -u Kommando ("-u" steht für unbind).

Nachtrag (Okt 2019)

Man kann auch vor dem Anstecken des VL Discovery folgendes Kommando auf der Shell eingeben:

# echo "0483:3744:i" >/sys/module/usb_storage/parameters/quirks

(Tipp von http://fabooh.com/2014/03/16/how-to-deal-with-a-problematic-stm32-st-linkv1-device-and-ubuntu)

Literatur:

3   Beispielprogramme

3.1   STM32L476 Nucleo

Die Beispielprogramme für das Nucleo STM32L476 Board sind hier:

https://r-n-d.informatik.hs-augsburg.de:8080/es2/es2-nucl476

3.2   STM32 VL Discovery

Die Beispielprogramme für das VL-Discovery Board sind hier:

https://r-n-d.informatik.hs-augsburg.de:8080/es2/es2-vldisco

5   Fragen und Antworten

F Warum werden meine installierten Programme nicht gefunden?

A Falls manche der Programme an einem unüblichen Ort installiert sind, z.B. in /opt, muss auch die Umgebungsvariable PATH in ~/.bashrc angepasst werden, z.B. so:

export PATH=$PATH:/opt/openocd-0.10.0/bin
export PATH=$PATH:/opt/gcc-arm-none-eabi-4_9-2015q2/bin

Ein anderes Beispiel wären die (optionalen) "stlink" Tools. Nach dem Kompilieren und der Installation in /opt/stlink muss man den PATH erweitern:

export PATH=$PATH:/opt/stlink/usr/local/bin/

In diesem Fall muss man auch den Linker-Pfad erweitern, sonst wird die Bibliothek libstlink.so nicht gefunden:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/stlink/usr/local/lib/

F Funktioniert das Flashen über st-flash wenn der OpenOCD gleichzeitig läuft?

A Nein. Da der STLINK Adapter nur einmal vorhanden ist, kann er nur einmal geöffnet werden.


F Wie scrollt man im Kommandofenster?

A Intuitiv verwenden GDB Anwender die Pfeiltasten um das Kommandofenster zu scrollen, sehen aber dann, das sich das Quelltext-Fenster bewegt, und nicht das Kommandofenster.

Mit den Tastenkombinationen C-p (previous) und C-n (next) kann man zumindest frühere Kommandos aus der History auf die GDB Kommandozeile bringen. Wenn man frühere Ausgaben sehen möchte, dann muss man Tricks anwenden. Am besten, man gibt eine Logdatei aus mit den folgenden Einträgen in .gdbinit:

set logging file gdb_logfile.txt
set logging on

Nun kann man die Logdatei z.B. mit dem Textbrowser less in einem Terminal-Fenster ansehen:

less gdb_logfile.txt

Mit dem Kommando F in less kann man an das Ende der Logdatei gehen bzw. an eine beliebige Stelle mit den üblichen Navigationskommandos.

Mit der Kommandozeile !less gdb_logfile funktioniert das auch auf dem GDB Prompt.


F Das GDB Fenster ist völlig durcheinander. Wie kann ich es wieder in Ordnung bringen?

A Mit C-L (redraw) ist wieder alles okay.


F Wie liest man ein geändertes .gdbinit neu ein?

A source .gdbinit


F Der gdb macht wirre, unverständliche Ausgaben im Quelltext-Fenster. Was kann ich tun?

A Meist ist das Target noch nicht mit dem neuesten Softwarestand geflasht worden.


F Der Editor, z.B. vim, zeigt in tmux nicht die gewohnten schönen Farben an.

A Man muss die Umgebungsvariable TERM auf screen-256color setzen:

export TERM=screen-256color

Tmux wird über ESTOOL mit der Option -2 gestartet. Das bedeutet, dass Tmux davon ausgeht, dass das Terminal 256 Farben anzeigen kann.

6   Literaturtipps

  1. Brian P. Hogan, tmux - Productive Mouse-Free Development, The Pragmatic Programmers, 2012.

    https://pragprog.com/book/bhtmux/tmux

  2. Tony Narlock, The Tao of tmux

    http://tmuxp.git-pull.com/en/latest/about_tmux.html

  3. Daniele Lacamera, Embedded Systems Architecture, Packt Publishing, 2018.

    http://proquest.tech.safaribooksonline.de/book/software-engineering-and-development/9781788832502

  4. Warren Gay, Beginning STM32, Apress 2018.

    https://proquest.tech.safaribooksonline.de/book/hardware/arduino/9781484236246

  5. Joseph Yiu, The Definitive Guide to ARM® Cortex®-M3 and Cortex®-M4 Processors, 3rd Edition, Newnes 2013.

    http://proquest.tech.safaribooksonline.de/book/electrical-engineering/computer-engineering/9780124080829

  6. Jacob Mossberg, Run a C program bare metal on an ARM Cortex M3, August 2018

    https://jacobmossberg.se/posts/2018/08/11/run-c-program-bare-metal-on-arm-cortex-m3.html#hardware-equipment

  7. Hussam al-Hertani, STM32F0Discovery Under Linux Tutorial

    Part 1 - Setting up the GCC ARM Toolchain, OpenOCD and stlink, 2013.

    http://www.hertaville.com/stm32f0discovery-part-1-linux.html

    Part 2 - Using a Minimalist Integrated Development Environment From the Command Line, 2013.

    http://www.hertaville.com/stm32f0discovery-command-line-ide.html