RISC-V Assembler-Programmierung
Die Begeisterung für RISC-V deutet darauf hin, dass die Architektur eine Größe ist, mit der man rechnen muss. Dies macht die Architektur in vielen Fällen zu einer guten Investition. Wenn Sie sich mit der Assemblersprache RISC-V vertraut machen, können Sie direkt optimierte Funktionen entwickeln.
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.
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.
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.
Table 1: RISC-V Basic 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.
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.
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.
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.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.
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.