Files
sdes_lab/sdes_skipt_mkdocs/docs/5_aufgabe1.md

11 KiB
Raw Blame History

5. Aufgabe 1 - Makefile

Die in dem Skript stehenden Aufgaben dienen der Anweisung was programmiert werden soll. Zusätzlich zu den Programmieraufgaben halten Sie Ihre Ergebnisse in dem vorgefertigten Dokument doku.odt fest. Dieses finden Sie im Repository, welches Sie im Folgenden für alle Aufgaben verwenden. Die Dokumentation dient als Hilfestellung für Sie in den Kolloquien, um die Schritte Ihrer Lösung erklären zu können.

5.1. Wissen

5.1.1. Toolchain

Jedes in Hochsprache geschriebenes Programm muss in Maschinencode übersetzt werden. Die Toolchain ist eine Aneinanderreihung von Routinen zur Erstellung eines ausführbaren Programms aus dem Code einer Hochsprache wie zum Beispiel der Sprache C. Damit der Code unserer Hochsprache auf unserem Zielsystem ausgeführt werden kann, muss er zuerst in die dem Zielsystem entsprechende Maschinensprache übersetzt werden. Der Compiler unserer Toolchain übersetzt den von uns geschriebenen Code aus der Hochsprache in Assembler-Code. Dieser Code hängt bereits von dem verwendeten Ziel ab. Je nach Befehlssatz des Zielarchitektur (ARM, AVR, x86, ...) sieht der Assemblercode verschieden aus. Der vom Compiler erstellte Assembly-Code wird vom Assembler in Maschinencode umgewandelt. Als Basis für das weitere Verständnis zur Toolchain kann das Dokument How a Compiler Works [RS14, Kapitel 2, S. 2] genutzt werden. In dem Diagramm 5.1 können zum Verständnis die Arbeitsschritte der Toolchain eingetragen werden. Nutzen Sie dafür das zur Verfügung gestellte .odt Dokument.

5.1.2 Makefile

Das Programm Make wird verwendet, um den Buildprozess zu automatisieren. Dafür liest Make die Makefile aus und gibt die entsprechenden Anweisungen an die Toolchain weiter (z.b. Compiler, Linker, ...). Dies ist besonders bei größeren Projekten hilfreich, da der Buildprozess aus vielen Einzelanweisungen bestehen kann. Außerdem können unterschiedliche Build-Konfigurationen und Targets benutzt werden. Eine Erklärung von Makefiles bietet die Website [mak]. Schauen Sie sich den Inhalt an und verinnerlichen Sie den Sinn und die Arbeitsweise von Makefiles.

Screenshot Abbildung 5.1.: Toolchain Diagramm zum Ausfüllen und zur Vorbereitung auf das Prekolloquium

Screenshot Abbildung 5.2.: Beispiel zum Aufbau einer Makefile

5.1.3 Printf-Debugging

Funktionsdefinition

Eine intuitive und einfache Methode des Debuggens ist die Ausgabe von Werten oder Nachrichten über eine serielle Schnittstelle. Zum Lesen solcher Nachrichten auf der Entwicklungsplattform ist es meist nötig, einen Seriell-zu-USB Adapter einzusetzen. Diese sind günstig und weit verbreitet. Als Software dient ein serieller Monitor.

Anwendung

Möchte man die Implementierung einer Berechnung überprüfen, so kann dies über einen Printf-Befehl getan werden, der das Ergebnis ausgibt. Auch eignet sich diese Debugging-Methode gut als Indikator, ob bestimmte Stellen im Programmcode erreicht werden. Besonders hilfreich ist diese Methode zum Überprüfen von Variablenwerten in Schleifendurchläufen. Auf die gleiche Art und Weise können falsche Übergabe- oder Rückgabeparameter erkannt werden.

Grenzen

Der Rahmen in dem Printf-Debugging zum Erfolg führt, ist stark begrenzt. Es bietet keinerlei Hilfe bei Problemen, die mit Speicherallozierung oder Interrupts zu tun haben. Printf nutzt die langsame serielle Schnittelle und verändert das Zeitverhalten des Programmes stark. Das kann dazu führen, dass sich Fehler in einem auf Echtzeitfähigkeit ausgelegten System anders verhalten, wenn eine Printf-Anweisung in den Code eingefügt wurde. Es ist dadurch nicht möglich zeitkritische Anwendungen zu debuggen. Als Beispiel dafür gilt die Kommunikation über Bussysteme. Dazu kommt der Aufwand und die Dauer des wiederkehrenden Build-Prozesses, da nach dem Verschieben der Printf-Anweisung an eine andere Stelle im Programm, das Programm erneut kompiliert werden muss. Vor allem bei großen Projekten bedeutet dies lange Wartezeiten und ist nicht praktikabel.

5.2. Pre-Kolloquium

Für das Kolloquium sollte klar sein, wie die Toolchain funktioniert und welche Werkzeuge in den Programmbau involviert sind. Als Visualisierung sollen Sie das Diagramm zur Toolchain ausfüllen. Machen Sie sich mit den einzelnen Schritten vertraut. Die Regeln, nach denen das Programm gebaut wird, finden sich in dem Makefile. Sie sollten erklären können welche Teile im Makefile welche Funktion erfüllen. In der folgenden Aufgabe werden Sie unterschiedliche Fehler im Code aber auch im gegebenen Makefile finden müssen. Die Fehler im Makefile sollten Sie durch genaue Analyse des Makefiles bereits zum Teil finden können. Die Datei toolchain.odt enthält das Diagramm aus dem Skript, welches den exemplarischen Ablauf einer Toolchain zeigt. Füllen Sie die Lücken der Dateien und Tools und erklären Sie was in welchem Schritt passiert. Machen Sie sich zudem mit den Linux Befehlen find und grep vertraut.

5.3. Aufgabenstellung

5.3.1. Toolchain

Die erste Aufgabe formt den Einstieg in die Programmierung des Praktikumsboards. Es wird sich mit der Ordnerstruktur und der Entwicklungsumgebung vertraut gemacht und die Struktur des Gits verstanden. Es soll das erste Programm gebaut und geflasht sowie der Umgang mit Makefiles geübt werden. Außerdem soll die Funktionsweise der Toolchain verinnerlicht werden.

Erstellen Sie zunächst einen Fork des Repository von

https://git.ida.ing.tu-bs.de/IDA_Lehre/lab_sdes_student

Dazu clonen Sie zunächst Ihren Fork mit dem angezeigten Link aus dem Webinterface in Ihren lokalen Ordner.

Zusätzlich sollten Sie einen neuen Branch in folgender Form anlegen:

git checkout -b praktikum

Es kommt vor, dass der Betreuer im Praktikumsverlauf Änderungen am Master vorneh- men muss, dies führt häufig zu Konflikten. Durch den Branch werden diese vermieden.

Sie arbeiten in ihrem Fork auf dem angelegten Branch.

In dem bereitgestellten git Repository finden sich alle für die Aufgabe benötigten Dateien. In dem Ordner src/APP befinden sich der Quellcode der Aufgaben des Praktikums. Der Ordner src/APP/Aufgabe1/ps7/core0/ enthält den Quellcode der Aufgabe 1 für den die Architektur ps7 und den Kern 0. In ihm finden sich weitere Unterordner. In Aufgabe1/ps7/core0/src findet man alle .c-Dateien außer der main.c.

Nach dem Klonen des Gits ist die Entwicklungsumgebung einzurichten:

  • Terminal in Verzeichnis der Wahl (außer innerhalb des Repository) öffnen
  • Eine Integrated Development Environment (IDE) bzw. Texteditor Ihrer Wahl starten (z.B. VSCode)
  • Falls gewünscht, kann das Makefile-Projekt eingerichtet werden, um den Buildprozess aus der IDE heraus zu starten

Ihre Aufgabe ist es, das Programm zu kompilieren und in die Laufzeitumgebung zu laden. Dabei auftretende Fehler sind zu beheben und der Arbeitsvorgang zu dokumentieren. Zunächst ist es sinnvoll sich den Programmcode der Datei main.c anzusehen und zu verstehen. Um das Programm zu kompilieren gehen sie in den Repositoryordner, öffnen ein Terminal und führen den Befehl make aus. Es ist nötig dem Programm make mitzu- teilen, für welche Aufgabe und Architektur das Programm kompiliert werden soll. Die Syntax des Aufrufs ist folgende:

make ARCH=ps7 APP=Aufgabe1 CORE=0

Falls Fehler auftreten, analysieren Sie diese und versuchen Sie ihre Gründe herauszufinden. Es lohnt sich die Ausgabe genauer anzusehen und mit dem Wissen über die Toolchain und Makefile zu verknüpfen. So kann der Ursprung des Fehlers schnell eingegrenzt werden. Nutzen sie die Ausgabe des Kompiliervorgangs und lösen Sie die auftretenden Fehler, um den Build-Prozess zu ermöglichen. Tipp: Alle von der Toolchain benötigten Abhängigkeiten finden sich in dem Ordner Aufgabe1/ps7/core0/build. Suchen Sie auch in dem Makefile nach Fehlern und achten Sie auf Groß- und Kleinschreibung!

Der Ordner Aufgabe1/ps7/core0/cfg enthält die Header-Dateien und der Ordner linker das Linkerscript.

Wichtig ist außerdem der Aufgabe1/ps7/core0/build Ordner. In den Dateien config.mk, includes.mk und sources.mk festgelegt, welche Pfade beim Build-Prozess überhaupt berücksichtigt und welche Compilerflags gesetzt werden. Neue Dateien in bisher nicht inkludierten Pfaden müssen in den entsprechenden Dateien eingetragen werden. In dem Ordner out finden sich geordnet nach den Aufgaben, Architektur und Core die entsprechenden Zielpfade für die aus dem Build-Prozess entstehenden Objekt-Dateien.

Immer wenn eine neue Terminal-Session gestartet wird müssen zunächst einige Umgebungsvariablen gesetzt werden, damit die benötigten Tools gefunden werden. Dazu dienen hier die “setup-lm” Befehle, die die PATH-Variable um die gewünschten Tool- Verzeichnisse erweitern und bei Bedarf Lizenzserver zu setzen.

setuplm lauterbach r_2020_09
setuplm gcc gccarmnoneeabi72018q2

Der Ordner Debug/ps7 im Oberverzeichnis enthält das Skript "start_amp_session.sh", welches die Debug-Umgebung lädt. Zur Anwendung des Skripts wird ein Terminal in dem Ordner ps7 geöffnet und der Befehl

./ start_amp_session.sh lauterbach[Lauterbachnummer]

ausgeführt. Die [Lauterbachnummer] muss angepasst werden und entspricht der Gruppennummer.

Achtung: Es kommt vor, dass die vorherige Lauterbach-Session auf dem Debugger nicht ordnungsgemäß beendet wurde oder der Lauterbach von einem anderen Nutzer belegt war. Dann wirft der Befehl zunächst den Fehler: Selected device already in use by... Dann bitte einmal prüfen ob wirklich der richtige Lauterbach angesprochen ist und nicht der einer anderen Gruppe. Ein erneutes Ausführen dauert länger, sollte dann aber erfolgreich sein.

Nach dem erfolgreichen Kompilieren muss das Programm auf das Board geflasht werden. Dafür starten wir die Lauterbach Software ”Trace 32” wie oben beschrieben. Für jede Aufgabe gibt es im Ordner Debug/ps7/ einen entsprechenden Unterordner, welcher ein Lauterbach-Skript enthält. Diese kann über die Befehlszeile in Trace32 ausgeführt werden:

do Aufgabe1/zc706_onchip_trace.cmm

Generell arbeitet Trace32 vollständig skript-basiert und jedes GUI Kommando kann auch in einem Skript eingesetzt werden. Dies können Sie sich für spätere Aufgaben merken um wiederkehrende Befehle zu automatisieren.

Das zu Aufgabe 1 gehörige Skript sorgt dafür, dass das Board durch die Software geflasht wird, sich aber keine weiteren Fenster in der Software öffnen. Ziel dieser Aufgabe ist das Debuggen über printf. Nachdem Sie das den Befehl zum Flashen im richtigen Verzeichnis ausgeführt haben, sollte sich ein Fenster ähnlich der Abbildung 5.3 öffnen. Das Programm wird nun durch einen Klick auf “Go” gestartet. Sie können dieses Fenster nun ignorieren und in einer freien Konsole die Verbindung zur Ausgabe des Boards aufbauen:

telnet idaser2net 800X

Der Port hängt von Ihrer Gruppennummer und dem verwendeten Lauterbach ab. Erset- zen Sie das X durch die Nummer ihres Lauterbach-Debuggers. Das Board sollte Ihnen jetzt jede Sekunde ein “ILL BE BACK” ausgeben.

Bei Überprüfung der Arbeitsergebnisse sollten Sie auftretende Fehler dem Linker oder dem Compiler zuordnen können.

Screenshot Abbildung 5.3.: Lauterbachumgebung zum Flashen des Boards in Aufgabe 1