{"id":973,"date":"2011-07-15T15:00:51","date_gmt":"2011-07-15T14:00:51","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=973"},"modified":"2011-07-15T15:00:51","modified_gmt":"2011-07-15T14:00:51","slug":"signes-de-vie-dun-systeme-embarque","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2011\/07\/15\/signes-de-vie-dun-systeme-embarque\/","title":{"rendered":"Signes de vie d&rsquo;un syst\u00e8me embarqu\u00e9"},"content":{"rendered":"<p style=\"text-align: justify;\">Suite \u00e0 une question pos\u00e9e par <em>Chriss<\/em> en <a title=\"http:\/\/www.blaess.fr\/christophe\/2011\/05\/20\/construire-son-systeme-personnel-sur-une-carte-pandaboard-3\/#comment-162\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/05\/20\/construire-son-systeme-personnel-sur-une-carte-pandaboard-3\/#comment-162\" target=\"_blank\">commentaire<\/a> d&rsquo;un <a title=\"Construire son syst\u00e8me personnel sur une carte Pandaboard (3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/05\/20\/construire-son-systeme-personnel-sur-une-carte-pandaboard-3\/\" target=\"_blank\">pr\u00e9c\u00e9dent article<\/a>, j&rsquo;ai eu envie de revenir rapidement sur un \u00e9l\u00e9ment essentiel pour la mise au point d&rsquo;un syst\u00e8me embarqu\u00e9&nbsp;: <strong>le signe de vie<\/strong>. Il s&rsquo;agit simplement de faire effectuer par le syst\u00e8me une t\u00e2che r\u00e9guli\u00e8re, avec un effet facilement observable par l&rsquo;utilisateur, afin de s&rsquo;assurer du bon fonctionnement global du dispositif. Ce signe de vie peut prendre diverses formes&nbsp;: signal \u00e9lectrique visible \u00e0 l&rsquo;oscilloscope sur une broche de test de la carte, trame vide \u00e9mise r\u00e9guli\u00e8rement sur un port r\u00e9seau, compteur incr\u00e9ment\u00e9 p\u00e9riodiquement dans une zone de m\u00e9moire partag\u00e9e, etc. Le signe de vie le plus simple \u00e0 mettre en oeuvre sur un syst\u00e8me embarqu\u00e9 est le clignotement d&rsquo;une LED.<\/p>\n<p>\n<!--more-->\n<\/p>\n<h1>Premier exemple sur carte Pandaboard<\/h1>\n<p style=\"text-align: justify;\">La carte Pandaboard, qui a d\u00e9j\u00e0 fait l&rsquo;objet de plusieurs articles, dispose de trois LEDs. Les deux premi\u00e8res se trouvent \u00e0 c\u00f4t\u00e9 du support pour m\u00e9moire MicroSD, la troisi\u00e8me est plac\u00e9e \u00e0 c\u00f4t\u00e9 du connecteur d&rsquo;alimentation. Cette derni\u00e8re n&rsquo;est pas contr\u00f4lable par l&rsquo;utilisateur, elle indique une surtension d&rsquo;alimentation. Nous allons donc nous int\u00e9resser uniquement aux LEDs 1 et 2.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-974\" title=\"LEDs sur carte Pandaboard\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/07\/IMG_4336.jpg\" alt=\"LEDs sur carte Pandaboard\" width=\"400\" height=\"269\" \/><\/p>\n<p style=\"text-align: justify;\">La premi\u00e8re m\u00e9thode pour acc\u00e9der \u00e0 ces LEDs, et en conserver un contr\u00f4le complet, va consister \u00e0 les piloter en programmant les <strong>broches GPIO<\/strong> (<em>General Purpose Input Output<\/em>) du processeur auxquelles les LEDs sont reli\u00e9es. Nous d\u00e9marrons la carte en utilisant un kernel Linux 3.0-rc7 compil\u00e9 (avec <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/config-linux-3.0-rc7-Panda\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/config-linux-3.0-rc7-Panda\" target=\"_blank\">ce fichier <code>.config<\/code><\/a>) sans support particulier pour les LEDs. Nous avons simplement activ\u00e9<\/p>\n<ul>\n<li style=\"text-align: justify;\">le support GPIO (dans le menu \u00ab\u00a0Device Drivers\u00a0\u00bb),<\/li>\n<li style=\"text-align: justify;\"> l&rsquo;interface \u00ab\u00a0<code>\/sys\/class\/gpio\/<\/code>\u00a0\u00bb (dans le menu \u00ab\u00a0GPIO Support\u00a0\u00bb activ\u00e9 pr\u00e9c\u00e9demment),<\/li>\n<li style=\"text-align: justify;\">et le driver pour <em>Texas Instruments TWL 4030<\/em> et ult\u00e9rieurs.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Connectons-nous sur la carte Pandaboard, et examinons le contenu du r\u00e9pertoire<code> \/sys\/class\/gpio\/<\/code>.<\/p>\n<pre>[~]$ <strong>telnet 192.168.3.152<\/strong>\nTrying 192.168.3.152...\nConnected to 192.168.3.152.\nEscape character is '^]'.\n(none) login: <strong>root<\/strong>\nPassword:\nBusyBox v1.18.4 (2011-06-22 12:27:46 CEST) built-in shell (ash)\nEnter 'help' for a list of built-in commands.\n(panda)[root]$ <strong>cd \/sys\/class\/gpio\/<\/strong>\n(panda)[gpio]$ <strong>ls<\/strong>\nexport       gpio62       gpiochip128  gpiochip32   gpiochip96\ngpio1        gpiochip0    gpiochip160  gpiochip64   unexport\n(panda)[gpio]$<\/pre>\n<p style=\"text-align: justify;\">Nous voyons que dans ce r\u00e9pertoire le noyau nous propose l&rsquo;acc\u00e8s \u00e0 certaines broches GPIO (1 et 62). Toutefois ce ne sont pas celles qui correspondent aux LEDs. En consultant <a title=\"http:\/\/www.blaess.fr\/files\/article-2011-07-15\/Panda_Board_Spec_REVEA1_04.pdf\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/Panda_Board_Spec_REVEA1_04.pdf\" target=\"_blank\">les sp\u00e9cifications de notre carte<\/a> (pages 48-49), nous voyons que les LEDs 1 et 2 sont connect\u00e9es aux GPIO 7 et 8. Demandons au noyau d&rsquo;exporter (c&rsquo;est-\u00e0-dire de nous rendre accessible) la broche GPIO 8. Nous remarquons alors que le contenu du r\u00e9pertoire <code>\/sys\/class\/gpio\/<\/code> est modifi\u00e9.<\/p>\n<pre>(panda)[gpio]$ <strong>echo 8 &gt; export <\/strong>\n(panda)[gpio]$ <strong>ls<\/strong>\nexport       gpio62       gpiochip0    gpiochip160  gpiochip64   unexport\ngpio1        <strong>gpio8<\/strong>        gpiochip128  gpiochip32   gpiochip96\n(panda)[gpio]$<\/pre>\n<p style=\"text-align: justify;\">L&rsquo;entr\u00e9e <code>gpio8<\/code> a fait son apparition, il s&rsquo;agit d&rsquo;un sous-r\u00e9pertoire contenant des fichiers virtuels, dont les contenus repr\u00e9sentent des param\u00e8tres internes du noyau. Voyons donc la direction par d\u00e9faut de la broche GPIO 8.<\/p>\n<pre>(panda)[gpio]$ <strong>ls gpio8\/<\/strong>\nactive_low  edge        subsystem   value\ndirection   power       uevent\n(panda)[gpio]$ <strong>cat gpio8\/direction <\/strong>\nin\n(panda)[gpio]$<\/pre>\n<p style=\"text-align: justify;\">Le processeur initialise par d\u00e9faut ses broches GPIO en entr\u00e9e, pour des raisons de s\u00e9curit\u00e9. Elles pr\u00e9sentent alors un \u00e9tat de haute imp\u00e9dance, et les manipulations externes (mises \u00e0 la masse ou au +5V, court-circuit, etc.) n&rsquo;ont pas d&rsquo;influence. Toutefois, pour piloter la LED 2, il faut basculer la broche en sortie.<\/p>\n<pre>(panda)[gpio]$ <strong>echo out &gt; gpio8\/direction <\/strong>\n(panda)[gpio]$<\/pre>\n<p style=\"text-align: justify;\">Nous pouvons alors allumer et \u00e9tendre la LED 2 ainsi&nbsp;:<\/p>\n<pre>(panda)[gpio]$ <strong>echo 1 &gt; gpio8\/value<\/strong>\n(panda)[gpio]$ <strong>echo 0 &gt; gpio8\/value<\/strong>\n(panda)[gpio]$<\/pre>\n<p style=\"text-align: justify;\">Il devient alors facile de programmer un petit signe de vie en utilisant un script shell simple&nbsp;:<\/p>\n<pre style=\"padding-left: 30px;\"><strong>\/usr\/bin\/heartbeat.sh<\/strong>\n#! \/bin\/sh\n\necho 7 &gt; \/sys\/class\/gpio\/export\necho 8 &gt; \/sys\/class\/gpio\/export\necho out &gt; \/sys\/class\/gpio\/gpio7\/direction\necho out &gt; \/sys\/class\/gpio\/gpio8\/direction\n\nwhile true\ndo\n        echo 1 &gt; \/sys\/class\/gpio\/gpio7\/value\n        usleep 150000\n        echo 0 &gt; \/sys\/class\/gpio\/gpio7\/value\n        usleep 100000\n        echo 1 &gt; \/sys\/class\/gpio\/gpio8\/value\n        usleep 150000\n        echo 0 &gt; \/sys\/class\/gpio\/gpio8\/value\n        usleep 100000\n        usleep 500000\ndone<\/pre>\n<p style=\"text-align: justify;\">Lanc\u00e9 en arri\u00e8re-plan dans le script de d\u00e9marrage <code>\/etc\/init.d\/rcS<\/code> ainsi<\/p>\n<pre>  \/usr\/bin\/heartbeat.sh &amp;<\/pre>\n<p style=\"text-align: justify;\">ce petit script nous permet de contr\u00f4ler visuellement que le syst\u00e8me est op\u00e9rationnel, et que l&rsquo;ordonnancement des processus fonctionne normalement (sans qu&rsquo;une t\u00e2che temps-r\u00e9el ne consomme tout le CPU disponible par exemple).<\/p>\n<h1>Deuxi\u00e8me exemple, sur carte IGEP<\/h1>\n<p style=\"text-align: justify;\">Sur la carte IGEP v2, que nous avons \u00e9galement abord\u00e9e pr\u00e9c\u00e9dement, il existe deux LEDs bicolores. La couleur verte de l&rsquo;une d&rsquo;entre elles est programmable par l&rsquo;I2C. Les trois autres couleurs sont accessibles via les GPIO 26, 27, et 28. \u00c0 noter&nbsp;: lorsque les couleurs rouge et verte de la m\u00eame LED sont allum\u00e9es simultan\u00e9ment, la couleur visible est jaune orang\u00e9e. On peut donc obtenir un signe de vie visuellement plus riche en jouant sur les changements de couleur.<\/p>\n<p>Voici un <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/sdv-igepv2.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/sdv-igepv2.c\" target=\"_blank\">petit programme C<\/a> qui assure un scintillement permanent des LEDs et remplit un r\u00f4le similaire au premier script ci-dessus.<\/p>\n<pre style=\"padding-left: 30px;\"><strong>sdv-igepv2.c<\/strong>\n#include &lt;fcntl.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;unistd.h&gt;\n\nint main(void)\n{\n\tint i;\n\tint compteur = 0;\n\tint fd[3];\n\tchar buffer[80];\n\n\tfd[0] = open(\"\/sys\/class\/gpio\/gpio26\/value\", O_WRONLY);\n\tfd[1] = open(\"\/sys\/class\/gpio\/gpio27\/value\", O_WRONLY);\n\tfd[2] = open(\"\/sys\/class\/gpio\/gpio28\/value\", O_WRONLY);\n\tif ((fd[0] &lt; 0) || (fd[1] &lt; 0) || (fd[2] &lt; 0)) {\n\t\tperror(\"open\");\n\t\texit(EXIT_FAILURE);\n\t}\n\twhile(1) {\n\t\tfor (i = 0; i &lt; 3; i ++) { \t\t\tsprintf(buffer, \"%d\", (compteur &gt;&gt; i) &amp; 1);\n\t\t\twrite(fd[i], buffer, 2);\n\t\t}\n\t\tcompteur ++;\n\t\tcompteur %= 8;\n\t\tusleep(100000);\n\t}\n}<\/pre>\n<h1>Troisi\u00e8me exemple,  avec les triggers du noyau Linux<\/h1>\n<p style=\"text-align: justify;\">Le kernel Linux nous offre une interface pour acc\u00e9der aux LEDs de notre syst\u00e8me, et propose m\u00eame des <em>triggers<\/em>, c&rsquo;est-\u00e0-dire des comportements pr\u00e9d\u00e9finis pour leur clignotement. Pour que le noyau puisse acc\u00e9der aux LEDs et nous offrir un moyen de les contr\u00f4ler, il est n\u00e9cessaires de s\u00e9lectionner les options suivantes lors de sa compilation (cliquez sur l&rsquo;aper\u00e7u ci-dessous). Dans le sous-menu \u00ab\u00a0LED Support\u00a0\u00bb du menu \u00ab\u00a0Device Drivers\u00a0\u00bb.<\/p>\n<p><a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/07\/Capture.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-977\" title=\"make ARCH=arm menuconfig\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/07\/Capture-300x250.png\" alt=\"make ARCH=arm menuconfig\" width=\"300\" height=\"250\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Vous pouvez utiliser directement <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/config-linux-3.0-rc7-Panda-GPIO-LED\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-07-15\/config-linux-3.0-rc7-Panda-GPIO-LED\" target=\"_blank\">ce fichier<\/a> de configuration <code>.config<\/code> pour Linux 3.0-rc7 sur Pandaboard.<\/p>\n<p style=\"text-align: justify;\">Dans cette configuration, nous ajoutons le support pour les LEDs pilot\u00e9es par un GPIO, ainsi que la configuration sp\u00e9cifique \u00e0 la plateforme. Cette configuration se trouve dans le fichier <code>arch\/arm\/mach-omap2\/board-omap4panda.c<\/code> des sources du kernel.<\/p>\n<pre style=\"padding-left: 30px;\">[...]\nstatic struct gpio_led gpio_leds[] = {\n        {\n                .name                   = \"pandaboard::status1\",\n                .default_trigger        = \"heartbeat\",\n                .gpio                   = 7,\n        },\n        {\n                .name                   = \"pandaboard::status2\",\n                .default_trigger        = \"mmc0\",\n                .gpio                   = 8,\n        },\n};\n\nstatic struct gpio_led_platform_data gpio_led_info = {\n        .leds           = gpio_leds,\n        .num_leds       = ARRAY_SIZE(gpio_leds),\n};\n[...]<\/pre>\n<p style=\"text-align: justify;\">On y retrouve bien les num\u00e9ros de GPIO que nous avons utilis\u00e9s plus t\u00f4t. Apr\u00e8s compilation du noyau et <em>reboot<\/em> de la carte, nous trouvons une nouvelle interface dans <code>\/sys<\/code>.<\/p>\n<pre>(panda)[root]$ <strong>cd \/sys\/class\/<\/strong>\n(panda)[class]$ <strong>ls<\/strong>\nbacklight     display       graphics      i2c-dev       <strong>leds<\/strong>          misc          net           rtc           scsi_host     ubi           vtconsole\nbdi           firmware      hwmon         input         mdio_bus      mmc_host      power_supply  scsi_device   spi_master    usb_device\nblock         gpio          i2c-adapter   lcd           mem           mtd           regulator     scsi_disk     tty           vc\n(panda)[class]$<\/pre>\n<p style=\"text-align: justify;\">Allons voir le contenu de cette classe LEDs.<\/p>\n<pre>(panda)[class]$ <strong>cd leds\/<\/strong>\n(panda)[leds]$ <strong>ls<\/strong>\npandaboard::status1  pandaboard::status2\n(panda)[leds]$ <strong>ls pandaboard::status1\/<\/strong>\nbrightness      device          max_brightness  power           subsystem       trigger         uevent\n(panda)[leds]$<\/pre>\n<p style=\"text-align: justify;\">Nous y trouvons deux sous-r\u00e9pertoires, un pour chaque LED, avec les noms observ\u00e9s plus haut dans le code source du noyau. Le pseudo-fichier <code>trigger<\/code> indique l&rsquo;\u00e9venement qui d\u00e9clenche le changement d&rsquo;\u00e9tat de la LED.<\/p>\n<pre>(panda)[leds]$ <strong>cat pandaboard::status1\/trigger<\/strong>\nnone nand-disk mmc0 mmc1 timer [heartbeat] gpio default-on\n(panda)[leds]$<\/pre>\n<p style=\"text-align: justify;\">Par d\u00e9faut il s&rsquo;agit du <em>trigger<\/em> <strong>heartbeat<\/strong>, qui simule un battement de coeur, dont la fr\u00e9quence augmente en fonction de la charge du syst\u00e8me, mais on peut en choisir d&rsquo;autres&nbsp;:<\/p>\n<ul>\n<li><code>none<\/code> nous donne l&rsquo;acc\u00e8s direct \u00e0 la LED depuis l&rsquo;entr\u00e9e <code>brightness<\/code> du sous-r\u00e9pertoire,<\/li>\n<li><code>nand-disk<\/code> fait scintiller la LED lors de l&rsquo;acc\u00e8s \u00e0 la m\u00e9moire Flash interne (inutilis\u00e9e sur mon syst\u00e8me),<\/li>\n<li><code>mmc0<\/code> et <code>mmc1<\/code> signalent les acc\u00e8s aux partitions de la carte MicroSD, rappelant les LEDs d&rsquo;acc\u00e8s aux disques durs,<\/li>\n<li><code>timer<\/code> allume et \u00e9teint la LED p\u00e9riodiquement&nbsp;: elle reste allum\u00e9e pendant la dur\u00e9e en millisecondes indiqu\u00e9e dans <code>delay_on<\/code> puis s&rsquo;\u00e9teint pendant <code>delay_off<\/code> millisecondes,<\/li>\n<li><code>gpio<\/code> a un comportement proche de celui de <code>none<\/code>, l&rsquo;entr\u00e9e <code>brightness<\/code> permettant d&rsquo;allumer ou d&rsquo;\u00e9teindre \u00e0 volont\u00e9 la LED.<\/li>\n<li><code>default-on<\/code>: allumer la LED d\u00e8s le <em>boot<\/em>.<\/li>\n<\/ul>\n<p>Voici par exemple la configuration pour une LED clignotant \u00e0 10 Hz, et dont la dur\u00e9e d&rsquo;allumage est de 10 ms \u00e0 chaque cycle.<\/p>\n<pre>(panda)[leds]$<strong> echo timer &gt; pandaboard::status2\/trigger<\/strong>\n(panda)[leds]$ <strong>echo 10 &gt; pandaboard::status2\/delay_on<\/strong>\n(panda)[leds]$ <strong>echo 90 &gt; pandaboard::status2\/delay_off<\/strong>\n(panda)[leds]$<\/pre>\n<h1>Conclusion<\/h1>\n<p style=\"text-align: justify;\">Nous voyons que les cartes embarqu\u00e9es sur lesquelles on fait couramment fonctionner Linux nous permettent ais\u00e9ment de disposer d&rsquo;un petit signe de vie en employant des LEDs. Bien s\u00fbr ces LEDs peuvent servir \u00e0 d&rsquo;autres utilisations (indication de l&rsquo;\u00e9tat d&rsquo;un serveur, de la disponibilit\u00e9 des ressources, etc.). L&rsquo;avantage d&rsquo;un signe de vie programm\u00e9 dans l&rsquo;espace utilisateur sur celui int\u00e9gr\u00e9 dans le kernel, est de nous indiquer r\u00e9ellement si le syst\u00e8me est utilisable pour les applications, et pas seulement le bon fonctionnement de l&rsquo;espace noyau. J&rsquo;en emploie \u00e9galement sur les syst\u00e8mes embarquant des applications temps-r\u00e9el, afin de v\u00e9rifier facilement si CPU est surcharg\u00e9 ou s&rsquo;il reste du temps processeur pour les t\u00e2ches temps-partag\u00e9.<\/p>","protected":false},"excerpt":{"rendered":"<p>Suite &agrave; une question pos&eacute;e par Chriss en commentaire d&rsquo;un pr&eacute;c&eacute;dent article, j&rsquo;ai eu envie de revenir rapidement sur un &eacute;l&eacute;ment essentiel pour la mise au point d&rsquo;un syst&egrave;me embarqu&eacute;&nbsp;: le signe de vie. Il s&rsquo;agit simplement de faire effectuer par le syst&egrave;me une t&acirc;che r&eacute;guli&egrave;re, avec un effet facilement observable par l&rsquo;utilisateur, afin de [&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],"tags":[],"class_list":["post-973","post","type-post","status-publish","format-standard","hentry","category-embarque","category-linux-2","category-microprocesseur"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/973","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=973"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/973\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}