2  Rechner vorbereiten

Dieser Text beschreibt die Installation der ES2 Arbeitsumgebung unter Linux. Wir werden beim Kurs hauptsächlich unter Linux im Terminal auf der Kommandozeile arbeiten, sollte ihnen das noch nicht so geläufig sein, dann nehmen sie den Kurs gerne als Anlass hier etwas aufzuholen. Wir werden auch nur freie Software (im Sinne von Open-Source) zur Programmentwicklung verwenden, im wesentlichen sind das die “GNU” Tools.

Der erste Abschnitt richtet sich an Leute die Windows 10 oder 11 auf ihrem Rechner installiert haben. Mit dem Windows Subsystem für Linux in der Version 2 kann man Linux innerhalb von Windows betreiben. Alle weiteren Abschnitte sind unabhängig davon, ob man auf einem “realen” Linux, in WSL2 oder in VirtualBox arbeitet.

2.1 WSL2 installieren (nur bei Windows 10/11)

Bei dieser Anleitung habe ich mich an https://goneuland.de/windows-10-subsystem-fuer-linux-wsl-2-installieren gehalten.

Wichtig ist auch, dass zunächst im BIOS des Rechners die Virtualisierung aktiviert wird. Der folgende Artikel behandelt diese BIOS Einstellungen ausführlich: https://s1gr1d.medium.com/how-to-set-up-linux-on-windows-with-wsl-2-debe2a64d20d

WSL aktivieren

In Powershell (Administrator) eingeben

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

Update auf WSL2

  • Windows muss mindestens Version 1903 sein (Windows Taste + R”, winver eingeben)

  • Powershell Eingabe:

    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  • PC neu starten

  • WSL update herunterladen von https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi und installieren

  • WSL2 als Standard festlegen

    wsl --set-default-version 2
  • Welche Linux Distributionen gibt es?

    wsl.exe --list --online
  • Debian installieren

    wsl.exe --install -d Debian
  • Distro entfernen - auch alle Daten sind dann gelöscht!

    wsl --unregister Debian

Kommandos

Version und Status ausgeben

wsl.exe -l -v

Welche Distributionen gibt es?

wsl.exe --list --online

Distribution installieren

wsl.exe --install -d Debian

Distribution für Benutzer ausführen

wsl.exe --distribution <Distribution Name> --user <User Name>

WSL Version ausgeben

wsl.exe --version

Shutdown

wsl.exe --shutdown Debian

Beenden und neu starten (das WSL wird neu gestartet, auf der Kommandozeile in WSL sieht man das aber nicht)

wsl.exe --terminate debian

Mountpunkte

  • /mnt/c
  • /mnt/wsl
  • /mnt/wslg

USBIPD installieren unter Windows

Dieser Schritt ist nötig, da sich Windows alle angeschlossenen USB Geräte schnappt. Mit USBIPD gibt man bestimmte USB Geräte an die Linux Distribution weiter.

Auf der Homepage des Projekts unter

https://github.com/dorssel/usbipd-win

findet man einen msi Installer:

https://github.com/dorssel/usbipd-win/releases/

Mit

usbipd.exe wsl list

bekommt man eine Liste der angeschlossenen USB Geräte (das STM32L476 Nucleo ist über USB angeschlossen):

BUSID  VID:PID    DEVICE
STATE
3-1    046d:c534  USB-Eingabegerät                                              Not attached
3-6    04f2:b221  Integrated Camera                                             Not attached
4-2    0483:374b  ST-Link Debug, USB-Massenspeichergerät, Serielles USB-Ger...  Not attached

Danach “attached” man das gewünschte Gerät, in unserem Fall ist das der ST-Link Debugger auf dem Nucleo Board:

usbipd.exe wsl attach --busid 4-2

Mit usbipd.exe wsl list sieht man, dass das Gerät nun im Zustand “attached” ist.

Im Debian (in WSL2) installiert man die Pakete “usbip” und “usbutils” (darin ist lsusb).

sudo apt install usbip usbutils

Danach erkennt das lsusb Kommando in Debian das USB Gerät (sudo ist dazu nötig). Die Ausgabe sollte so ähnlich sein:

$ sudo lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 0483:374b STMicroelectronics ST-LINK/V2.1
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Quelle: https://devblogs.microsoft.com/commandline/connecting-usb-devices-to-wsl/

Damit man ohne sudo auf die USB Geräte zugreifen kann müssen udev Regeln angelegt werden. Prinzipiell funktioniert das unter dem virtuellen Debian genauso wie im richtigen Debian - ist also weiter unten im Text beschrieben. Allerdings muss man bei WSL2 zunächst noch den udev Service aktivieren. Den aktuellen Status findet man mit sudo service udev status heraus.

Falls /etc/wsl.conf noch nicht existiert, legt man sie an mit den folgenden drei Zeilen:

[boot]
command="service udev start"
systemd=true

Die dritte Zeile ist optional, wenn sie vorhanden ist wird der systemd aktiviert.

Um das Zusammenspiel mit Windows zu verbessern kann man auch die folgenden zwei Zeilen einfügen (Danke für den Tipp):

[interop]
appendWindowsPath=true

Nun beendet man Debian und startet es sofort neu mit dem Kommando

wsl.exe --terminate debian

Dieser Vorgang dauert einige Sekunden, danach sollte der Zugriff auf die USB Geräte auch ohne sudo möglich sein, sofern die USB Regeln installiert sind.

Falls systemd aktiviert wurde, kann man die laufenden Dienste wie folgt ausgeben:

systemctl list-units --type=service

WSL Konfiguration

Es gibt zwei Konfigurationsdateien, die am Anfang noch nicht existieren:

  • C:\Users\<UserName>\.wslconfig (in Windows)

    In diese Datei stehen globale WSL2 Einstellungen, z.B. wie viel Speicher
    und Prozessoren die Linux VMs bekommen sollen.

  • /etc/wsl.conf (in Linux)

    Hier sind die Einstellungen der jeweiligen Linux VM zu finden. Zum Beispiel kann man Dienste beim Booten starten oder systemd aktivieren.

Quelle: https://learn.microsoft.com/en-us/windows/wsl/wsl-config

Pakete in Linux installieren

  • Pakete, die sie unter Linux installieren sollten, falls sie noch nicht vorhanden sind (sudo apt install ...):

    • wget

    • openssh-client

    • git

    • tmux

      Die Konfigurationsdatei holt man wie folgt:

      $ cd ~
      $ wget https://hhoegl.informatik.hs-augsburg.de/es2/tools/_tmux.conf -O .tmux.conf
    • helix - Ein Editor der ähnlich wie Vim ist, aber leichter zu installieren, zu konfigurieren und zu verwenden (https://helix-editor.com).

      Wer C Code mit Helix (Kommando hx) editiert, sollte in ~/.config/helix/languages.toml den folgenden Abschnitt aufnehmen. Am Anfang ist es der einzige Eintrag, da die Datei nach der Installation noch nicht existiert. Damit wird der C/C++ language server clangd im Editor konfiguriert. Das Paket clang installiert man mit sudo apt install clangd.

      [[language]]
      name = "c"
      auto-format = false
      language-servers = [ "clangd" ]
      
      [language-server.clangd]
      command = "clangd"
      config = { clangd.fallbackFlags = [ "-std=gnu11" ] }
      args = []

      Damit clangd in einem Verzeichnis mit C/C++ Quelltext aktiv wird, muss es eine Datei compile_commands.json geben, sie wird auch “Compilation Database” genannt. Diese Datei muss zunächst erzeugt werden. Wenn die Übersetzung mit make gesteuert wird (wie meistens bei uns), dann führt das Kommando bear -- make zum Ziel. Bear (sudo apt install bear) lässt make laufen und wandelt die Ausgabe von make in die compile_commands.json um. Daneben gibt es auch das Python Programm compiledb, das Ähnliches macht. Die Installation erfolgt mit pip install compiledb. Ein alternativer Sprachserver für C/C++ ist ccls.

      hx --health gibt aus, welche Sprachen durch einen Sprachserver unterstützt werden.

  • vim

    Wer vim verwendet braucht zumindest eine rudimentäre Startup Datei ~/.vimrc. Ein Anfang wird mit der folgenden Datei gemacht:

    $ wget https://hhoegl.informatik.hs-augsburg.de/es2/tools/_vimrc -o .vimrc

    Zum Editieren von C Code verwende ich die “ALE” Erweiterung, siehe https://github.com/dense-analysis/ale. ALE spielt gut mit dem clangd Sprachserver zusammen.

  • Python Pakete, die sie installieren sollten (sudo pip install ...)

    • compiledb
    • pyserial

Windows Terminal

Komfortables Terminal, bei dem man Powershell und Linux in verschiedenen Tabs öffnen kann. Man kann das Terminal auch teilen wie bei einem Terminal Multiplexer.

https://learn.microsoft.com/en-us/windows/terminal/install

APT Repository

Wer häufig Pakete installiert sollte den Server in /etc/apt/sources.list auf einen Server in der Region ändern.

Literatur

2.2 ARM-GCC

Es gibt zwei Möglichkeiten, 1. Installation der Linux Pakete, oder 2. Download und Installation einer ARM Toolchain.

  1. Linux Pakete installieren

    $ sudo apt install binutils-arm-none-eabi gcc-arm-none-eabi
    $ sudo apt install gdb-multiarch

    Hinweis: Das ausführbare Programm des Debuggers heisst wie das Paket gdb-multiarch. Die Beispielprogramme haben in .estool/estool.ini den Namen arm-none-eabi-gdb oder gdb-multiarch konfiguriert. Eventuell den eingetragenen Namen ändern.

  2. Die aktuellen Toolchains von ARM findet man unter

    https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

    im Bereich “x86_64 Linux hosted cross toolchains” / AArch32 bare-metal target (arm-none-eabi).

    Zur Zeit (10/2023) ist das arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz. Eine Kopie ist unter https://hhoegl.informatik.hs-augsburg.de/es2/tools/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz.

    $ cd /opt
    $ sudo tar Jxvf ~/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz

    In ~/.bashrc die PATH Variable erweitern:

    export PATH=$PATH:/opt/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin

    Das Installationsverzeichnis /opt/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi ist knapp 1 GByte gross.

2.3 OpenOCD

Auch hier gibt es wieder zwei Möglichkeiten: 1. Installation des Pakets, oder 2. Sourcen holen, kompilieren und installieren.

  1. Paket installieren

    $ sudo apt install openocd

    Die ausführbare Datei ist nachher in /usr/bin/openocd. Die Konfigurationsdateien liegen unter /usr/share/openocd.

  2. Selber kompilieren

    $ sudo apt install libusb-1.0-0-dev libtool pkg-config libusb-1.0-0-dev automake autoconf
    $ wget https://hhoegl.informatik.hs-augsburg.de/es2/tools/openocd-0.12.0.tar.bz2
    $ tar jtf openocd-0.12.0.tar.bz2
    $ cd openocd-0.12.0
    $ ./bootstrap 
    $ ./configure --enable-stlink --prefix=/opt/openocd-0.12.0
    $ make
    $ sudo make install
    # PATH um /opt/openocd-0.12.0/bin erweitern

    Optional lässt sich noch die Dokumentation im PDF Format erzeugen. Es sollte vorher schon LaTeX installiert sein:

    sudo apt install texinfo
    make pdf

    Danach ist die Doku in doc/openocd.pdf zu finden.

    Siehe die PDF Datei

    Die aktuellen OpenOCD Sourcen findet man unter https://github.com/openocd-org/openocd.

2.4 Udev Regeln

Damit man als gewöhnlicher User auf die USB Schnittstelle des STLINK Adapters zugreifen kann, müssen sogenannte udev Regeln in das Verzeichnis /etc/udev/rules.d/ kopiert werden. Es genügt, eine einzelne Datei 60-openocd.rules zu kopieren:

$ sudo cp /lib/udev/rules.d/60-openocd.rules /etc/udev/rules.d/

Die Datei /lib/udev/rules.d/60-openocd.rules ist nur vorhanden, wenn man das Linux Paket openocd installiert hat. Wenn man OpenOCD manuell installiert, dann muss man den Pfad ändern, ähnlich wie in folgendem Beispiel: /opt/openocd-0.12.0/share/openocd/contrib/60-openocd.rules.

Damit die Regeln aktiviert werden, gibt man abschliessend die Kommandos ein:

$ sudo udevadm control --reload-rules
$ sudo udevadm trigger

2.5 Estool installieren

Das estool Program ist ein Hilfsprogramm, um die Arbeit mit dem STM32 etwas zu erleichtern. Der Python Quelltext liegt auf gitlab (VPN nötig):

https://gitlab.com/hhoegl-tha/es/estool

  1. Python Installation testen

    Mit which kann man den Pfad ausgeben, an dem das Programm gefunden wird.

    $ which python
    /usr/bin/python

    Es kann auch vorkommen, dass der Interpreter python3 heisst.

    Man sollte auch mal den Interpreter starten, damit man die Version sieht:

    $ python
    Python 3.10.9 | packaged by conda-forge | (main, Feb  2 2023, 20:20:04) [GCC 11.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 

    Mit Strg-D beendet man den >>> Eingabeprompt.

    Wer mit einer eigenen, von der systemweiten Python Installation unabhängig arbeiten will, der installiert Miniforge:

    https://github.com/conda-forge/miniforge/releases

    Die aktuelle Release (10/2023) für Linux ist Miniforge3-25.3.1-0-Linux-x86_64.sh. Die Installation erfolgt mit

    $ cd ~
    $ bash Miniforge3-25.3.1-0-Linux-x86_64.sh

    Wenn die Installation beendet ist, gibt es im Home Verzeichnis den Ordner miniforge3, der aktive Python Interpreter ist dann

    $ which python
    $ /home/<user>/miniforge3/bin/python
  2. Virtuelle Python Umgebung erzeugen

    cd ~
    python -m venv es2_pyvenv
    source es2_pyvenv/bin/activate 

    Das Kommando which python sollte den Pfad /home/<user>/es2_pyvenv/bin/python ausgeben.

    Mit deactivate kann man die virtuelle Python Umgebung wieder deaktivieren.

  3. Estool in die virtuelle Umgebung installieren (venv muss voher aktiviert werden). Damit man mit dem angegebenen ssh URL klonen kann, muss ein öffentlicher ssh Schlüssel auf gitlab übertragen werden. Wie das geht steht unter “Allgemeine Tipps” weiter unten.

    $ git clone https://gitlab.com/hhoegl-tha/es/estool
    $ cd estool
    $ python -m pip install .      # Alternativ: python -m pip install --upgrade .

    Mit der --check Option kann man prüfen, ob alle Werkzeuge richtig installiert wurden:

    $ estool --check

    Hinweis: Damit --check klappt muss man in einem Projektordner sein, also wie im nächsten Kapitel beschrieben z.B. “starter” holen und in das Verzeichnis gehen.

    Estool erhält seine Einstellungen in jedem Projektordner durch eine Konfigurationsdatei .estool/estool.ini, also z.B. starter/.estool/estool.ini.

2.6 Beispiel “starter” für STM32F446 Nucleo holen, kompilieren und flashen

https://gitlab.com/hhoegl-tha/es/f446/starter

$ git clone https://gitlab.com/hhoegl-tha/es/f446/starter
$ cd starter 
$ ls -a
.  ..  .estool  .git  .gitignore  img  Makefile  README.md  src STM32F446RETx_FLASH.ld

Im Beispielverzeichnis starter ist nun die Konfigurationsdatei vom OpenOCD Server im Verzeichnis .estool enthalten. Das Verzeichnis beginnt mit einem Punkt (“.”), deshalb sieht man es nicht in der Ausgabe des ls Programms. Damit man es sieht, muss man ls -a angeben. Wir starten den OpenOCD Server probeweise mit

$ openocd -f .estool/openocd.cfg 
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 1
adapter speed: 500 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
<hier hängt das Programm; abbrechen mit Strg-c>

Man bricht den im Vordergrund laufenden OpenOCD mit Strg-c (Steuerung-C, auf englisch control-c) ab. Damit OpenOCD erfolgreich starten kann, muss er mit dem Debug-Adapter STLINK Verbindung aufnehmen können. Als gewöhnlicher User kann man das nur mit der installierten udev Datei (siehe oben).

Nun kompilieren und flashen:

$ cd starter
$ make          
$ make flash    

Bei make wird der Quelltext mit dem zuvor installierten ARM GCC Compiler kompiliert. Mit make flash wird der STM32 mit dem Programm geflasht. Das make flash Kommando startet in Hintergrund das estool, das wiederum den OpenOCD zum Flashen des STM32 startet und danach wieder beendet.

Danach sollte das über USB angesteckte Nucleo Board geflasht worden sein und die LED auf dem Board blinken. Über den UART, der auch über den STLINK Adapter verfügbar ist, werden die Schleifendurchläufe in ASCII mit 9600 Baud an den PC übertragen. Die Details stehen in der README.md Datei im starter Verzeichnis, und natürlich im Quelltext starter/src/.

Man kann ausserdem mit make gdb den GNU Debugger starten. Dazu muss allerdings der OpenOCD Server bereits im Hintergrund laufen. Diese Arbeit nimmt einem das estool ab mit estool --start-oocd. Nach getaner Debug Arbeit kann man OpenOCD wieder beenden mit estool --stop-oocd. Mit --ask-oocd kann man nachschauen, ob der OpenOCD Server läuft.

2.7 Ohne ESTOOL

Man kann auch ohne das ESTOOL arbeiten. Allerdings muss man dann in einem zweiten Shell-Fenster den OpenOCD Server starten

  • OpenOCD Server starten

    Zunächst in ein Projekt-Verzeichnis gehen, z.B. mit cd starter.

    $ openocd -f .estool/openocd.cfg 
    Open On-Chip Debugger 0.12.0
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    srst_only separate srst_nogate srst_open_drain connect_deassert_srst
    
    [stm32f4x.cpu] halted due to breakpoint, current mode: Thread 
    xPSR: 0x61000000 pc: 0x080003fa msp: 0x20017fe8
    <blockiert - Abbrechen mit Ctrl-C>
  • Flashen mit telnet (dazu muss der OpenOCD im Hintergrund laufen). Das zu flashende Programm ist in main.bin:

    $ 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 mit OpenOCD, ohne dass Server im Hintergrund läuft. Der OpenOCD wird gestartet und die Anweisungen auf der Kommandozeile (-c ...) werden abgearbeitet.:

    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"
  • GDB starten

    Die Kommandozeile zum Starten von GDB sieht wie folgt aus:

    gdb-multiarch --tui -silent -ex 'set $gdbport = 3333' -x '.estool/gdbinit' -iex 'set auto-load safe-path /'

    Tipp: In .estool/estool.ini finden Sie die genau diese Kommandozeile. Sie könnten also im Projekt die konkreten Argumente ändern und beim Aufruf von estool --gdb würde das berücksichtigt werden.

    Erläuterung zu den Kommandozeilen-Argumenten:

    --tui - Text User Interface (sowas wie eine grafische Oberfläche in der Shell)

    -ex 'set $gdbport = 3333' - Die Variable gdbport wird auf 3333 gesetzt

    -x '.estool/gdbinit' - Die Datei gdbinit wird beim Start gelesen und ausgeführt. Darin wird in einem kurzen Abschnitt in Python die Variable gdbport gelesen und das Kommando target remote localhost:<port> abgesetzt. Das ist aktuell der einzige Grund warum der Python-Support in GDB nötig ist. Ein GDB mit eingebautem Python Interpreter ist nützlich, weil man alle Debug-Aufgaben damit auch per Python-Skript steuern kann.

    -iex 'set auto-load safe-path /' - Wird in der GDB Doku erklärt https://sourceware.org/gdb/current/onlinedocs/gdb.html/Auto_002dloading-safe-path.html

    Die GDB Doku finden Sie online unter https://sourceware.org/gdb/current/onlinedocs/gdb.html.

2.8 Tipps

  • Beachten Sie, dass Sie nur kurzzeitig für die notwendigen Administrationsaufgaben root werden sollen. Vermeiden Sie es, die gewöhnlichen Anwendungsprogramme (gcc, gdb, make, openocd, estool, …) als root laufen zu lassen.

  • HSA Home mounten

    (Anleitung von Hr. Schäferling)

    $ sudo apt install sshfs
    $ mkdir /opt/bin
    $ cd /opt/bin
    $ sudo wget https://ti-srv.informatik.hs-augsburg.de/labs/common/bin/mount_HSA-Home.sh
    $ sudo wget https://ti-srv.informatik.hs-augsburg.de/labs/common/bin/umount_HSA-Home.sh
    $ sudo chmod +x mount_HSA-Home.sh umount_HSA-Home.sh
    $ echo "PATH=$PATH:/opt/bin" >> ~/.bashrc
    $ mount_HSA-Home.sh
    $ umount_HSA-Home.sh
    $ echo "PATH=$PATH:/opt/bin" >> ~/.bashrc
  • Serielle Schnittstelle als “normaler” User nutzen

    Dazu muss man den Usernamen in die Gruppe “dialout” aufnehmen. Das geht mit dem Kommando

    $ sudo usermod -a -G dialout $USER

    Damit das Kommando wirksam wird muss man sich aus- und wieder einloggen. Es kann auch sein, dass man den Rechner neu starten muss.