{"id":4823,"date":"2017-03-20T18:32:05","date_gmt":"2017-03-20T17:32:05","guid":{"rendered":"https:\/\/www.blaess.fr\/christophe\/?p=4823"},"modified":"2024-08-07T21:29:25","modified_gmt":"2024-08-07T20:29:25","slug":"xenomai-sur-raspberry-pi-3-bilan-mitige","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2017\/03\/20\/xenomai-sur-raspberry-pi-3-bilan-mitige\/","title":{"rendered":"Xenomai sur Raspberry Pi 3&nbsp;: bon espoir mais bilan mitig\u00e9"},"content":{"rendered":"<p style=\"text-align: justify;\">Depuis plusieurs mois, on m&rsquo;interroge r\u00e9guli\u00e8rement sur le support de <strong>Xenomai<\/strong> sur <strong>Raspberry Pi 3<\/strong> tant durant mes sessions de formations sur Xenomai que dans des messages par mail. J&rsquo;avais l&rsquo;habitude de r\u00e9pondre que Xenomai ne fonctionnait pas encore sur ce mod\u00e8le de Raspberry Pi.<\/p>\n<p style=\"text-align: justify;\">Une <a href=\"https:\/\/www.blaess.fr\/christophe\/2016\/05\/22\/xenomai-3-sur-raspberry-pi-2\/#comment-187468\">remarque r\u00e9cente<\/a> de Syrine dans les commentaires de l&rsquo;article \u00ab\u00a0<a href=\"https:\/\/www.blaess.fr\/christophe\/2016\/05\/22\/xenomai-3-sur-raspberry-pi-2\/\">Xenomai 3 sur Raspberry Pi 2<\/a>\u00a0\u00bb a attir\u00e9 mon attention sur un site japonais qui utilise les m\u00eames commandes que celles pr\u00e9sent\u00e9es dans cet article et fait fonctionner l&rsquo;ensemble sur un Raspberry Pi 3. J&rsquo;ai voulu tenter \u00e9galement cette installation. Le r\u00e9sultat est un peu mitig\u00e9\u00a0: Xenomai fonctionne parfaitement avec une bonne stabilit\u00e9, sauf en ce qui concerne la gestion des interruptions des GPIO qui n&rsquo;est pas support\u00e9e encore. Si vous \u00eates n\u00e9anmoins tent\u00e9s par l&rsquo;exp\u00e9rience, voici comment proc\u00e9der simplement.<\/p>\n<p style=\"text-align: justify;\">\n<!--more-->\n<\/p>\n<h1 style=\"text-align: justify;\">Compilation et installation<\/h1>\n<p style=\"text-align: justify;\">Dans le cadre d&rsquo;une mise en \u0153uvre professionnelle pour un client je travaillerais en <em>cross-compilation<\/em> sur une machine de d\u00e9veloppement de type PC pour produire l&rsquo;image qui serait install\u00e9e ensuite sur la cible. Pour ce petit article, j&rsquo;ai pr\u00e9f\u00e9r\u00e9 simplifier la mise en \u0153uvre et r\u00e9aliser une compilation native directement sur le Raspberry Pi 3. Le temps de construction est plus long, mais il reste tr\u00e8s raisonnable (2h tout compris pour cette exp\u00e9rience).<\/p>\n<p style=\"text-align: justify;\">Tout d&rsquo;abord, installons une image de la distribution <em>Raspbian<\/em> toute neuve. N&rsquo;utilisez pas la distribution <em>Noob<\/em>, l&rsquo;organisation des partitions est diff\u00e9rente.<\/p>\n<pre>[~]$ <strong>sudo dd if=2017-02-16-raspbian-jessie-lite.img of=\/dev\/sdc bs=4M<\/strong><\/pre>\n<p style=\"text-align: justify;\">Nous d\u00e9marrons \u00e0 pr\u00e9sent le Raspberry pi 3 sur cette nouvelle distribution. Elle va rebooter automatiquement pour agrandir la partition et occuper tout la carte SD. Connectons-nous<\/p>\n<pre>raspberrypi login: <strong>pi<\/strong>\nPassword: <strong>raspberry<\/strong><\/pre>\n<p style=\"text-align: justify;\">Il nous faudra quelques outils suppl\u00e9mentaires \u00e0 ajouter \u00e0 la distribution d&rsquo;origine\u00a0:<\/p>\n<pre>pi@raspberrypi:~$ <strong>sudo apt install -y git ncurses-dev bc autoconf libtool<\/strong><\/pre>\n<p style=\"text-align: justify;\">T\u00e9l\u00e9chargeons les sources de Xenomai. Je prends la derni\u00e8re version disponible \u00e0 ce jour\u00a0:<\/p>\n<pre>pi@raspberrypi:~$ <strong>wget http:\/\/xenomai.org\/downloads\/xenomai\/stable\/xenomai-3.0.3.tar.bz2<\/strong>\npi@raspberrypi:~$ <strong>tar xjf xenomai-3.0.3.tar.bz2<\/strong>\npi@raspberrypi:~$ <strong>ls xenomai-3.0.3\/kernel\/cobalt\/arch\/arm\/patches\/<\/strong>\nipipe-core-3.10.32-arm-13.patch  ipipe-core-3.18.20-arm-9.patch  README\nipipe-core-3.14.44-arm-16.patch  ipipe-core-4.1.18-arm-4.patch<\/pre>\n<p style=\"text-align: justify;\">Le patch <code>ipipe<\/code> le plus r\u00e9cent propos\u00e9 par Xenomai s&rsquo;applique sur un noyau Linux 4.1. Nous avons de la chance, il existe une branche 4.1 pour le kernel sp\u00e9cifiquement modifi\u00e9 pour Raspberry Pi. T\u00e9l\u00e9chargeons cette branche. L&rsquo;option <code>--depth 1<\/code> raccourcit le temps de t\u00e9l\u00e9chargement (2 \u00e0 3 minutes) en limitant l&rsquo;historique au seul dernier <em>commit<\/em>\u00a0:<\/p>\n<pre>pi@raspberrypi:~$<strong> git clone https:\/\/github.com\/raspberrypi\/linux.git -b rpi-4.1.y --depth 1<\/strong>\npi@raspberrypi:~$ <strong>head -4 linux\/Makefile<\/strong>\nVERSION = 4\nPATCHLEVEL = 1\nSUBLEVEL = 21\nEXTRAVERSION =\npi@raspberrypi:~$<\/pre>\n<p style=\"text-align: justify;\">Le noyau est un 4.1.21. Il n&rsquo;y a pas beaucoup de diff\u00e9rences avec le 4.1.18, Xenomai fonctionnera. N\u00e9anmoins une option de configuration a \u00e9t\u00e9 modifi\u00e9e, et pour que le <em>patch<\/em> <code>ipipe<\/code> puisse s&rsquo;applique nous devons le modifier. Pour cela, j&rsquo;ai pr\u00e9par\u00e9 un petit <em>patch<\/em> (un <em>patch<\/em> de <em>patch<\/em>, cela explique qu&rsquo;il contienne un signe <code>'+'<\/code> d\u00e9cal\u00e9) que nous t\u00e9l\u00e9chargeons\u00a0:<\/p>\n<pre>pi@raspberrypi:~$ <strong>wget <a href=\"https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/001-adapt-4.1.18-patch-to-rpi-4.1.21-kernel.patch\">https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/001-adapt-4.1.18-patch-to-rpi-4.1.21-kernel.patch<\/a><\/strong><\/pre>\n<p style=\"text-align: justify;\">Appliquons ce mini-<em>patch<\/em> \u00e0 Xenomai.<\/p>\n<pre>pi@raspberrypi:~$ <strong>ls<\/strong>\n001-adapt-4.1.18-patch-to-rpi-4.1.21-kernel.patch  linux  xenomai-3.0.3  xenomai-3.0.3.tar.bz2\npi@raspberrypi:~$ <strong>cd xenomai-3.0.3\/<\/strong>\npi@raspberrypi:~\/xenomai-3.0.3$ <strong>patch -p1 &lt; ..\/001*<\/strong>\npatching file kernel\/cobalt\/arch\/arm\/patches\/ipipe-core-4.1.18-arm-8.patch\npi@raspberrypi:~\/xenomai-3.0.3$<\/pre>\n<p style=\"text-align: justify;\">Nous pouvons maintenant appliquer le <em>patch<\/em> <code>ipipe<\/code> modifi\u00e9 au noyau Linux que nous avons t\u00e9l\u00e9charg\u00e9\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>.\/scripts\/prepare-kernel.sh --arch=arm --linux=..\/linux --ipipe=kernel\/cobalt\/arch\/arm\/patches\/ipipe-core-4.1.18-arm-8.patch<\/strong><\/pre>\n<p style=\"text-align: justify;\">Il y a quelques messages indiquant un d\u00e9calage entre le noyau standard et le noyau pour Raspberry Pi (<code>offset xx lines<\/code>) mais la commande <code>patch<\/code> arrive \u00e0 r\u00e9soudre ces probl\u00e8mes (<code>Hunk #x succeeded<\/code>).<\/p>\n<p style=\"text-align: justify;\">Un second <em>patch<\/em> va \u00eatre n\u00e9cessaire. Comme je l&rsquo;indiquais dans<a href=\"https:\/\/www.blaess.fr\/christophe\/2016\/05\/22\/xenomai-3-sur-raspberry-pi-2\/\"> cet article<\/a>, il s&rsquo;agit d&rsquo;une gestion des <em>timers<\/em> sp\u00e9cifique au Raspberry Pi.<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>cd ..<\/strong>\npi@raspberrypi:~$ <strong>wget <a href=\"https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/002-xenomai-3-on-bcm-2709.patch\">https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/002-xenomai-3-on-bcm-2709.patch<\/a><\/strong>\npi@raspberrypi:~$ <strong>cd linux<\/strong>\npi@raspberrypi:~\/linux$ <strong>patch -p1 &lt; ..\/002*<\/strong><\/pre>\n<p style=\"text-align: justify;\">Nous allons compiler ce noyau. Pour cela, j&rsquo;ai pr\u00e9par\u00e9 un fichier de configuration qui regroupe les options n\u00e9cessaires. Il s&rsquo;agit d&rsquo;une configuration un peu all\u00e9g\u00e9e pour r\u00e9duire le temps de compilation&nbsp;; s&rsquo;il vous manque des fonctionnalit\u00e9s, n&rsquo;h\u00e9sitez pas \u00e0 l&rsquo;\u00e9diter (avec <code>make menuconfig<\/code>) et la modifier\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/linux$ <strong>wget <a href=\"https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/linux.config\">https:\/\/www.blaess.fr\/christophe\/files\/article-2017-03-20\/linux.config<\/a><\/strong>\npi@raspberrypi:~\/linux$ <strong>mv linux.config .config<\/strong><\/pre>\n<p style=\"text-align: justify;\">Pour la compilation proprement dite, le Raspberry Pi 3 va \u00eatre tr\u00e8s sollicit\u00e9, d&rsquo;autant que nous occupons ses quatre c\u0153urs au maximum (option <code>-j 4<\/code> pour quatre jobs en parall\u00e8le).<br \/>\nVu la chaleur qu&rsquo;il d\u00e9gage, je vous conseille de le placer de fa\u00e7on \u00e0 ce que le processeur soit bien ventil\u00e9 (pas de bo\u00eetier ferm\u00e9). L&rsquo;id\u00e9al consiste \u00e0 placer sur le processeur un petit radiateur de dissipation comme <a href=\"http:\/\/amzn.to\/2mpmePT\" target=\"_blank\" rel=\"noopener\">celui-ci<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\">Pour un Raspberry Pi 3 dans un bo\u00eetier ferm\u00e9 sans dissipateur, j&rsquo;aurais tendance \u00e0 supprimer l&rsquo;option <code>-j 4<\/code> de la ligne suivante, afin de soulager la charge du processeur, au prix d&rsquo;un temps de compilation\u00a0 plus long.<\/p>\n<pre>pi@raspberrypi:~\/linux$ <strong>time make -j 4<\/strong>\n[...]\n  IHEX2FW firmware\/keyspan_pda\/keyspan_pda.fw\n  IHEX2FW firmware\/keyspan_pda\/xircom_pgs.fw\n\nreal    103m36.178s\nuser    277m51.420s\nsys     13m39.250s\npi@raspberrypi:~\/linux$ \npi@raspberrypi:~\/linux$<\/pre>\n<p style=\"text-align: justify;\">Comme vous le voyez, il faut environ 1h30 de compilation sur un Raspberry Pi 3 pour obtenir notre noyau. Ne soyez pas surpris de voir passer pendant la compilation des <em>warnings<\/em> indiquant du code douteux. Ils se produisent tous dans des modules sp\u00e9cifiques au Raspberry Pi&nbsp;; c&rsquo;est leur niveau in\u00e9gal de qualit\u00e9 qui a emp\u00each\u00e9 leur int\u00e9gration dans le noyau Linux standard.<\/p>\n<p style=\"text-align: justify;\">Nous allons installer ce nouveau kernel \u00e0 c\u00f4t\u00e9 de celui de la distribution Raspbian afin de pouvoir revenir en arri\u00e8re en cas de probl\u00e8me\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/ipipe$ <strong>sudo cp arch\/arm\/boot\/zImage \/boot\/kernel-xenomai.img<\/strong>\npi@raspberrypi:~\/ipipe$ <strong>sudo make modules_install<\/strong>\npi@raspberrypi:~\/ipipe$ <strong>sudo make dtbs_install<\/strong>\npi@raspberrypi:~\/ipipe$ <strong>ls \/boot\/dtbs\/4.1.21-xenomai+\/<\/strong>\nbcm2709-rpi-2-b.dtb  bcm2710-rpi-3-b.dtb  overlays<\/pre>\n<p style=\"text-align: justify;\">Le nouveau noyau, ses modules et son <em>device tree<\/em> \u00e9tant install\u00e9s, nous devons modifier le fichier de configuration du <em>bootloader<\/em> pour lui indiquer quel kernel charger\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/ipipe$ <strong>sudo nano \/boot\/config.txt<\/strong><\/pre>\n<p style=\"text-align: justify;\">Ajoutez les deux lignes suivantes \u00e0 la fin du fichier\u00a0:<\/p>\n<pre>kernel=kernel-xenomai.img\ndevice_tree=dtbs\/4.1.21-xenomai+\/bcm2710-rpi-3-b.dtb<\/pre>\n<p style=\"text-align: justify;\">Testons notre noyau incluant <code>ipipe<\/code>\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/ipipe$ <strong>sudo reboot<\/strong><\/pre>\n<p style=\"text-align: justify;\">Si le syst\u00e8me ne red\u00e9marre pas, montez la carte SD sur un PC, mettez en commentaire les deux lignes ci-dessus (en les pr\u00e9c\u00e9dant d&rsquo;un <code>'#'<\/code>) pour red\u00e9marrer sur la distribution Raspbian initiale. V\u00e9rifiez bien l&#8217;emplacement du noyau, du <em>device tree<\/em>, et le contenu du fichier <code>config.txt<\/code>.<\/p>\n<p style=\"text-align: justify;\">Le Raspberry Pi 3 ayant bien red\u00e9marr\u00e9 sur le noyau <em>patch\u00e9<\/em> avec <code>ipipe<\/code>, nous pouvons v\u00e9rifier sa pr\u00e9sence ainsi<\/p>\n<pre>raspberrypi login: <strong>pi<\/strong>\nPassword: <strong>raspberry<\/strong>\n[...]\npi@raspberrypi:~$ <strong>uname -a<\/strong>\nLinux raspberrypi 4.1.21-xenomai+ #1 SMP PREEMPT Sat Mar 18 10:12:21 UTC 2017 armv7l GNU\/Linux\npi@raspberrypi:~$ <strong>cat \/proc\/ipipe\/version<\/strong>\n8\npi@raspberrypi:~$ <strong>cat \/proc\/xenomai\/version<\/strong>\n3.0.3\npi@raspberrypi:~$<\/pre>\n<p style=\"text-align: justify;\">Le travail n&rsquo;est pas termin\u00e9 pour autant, nous devons compiler les biblioth\u00e8ques et les outils de tests de Xenomai.<\/p>\n<pre>pi@raspberrypi:~$ <strong>cd xenomai-3.0.3\/<\/strong>\npi@raspberrypi:~\/xenomai-3.0.3$ <strong>.\/scripts\/bootstrap<\/strong><\/pre>\n<p style=\"text-align: justify;\">Cette \u00e9tape reste silencieuse durant quelques minutes. Laissez le script travailler, il n&rsquo;est pas bloqu\u00e9.<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>.\/configure --enable-smp<\/strong>\npi@raspberrypi:~\/xenomai-3.0.3$ <strong>make<\/strong>\npi@raspberrypi:~\/xenomai-3.0.3$ <strong>sudo make install<\/strong><\/pre>\n<p style=\"text-align: justify;\">Deux heures apr\u00e8s le d\u00e9but de notre exp\u00e9rience, Xenomai est pr\u00eat \u00e0 \u00eatre utilis\u00e9. Le test le plus simple &#8211; et l&rsquo;un des plus repr\u00e9sentatifs &#8211; consiste \u00e0 mesure les fluctuations d&rsquo;un <em>timer<\/em>. Pour cela un outil est directement fourni. Je le lance en lui demandant de s&rsquo;ex\u00e9cuter pendant 60 secondes\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>sudo \/usr\/xenomai\/bin\/latency -T 60<\/strong>\n== Sampling period: 1000 us\n== Test mode: periodic user-mode task\n== All results in microseconds\nwarming up...\nRTT|  00:00:01  (periodic user-mode task, 1000 us period, priority 99)\nRTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst\nRTD|     -3.594|     -2.786|      1.822|       0|     0|     -3.594|      1.822\nRTD|     -3.647|     -2.923|      0.051|       0|     0|     -3.647|      1.822\nRTD|     -3.595|     -2.920|      1.613|       0|     0|     -3.647|      1.822\nRTD|     -3.648|     -2.946|     -0.106|       0|     0|     -3.648|      1.822\n[...]\nRTD|     -3.616|     -2.936|     -0.230|       0|     0|     -5.017|      1.863\nRTD|     -3.616|     -2.871|      1.488|       0|     0|     -5.017|      1.863\nRTD|     -3.669|     -2.848|      0.186|       0|     0|     -5.017|      1.863\n---|-----------|-----------|-----------|--------|------|-------------------------\nRTS|     -5.017|     -2.893|      1.863|       0|     0|    00:01:00\/00:01:00\npi@raspberrypi:~\/xenomai-3.0.3$<\/pre>\n<p style=\"text-align: justify;\">Ces premiers r\u00e9sultats sont int\u00e9ressants, ce sont les deux derni\u00e8res colonnes qui sont les plus significatives.<\/p>\n<p style=\"text-align: justify;\">La derni\u00e8re colonne indique la pire latence mesur\u00e9e, c&rsquo;est \u00e0 dire le pire retard de d\u00e9clenchement d&rsquo;un <em>timer<\/em> p\u00e9riodique. La valeur de 1,863 microsecondes est excellente, mais le syst\u00e8me est au repos et ce n&rsquo;est pas repr\u00e9sentatif.<br \/>\nL&rsquo;avant-derni\u00e8re valeur montre la meilleure latence observ\u00e9e. Elle est n\u00e9gative (-5,017 microsecondes), ce qui indique que le <em>timer<\/em> s&rsquo;est d\u00e9clench\u00e9 plus t\u00f4t que pr\u00e9vu. En effet, Xenomai anticipe les retards inh\u00e9rents au mat\u00e9riel en d\u00e9clenchant les <em>timers<\/em> un peu en avance. Ceci est int\u00e9ressant pour avoir une bonne pr\u00e9cision, mais n\u00e9cessite une calibration. Nous pouvons consulter l&rsquo;avance par d\u00e9faut\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>cat \/proc\/xenomai\/latency<\/strong> \n10052<\/pre>\n<p style=\"text-align: justify;\">La valeur est de 10052 nanosecondes soit 10,052 microsecondes. Tous les <em>timers<\/em> sont donc anticip\u00e9s de 10 microsecondes environ. Ceci peut \u00eatre int\u00e9ressant en production, mais dans un cadre exp\u00e9rimental, ce sont les vraies valeurs de latences qui m&rsquo;int\u00e9ressent. Je d\u00e9sactive donc cette avance\u00a0:<\/p>\n<pre>pi@raspberrypi:~\/xenomai-3.0.3$ <strong>sudo -i<\/strong>\nroot@raspberrypi:~# <strong>echo 0 &gt; \/proc\/xenomai\/latency<\/strong> \nroot@raspberrypi:~# <strong>cat \/proc\/xenomai\/latency<\/strong> \n0\nroot@raspberrypi:~# <strong>exit<\/strong><\/pre>\n<p style=\"text-align: justify;\">Je relance la mesure pendant une minute pour v\u00e9rifier\u00a0:<\/p>\n<pre>[...]\nRTD|      6.385|      7.073|      9.979|       0|     0|      5.405|     35.980\nRTD|      6.437|      7.077|     10.499|       0|     0|      5.405|     35.980\nRTD|      6.436|      7.074|      9.561|       0|     0|      5.405|     35.980\nRTD|      6.384|      7.083|      9.874|       0|     0|      5.405|     35.980\n---|-----------|-----------|-----------|--------|------|-------------------------\nRTS|      5.405|      7.142|     35.980|       0|     0|    00:01:00\/00:01:00<\/pre>\n<p style=\"text-align: justify;\">Presque 36 microsecondes de latence, voil\u00e0 qui est plus r\u00e9aliste (et tr\u00e8s bien, notons-le).<\/p>\n<p style=\"text-align: justify;\">Je vais lancer une nouvelle mesure pendant une heure en conservant un histogramme des latences observ\u00e9es\u00a0:<\/p>\n<pre>pi@raspberrypi:~$ <strong>sudo \/usr\/xenomai\/bin\/latency  -T 3600 -g histo-01.plot<\/strong>\n[...]\nRTD|      6.492|      7.145|      9.825|       0|     0|      4.229|     36.862\nRTD|      6.439|      7.146|      9.877|       0|     0|      4.229|     36.862\nRTD|      6.491|      7.166|      9.877|       0|     0|      4.229|     36.862\nHSH|--param|--samples-|--average--|---stddev--\nHSS|    min|      3600|      5.972|      0.205\nHSS|    avg|   3600017|      6.586|      0.870\nHSS|    max|      3600|      9.651|      1.783\n---|-----------|-----------|-----------|--------|------|-------------------------\nRTS|      4.229|      7.199|     36.862|       0|     0|    01:00:00\/01:00:00\npi@raspberrypi:~\/xenomai-3.0.3$<\/pre>\n<p style=\"text-align: justify;\">L&rsquo;histogramme peut \u00eatre dessin\u00e9 par Gnuplot. En abscisse la latence observ\u00e9e en microsecondes et en ordonn\u00e9e le nombre d&rsquo;occurrences de chaque classe. Le r\u00e9sultat est le suivant\u00a0:<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-01.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-4826\" src=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-01-300x225.png\" alt=\"Xenomai latency - Low system load\" width=\"300\" height=\"225\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-01-300x225.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-01-768x576.png 768w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-01.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Il est int\u00e9ressant de voir que tr\u00e8s peu d&rsquo;occurrences se produisent au-del\u00e0 de 10 microsecondes. Pour avoir un aper\u00e7u plus pr\u00e9cis sur ce qui se passe au-del\u00e0 de 13 microsecondes, il est pr\u00e9f\u00e9rable de faire une repr\u00e9sentation logarithmique en ordonn\u00e9e qui va dilater et rendre plus visibles les faibles occurrences&nbsp;:<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-02.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-4827\" src=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-02-300x225.png\" alt=\"Xenomai latency - Low system load\" width=\"300\" height=\"225\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-02-300x225.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-02-768x576.png 768w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-02.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">La mesure a \u00e9t\u00e9 faite alors que le syst\u00e8me \u00e9tait au repos, ce qui ne refl\u00e8te pas un comportement en production. Je relance la mesure en ajoutant une tr\u00e8s forte charge du syst\u00e8me avec le script <code>dohell<\/code> fourni avec Xenomai\u00a0:<\/p>\n<pre>pi@raspberrypi:~$ <strong>sudo \/usr\/xenomai\/bin\/dohell 3600 &amp; sudo \/usr\/xenomai\/bin\/latency  -T 3600 -g histo-02.plot<\/strong>\nRTD|      7.690|     14.418|     49.044|       0|     0|      5.644|     62.846\nRTD|      7.637|     14.028|     37.637|       0|     0|      5.644|     62.846\nRTD|      7.585|     14.297|     44.356|       0|     0|      5.644|     62.846\nRTD|      8.261|     14.237|     33.939|       0|     0|      5.644|     62.846\nHSH|--param|--samples-|--average--|---stddev--\nHSS|    min|      3600|      7.507|      0.799\nHSS|    avg|   3600006|     14.871|      5.938\nHSS|    max|      3600|     41.476|      4.462\n---|-----------|-----------|-----------|--------|------|-------------------------\nRTS|      5.644|     15.366|     62.846|       0|     0|    01:00:00\/01:00:00<\/pre>\n<p style=\"text-align: justify;\">En outre, des rafales de <code>ping<\/code> en mode <em>flood<\/em> provenaient r\u00e9guli\u00e8rement d&rsquo;un PC, produisant de nombreuses interruptions r\u00e9seau.<\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-03.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-4828\" src=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-03-300x225.png\" alt=\"Xenomai latency - High system load\" width=\"300\" height=\"225\" srcset=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-03-300x225.png 300w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-03-768x576.png 768w, https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2017\/03\/fig-03.png 800w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Nous voyons donc qu&rsquo;il y a une latence intrins\u00e8que de l&rsquo;ordre de 4.2 microsecondes au repos, et qu&rsquo;en fonction de la charge du syst\u00e8me elle peut aller jusqu&rsquo;\u00e0 une soixantaine de microsecondes. Ces r\u00e9sultats sont tout \u00e0 fait coh\u00e9rents avec ceux que l&rsquo;on peut obtenir avec Xenomai sur d&rsquo;autres cartes \u00e0 processeur ARM et correspondent bien \u00e0 ce que l&rsquo;on attend d&rsquo;un syst\u00e8me d&rsquo;exploitation complet comme Linux sous des contraintes temps r\u00e9el fortes.<\/p>\n<p style=\"text-align: justify;\">J&rsquo;ai \u00e9galement fait l&rsquo;essai d&rsquo;ajouter sur la ligne de commande du kernel les options <code>dwc_otg.fiq_enable=0<\/code> et <code>dwc_otg.fiq_fsm_enable=0<\/code> afin d&rsquo;\u00e9viter l&rsquo;utilisation des <em>Fast Interrupt Request<\/em> qui perturbent le d\u00e9terminisme du traitement des autres interruptions par Xenomai. Cela n&rsquo;a pas chang\u00e9 les performances observ\u00e9es.<\/p>\n<h1 style=\"text-align: justify;\">Conclusion<\/h1>\n<p style=\"text-align: justify;\">Xenomai 3.0.3 s&rsquo;installe bien sur un Raspberry Pi 3. La gestion des <em>timers<\/em> est pr\u00e9cise et pr\u00e9sente peu de latences, m\u00eame sous une forte charge syst\u00e8me et interruptive.<\/p>\n<p style=\"text-align: justify;\">Toutefois, il y a un point tr\u00e8s d\u00e9cevant&nbsp;: je ne suis pas arriv\u00e9 \u00e0 g\u00e9rer (avec l&rsquo;API <code>RTDM<\/code>) les <em>handlers<\/em> d&rsquo;interruptions des GPIO. Je suppose que le patch <code>ipipe<\/code> n&rsquo;a pas encore \u00e9t\u00e9 ajust\u00e9 pour le Raspberry Pi 3. Il va nous falloir patienter encore un peu, je continuerai \u00e0 utiliser des Raspberry Pi 2 pour les exemples de mes formations sur le temps r\u00e9el.<\/p>","protected":false},"excerpt":{"rendered":"<p>Depuis plusieurs mois, on m&rsquo;interroge r&eacute;guli&egrave;rement sur le support de Xenomai sur Raspberry Pi 3 tant durant mes sessions de formations sur Xenomai que dans des messages par mail. J&rsquo;avais l&rsquo;habitude de r&eacute;pondre que Xenomai ne fonctionnait pas encore sur ce mod&egrave;le de Raspberry Pi. Une remarque r&eacute;cente de Syrine dans les commentaires de l&rsquo;article [&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,10,11,14],"tags":[],"class_list":["post-4823","post","type-post","status-publish","format-standard","hentry","category-embarque","category-linux-2","category-microprocesseur","category-raspberry-pi","category-temps-reel"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4823","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=4823"}],"version-history":[{"count":21,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4823\/revisions"}],"predecessor-version":[{"id":6421,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/4823\/revisions\/6421"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=4823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=4823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=4823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}