Bei einer Vielzahl der heutigen Elektronikprojekte wird ein Mikroprozessor-Chip verwendet, weil die Software-Steuerung so viel Flexibilität bietet. Aber welchen Mikroprozessor soll man wählen? Welche Programmiersprachen sollten verwendet werden? Dies sind wichtige Fragen für jeden Projektentwickler. RISC-V Mikroprozessoren bieten zusätzliche Hardware-Flexibilität. Die Kosten für die Hersteller werden gesenkt, da sie keine IP-Lizenzen und Einschränkungen einhalten müssen. Ohne diese Beschränkungen können die Hersteller ihre CPU mit benutzerdefinierten Funktionen ausstatten, was spezielle Projektvorteile bietet. Die gut durchdachte RISC-V-Spezifikation ist in Funktionskategorien gegliedert (die als Erweiterungen bezeichnet werden). Dadurch kann der Hersteller nur die Funktionen implementieren, die für die Anwendung erforderlich sind. Die Verringerung der Anzahl der Transistoren auf einem Chip führt zu einem geringeren Leistungsbedarf und niedrigeren Kosten.


Bastler und Hersteller profitieren gleichermaßen von der Verfügbarkeit der freien Gnu C/C++ Compiler-Toolchain. Was manchmal übersehen wird, ist, dass der Assembler in der Toolchain enthalten ist. In den meisten Fällen wird C/C++ weiterhin die produktivste Programmiersprache sein. Manchmal besteht jedoch ein Bedarf an hoch optimierten Funktionen, die nur mit Assembler-Programmierung erreicht werden können. Ein herausragendes Beispiel hierfür ist die Entwicklung kurzer Interrupt-Service-Routinen.
 
RISC-V in action
RISC-V-Modul auf dem Schreibtisch.

Warum sollten Sie RISC-V für Ihr Projekt wählen?

Viele bestehende Befehlsarchitekturen müssten seit Jahrzehnten erweitert werden, damit bestehende Software kompatibel bleibt. Dies zwingt den Softwareentwickler zu einer steilen Lernkurve, um die Architektur zu beherrschen. Das ist mühsam und kann zu längeren Debugging-Zeiten und verpassten Terminen führen. Mit der RISC-V-Spezifikation wurde reiner Tisch gemacht und ein neuer Befehlssatz entwickelt.

Der Enthusiasmus der Anbieter, einschließlich Intel, für RISC-V deutet darauf hin, dass die Architektur eine ernstzunehmende Größe ist. Dies macht die Architektur zu einer guten Investition. Wenn Sie sich mit der RISC-V-Assemblersprache vertraut machen, können Sie direkt optimierte Funktionen entwickeln. Oder Sie können C/C++-Builds auf Befehlsebene überprüfen, um zu sehen, was der optimierende Compiler für Sie produziert hat. Manchmal führt die High-Level-Optimierung eines Compilers zu fehlerhaftem Code. Daher spart das Erkennen solcher Probleme Zeit.

What Is This Book About?

Das Buch, RISC-V Assembly Language Programming using ESP32-C3 and QEMU,ist eine Anleitung, die Ihnen den Einstieg erleichtern soll. Es ist als einfaches Lernprogramm konzipiert. In jedem Kapitel werden nur einige wenige Konzepte vorgestellt, damit Sie nicht zu viel auf einmal lernen müssen. Spätere Kapitel bauen dann auf dem auf, was Sie bereits gelernt haben. Jedes Projekt beginnt mit einem C-Hauptprogramm, das ein oder mehrere Assembler-Unterprogramme aufruft. Dies demonstriert den Nutzen des Einsatzes der C/C++-Sprache, wo es sinnvoll ist, und die gleichzeitige Nutzung des Assemblers.
RISC-V Book

Die Wahl fiel auf den ESP32-C3, weil der für Bastler und Studenten gleichermaßen kostengünstig ist. Dennoch ist das Device hochfunktional, mit USB, Wi-Fi, SPI, I2C und mehr. Der ESP32-C3 ist eine hervorragende Plattform, um die RISC-V RV32 ISA (32-Bit-Befehlssatzarchitektur) kennenzulernen. Das ESP-IDF Entwicklungssystem von Espressif wird für den ESP32-C3 verwendet. Man ist nicht abhängig von Arduino-Software.

Mit dem QEMU-Emulator können die Leser ihren Desktop-Computer verwenden, um Fedora Linux in der RISC-V RV64 ISA (64-Bit-Architektur) auszuführen. Darüber hinaus bietet diese Umgebung ihnen die Möglichkeit, die Verwendung der RISC-V Gleitkomma-Erweiterungen zu üben.
 
RISC-V
 
RISC-V
 

Was bekommt man mit einer RISC-V-CPU?

Tabelle 1 gibt einen Überblick über die 32 grundlegenden Integer-Register, die die CPU dem Programmierer zur Verfügung stellt. Diese können als x0 bis x31 bezeichnet werden oder durch die freundlicheren ABI-Namen (Application Binary Interface), wie z. B. a0 für Argument Null. Bei RV32-Plattformen wie dem ESP32-C3 handelt es sich um 32-Bit-Register. Für RV64-Plattformen sind die Register stattdessen 64 Bit breit. 

Table 1: RISC-V Basic Registers.
Register ABI-Name Beschreibung
x0 zero Hardwired to return zero
x1 ra Return Address
x2 sp Stack pointer
x3 gp Global pointer
x4 tp Thread pointer
x5-x7 t0-t2 Temporary registers
x8 s0/fp Saved register / frame pointer
x9 s1 Saved register
x10-x11 a0-a1 Function arguments / return value
x12-x17 a2-a7 Function arguments (continued)
x18-x27 s2-s11 Saved registers
x28-x31 t3-t6 Temporary registers
 
Mit einer großen Anzahl solcher Register kann eine gut konstruierte Funktion den Zugriff auf den Speicher vollständig vermeiden, was eine schnellere Ausführung bringt. Die Register bieten unmittelbaren Zugriff auf Daten, während der Speicherzugriff zusätzliche Taktzyklen erfordert. Alle RISC-V-CPUs verfügen über diese 32 Register, mit einer Ausnahme. Die Erweiterung E für RISC-V wurde entwickelt, um Herstellern die Möglichkeit zu geben, eine CPU mit nur 16 Registern zu entwickeln. Diese sind für sehr preisgünstige Mikrocontroller gedacht.

Alle Register sind gleichwertig, mit Ausnahme von x0, das ein besonderes Talent hat. Wenn x0 als Quelle angegeben wird, liefert es den ganzzahligen Wert Null. Wenn es als Ziel für das Ergebnis angegeben wird, wird dieses Ergebnis verworfen. Obwohl die übrigen Register in ihrer Funktion gleich sind, reserviert die Gnu-Calling-Konvention Gruppen von Registern für bestimmte Zwecke. Beispiele dafür sind a0 bis a7, die zur Übergabe von Argumenten verwendet werden, t0 bis t6, um temporäre Werte zu halten, und Register ra (x1), um eine Return Adresse zu erhalten.

Zusätzlich zu diesen Registern fügen die RISC-V-Erweiterungen F, D oder Q die folgenden Gleitkommaregister hinzu, wie in Tabelle 2 dargestellt.

Tabelle 2: Gleitkommaregister und ihre ABI-Namen.
Register ABI-Name Beschreibung
f0-f7 ft0-ft7 Floating-point temporaries
f8-f9 fs0-fs1 Floating-point saved registers
f10-f11 fa0-fa1 Floating-point arguments/return values
f12-f17 fa2-fa7 Floating-point arguments
f18-f27 fs2-fs11 Floating-point saved registers
f28-f31 ft8-ft11 Floating-point temporaries
 
Die Breite dieser Register hängt von den unterstützten Erweiterungen ab. Die Erweiterung F unterstützt den Float-Typ der Sprache C, während die Erweiterung D den Double-Typ unterstützt.  Erweiterung Q schließlich unterstützt das Vierfach-Gleitkommaformat.

Dem aufmerksamen Leser ist vielleicht aufgefallen, dass etwas fehlt. Es gibt keine Status-Flag-Bits, wie z. B. Carry, Overflow, Negative usw., und somit auch kein Statusregister. Die Entwickler der RISC-V-Architektur haben beschlossen, dass es am besten ist, diese wegzulassen. Dadurch verringert sich der Aufwand für die Interrupt-Service-Routine, da die Statusflags nicht mehr gespeichert und wiederhergestellt werden müssen. Die RISC-V-Architektur geht diesen Bedarf auf andere Weise an, wie in diesem Buch beschrieben wird.

Zum Schluss

Die RISC-V-CPU ist wie eine gut geölte Zustandsmaschine. Ein leicht verständlicher Befehlssatz erlaubt es Ihnen als Programmierer, jeden Schritt zu steuern.  Es ist sehr befriedigend, dieses Maß an Kontrolle zu perfektionieren. Warum sollten Sie nicht ein wenig Spaß haben, indem Sie diese einfache Einführung folgen?