C est un vieux langage. Il est dangereux. Il ne protège de rien. On peut écrire du code qui compile, passe la revue, et corrompt la mémoire en production trois mois plus tard. Tout ce que la critique dit du C est exact.
Et pourtant, en 2025, nous l'utilisons encore dans la majorité de nos projets embarqués. Pas par nostalgie, pas par flemme, et pas par désaccord avec Rust. Par contrainte. Voici laquelle.
L'enveloppe mémoire
Sur un STM32L0 qui est notre cible industrielle pour les capteurs basse consommation, nous disposons de 8 à 20 Ko de RAM et 32 à 192 Ko de flash. Le toolchain Rust génère un binaire fonctionnel, mais le landing zone est étroit : le support officiel no_std fonctionne, mais l'écosystème de crates embarquées est, à la date d'écriture, encore incomplet pour certains périphériques que nos clients spécifient.
Ce n'est pas que Rust ne tient pas. C'est que chaque semaine où l'équipe doit écrire un pilote I2C custom parce que embedded-hal n'a pas la variante du capteur qu'on a, est une semaine pendant laquelle on n'écrit pas le produit. En C, le pilote existe déjà dans le SDK du fabricant.
L'allocation prédictible
Un système embarqué industriel doit avoir une consommation mémoire déterministe sur toute sa durée de fonctionnement. Pas un pic inattendu à 95 % un mardi après-midi. Pas une fragmentation qui provoque un échec d'allocation au bout de six semaines d'uptime.
En C, on obtient cette propriété en interdisant malloc. Tout est statique, tout est dimensionné au compile-time. L'outil principal est la discipline de l'équipe, pas le langage. Rust propose une propriété similaire avec son système de types, et c'est une vraie amélioration. Mais la discipline C bien appliquée produit le même résultat, sur une base de code que toute l'équipe connaît depuis vingt ans.
malloc et free dans le firmware de production. Le linker est configuré pour échouer si un appel à _sbrk apparaît dans le binaire final. Ce n'est pas Rust qui nous donne cette sécurité — c'est le linker.
La maturité du toolchain
GCC ARM a 20 ans de corrections de bugs en code généré pour Cortex-M0+. Pour un produit que nous livrons à 50 000 exemplaires et qui doit fonctionner dix ans en conditions industrielles, ça compte. Le compilateur Rust pour embarqué est excellent, mais il a moins de miles sur des cas limite : optimisations avec interrupts imbriqués, comportement sur des cores sans unité de division, interaction avec des outils de trace propriétaires.
Ces cas limites ne sont pas rares pour nous. Ils sont la norme. Un bug de compilateur qui apparaît chez un client une fois par mois en production est un problème que personne ne veut diagnostiquer.
L'interopérabilité avec les SDK fabricants
ST, NXP, Nordic, Silicon Labs publient leurs SDK en C. Leur middleware, leurs exemples, leurs drivers : en C. On peut wrapper tout ça en Rust. Mais on hérite alors du pire des deux mondes : la sécurité mémoire de Rust aux frontières, et l'unsafe de C au centre, où se passe le vrai travail.
Cette frontière unsafe est grosse, et elle n'est pas juste un détail de présentation. Elle signifie que dans nos architectures, l'avantage mémoire de Rust s'applique à une petite fraction du code et non à la majorité. Le ratio effort/bénéfice baisse en conséquence.
Là où nous n'écrivons plus de C
Cette position n'est pas idéologique. Sur les cibles avec 512 Ko de RAM et plus — typiquement Cortex-M7 ou Cortex-A embarqué — nous écrivons en Rust quand le projet le permet. La frontière est matérielle : dès que l'enveloppe mémoire permet une stack, un allocateur, et un écosystème de crates viable, Rust gagne.
Pour les outils de test, les ferme d'intégration, les pipelines de données, c'est du Rust ou du Python. Le C est confiné aux cibles où il n'a pas de substitut crédible en 2025.
Ce que nous surveillons
L'écosystème Rust embarqué progresse vite. embassy mature. Les crates HAL s'étendent. Le support des MCU Cortex-M0+ s'améliore. Notre estimation interne : dans trois à quatre ans, le calcul basculera pour la majorité de nos cibles. À ce moment-là, nous migrerons. Pas avant.
Cette phrase résume notre position sur beaucoup de décisions techniques : on migre quand le bénéfice dépasse le coût. On n'essaie pas de faire mieux que ce que la physique et l'industrie autorisent aujourd'hui. On fait ce qui marche, avec ce qui existe, et on surveille ce qui vient.