Un Raspberry Pi en production ?

Publié par cpb
Fév 01 2019

(ou “Jouons avec un Compute Module 3+, Raspbian, Buildroot et Yocto“)

Je réalise des prestations de conseil et de formation auprès d’entreprises qui souhaitent utiliser Linux pour produire un système embarqué. La plupart de ces projets commencent par un prototype sur Raspberry Pi.

Lorsqu’elles me consultent sur le choix d’une plate-forme pour l’industrialisation de leur produit, je leur conseille de laisser de côté le Raspberry Pi et de se tourner vers une carte plus adaptée à la production en série.

Mais cette réponse pourrait bien évoluer…

System-On-Chip, Single-Board-Computer et System-On-Module

Pour commencer, quelques rappels sur le vocabulaire des systèmes embarqués ; la plupart d’entre-eux sont construits autour d’un System-On-Chip (S.O.C.) c’est-à-dire une “puce” comprenant un processeur, des circuits électroniques (diviseurs d’horloge, logique de reset, etc.), des contrôleurs d’entrées-sorties, de la mémoire… Le S.O.C. utilisé par le Raspberry Pi (3B+) est le BCM2837B0 de Broadcom.

Le Raspberry Pi associe ce S.O.C. avec un peu de mémoire, un contrôleur USB/Ethernet et ajoute des fonctions électroniques (alimentation, amplification des signaux, etc.). Il suffit d’ajouter une carte micro-SD contenant le système d’exploitation et d’alimenter le Raspberry Pi pour qu’il soit opérationnel. On lui connecte, au choix, un écran, un clavier, un câble Ethernet, des périphériques série, SPI, i²c, etc. C’est ce que l’on nomme un Single-Board-Computer (S.B.C.)

Un S.B.C. est très adapté pour le prototypage, les projets personnels (media center, retro-gaming, station météo, serveur domotique…) ou la production de mini-séries de quelques exemplaires. Dès que l’on souhaite dépasser quelques dizaines d’unités à produire, l’utilisation d’un S.B.C. devient peu souhaitable.

Il est très rare qu’un produit ne nécessite pas d’autres composants électroniques externes (capteurs, actionneurs, leds, boutons, interrupteurs, etc.). Il faut alors développer une carte électronique dédiée pour supporter ces éléments spécifiques au projet. Cette carte “métier” et le S.B.C. doivent être reliés par l’intermédiaire de câbles, de connecteurs, et probablement solidarisés physiquement par le biais d’entretoises, de boulons, etc. Tout ceci ajoute de la complexité dans la production et des points de dysfonctionnements potentiels du système.

Dans le cas du Raspberry Pi, on peut développer une carte venant se brancher sur le connecteur d’entrée-sortie à la manière des hats proposés pour cette carte (par exemple le P.O.E. hat ou le Pi TV hat) mais ce n’est pas toujours possible pour des raisons pratiques. Pour un projet récent, mon client était limité à une électronique ne dépassant pas 17 mm d’épaisseur, soit à peine plus que les connecteurs USB/Ethernet. Impossible donc de se brancher sur le connecteur d’extension sauf en soudant directement sur les broches à mi-hauteur. Autrement dit, parfaitement réalisable pour un prototype mais totalement irréaliste pour une production en nombre.

L’idéal est de regrouper toute l’électronique métier sur une seule carte qui inclue également le S.O.C. Toutefois ceci nécessite un investissement en développement électronique conséquent, que l’on ne considère en général pas rentable en deçà de plusieurs milliers d’unités à produire.

La solution consiste à utiliser un System-On-Module (S.O.M.) c’est à dire une petite carte contenant toute l’électronique complexe du S.B.C. avec un seul connecteur spécifique, par exemple une rangée de mini broches à la manière des barrettes de mémoires SO-DIMM. Il suffit alors d’ajouter sur la carte métier un support d’insertion accueillant le S.O.M. pour qu’il puisse communiquer avec les périphériques. L’intégration d’un S.O.M. dans la conception d’une carte électronique métier est une opération relativement simple pour un bureau d’étude, l’interface électronique et logique étant bien documentée par le fournisseur de module.

Pour les projets de mes clients, j’ai eu à utiliser plusieurs modules à vocation industrielle, je citerais par exemple les OposSOM d’Armadeus, les Phycore de Phytec ou les A20-SOM d’Olimex.

Mais le Raspberry Pi dans tout ça ?

Raspberry Pi Compute Module

La Raspberry Pi Fundation avait compris depuis longtemps l’intérêt pour le développeur d’un produit industriel de disposer d’un module regroupant toutes les fonctionnalités du Raspberry Pi, sur lequel il puisse faire fonctionner l’application prototypée et mise au point sur un S.B.C. classique. Elle a proposé le modèle Raspberry Pi Compute Module CM1 qui dans un premier temps était équivalent au Raspberry Pi 1 B+, puis le CM3 équivalent au Raspberry Pi 3. Toutefois la disponibilité de ces modules laissait à désirer et la pérennité de leur production n’était pas garantie.

Le nouveau Raspberry Pi Compute Module 3+ disponible depuis le 29 janvier 2019 franchit une étape en garantissant une disponibilité du module jusqu’au début 2026.

Raspberry Pi Compute Module 3

Il est également disponible en plusieurs versions suivant la taille de la mémoire eMMC désirée. En effet, il est difficilement envisageable dans un produit industriel que tout le logiciel du système soit installé sur une simple carte micro-SD, avec tous les risques que cela comporte : extraction involontaire, mauvais contacts par vibrations, duplication et reverse ingeniering du code applicatif (piratage), etc. Le Raspberry Pi Compute Module contient donc une mémoire flash eMMC que l’on programme avec l’O.S. désiré (une distribution Raspbian par exemple, ou une image personnalisée obtenue avec Yocto ou Buildroot).

Pour programmer le module, il est nécessaire de disposer d’un petit kit de développement dédié, qui permet d’insérer le S.O.M. et de disposer de la connectique équivalente au S.B.C. initial. Cette carte s’appelle un Compute Module I/O Board (CMIO board). Il en existe deux versions, la première v.1.2 date de 2014 environ, lors de la sortie du premier Compute Module, la seconde v.3 date de 2017. La documentation indique que la CMIO board v1.2 ne fonctionne pas avec le CM3+, pourtant c’est celle que j’ai utilisée avec succès. Il est possible que certaines fonctionnalités ne soient pas supportées, mais pour la programmation de base, pas de souci.

Kit de développement CMIO board v.1.2 & Raspberry Pi CM3

Raspbian sur CM3+

Le première expérience à tenter est de flasher une distribution Raspbian standard dans la mémoire eMMC du Compute Module 3+. Pour cela, il existe un tutoriel très bien fait sur le site de la Raspberry Pi Fundation, aussi vais-je simplement lister les opérations que je réalise sans trop les détailler. Je décrirai plus précisément l’utilisation de Buildroot et Yocto.

J’ai téléchargé sur mon PC l’image 2018-11-13 de Raspbian. Sur ce même PC, je compile l’utilitaire usbboot qui nous servira à préparer le CM3+ à l’installation de l’image. Pour cela je dois d’abord installer une version de développement de la bibliothèque libusb.

[~]$ sudo  apt  install  -y  libusb-1.0.0-dev
[~]$ git clone --depth=1 https://github.com/raspberrypi/usbboot
[~]$ cd usbboot
[usbboot]$ make

Une fois la compilation achevée, je regarde la liste des partitions présentes sur ce PC, avant de lancer l’utilitaire de programmation du module.

[usbboot]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 140,7M 1 loop /snap/gnome-3-26-1604/74
[...]
sda 8:0 0 1,8T 0 disk
├─sda1 8:1 0 1,8T 0 part /
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 3G 0 part [SWAP]
sr0 11:0 1 1024M 0 rom
[usbboot]$ sudo ./rpiboot
Waiting for BCM2835/6/7

J’ai inséré le module CM3+ dans la carte CMIO. Je connecte son port “USB Slave” à un port USB de mon PC. Le jumper J4 “USB Slave Boot” est sur la position “Enable“.

Programmation du CM3+ avec la CMIO board v.1.2

Je branche l’alimentation de la CMIO board. L’utilitaire rpiboot la détecte…

Sending bootcode.bin
Successful read 4 bytes
Waiting for BCM2835/6/7
Second stage boot server
File read: start.elf
Second stage boot server done
[usbboot]$

Je vérifie à nouveau la liste des partitions, un nouveau périphérique bloc est présent, qui représente la mémoire eMMC du module CM3+.

[usbboot]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 140,7M 1 loop /snap/gnome-3-26-1604/74
[...]
sda 8:0 0 1,8T 0 disk
├─sda1 8:1 0 1,8T 0 part /
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 3G 0 part [SWAP]
sdb 8:16 1 3,7G 0 disk
sr0 11:0 1 1024M 0 rom

On peut alors copier directement l’image de la distribution sur ce périphérique.

[usbboot]$ sudo  cp  ../2018-11-13-raspbian-stretch.img  /dev/sdb

La copie dure plusieurs minutes. Vous pouvez également utiliser la commande dd dont la syntaxe est légèrement plus compliquée, mais qui sera un peu plus rapide. Une fois la copie terminée, je débranche le câble USB qui reliait la CMIO board à mon PC et je le rebranche. Deux nouvelles partitions formatées apparaissent et sont automatiquement montées.

[usbboot]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 140,7M 1 loop /snap/gnome-3-26-1604/74
[...]
sda 8:0 0 1,8T 0 disk
├─sda1 8:1 0 1,8T 0 part /
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 3G 0 part [SWAP]
sdb 8:16 1 7,3G 0 disk
├─sdb1 8:17 1 43,9M 0 part /media/cpb/boot
└─sdb2 8:18 1 3,1G 0 part /media/cpb/rootfs
sr0 11:0 1 1024M 0 rom

Comme je souhaite utiliser le port série pour me connecter sur mon Compute Module, j’édite le fichier /media/cpb/boot/config.txt pour y ajouter cette ligne :

enable_uart=1

Je démonte consciencieusement les deux partitions et je fais démarrer la CMIO board après avoir placé le cavalier “USB Slave Boot” en position “Disable”.

Boot normal du module CM3+

Voici quelques traces de ma connexion sur le port série.

Raspbian GNU/Linux 9 raspberrypi ttyAMA0
raspberrypi login: pi
Password: (raspberry)
Last login: Tue Nov 13 14:13:35 GMT 2018 on ttyAMA0
Linux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l
[...]
pi@raspberrypi:~$ cat /sys/firmware/devicetree/base/model
Raspberry Pi Compute Module 3 Plus Rev 1.

Le modèle est bien reconnu, vérifions son processeur et sa mémoire RAM (1 Go).

pi@raspberrypi:~$ lscpu
Architecture: armv7l
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Model: 4
Model name: ARMv7 Processor rev 4 (v7l)
CPU max MHz: 1200.0000
CPU min MHz: 600.0000
BogoMIPS: 38.40
Flags: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
pi@raspberrypi:~$ free
total used free shared buff/cache available
Mem: 949452 69364 730168 14012 149920 816484
Swap: 102396 0 102396

Le modèle que j’ai choisi est celui avec 8 Go de mémoire eMMC, je peux le vérifier également.

pi@raspberrypi:~$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 7400936 2657104 4382080 38% /
devtmpfs 470116 0 470116 0% /dev
tmpfs 474724 0 474724 0% /dev/shm
tmpfs 474724 12216 462508 3% /run
tmpfs 5120 4 5116 1% /run/lock
tmpfs 474724 0 474724 0% /sys/fs/cgroup
/dev/mmcblk0p1 44220 22540 21681 51% /boot
tmpfs 94944 0 94944 0% /run/user/1000

J’avais par ailleurs connecté un petit écran sur le port HDMI de la CMIO board, on peut voir que l’IHM de la distribution Raspbian fonctionne parfaitement.

Raspbian 2018.11 sur CM3+

La distribution Raspbian est donc bien supportée par ce nouveau module. Toutefois, pour les systèmes embarqués industriels, on utilise rarement de distribution complète, on préfère construire une image personnalisée ne contenant que le strict nécessaire. Pour cela on utilise un build system comme Buildroot ou Yocto. Commençons par tester notre module avec Buildroot.

Raspberry Pi CM3+ et Buildroot

J’ai déjà décrit la production complète d’un système embarqué avec Buildroot dans cet article. Nous ne verrons ici que les opérations de base pour s’assurer du fonctionnement minimal.

Je télécharge la dernière version stable de Buildroot, j’extrais les sources, je prépare une configuration pour l’ensemble des modèles compatibles avec le Raspberry Pi 3, et je lance la compilation.

[~]$ wget  https://buildroot.org/downloads/buildroot-2018.11.2.tar.bz2
[~]$ tar xf buildroot-2018.11.2.tar.bz2
[~]$ cd buildroot-2018.11.2/
[buildroot-2018.11.2]$ make raspberrypi3_defconfig
[buildroot-2018.11.2]$ make

La compilation initiale prend une demi-heure environ. Ensuite je replace le cavalier “USB Slave Boot” de la CMIO board sur “Enable” et je redémarre la carte, en lançant sur mon PC :

[buildroot-2018.11.2]$ cd  ../usbboot/
[usbboot]$ sudo ./rpiboot
Waiting for BCM2835/6/7
Sending bootcode.bin
Successful read 4 bytes
Waiting for BCM2835/6/7
Second stage boot server
File read: start.elf
Second stage boot server done

[usbboot]$ umount /media/cpb/*
[usbboot]$ sudo cp ../buildroot-2018.11.2/output/images/sdcard.img /dev/sdb

Après copie et re-positionnement du cavalier sur “Disable“, j’observe les traces de boot suivantes :

[    0.000000] Booting Linux on physical CPU 0x0                                                                
[ 0.000000] Linux version 4.14.74-v7 (cpb@why-cpb) (gcc version 7.3.0 (Buildroot 2018.11.2)) #1 SMP Thu Jan 31 08:10:44 CET 2019
[ 0.000000] CPU: ARMv7 Processor [410fd034] revision 4 (ARMv7), cr=10c5383d
[...]
[ 2.089583] devtmpfs: mounted
[ 2.097822] Freeing unused kernel memory: 1024K
[ 2.186441] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
Starting logging: OK
Initializing random number generator…
[ 2.261917] random: dd: uninitialized urandom read (512 bytes read)
done.
Starting network:
[ 2.447091] NET: Registered protocol family 10
[ 2.455052] Segment Routing with IPv6
Waiting for interface eth0 to appear…………… timeout!
run-parts: /etc/network/if-pre-up.d/wait_iface: exit status 1
FAIL
Welcome to Buildroot
buildroot login:

L’erreur en fin de boot est normale, le Compute Module n’a pas d’interface Ethernet (sur le Raspberry Pi classique, cette interface est fournie par un convertisseur USB / Ethernet LAN9512), le script de configuration par DHCP échoue donc au bout de quelques secondes. Ceci ne nous empêche pas de nous connecter et de passer quelques commandes.

Welcome to Buildroot
buildroot login: root
# uname -a
Linux buildroot 4.14.74-v7 #1 SMP Thu Jan 31 08:10:44 CET 2019 armv7l GNU/Linux
# cat /sys/firmware/devicetree/base/model
Raspberry Pi Compute Module 3 Plus Rev 1.0

Notre Compute Module est bien reconnu et utilisable avec la dernière version stable de Buildroot. Comme j’en avais parlé dans cet article, il est possible de configurer à loisir la composition du système et de le rendre très robuste.

Raspberry Pi CM3+ et Yocto Project

Le projet Yocto, à l’instar de son confrère Buildroot, permet de construire une image personnalisée pour un système embarqué en le limitant au strict nécessaire. Nous allons l’utiliser pour produire une image pour le Raspberry Pi Compute Module 3+.

Tout d’abord téléchargeons la dernière version de Yocto. Début 2019, il s’agit de la branche “Thud”.

[~]$ mkdir  CM3lab
[~]$ cd CM3lab
[CM3lab]$ git clone git://git.yoctoproject.org/poky.git -b thud

Téléchargeons également le layer pour Raspberry Pi, il s’agit d’un répertoire préfixé par meta contenant les recipes – les recettes nécessaires pour générer les composants du système – dédiées à cette plateforme.

[CM3lab]$ git  clone git://git.yoctoproject.org/meta-raspberrypi  -b  thud

Appelons le script oe-build-env pour créer un répertoire de travail et préparons la configuration de la compilation.

[CM3lab]$ source  poky/oe-init-build-env  build-cm3+
[build-cm3+]$

On remarque que le script nous a placé dans le répertoire de travail nouvellement créé. Ajoutons le layer du Raspberry Pi pour notre compilation.

[build-cm3+] $ bitbake-layers   add-layer   ../meta-raspberrypi

Éditons le fichier de configuration de Yocto, et modifions le type de machine ainsi :

[build-cm3+]$ nano  conf/local.conf
[...]
MACHINE = "raspberrypi-cm3"
[...]

Nous pouvons maintenant lancer la compilation…

[build-cm3+]$ bitbake  rpi-basic-image

La durée de compilation varie sensiblement en fonction de la puissance processeur disponible et du débit de la connexion Internet, mais elle est de l’ordre de deux heures environ.

Le fichier à copier sur la partition eMMC (à partir du répertoire courant) est le suivant :

tmp/deploy/images/raspberrypi-cm3/rpi-basic-image-raspberrypi-cm3.rpi-sdimg

Si on veut utiliser la connexion par port série, il faut ajouter deux opérations. Une fois le fichier copié, il faut déconnecter puis reconnecter le câble USB Slave afin de voir apparaître sur le PC les deux partitions. On édite le fichier config.txt se trouvant sur la première pour, comme avec la distribution Raspbian, ajouter la ligne suivante.

enable_uart=1

En outre, il faut éditer le fichier /etc/inittab se trouvant sur la seconde partition et remplacer la ligne

S0:12345:respawn:/bin/start_getty 115200 ttyS0 vt102

par

S0:12345:respawn:/bin/start_getty 115200 ttyAMA0 vt102

Comme avec les images précédentes, nous pouvons vérifier le boot du système :

Poky (Yocto Project Reference Distro) 2.6.1 raspberrypi-cm3 /dev/ttyAMA0
raspberrypi-cm3 login: root
root@raspberrypi-cm3:~# uname -a
Linux raspberrypi-cm3 4.14.87 #1 SMP Thu Jan 31 09:49:20 UTC 2019 armv7l GNU/Linux
root@raspberrypi-cm3:~# cat /sys/firmware/devicetree/base/model
Raspberry Pi Compute Module 3 Plus Rev 1.0

Conclusion

Nous voyons que le nouveau Raspberry Pi Compute Module 3+ fonctionne avec la même configuration que le CM3 précédent, tant avec une distribution complète comme Raspbian, qu’avec des images minimales et customisées produites par Buildroot ou Yocto. La gamme de choix étendue en ce qui concerne la mémoire eMMC, la disponibilité prolongée sur six ans, et le prix raisonnable en font une solution intéressante pour industrialiser un produit prototypé sur le Raspberry Pi classique.

Pour pouvoir ensuite utiliser le module ainsi programmé sur une carte métier, on trouvera la documentation de référence sur le site de la Raspberry Pi Fundation, mais aussi des sites indépendants comme ce projet Instructables de Manolis Agkopplan (merci à François Mocq pour le lien).

URL de trackback pour cette page