wil je meer weten over de verschillen tussen rust en c?

download onze vergelijking

We vertelden je eerder al over de voordelen die Rust als programmeertaal met zich meebrengt. Een van de belangrijkste voordelen is dat fouten in de software vroeger ontdekt worden - en dus niet pas bijvoorbeeld wanneer het prototype al ontwikkeld is. Rust is dus een veilige taal om te gebruiken bij het ontwikkelen van embedded systems. 

Rust heeft zeker ook nog verschillende andere fijne features die het vermelden waard zijn voor iedereen die Rust in embedded wil gaan gebruiken. We zetten die hieronder voor je op een rij, samen met een aantal good to knows.

zero-cost abstracties.

Een van de leuke dingen van Rust? De zero-cost abstracties. Je krijgt de kans om code te schrijven die lijkt op high-level talen, zonder de overhead kosten. De compiler zal meestal dezelfde instructies genereren als wanneer je low-level code zou schrijven die minder leesbaar is. Dat betekent ook dat de compiler kan controleren op subtiele fouten in de code, door bijvoorbeeld toegang te krijgen tot een GPIO-pin vóór initialisatie, en een output op hoog in te stellen wanneer deze als input is geconfigureerd.

rust op bare metal.

In bare metal omgevingen hebben we niet de luxe van een besturingssysteem dat een systeeminterface zoals POSIX aanbiedt en de toegang tot bestandssystemen, netwerken enz. voor ons afhandelt. Rust hoeft dus niet de moeite te nemen om de standaard library te laden. Met behulp van het #![No_std] kenmerk zullen we in plaats daarvan een koppeling maken met de libcore-crate.

Dat is een platformonafhankelijke subset van de std crate die geen aannames doet over het systeem waarop de software zal draaien.

rust features op bare metal target

feature no_std std
heap (dynamisch geheugen) *
collections (Vec, HashMap, etc) **
stack overflow bescherming X
voert init-code uit vóór main X
libstd beschikbaar X
libcore beschikbaar
schrijven van firmware-, kernel- of bootloadercode X

* Alleen als je de alloc crate en een geschikte allocator zoals alloc-cortex-m gebruikt.
** Alleen als je de collections crate gebruikt en een globale default allocator configureert.
 
Zoals je kunt zien, moeten er, wanneer het toewijzen van dynamisch geheugen noodzakelijk is in je project, nog enkele stappen worden ondernomen om deze functionaliteit terug te krijgen. Als alternatief kan de heapless crate worden gebruikt: er is geen installatie vereist, maar de ontwikkelaar moet wel de capaciteit van een collection definiëren tijdens het compileren.

randapparatuur registers.

Iedereen die met aan het geheugen toegewezen randapparatuur werkt, weet dat het noodzakelijk is om een variabele als volatile te definiëren, zodat de compiler deze variabele niet weg optimaliseert. In Rust wordt de toegang gemarkeerd als volatile in plaats van de variabele. Dit betekent dat we de functies read_volatile() en write_volatile() gebruiken op pointers waarmee we werken.

introduceer rust in je c-omgeving… en vice versa.

We weten dat software niet in één dag wordt gebouwd, en veel bedrijven hebben miljoenen regels code in kritieke oudere software geschreven in C. Het herschrijven van dit alles is een onmogelijke taak, en dat raden we absoluut niet aan. 

Nieuwe functies of veiligheidskritieke software kunnen echter in Rust worden geschreven en eenvoudig worden geïntegreerd met je C-software. Dat is een minder ontmoedigende taak die je stap voor stap kan uitvoeren. Met behulp van de cbindgen tool kunnen ontwikkelaars snel boilerplate code genereren om Rust functies uit te voeren vanuit een C-omgeving. Omgekeerd kan dat ook, met behulp van Rust-bindgen.

Met behulp van cargo kunnen we een gedeeld object of archiefbestand maken dat de C-linker kan ophalen en integreren in het uiteindelijke binaire bestand.

Dankzij bindgen is het relatief eenvoudig om een driver binaire blob van een silicon vendor met een C-interface te gebruiken en ermee te communiceren vanuit Rust-code.

A man looking at his computer.

bestaande libraries.

Vanwege zijn leeftijd is het ecosysteem van Rust niet zo volgroeid als andere talen. Er zijn echter al veel handige crates die zonder problemen in de productie kunnen worden gebruikt. Dankzij Cargo en de website crates.io is het uiterst eenvoudig om deze in een project op te nemen zonder een hoop dependency moeilijkheden te creëren. 

Crates maken gebruik van semantic versioning: jij specificeert welke versie van een crate je wilt, en Cargo zorgt ervoor dat het de nieuwste versie gebruikt die garandeert dat je code niet breekt na een update, terwijl je bijvoorbeeld nog steeds bug fixes krijgt. Als er echter een zeer specifieke versie vereist is, kan Cargo worden geïnstrueerd om alleen die versie te gebruiken. 

Ten slotte, als je dependencies hebt van private libraries, kun je Cargo de opdracht geven om het op te halen uit een Git-repository of een specifiek pad op het bestandssysteem.

embedded-HAL.

Dit is de go-to-crate bij het schrijven van Rust op een embedded target. Deze crate abstraheert mooi alle onderliggende hardware toegangscode door het verstrekken van een duidelijke en eenvoudig te gebruiken API. Verschillende architecturen en boards worden al ondersteund en er worden er voortdurend meer toegevoegd.

cty.

Cty wordt gebruikt in combinatie met bindgen om je Rust-code gemakkelijker te koppelen aan C-code. Het biedt type-aliassen voor C-typen zoals c_int, c_uchar en c_void.

serde.

Iedereen die met de-serialisatie van data heeft gewerkt, weet hoe moeilijk het kan zijn om een robuust systeem te ontwikkelen. De Serde crate werkt helemaal tot embedded systemen, en is een geweldige manier om rommelig geheugenbeheer of byte-packing voor aangepaste formaten te voorkomen.

termenlijst

term uitleg
crate Rust's naam voor een module of bibliotheek
std Rust Standaard Bibliotheek
bindgen Tool om foreign function interfaces te maken tussen Rust en C / C ++
over de auteur

devon kerkhove

project manager

Elke dag meewerken aan de (onzichtbare) technologie van morgen, samen met onze klanten, da’s waar we het voor doen. Gebeten door embedded systems, gebrand om te innoveren.