Een groot aantal hedendaagse elektronicaprojecten maakt gebruik van microprocessorchips vanwege de flexibiliteit die softwarebesturing biedt. Maar welke microprocessor kies je? Welke programmeertalen gebruiken we? Dit zijn belangrijke vragen voor elke projectontwerper. RISC-V microprocessoren bieden extra hardware flexibiliteit. De fabricagekosten zijn lager omdat ze niet onderworpen zijn aan IP-licenties en beperkingen. Zonder deze beperkingen kunnen fabrikanten aangepaste functies aan hun CPU toevoegen, wat gespecialiseerde projectvoordelen biedt. De goed ontworpen RISC-V-specificatie is georganiseerd in categorieën van eigenschappen (extensies genoemd). Hierdoor kan de fabrikant ervoor kiezen alleen die functies te implementeren die de toepassing vereist. Vermindering van het aantal transistors op een chip leidt tot minder stroomverbruik en lagere kosten.

Zowel hobbyisten als fabrikanten profiteren van de beschikbaarheid van de gratis Gnu C/C++ compiler toolchain. Wat soms over het hoofd wordt gezien is dat een assembler in de toolchain aanwezig is. Voor het grootste deel zal C/C++ de productiefste programmeertaal blijven. Toch blijft er soms behoefte bestaan aan sterk geoptimaliseerde functies die alleen in assembler kunnen worden geprogrammeerd. Een belangrijk gebied hiervoor is de ontwikkeling van korte interrupt-service-routines.
 
RISC-V in action
RISC-V module op het bureau.

Waarom RISC-V kiezen voor je project?

Veel bestaande instructie-architecturen moeten tientallen jaren worden uitgebreid zodat bestaande software compatibel blijft. Dit duwt de softwareontwikkelaar op een steile leercurve om de architectuur onder de knie te krijgen. Dit is vervelend en kan leiden tot langer debuggen en gemiste deadlines. De RISC-V-specificatie veegt de lei schoon en presenteert een nieuwe instructieset.

Het enthousiasme van leveranciers, waaronder Intel, voor RISC-V wijst erop dat de architectuur een kracht is waarmee rekening moet worden gehouden. Dit maakt de architectuur tot een goede investering. Als je met de RISC-V assembler begint, kun je direct geoptimaliseerde functies ontwikkelen. Of je kunt C/C++ builds op instructieniveau controleren om te zien wat de optimaliserende compiler voor je heeft geproduceerd. Soms resulteert de high-level optimalisatie van een compiler in foutieve code. Daarom bespaart het opsporen van dit soort problemen tijd.
 

Waar gaat dit boek over?

Het boek, RISC-V Assembly Language Programming using ESP32-C3 and QEMU, is een handleiding om je op weg te helpen. Het is ontworpen als een eenvoudig leerboek. Elk hoofdstuk introduceert een paar minimale concepten, zodat je niet te veel in één keer hoeft te leren. Latere hoofdstukken bouwen dan voort op wat je al geleerd hebt. Elk project begint met een hoofdprogramma in C dat één of meer onder programma’s in assembler oproept. Dit demonstreert het nut van het gebruik van de C/C++ taal waar het zinvol is en het tegelijkertijd benutten van assembler.
RISC-V Book

De ESP32-C3 werd gekozen vanwege zijn lage kosten voor zowel de hobbyist als de student. Toch is dit device zeer functioneel, inclusief USB, Wi-Fi, SPI, I2C en meer. De ESP32-C3 is een uitstekend platform om kennis te maken met de RISC-V RV32 ISA (32-bit instructieset architectuur). Het ESP-IDF ontwikkelingssysteem van Espressif wordt gebruikt voor de ESP32-C3. Men is niet afhankelijk van Arduino software.

Met de QEMU-emulator kan de lezer zijn desktopcomputer gebruiken om Fedora Linux te draaien in de RISC-V RV64 ISA (64-bit architectuur). Bovendien biedt deze omgeving hem de mogelijkheid om te oefenen met de RISC-V floating-point extensies.
RISC-V
 
RISC-V
 

Wat krijg je met een RISC-V CPU?

Tabel 1 geeft een overzicht van de 32 integer basisregisters die de CPU de programmeur biedt. Deze kunnen worden aangeduid met x0 t/m x31 of met de vriendelijkere ABI-namen (application binary interface), zoals a0 voor argument nul. Voor RV32-platforms zoals de ESP32-C3 zijn dit 32-bits registers. Bij RV64-platforms zijn de registers 64 bits breed.

Table 1: RISC-V Basic Registers.
Register ABI Naam Beschrijving
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
 
Met zo'n groot aantal registers kan een goed geconstrueerde functie het aanspreken van het geheugen volledig vermijden, wat leidt tot een snellere uitvoering. De registers bieden onmiddellijke toegang tot data, terwijl voor toegang tot het geheugen extra klokcycli nodig zijn. Alle RISC-V CPU's bieden deze 32 registers, met één uitzondering. Uitbreiding E voor RISC-V is ontwikkeld om fabrikanten in staat te stellen een CPU te maken met slechts 16 registers. Deze zijn gericht op zeer goedkope microcontrollers.

Alle registers hebben dezelfde mogelijkheden, met uitzondering van x0 dat een speciale gave heeft. Wanneer x0 als bron wordt opgegeven, levert het de gehele waarde nul. Als het als bestemming voor een resultaat wordt opgegeven, wordt dit resultaat geëlimineerd. Hoewel de overige registers alle dezelfde functie hebben, reserveert de Gnu-calling-conventie groepen registers voor specifieke doeleinden. Voorbeelden zijn a0 tot a7, die worden gebruikt om argumenten op te slaan, t0 tot t6 om tijdelijke getallen te onthouden en register ra (x1) om een return adres te ontvangen.

Naast deze registers voegen de RISC-V-uitbreidingen F, D of Q de volgende floating-point-registers toe, zoals aangegeven in tabel 2.

Table 2: Floating-point registers en hun ABI-namen.
Register ABI Naam Beschrijving
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
 
De breedte van deze registers hangt af van de ondersteunde extensies. Extensie F ondersteunt het float type van C, terwijl extensie D het double type ondersteunt. Extensie Q tenslotte ondersteunt het quad floating-point formaat.

De oplettende lezer heeft misschien gemerkt dat er iets ontbreekt. Er zijn geen status flag bits, zoals Carry, Overflow, Negative, etc., en dus ook geen statusregister. De ontwerpers van de RISC-V architectuur besloten dat het het beste was om deze weg te laten. Dit vermindert de overhead van de interrupt-service-routine omdat de status flags niet meer hoeven te worden opgeslagen en hersteld. RISC-V voorziet in die behoefte op andere manieren, die in het boek worden beschreven.
 

Tot slot

De RISC-V CPU is als een goed geoliede statemachine. Een gemakkelijk te begrijpen instructieset stelt de programmeur in staat elke stap te sturen.  Het geeft veel voldoening om dit niveau van controle te perfectioneren. Waarom niet wat plezier beleven door de eenvoudige handleiding te volgen?