Nous vous avons déjà parlé des avantages de Rust en tant que langage de programmation. L'un des avantages les plus importants est que les erreurs dans le logiciel sont découvertes plus tôt - et non, par exemple, lorsque le prototype a déjà été développé. Rust est donc un langage sûr à utiliser pour le développement de systèmes embedded. 

Rust possède également plusieurs autres fonctionnalités intéressantes qui méritent d'être mentionnées pour tous ceux qui souhaitent utiliser Rust dans le cadre du développement embedded. Nous en dressons la liste ci-dessous, accompagnée de quelques autres informations utiles.

abstractions à coût zéro.

L'un des avantages de Rust réside dans ses abstractions à coût zéro. Cela signifie que vous pouvez écrire un code ressemblant à un langage de haut niveau sans frais supplémentaires. Le compilateur générera en principe des instructions identiques à celles que l'on obtient en écrivant un code de bas niveau, moins lisible par l'homme. Cela signifie également que le compilateur est en mesure de détecter les erreurs subtiles dans le code, par exemple l'accès à une GPIO pin avant l'initialisation, la mise à l'état de haut niveau d'une sortie lorsque celle-ci est configurée comme une entrée ...

rust sur bare metal.

Dans les environnements de type bare metal, nous n'avons pas le luxe de disposer d'un système d'exploitation fournissant une interface de système telle que POSIX et gérant pour nous l'accès aux systèmes de fichiers, aux réseaux, etc. Cela signifie que Rust ne prendra pas en charge la bibliothèque standard. À l'aide de l'attribut # ![no_std], nous lierons plutôt avec le crate libcore.

Il s'agit d'un sous-ensemble agnostique de la plate-forme std crate qui ne fait aucune hypothèse quant au système sur lequel le logiciel sera exécuté.

fonctionnalités rust disponibles sur cible bare metal

fonctionnalité no_std std
heap (mémoire dynamique) *
collections (Vec, HashMap, etc) **
stack overflow protection X
exécution du code d'initialisation avant le programme principal X
libstd disponible X
libcore disponible
écriture du code du firmware, du noyau ou du bootloader X

Seulement si vous utilisez le crate alloc et utilisez un allocateur approprié comme alloc-cortex-m. ** Seulement si vous utilisez le crate collections et configurez un allocateur global par défaut.

Comme vous pouvez le constater, lorsque l'allocation dynamique de mémoire est une nécessité dans votre projet, quelques étapes supplémentaires doivent être prises pour retrouver cette fonctionnalité. Alternativement, le heapless crate peut être utilisé, celui-ci ne nécessitant aucune configuration mais obligeant le développeur à définir la capacité d'une collection au moment de la compilation.

périphériques à mémoire.

Tous ceux qui travaillent avec des périphériques à mémoire savent qu'il est nécessaire de définir une variable comme étant volatile pour éviter que le compilateur n'optimise cette variable. Dans Rust, l'accès est marqué comme étant volatile et non pas de variable. Cela signifie que nous employons les fonctions read_volatile() et write_volatile() pour travailler avec des pointeurs.

introduire rust dans votre environnement c... et vice versa.

Nous savons que les logiciels ne se construisent pas en un jour et que de nombreuses entreprises utilisent des millions de lignes de code en C dans des logiciels hérités critiques. Réécrire tout ceci est une tâche impossible, et nous ne vous le conseillons pas. Cependant, les nouvelles fonctionnalités ou les logiciels critiques pour la sécurité peuvent être écrits en Rust et s'intégrer facilement à votre logiciel C. Ceci est une tâche moins intimidante et se fait étape par étape. À l'aide de l'outil cbindgen, les développeurs peuvent rapidement générer un code passe-partout pour appeler des fonctions Rust à partir d'un environnement C et vice versa en utilisant rust-bindgen.

Avec cargo, nous pouvons créer un objet partagé ou un fichier d'archive que le linker C peut récupérer et intégrer dans le binaire final.

Grâce à bindgen, il est relativement facile d'utiliser un blob binaire de pilote d'un fournisseur de silicium avec une interface C et d'interagir avec lui à partir du code Rust.

photo of a male person sitting at a desk and working on his computer
photo of a male person sitting at a desk and working on his computer

bibliothèques existantes.

En raison de son âge, l'écosystème de Rust n'est pas aussi mature que d'autres langages. Il existe cependant déjà de nombreux crates utiles pouvant être utilisés en production sans problème. Grâce à Cargo et au site crates.io, il est extrêmement facile de les incorporer dans un projet sans avoir un enfer de dépendances. Les crates utilisent le versioning sémantique, ce qui signifie que vous spécifiez la version souhaitée d'un crate et que Cargo peut veiller à utiliser la dernière version qui garantit de ne pas casser votre code après une mise à jour tout en bénéficiant par exemple des corrections de bugs. Toutefois, si une version très spécifique est requise, Cargo peut recevoir l'instruction de n'utiliser que celle-ci. Enfin, si vous avez des dépendances sur des bibliothèques privées, vous pouvez indiquer à Cargo de les récupérer depuis un dépôt Git ou un chemin spécifique au sein du système de fichiers.

embedded-HAL.

Il s'agit du crate de référence pour développer Rust sur une cible embarquée. Ce crate fait abstraction de tout le code d'accès matériel sous-jacent en fournissant une API claire et facile à utiliser. Plusieurs architectures et cartes sont déjà prises en charge et d'autres sont constamment ajoutées.

cty.

Cty est utilisé en combinaison avec bindgen afin d'interfacer plus facilement votre code Rust avec le code C. Il fournit des alias de types pour les types C tels que c_int, c_uchar et c_void.

serde.

Quiconque ayant travaillé avec la dé-sérialisation de données connaît la difficulté de développer un système robuste. Le crate Serde fonctionne jusqu'aux systèmes embedded et constitue un excellent moyen d'éviter la gestion désordonnée de la mémoire ou le byte-packing pour les formats personnalisés.

glossaire

terme explication
crate le nom Rust pour un module ou une bibliothèque
std bibliothèque standard Rust
bindgen outil permettant de créer des interfaces de fonctions étrangères entre Rust et C/C++
à propos de l'auteur
Portrait of Kris van der Stappen
Portrait of Kris van der Stappen

devon kerkhove

project manager

Travailler chaque jour sur la technologie (invisible) de demain, avec nos clients, c'est notre raison d'être. Mordu des embedded systems, désireux d'innover.