Il m’arrive fréquemment de développer de petits drivers Linux pour des clients afin de gérer des périphériques spécifiques. Ceci la plupart du temps dans un contexte de système embarqué.
Pour la construction d’un système Linux embarqué, ma préférence va généralement à l’environnement de production Buildroot. Celui-ci est plus léger (mais moins riche, il est vrai) que son principal concurrent Yocto.
La documentation de Buildroot est claire et bien fournie, toutefois il n’est pas très facile d’y trouver comment intégrer un driver Linux spécifique, développé pour une cible donnée. Voici donc un petit rappel des fichiers à ajouter ou modifier.
Module spécifique
Je prendrai comme exemple ici un petit module de démonstration que j’ai développé pour lire la position d’un capteur incrémental d’angle de rotation. Ce code est encore en cours de mise au point, j’en parlerai plus en détail dans un prochain article. Nous allons l’employer simplement à titre d’exemple d’un module kernel fourni sous forme de fichier source avec un Makefile
classique.
Le driver est stocké sur Github à l’adresse suivante git://github.com/cpb-/rotation-sensor-module.git
Buildroot
J’utilise la dernière version de Buildroot (2014-05) que je décompresse. Puis je me place dans son répertoire principal.
[~]$ tar xjf buildroot-2014.05.tar.bz2 [~]$ cd buildroot-2014.05/ arch/ CHANGES configs/ fs/ Makefile.legacy support/ board/ Config.in COPYING linux/ package/ system/ boot/ Config.in.legacy docs/ Makefile README toolchain/ [buildroot-2014.05]$
Dans le répertoire package
, je crée habituellement un sous-répertoire correspondant au client pour lequel je développe le projet. Ici, je vais appeler ce sous-répertoire avec le nom de ma société.
[buildroot-2014.05]$ mkdir package/logilin/ [buildroot-2014.05]$
J’ajoute généralement dans ce dossier des sous-répertoires pour chaque développements spécifiques pour le client concerné. En l’occurrence, je vais juste en créer un pour le module rotation-sensor
.
[buildroot-2014.05]$ mkdir package/logilin/rotation-sensor-module/ [buildroot-2014.05]$
Dans ce dernier répertoire, j’insère deux fichiers.
- Un fichier
Config.in
qui décrit le rôle du module et qui s’intégrera dans le menu de configuration de Buildrootconfig BR2_PACKAGE_ROTATION_SENSOR_MODULE bool "Rotation sensor module" depends on BR2_LINUX_KERNEL help Kernel module to support rotation sensors using incremental encoders. comment "Rotation sensor module requires a linux kernel to be built" depends on !BR2_LINUX_KERNEL
- Un fichier
rotation-sensor-module.mk
qui contient les informations pour compiler le projet. C’est surtout ce fichier qui diffère légèrement d’une application classique pour l’espace utilisateur de Linux.################################################################################ # # rotation-sensor-module # ################################################################################ ROTATION_SENSOR_MODULE_VERSION = 1.0.0 ROTATION_SENSOR_MODULE_SITE = git://github.com/cpb-/rotation-sensor-module.git #ROTATION_SENSOR_MODULE_SITE = $(call github,cpb-,rotation-sensor-module,$(ROTATION_SENSOR_MODULE_VERSION)) ROTATION_SENSOR_MODULE_SITE_METHOD = git ROTATION_SENSOR_MODULE_DEPENDENCIES = linux define ROTATION_SENSOR_MODULE_BUILD_CMDS $(MAKE) -C $(@D) $(LINUX_MAKE_FLAGS) KERNELDIR=$(LINUX_DIR) endef define ROTATION_SENSOR_MODULE_INSTALL_TARGET_CMDS $(MAKE) -C $(@D) $(LINUX_MAKE_FLAGS) KERNELDIR=$(LINUX_DIR) modules_install endef $(eval $(generic-package))
Au niveau du répertoire package/logilin
j’ajoute également deux fichiers qui viendront chercher ceux précédemment décrits.
- Un fichier
Config.in
qui correspond au menu des applications spécifiques pour Logilinmenu "Logilin packages" source "package/logilin/rotation-sensor-module/Config.in" endmenu
Bien sûr, j’ai en général plusieurs lignes «
source
… » pour tous les packages spécifiques du client. - Un fichier
logilin.mk
permettant de compiler tous ces packages.########################################################## # # Logilin specific packages # ########################################################## include package/logilin/*/*.mk
Enfin, le fichier package/Config.in
est modifié pour ajouter vers la fin la ligne « source
» chargeant package/logilin/Config.in
.
menu "Target packages" source "package/busybox/Config.in" menu "Audio and video applications" [...] source "package/logilin/Config.in" endmenu
Compilation
Nous allons compiler une image pour une cible bien connue : le Raspberry Pi.
[buildroot-2014.05]$ make raspberrypi_defconfig mkdir -p /home/cpb/buildroot-2014.05/output/build/buildroot-config/lxdialog make CC="/usr/bin/gcc" HOSTCC="/usr/bin/gcc" obj=/home/cpb/buildroot-2014.05/output/build/buildroot-config -C support/kconfig -f Makefile.br conf make[1]: entrant dans le répertoire « /home/cpb/buildroot-2014.05/support/kconfig » /usr/bin/gcc -DCURSES_LOC="" -DLOCALE -I/home/cpb/buildroot-2014.05/output/build/buildroot-config -DCONFIG_=\"\" /home/cpb/buildroot-2014.05/output/build/buildroot-config/conf.o /home/cpb/buildroot-2014.05/output/build/buildroot-config/zconf.tab.o -o /home/cpb/buildroot-2014.05/output/build/buildroot-config/conf make[1]: quittant le répertoire « /home/cpb/buildroot-2014.05/support/kconfig » # # configuration written to /home/cpb/buildroot-2014.05/.config # [buildroot-2014.05]$ make menuconfig
Pendant la configuration de Buildroot, nous examinons le menu package
(cliquez sur l’image pour voir le détail).
Nous y trouvons à la fin de la liste le menu « Logilin ».
Nous pouvons alors activer l’option spécifique du codeur incrémental.
Il est possible de modifier d’autres paramètres si besoin, voire modifier la configuration du noyau avec
[buildroot-2014.05]$ make linux-menuconfig [...] [buildroot-2014.05]$
Habituellement j’ajoute également un répertoire spécifique board/<nom-client>/<nom-projet>/rootfs
dans lequel je place les fichiers de configuration ajoutés ou modifiés. Par exemple, on peut ajouter une ligne dans etc/inittab
pour disposer outre la connexion sur le tty1, d’un shell sur le port série du Raspberry Pi. Bien sûr, il faut configurer l’option BR2_ROOTFS_OVERLAY
en conséquence.
Nous lançons alors la compilation.
[buildroot-2014.05]$ make
Une fois la compilation terminée, nous pouvons vérifier que notre module a bien été intégré dans l’image de la cible :
[buildroot-2014.05]$ ls output/target/lib/modules/3.12.18-logilin/extra/ rotation-sensor.ko [buildroot-2014.05]$
Essai
Insérons une carte SD contenant deux partitions nommées respectivement « BOOT
» (au format vfat
) et « ROOT
» (au format ext4
).
[buildroot-2014.05]$ cp output/images/rpi-firmware/* /media/cpb/BOOT/ [buildroot-2014.05]$ cp output/images/zImage /media/cpb/BOOT/ [buildroot-2014.05]$ sudo tar x -C /media/cpb/ROOT/ -f output/images/rootfs.tar [buildroot-2014.05]$ umount /media/cpb/* [buildroot-2014.05]$
En plaçant la carte SD dans un Raspberry Pi, nous pouvons vérifier que notre module personnel peut être chargé dans le noyau généré.
Welcome to Buildroot / Raspberry Pi R-Pi login: root Password: # modprobe rotation-sensor # lsmod Module Size Used by Tainted: G rotation_sensor 1691 0 # ls /dev/ro* /dev/rotation_sensor #
Merci, juste ce qu’il me fallait, j’ai pu reprendre ton makefile et ton package pour builder mon propre module.
🙂
Bonjour Christophe. Super tuto, merci !
Grâce à vous j’ai réussi à ajouter le module avec lequel je veux communiquer (http://www.st.com/web/catalog/sense_power/FM89/SC1449/PF253884) au menuconfig de mon buildroot.
Par contre, à la compilation je rencontre des soucis, j’ai réutilisé votre makefile en y changeant simplement « obj-m = rotation-sensor.o » par « obj-m = lsm303d.o ».
Pourriez vous m Ȏclairer ?
Merci d’avance
Bonjour,
Quel est le problème de compilation ? Quel message est affiché ?
Bonjour, merci pour votre rapide réponse.
Je ne suis pas un expert dans le domaine, je propose donc de vous donner un screenshot de mon erreur en suivant ce lien : http://tinyurl.com/zl7o7t3
J’i l’impression que le problème vient du driver mais cela me semblerait bizarre…
Merci d’avance! 🙂
Bonjour,
J’essaie depuis longtemps de « cross-compiler » un pilote pour mon NAS Synology.
J’aimerais créer un réseau i2c qui serait pris en charge par le NAS.
j’ai trouvé le chip ch341 et son driver i2c-ch341-usb adapté par Gunar Schorcht (https://github.com/gschorcht) qui est très bien documenté.
j’ai sur mon PC: Ubuntu qui tourne sous VirtualBox, j’y ai installé les headers de mon NAS ainsi que sa toolchain.
solution1:
J’essaie de compiler le driver de Gunar Schorcht en utilisant son propre Makefile mais j’ai une foule de Warning et d’erreurs.
Solution2:
J’ai bien compilé un pilote ch341.c présent dans le Menuconfig d’une version de noyau de mon NAS synology mais la source de i2c-ch341-usb.c ne s’y trouve pas. J’aimerai l’introduire dans la liste et essayer de la compiler par:
make menuconfig
make modules
Est-ce possible ? et si oui comment procéder pour y glisser le i2c-ch341-usb ?
D’avance merci.