Aller au contenu

Linux embarqué

Construire une image Linux minimale et reproductible pour une cible ARM — de Yocto à systemd, sans les 4 Go d'un Linux desktop.


Pourquoi Linux sur un système embarqué ?

Linux embarqué s'impose quand les besoins dépassent ce qu'un RTOS peut offrir : stack TCP/IP complète, drivers de périphériques complexes (caméras, GPU, USB hôte), interfaces graphiques, containerisation (Docker sur ARM), ou lorsque l'équipe maîtrise mieux Linux que le développement bare-metal.

La contrepartie : Linux nécessite un MMU (Memory Management Unit), donc au minimum un Cortex-A (pas un Cortex-M), un minimum de 16 Mo de RAM (réaliste : 128 Mo et plus), et un temps de démarrage de plusieurs secondes. Sur un Raspberry Pi Compute Module 4, un BeagleBone, un NXP i.MX 8 ou un STM32MP1, Linux est le choix naturel.


Yocto Project — le standard industriel

Yocto Project est un framework de construction d'images Linux embarqué. Il ne fournit pas une distribution — il fournit les outils pour construire votre propre distribution adaptée à votre matériel.

Concepts clés

Layers (couches) : Yocto s'organise en layers superposés. Chaque layer apporte des recettes (recipes), des configurations machine ou des customisations. La séparation est stricte : BSP (Board Support Package) dans un layer dédié, application dans un autre.

meta/              ← layer de base OpenEmbedded Core
meta-poky/         ← layer de référence Yocto
meta-openembedded/ ← layers communautaires (networking, multimedia...)
meta-raspberrypi/  ← BSP Raspberry Pi
meta-monproduit/   ← votre layer applicatif

Recipes (.bb) : une recipe décrit comment compiler un logiciel — sources, dépendances, configuration, installation.

# Exemple de recipe : mon-daemon_1.0.bb
DESCRIPTION = "Daemon d'acquisition IoT"
LICENSE = "MIT"
SRC_URI = "git://git.monserveur.fr/mon-daemon.git;branch=main"
SRCREV = "a3f9c12d..."

inherit cmake systemd

SYSTEMD_SERVICE:${PN} = "mon-daemon.service"
SYSTEMD_AUTO_ENABLE = "enable"

BitBake : le moteur de build de Yocto. Il analyse les recipes, résout les dépendances, exécute les tâches (do_fetch, do_compile, do_install, do_package) et gère le cache (sstate-cache) pour éviter de recompiler ce qui n'a pas changé.

Machine config : le fichier .conf qui décrit le matériel cible — architecture CPU, bootloader, kernel, formats d'image.

# conf/machine/stm32mp157-monproduit.conf
require conf/machine/stm32mp157c-dk2.conf
MACHINE_FEATURES += "wifi bluetooth"
IMAGE_FSTYPES = "wic.gz wic.bmap"

Construire une image Yocto

# Initialisation de l'environnement
source poky/oe-init-build-env build-monproduit

# Configuration de la machine cible
echo 'MACHINE = "stm32mp157-monproduit"' >> conf/local.conf

# Construction (première fois : 4 à 12 heures selon le matériel)
bitbake core-image-minimal

# Construction de l'image complète avec vos applications
bitbake monproduit-image

Le sstate-cache réduit les builds ultérieurs à quelques minutes pour les changements incrémentaux.


Buildroot — la simplicité efficace

Buildroot est une alternative à Yocto orientée simplicité. Il génère un système de fichiers root minimal via un menuconfig familier aux développeurs Linux kernel. Il ne supporte pas les mises à jour partielles ni la gestion fine des packages, mais sa courbe d'apprentissage est nettement plus courte.

Workflow Buildroot :

make menuconfig       # sélection architecture, packages, kernel
make                  # build complet (1 à 3 heures)
# Artefacts dans output/images/

Buildroot convient aux produits dont l'image est figée (pas de mise à jour de packages individuelle), avec une équipe restreinte et un besoin de démarrer rapidement.


Device Tree — décrire le matériel

Le Device Tree (DT) est la méthode standard Linux pour décrire le matériel non découvrable d'une carte embarquée : périphériques SPI/I2C, GPIO, mémoire, interruptions. Le kernel Linux utilise cette description pour instancier les bons drivers.

Structure DTS

// fragment de device tree : capteur SHT40 sur I2C1
&i2c1 {
    status = "okay";
    clock-frequency = <400000>;  /* I2C fast mode : 400 kHz */

    sht40: humidity-sensor@44 {
        compatible = "sensirion,sht4x";
        reg = <0x44>;             /* adresse I2C */
    };
};

&spi2 {
    status = "okay";
    max-baudrate = <10000000>;   /* 10 MHz */

    adc_ext: adc@0 {
        compatible = "microchip,mcp3204";
        reg = <0>;
        spi-max-frequency = <1000000>;
        vref-supply = <&vref_3v3>;
    };
};

Device Tree Overlays

Les overlays (.dtbo) permettent d'ajouter des périphériques sans recompiler le DTS complet. Sur Raspberry Pi, les overlays se chargent depuis config.txt. Sur Yocto, ils sont intégrés dans la recipe kernel.

# Chargement d'un overlay au runtime (Linux 4.4+)
dtoverlay monproduit-capteur.dtbo

Cross-compilation

Compiler sur une machine x86_64 pour une cible ARM requiert une toolchain croisée : compilateur, linker, et bibliothèques configurés pour l'architecture cible.

# Exemple avec la toolchain Linaro pour Cortex-A
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

# Compilation du kernel
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

# CMake cross-compilation (fichier toolchain)
# arm64-toolchain.cmake :
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_SYSROOT /opt/sysroot-arm64)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Le sysroot contient les headers et bibliothèques de la cible — il est généré par Yocto (populate_sdk) ou Buildroot (make sdk).


systemd sur embarqué

systemd est désormais standard sur la majorité des images Linux embarqué industrielles. Il gère le démarrage, les services, les timers et le watchdog matériel.

Service applicatif

# /etc/systemd/system/mon-daemon.service
[Unit]
Description=Daemon acquisition IoT
After=network.target
Requires=network.target

[Service]
Type=simple
ExecStart=/usr/bin/mon-daemon --config /etc/mon-daemon.conf
Restart=on-failure
RestartSec=5s
WatchdogSec=30s         # si le daemon ne notifie pas dans 30s → redémarrage
NotifyAccess=main

[Install]
WantedBy=multi-user.target

Le watchdog systemd (WatchdogSec) est distinct du watchdog matériel. Le daemon doit appeler sd_notify(0, "WATCHDOG=1") périodiquement. Si le daemon gèle, systemd le redémarre.

Timer systemd — remplacer les cron

# /etc/systemd/system/export-donnees.timer
[Unit]
Description=Export données capteurs toutes les 5 minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
AccuracySec=10s

[Install]
WantedBy=timers.target

Tableau comparatif Yocto vs Buildroot

Critère Yocto Project Buildroot
Taille image minimale ~8 Mo (core-image-minimal) ~2 Mo
Temps de build initial 4 à 12 heures 1 à 3 heures
Builds incrémentiels Rapides (sstate-cache) Moyens
Flexibilité Très haute (tout customisable) Moyenne
Gestion des packages Oui (opkg, rpm, deb) Non (image figée)
Mise à jour OTA Mender, SWUpdate intégrés SWUpdate possible
Courbe d'apprentissage Raide (2 à 4 semaines) Douce (2 à 5 jours)
Utilisé par Samsung, Intel, Wind River, Boeing Synology, Rockchip, petites séries
LTS Yocto LTS (2 ans) Buildroot LTS (1 an)

Pipeline de build Linux embarqué

flowchart TD
    A[Sources upstream\nKernel, U-Boot, glibc, busybox] --> B[Layers Yocto\nmeta-bsp, meta-app]
    B --> C[Recettes .bb\nSRC_URI, DEPENDS, do_compile]
    C --> D[BitBake\nRésolution dépendances\nCache sstate]
    D --> E[Compilation croisée\naarch64-poky-linux-gcc]
    E --> F[Packages .ipk/.rpm]
    F --> G[rootfs\nassembly]
    G --> H[Image .wic\nBootloader + Kernel + rootfs]
    H --> I[Flash SD card\nou update OTA]

    J[Device Tree .dts] --> K[DTC compilateur]
    K --> L[DTB binaire]
    L --> H

    style A fill:#2d4a6e,color:#fff
    style I fill:#1a6e3a,color:#fff
    style D fill:#6e3a1a,color:#fff

Ce qu'il faut retenir

  • Yocto est le standard industriel pour les produits à volume ou à longue durée de vie — sa complexité initiale est amortie sur la durée.
  • Buildroot convient aux petites équipes et aux images figées — démarrage en jours, pas en semaines.
  • Le Device Tree découple la description matérielle du code kernel — essentiel pour maintenir plusieurs variantes de carte.
  • systemd sur embarqué offre le watchdog applicatif, les timers et la supervision de services sans dépendance supplémentaire.
  • La cross-compilation avec sysroot est la méthode standard — ne jamais compiler directement sur la cible en production.

Chapitre suivant : Développement FPGA — HDL, HLS et synthèse pour les accélérateurs matériels et la logique temps réel.