Choisir un master EtherCAT open source sous Linux embarqué
Côté calculateur (PC industriel, SBC…), EtherCAT tient une promesse simple : une interface Ethernet ordinaire suffit, sans carte de bus ni matériel propriétaire. C’est souvent l’argument qui fait retenir ce bus plutôt qu’un autre, et c’est la première chose que le choix du MainDevice peut préserver ou casser.
Sur un calculateur Linux, ce choix n’est donc pas d’abord un choix de bibliothèque. C’est un choix sur ce qui entre dans l’image, sur ce qu’il faudra reconstruire à chaque montée de version du kernel, et sur le matériel que l’implémentation autorise encore.
Deux implémentations open source sont aujourd’hui couramment retenues, SOEM et IgH EtherLab. Une troisième, EtherCrab, est beaucoup plus récente. Les trois sont comparées ici, les offres commerciales sont citées en fin d’article.
Vocabulaire
- MainDevice, SubDevice
Terminologie officielle de l’EtherCAT Technology Group depuis son renommage : le MainDevice remplace le master, le SubDevice remplace le slave. Les deux vocabulaires coexistent, la documentation et le code des implémentations emploient encore massivement master et slave. Cet article utilise les termes actuels, à l’exception du titre.
- Kernel module, user space
Un MainDevice en kernel module s’exécute dans le noyau Linux. En user space, il s’exécute comme un processus ordinaire, dans les threads de l’application. La différence se paie surtout au moment de construire l’image.
- Working Counter (WKC)
Compteur incrémenté par chaque SubDevice ayant traité la trame. Sa valeur en retour indique combien de participants ont effectivement répondu, et sert de premier diagnostic.
- Distributed Clocks (DC)
Synchronisation matérielle du bus. Chaque SubDevice aligne son horloge sur une horloge de référence, ce qui impose à la trame d’arriver avant un top d’horloge et non simplement à l’heure en moyenne.
- Image process
Zone mémoire échangée cycliquement, dans laquelle l’application écrit ses consignes et lit les états. Son organisation est décrite par le PDO mapping.
Avant de choisir : le kernel et la carte
Aucune implémentation ne rattrape un kernel mal choisi, et deux questions se posent donc en amont du comparatif.
Le BSP du fondeur (NXP, ST, TI, Intel…) permet-il PREEMPT_RT ? Depuis la
6.12, PREEMPT_RT est intégré au kernel mainline, ce qui supprime l’alternance
entre « kernel à jour » et « kernel temps réel ». Mais beaucoup de BSP restent figés
sur une version ancienne, parfois sans patch RT disponible. Sous Yocto, la
recette linux-yocto-rt couvre le cas générique. Un kernel vendeur, lui, se
vérifie avant de s’engager.
Quelle carte réseau ? Un adaptateur USB vers Ethernet est à exclure pour le bus : le jitter d’interrogation USB rend les mesures inexploitables. Le piège est que certains PC industriels et SBC du marché ont en réalité leurs ports Ethernet derrière un contrôleur USB interne.
Une interface native est nécessaire, par exemple directement sur PCIe, et elle doit être réservée au bus, pas partagée avec le trafic applicatif.
Le MainDevice est en revanche indifférent au média : un segment peut être en cuivre ou en fibre par convertisseur, sans incidence sur lui ni sur l’application.
Trois critères
Ils se classent par ordre de coût : le premier engage la maintenance sur toute la vie du produit, le deuxième le matériel, le troisième se découvre en cours d’intégration quand il n’a pas été vérifié.
Ce qui entre dans l’image
Un MainDevice en kernel module est out-of-tree : il se construit contre les
sources du kernel de l’image et doit être reconstruit à chaque montée de
version. Sous Yocto, cela signifie une recette de module liée à
kernel-module-*, un chargement à déclarer, et une dépendance dure entre deux
éléments qui évoluent à des rythmes différents.
En user space, le MainDevice est une bibliothèque ou une dépendance de l’application. Il ne connaît pas la version du kernel et ne se reconstruit pas quand elle change.
Le user space ne rend pas le système meilleur en temps réel, il rend la maintenance plus prévisible. Sur un produit maintenu dix ans, avec des correctifs de sécurité à livrer, la différence se paie à chaque montée de version.
Le chemin réseau, et ce qu’il exige du matériel
L’argument classique contre le user space porte sur le trajet d’une trame entre
la carte et l’application. Le chemin historique passe par une socket brute
(AF_PACKET), et son coût se paie au retour du softirq vers le user space et à
la sortie d’appel système.
Deux mécanismes plus récents du kernel réduisent ce trajet.
- io_uring
Les soumissions et les complétions passent par des anneaux partagés entre le kernel et l’application, ce qui supprime un appel système par opération.
- XDP et
AF_XDP Un programme eBPF intercepte la trame au niveau du driver, avant l’allocation du
skb, et la redirige vers une socketAF_XDPlue depuis le user space. La pile réseau est court-circuitée, avec copie évitable.
Ces mécanismes resserrent l’écart historique entre user space et kernel module, celui-là même qui justifiait le coût d’intégration d’un module out-of-tree.
Ils ne sont pas gratuits pour autant. XDP demande libxdp, libbpf et une
configuration soignée, et surtout, en mode natif, un driver réseau qui le
supporte, ce qui n’est pas le cas de beaucoup. Le mode générique fonctionne
partout, mais repasse par le skb et perd l’essentiel du bénéfice.
À retenir pour le choix du matériel : la contrainte sur le contrôleur ne pèse
pas que sur IgH et ses drivers natifs, elle revient dès qu’on veut AF_XDP en
user space. Le chemin AF_PACKET, lui, reste disponible sur n’importe quelle
carte.
Ce que l’implémentation couvre du protocole
Un MainDevice n’implémente pas tout EtherCAT, et le périmètre se vérifie à partir de la liste des SubDevices à piloter.
Le fonctionnement cyclique ne suffit pas : la configuration des SubDevices, la mise à jour de leur firmware et le tunnelage de protocoles passent par des mailbox protocols distincts.
- CoE, CANopen over EtherCAT
Configuration par SDO.
- FoE, File over EtherCAT
Mise à jour de firmware par le bus.
- EoE, Ethernet over EtherCAT
Tunnelage d’Ethernet vers un SubDevice, ce dont certains outils de configuration constructeur ont besoin. Typiquement pour faire passer du trafic TCP/IP jusqu’à un SubDevice.
- SoE, Servo over EtherCAT
Profil d’entraînement pour variateurs, alternatif au profil DS402 porté par CoE.
Des bornes de liaison série, par exemple, se configurent par CoE : le débit, la parité et le format de trame sont des objets SDO. Sans CoE, elles restent inertes.
La vérification tient en trois gestes : lister les SubDevices retenus, relever pour chacun les mailbox protocols que sa mise en œuvre exige, puis confronter cette liste aux fonctions annoncées par chaque implémentation. Une fonction manquante se contourne rarement au niveau applicatif.
Un dernier point si des cartes spécifiques doivent être développées : la spécification EtherCAT s’obtient par l’adhésion à l’EtherCAT Technology Group, qui délivre aussi l’identifiant fabricant. L’adhésion comme l’identifiant sont gratuits, mais la spécification n’est accessible qu’à ce titre.
Les trois implémentations
SOEM
SOEM est une bibliothèque C en user space, éprouvée et largement déployée.
Intégration. Une recette à écrire, simple parce que sans dépendance au
kernel : ni Buildroot ni les couches OpenEmbedded courantes ne l’empaquettent,
seules les couches ROS le font. Depuis une application Rust, l’accès passe par FFI
(Foreign Function Interface), donc par une couche unsafe à écrire et à
maintenir, qui devient elle-même un composant du projet.
Licence. Elle a changé en cours de route. Les versions 1.x sont en GPLv2 avec une exception d’édition de liens, qui autorise la liaison avec du code propriétaire. La version 2.0 est en GPLv3 ou licence commerciale chez RT-Labs, sans cette exception. Pour un produit fermé, la version retenue détermine le modèle de licence.
L’architecture bloquante de SOEM impose par ailleurs une gestion manuelle de la mémoire et des verrous explicites.
IgH EtherLab
IgH EtherCAT Master est implanté en kernel module, avec les meilleures caractéristiques temps réel des trois. Le code est sur GitLab, la documentation est publiée en PDF.
Intégration. C’est le plus coûteux, mais il est empaqueté : Buildroot
fournit igh-ethercat, qui construit le module contre le kernel cible avec une
option par driver natif, et OpenEmbedded a une recette équivalente dans
meta-tanowrt. Le
module se reconstruit à chaque montée de version du kernel.
IgH propose deux familles de drivers réseau. Les drivers natifs, pour des puces précises (Intel I210 à I226, e1000e, r8169, entre autres), pilotent la carte sans interruption et donnent les meilleures performances, mais ils suivent le kernel au même rythme que le module et contraignent le choix de la carte. Le driver générique fonctionne avec n’importe quelle carte gérée par Linux, au prix d’un passage par la pile réseau.
Avec un driver natif, l’image compte donc trois éléments couplés à valider ensemble : kernel, module et driver. Avec le driver générique, deux.
Licence. Les kernel modules sont en GPLv2, la bibliothèque user space en LGPLv2.1 : une application propriétaire peut s’y lier dynamiquement. La contrainte porte sur la maintenance du module, pas sur la diffusion du code applicatif.
EtherCrab
EtherCrab est un MainDevice écrit en Rust, exécuté en user space, sans dépendance C ni kernel module, sous licence MIT ou Apache 2.0. L’API est documentée sur docs.rs.
Le développeur principal détaille plusieurs points de conception sur son blog.
Intégration. Elle n’a de sens que dans une application Rust. Le MainDevice
y est une simple dépendance, déclarée dans Cargo.toml et compilée avec elle.
Rien n’apparaît séparément dans l’image. Sous Yocto, Rust est pris en charge depuis la 3.4 : la classe cargo gère la
compilation croisée, et cargo-bitbake génère une recette qui fige l’index des
crates pour la reproductibilité. Les chemins io_uring et XDP décrits plus haut
sont exposés en options de compilation, via des features Cargo.
Réserve. Le crate est en 0.x et son interface évolue encore. Sur la couverture fonctionnelle, il annonce CoE, l’autoconfiguration des SubDevices depuis leur EEPROM et les Distributed Clocks avec compensation de dérive ; EoE, FoE et SoE ne figurent pas dans la liste des fonctions annoncées.
La version se fige dans Cargo.toml, avec la possibilité de pointer une
révision git ou un chemin local pour corriger un défaut sans attendre une
publication, ce qui reste le meilleur recours face à une fonction manquante.
Ces réserves posées, je l’ai mis en œuvre chez plusieurs clients, sur des distributions construites avec Yocto.
Comparatif
| EtherCrab | SOEM | IgH EtherLab | |
|---|---|---|---|
Espace d’exécution | user space | user space | kernel module |
Dans l’image | rien de séparé | bibliothèque | module + driver réseau |
Montée de kernel | sans effet | sans effet | module et driver à reconstruire |
Contraint la carte réseau | non en | non | non avec le driver générique, oui avec un driver natif |
Intégration depuis Rust | native | FFI | FFI |
Licence | MIT / Apache 2.0 | GPLv2 + exception (1.x), GPLv3 ou commerciale (2.0) | GPLv2 kernel, LGPLv2.1 user space |
Maturité | 0.x | éprouvé | éprouvé |
Synthèse
EtherCrab pour une application Rust : rien de séparé dans l’image, aucune dépendance au kernel, licence permissive. En contrepartie, un crate en 0.x dont la version doit être figée, et une couverture protocolaire à vérifier avant de s’engager.
SOEM sur une base C existante, avec une recette simple et sans couplage au kernel. Vérifier d’abord quelle version, donc quelle licence, est engagée.
IgH EtherLab quand le cyclique le plus strict prime et que l’équipe accepte de maintenir un module au rythme du kernel, et un driver natif avec lui si les performances l’exigent, avec la contrainte sur la carte qui va avec.
Dans les trois cas, le choix ne suffit pas : le déterminisme ne vient pas que du MainDevice, il vient surtout du système qui l’exécute. Isolation des cœurs, réglages de l’interface, conception de la boucle applicative, tout cela reste à faire une fois l’implémentation retenue.
Les options commerciales
Elles sortent du périmètre de ce comparatif, mais elles existent et méritent d’être connues. La liste n’est pas exhaustive.
- Acontis EC-Master
MainDevice commercial, sous licence propriétaire avec redevance par équipement.
- Beckhoff TwinCAT
Beckhoff propose désormais un runtime TwinCAT pour Linux : il ne se limite plus à Windows et à TwinCAT/BSD. Ce runtime s’exécute cependant sur la distribution Linux de Beckhoff, dérivée de Debian et livrée avec un kernel temps réel, d’abord sur les PC embarqués ARM CX82x0 et CX9240, puis progressivement sur leurs autres IPC.
TwinCAT ne s’ajoute donc pas à une image construite avec Yocto ou Buildroot : c’est la distribution et le matériel qui sont adoptés avec lui. Le choix se pose au niveau de l’écosystème, pas de la recette, et l’application n’y possède pas le cycle, elle dialogue avec le runtime.
À noter que la frontière n’est pas étanche : SOEM 2.0 propose lui aussi une licence commerciale à côté de la GPLv3.
Hors périmètre
Le réglage du système qui exécute le MainDevice, isolation des cœurs et paramètres de l’interface réseau, fera l’objet d’un article séparé. La configuration des SubDevices depuis leurs fichiers de description ESI, le PDO mapping, le diagnostic de topologie et la redondance de câblage ne sont pas traités ici non plus.