{"id":4026,"date":"2014-07-22T06:00:38","date_gmt":"2014-07-22T05:00:38","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=4026"},"modified":"2014-07-25T00:42:43","modified_gmt":"2014-07-24T23:42:43","slug":"ajouter-un-module-noyau-personnel-dans-buildroot","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2014\/07\/22\/ajouter-un-module-noyau-personnel-dans-buildroot\/","title":{"rendered":"Ajouter un module noyau personnel dans Buildroot"},"content":{"rendered":"<p style=\"text-align: justify;\"><a title=\"Ajouter un module noyau personnel dans Buildroot\" href=\"http:\/\/www.blaess.fr\/christophe\/2014\/07\/22\/ajouter-un-module-noyau-personnel-dans-buildroot\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-full wp-image-4064\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/07\/miniature.png\" alt=\"Module kernel dans Buildroot\" width=\"200\" height=\"108\" \/><\/a>Il m&rsquo;arrive fr\u00e9quemment de d\u00e9velopper de petits drivers Linux pour des clients afin de g\u00e9rer des p\u00e9riph\u00e9riques sp\u00e9cifiques. Ceci la plupart du temps dans un contexte de syst\u00e8me embarqu\u00e9.<\/p>\n<p style=\"text-align: justify;\">Pour la construction d&rsquo;un syst\u00e8me Linux embarqu\u00e9, ma pr\u00e9f\u00e9rence va g\u00e9n\u00e9ralement \u00e0 l&rsquo;environnement de production <strong>Buildroot<\/strong>. Celui-ci est plus l\u00e9ger (mais moins riche, il est vrai) que son principal concurrent <strong>Yocto<\/strong>.<\/p>\n<p style=\"text-align: justify;\">La <a title=\"http:\/\/buildroot.uclibc.org\/docs.html\" href=\"http:\/\/buildroot.uclibc.org\/docs.html\" target=\"_blank\">documentation de Buildroot<\/a> est claire et bien fournie, toutefois il n&rsquo;est pas tr\u00e8s facile d&rsquo;y trouver comment int\u00e9grer <strong>un driver Linux sp\u00e9cifique<\/strong>, d\u00e9velopp\u00e9 pour une cible donn\u00e9e. Voici donc un petit rappel des fichiers \u00e0 ajouter ou modifier.<br \/>\n<!--more-->\n<\/p>\n<h1>Module sp\u00e9cifique<\/h1>\n<p style=\"text-align: justify;\">Je prendrai comme exemple ici un petit module de d\u00e9monstration que j&rsquo;ai d\u00e9velopp\u00e9 pour lire la position d&rsquo;un capteur incr\u00e9mental d&rsquo;angle de rotation. Ce code est encore en cours de mise au point,\u00a0 j&rsquo;en parlerai plus en d\u00e9tail dans un prochain article. Nous allons l&#8217;employer simplement \u00e0 titre d&rsquo;exemple d&rsquo;un module kernel fourni sous forme de fichier source avec un <code>Makefile<\/code> classique.<\/p>\n<p style=\"text-align: justify;\">Le driver est stock\u00e9 sur <strong>Github<\/strong> \u00e0 l&rsquo;adresse suivante\u00a0 <a title=\"git:\/\/github.com\/cpb-\/rotation-sensor-module.git\" href=\"git:\/\/github.com\/cpb-\/rotation-sensor-module.git\" target=\"_blank\">git:\/\/github.com\/cpb-\/rotation-sensor-module.git<\/a><\/p>\n<h1>Buildroot<\/h1>\n<p style=\"text-align: justify;\">J&rsquo;utilise la derni\u00e8re version de Buildroot (<a title=\"http:\/\/buildroot.uclibc.org\/downloads\/buildroot-2014.05.tar.bz2\" href=\"http:\/\/buildroot.uclibc.org\/downloads\/buildroot-2014.05.tar.bz2\" target=\"_blank\">2014-05<\/a>) que je d\u00e9compresse. Puis je me place dans son r\u00e9pertoire principal.<\/p>\n<pre>[~]$ <strong>tar xjf buildroot-2014.05.tar.bz2<\/strong>\n[~]$ <strong>cd buildroot-2014.05\/<\/strong>\narch\/   CHANGES           configs\/  fs\/       Makefile.legacy  support\/\nboard\/  Config.in         COPYING   linux\/    package\/         system\/\nboot\/   Config.in.legacy  docs\/     Makefile  README           toolchain\/\n[buildroot-2014.05]$<\/pre>\n<p style=\"text-align: justify;\">Dans le r\u00e9pertoire <code>package<\/code>, je cr\u00e9e habituellement un sous-r\u00e9pertoire correspondant au client pour lequel je d\u00e9veloppe le projet. Ici, je vais appeler ce sous-r\u00e9pertoire avec le nom de <a title=\"Logilin\" href=\"http:\/\/www.logilin.fr\" target=\"_blank\">ma soci\u00e9t\u00e9<\/a>.<\/p>\n<pre>[buildroot-2014.05]$ <strong>mkdir package\/logilin\/<\/strong>\n[buildroot-2014.05]$<\/pre>\n<p style=\"text-align: justify;\">J&rsquo;ajoute g\u00e9n\u00e9ralement dans ce dossier des sous-r\u00e9pertoires pour chaque d\u00e9veloppements sp\u00e9cifiques pour le client concern\u00e9. En l&rsquo;occurrence, je vais juste en cr\u00e9er un pour le module <code>rotation-sensor<\/code>.<\/p>\n<pre>[buildroot-2014.05]$ <strong>mkdir package\/logilin\/rotation-sensor-module\/<\/strong>\n[buildroot-2014.05]$<\/pre>\n<p style=\"text-align: justify;\">Dans ce dernier r\u00e9pertoire, j&rsquo;ins\u00e8re deux fichiers.<\/p>\n<ul>\n<li style=\"text-align: justify;\">Un fichier <strong><code>Config.in<\/code><\/strong> qui d\u00e9crit le r\u00f4le du module et qui s&rsquo;int\u00e9grera dans le menu de configuration de Buildroot\n<pre>config BR2_PACKAGE_ROTATION_SENSOR_MODULE\n\tbool \"Rotation sensor module\"\n\tdepends on BR2_LINUX_KERNEL\n\thelp\n\t  Kernel module to support rotation sensors\n\t  using incremental encoders.\n\ncomment \"Rotation sensor module requires a linux kernel to be built\"\n\tdepends on !BR2_LINUX_KERNEL<\/pre>\n<\/li>\n<li style=\"text-align: justify;\">Un fichier <strong><code>rotation-sensor-module.mk<\/code><\/strong> qui contient les informations pour compiler le projet. C&rsquo;est surtout ce fichier qui diff\u00e8re l\u00e9g\u00e8rement d&rsquo;une application classique pour l&rsquo;espace utilisateur de Linux.\n<pre>################################################################################\n#\n# rotation-sensor-module\n#\n################################################################################\n\nROTATION_SENSOR_MODULE_VERSION     = 1.0.0\nROTATION_SENSOR_MODULE_SITE        = git:\/\/github.com\/cpb-\/rotation-sensor-module.git\n#ROTATION_SENSOR_MODULE_SITE        = $(call github,cpb-,rotation-sensor-module,$(ROTATION_SENSOR_MODULE_VERSION))\nROTATION_SENSOR_MODULE_SITE_METHOD = git\nROTATION_SENSOR_MODULE_DEPENDENCIES = linux\n\ndefine ROTATION_SENSOR_MODULE_BUILD_CMDS\n\t$(MAKE) -C $(@D) $(LINUX_MAKE_FLAGS) KERNELDIR=$(LINUX_DIR)\nendef\n\ndefine ROTATION_SENSOR_MODULE_INSTALL_TARGET_CMDS\n\t$(MAKE) -C $(@D) $(LINUX_MAKE_FLAGS) KERNELDIR=$(LINUX_DIR) modules_install\nendef\n\n$(eval $(generic-package))<\/pre>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Au niveau du r\u00e9pertoire <code>package\/logilin<\/code> j&rsquo;ajoute \u00e9galement deux fichiers qui viendront chercher ceux pr\u00e9c\u00e9demment d\u00e9crits.<\/p>\n<ul>\n<li style=\"text-align: justify;\">Un fichier <strong><code>Config.in<\/code><\/strong> qui correspond au menu des applications sp\u00e9cifiques pour Logilin\n<pre>menu \"Logilin packages\"\n  source \"package\/logilin\/rotation-sensor-module\/Config.in\"\nendmenu<\/pre>\n<p>Bien s\u00fbr, j&rsquo;ai en g\u00e9n\u00e9ral plusieurs lignes \u00ab\u00a0<code>source<\/code>&#8230;\u00a0\u00bb pour tous les packages sp\u00e9cifiques du client.<\/li>\n<li style=\"text-align: justify;\">Un fichier <strong><code>logilin.mk<\/code><\/strong> permettant de compiler tous ces packages.\n<pre>##########################################################\n#\n# Logilin specific packages\n#\n##########################################################\n\ninclude package\/logilin\/*\/*.mk<\/pre>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Enfin, le fichier <code>package\/Config.in<\/code> est modifi\u00e9 pour ajouter vers la fin la ligne \u00ab\u00a0<code>source<\/code>\u00a0\u00bb chargeant <code>package\/logilin\/Config.in<\/code>.<\/p>\n<pre>menu \"Target packages\"\n\nsource \"package\/busybox\/Config.in\"\n\nmenu \"Audio and video applications\"\n[...]\n<strong>source \"package\/logilin\/Config.in\"<\/strong>\n\nendmenu<\/pre>\n<h1>Compilation<\/h1>\n<p style=\"text-align: justify;\">Nous allons compiler une image pour une cible bien connue&nbsp;: le Raspberry Pi.<\/p>\n<pre>[buildroot-2014.05]$ <strong>make raspberrypi_defconfig<\/strong>\nmkdir -p \/home\/cpb\/buildroot-2014.05\/output\/build\/buildroot-config\/lxdialog\nmake 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\nmake[1]: entrant dans le r\u00e9pertoire \u00ab \/home\/cpb\/buildroot-2014.05\/support\/kconfig \u00bb\n\/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\nmake[1]: quittant le r\u00e9pertoire \u00ab \/home\/cpb\/buildroot-2014.05\/support\/kconfig \u00bb\n#\n# configuration written to \/home\/cpb\/buildroot-2014.05\/.config\n#\n[buildroot-2014.05]$ <strong>make menuconfig<\/strong><\/pre>\n<p style=\"text-align: justify;\">Pendant la configuration de Buildroot, nous examinons le menu <code>package<\/code> (cliquez sur l&rsquo;image pour voir le d\u00e9tail).<br \/>\n<a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4047 size-medium\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-1-300x161.png\" alt=\"Menu Buildroot\" width=\"300\" height=\"161\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-1-300x161.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-1.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Nous y trouvons \u00e0 la fin de la liste le menu \u00ab\u00a0Logilin\u00a0\u00bb.<br \/>\n<a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4048 size-medium\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-2-300x162.png\" alt=\"Menu Package de Buildroot\" width=\"300\" height=\"162\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-2-300x162.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-2.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Nous pouvons alors activer l&rsquo;option sp\u00e9cifique du codeur incr\u00e9mental.<br \/>\n<a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4049 size-medium\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-3-300x162.png\" alt=\"Module sp\u00e9cifique dans Buildroot\" width=\"300\" height=\"162\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-3-300x162.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2014\/06\/img-3.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Il est possible de modifier d&rsquo;autres param\u00e8tres si besoin, voire modifier la configuration du noyau avec<\/p>\n<pre>[buildroot-2014.05]$ <strong>make linux-menuconfig<\/strong>\n   [...]\n[buildroot-2014.05]$<\/pre>\n<p style=\"padding-left: 60px; text-align: justify;\">Habituellement j&rsquo;ajoute \u00e9galement un r\u00e9pertoire sp\u00e9cifique <code>board\/&lt;<em>nom-client<\/em>&gt;\/&lt;<em>nom-projet<\/em>&gt;\/rootfs<\/code> dans lequel je place les fichiers de configuration ajout\u00e9s ou modifi\u00e9s. Par exemple, on peut ajouter une ligne dans <code>etc\/inittab<\/code> pour disposer outre la connexion sur le <em>tty1<\/em>, d&rsquo;un shell sur le port s\u00e9rie du Raspberry Pi. Bien s\u00fbr, il faut configurer l&rsquo;option <code>BR2_ROOTFS_OVERLAY<\/code> en cons\u00e9quence.<\/p>\n<p style=\"text-align: justify;\">Nous lan\u00e7ons alors la compilation.<\/p>\n<pre>[buildroot-2014.05]$ <strong>make<\/strong><\/pre>\n<p style=\"text-align: justify;\">Une fois la compilation termin\u00e9e, nous pouvons v\u00e9rifier que notre module a bien \u00e9t\u00e9 int\u00e9gr\u00e9 dans l&rsquo;image de la cible&nbsp;:<\/p>\n<pre>[buildroot-2014.05]$ <strong>ls output\/target\/lib\/modules\/3.12.18-logilin\/extra\/<\/strong>\nrotation-sensor.ko\n[buildroot-2014.05]$<\/pre>\n<h1>Essai<\/h1>\n<p style=\"text-align: justify;\">Ins\u00e9rons une carte SD contenant deux partitions nomm\u00e9es respectivement \u00ab\u00a0<code>BOOT<\/code>\u00a0\u00bb (au format <code>vfat<\/code>) et \u00ab\u00a0<code>ROOT<\/code>\u00a0\u00bb (au format <code>ext4<\/code>).<\/p>\n<pre>[buildroot-2014.05]$ <strong>cp output\/images\/rpi-firmware\/* \/media\/cpb\/BOOT\/<\/strong>\n[buildroot-2014.05]$ <strong>cp output\/images\/zImage \/media\/cpb\/BOOT\/<\/strong>\n[buildroot-2014.05]$ <strong>sudo tar x -C \/media\/cpb\/ROOT\/ -f output\/images\/rootfs.tar<\/strong> \n[buildroot-2014.05]$ <strong>umount \/media\/cpb\/*<\/strong>\n[buildroot-2014.05]$<\/pre>\n<p style=\"text-align: justify;\">En pla\u00e7ant la carte SD dans un Raspberry Pi, nous pouvons v\u00e9rifier que notre module personnel peut \u00eatre charg\u00e9 dans le noyau g\u00e9n\u00e9r\u00e9.<\/p>\n<pre>Welcome to Buildroot \/ Raspberry Pi\nR-Pi login: <strong>root<\/strong>\nPassword: \n# <strong>modprobe rotation-sensor<\/strong>\n# <strong>lsmod<\/strong>\nModule                  Size  Used by    Tainted: G  \nrotation_sensor         1691  0 \n# <strong>ls \/dev\/ro*<\/strong>\n\/dev\/rotation_sensor\n#<\/pre>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>Il m&rsquo;arrive fr&eacute;quemment de d&eacute;velopper de petits drivers Linux pour des clients afin de g&eacute;rer des p&eacute;riph&eacute;riques sp&eacute;cifiques. Ceci la plupart du temps dans un contexte de syst&egrave;me embarqu&eacute;. Pour la construction d&rsquo;un syst&egrave;me Linux embarqu&eacute;, ma pr&eacute;f&eacute;rence va g&eacute;n&eacute;ralement &agrave; l&rsquo;environnement de production Buildroot. Celui-ci est plus l&eacute;ger (mais moins riche, il est vrai) [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,8],"tags":[],"class_list":["post-4026","post","type-post","status-publish","format-standard","hentry","category-embarque","category-linux-2"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4026","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=4026"}],"version-history":[{"count":26,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4026\/revisions"}],"predecessor-version":[{"id":4065,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4026\/revisions\/4065"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=4026"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=4026"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=4026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}