tag:blogger.com,1999:blog-30147124664643270722024-02-19T05:09:03.011+01:00Coloc's BarMon expérience sur les systèmes embarquésColoc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-3014712466464327072.post-36886635657170804042014-01-06T21:04:00.002+01:002014-01-06T21:04:31.017+01:00Gstreamer et Serveur de streaming RTSP sur Raspberry Pi (2eme Partie)<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLEQlXJ2btb1Kbbfmyv-OtKHGzppVpEQmEK2lHWQRLJFM6bUn5GW6r4T52yncyTf2bdEIxCi4PSeqxwEBMQLhWP0zdFhYoMcVCsO2uWNAznAyp_x0C7JRzbfgXF1K68aXOvY-3f38kxrk/s1600/530px-Gstreamer-logo.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLEQlXJ2btb1Kbbfmyv-OtKHGzppVpEQmEK2lHWQRLJFM6bUn5GW6r4T52yncyTf2bdEIxCi4PSeqxwEBMQLhWP0zdFhYoMcVCsO2uWNAznAyp_x0C7JRzbfgXF1K68aXOvY-3f38kxrk/s1600/530px-Gstreamer-logo.svg.png" height="92" width="320" /></a></div>
Je vais partir du postulat que vous connaissez les bases de GStreamer (source, sink, pipeline, etc ...) sinon, je vous conseille fortement d'aller jeter un coup d'œil sur <a href="http://blog.nicolargo.com/2009/01/introduction-a-gstreamer-le-framework-multimedia.html">le blog de nicolargo</a> section GStreamer. Vous y trouverez toutes les informations nécessaires à la compréhension de la suite du billet.<br />
Je me suis même inspiré d'un de ses billets (<a href="http://blog.nicolargo.com/2009/02/jai-streame-avec-gstreamer.html">j'ai streamé avec GStreamer</a>) pour rédiger le mien.<br />
<br />
Les tests réalisés sont :<br />
<br />
<ul style="text-align: left;">
<li>Streaming UDP avec encodage vidéo Theora d'une vidéo test (Mire)</li>
<li>Streaming UDP avec encodage vidéo H264 d'une vidéo test (Mire)</li>
<li>Streaming TCP avec encodage vidéo H264 d'une vidéo test (Mire)</li>
<li>Streaming RTP/RTCP avec encodage vidéo H264 d'une vidéo test (Mire)</li>
<li>Streaming RTSP avec encodage vidéo H264 d'une vidéo test (Mire)</li>
<li>Utilisation de la Webcam PS3 EyeToy. </li>
</ul>
<br />
<br />
<a name='more'></a><br />
<br />
<h3 style="text-align: left;">
Préambule</h3>
<br />
On vérifie que tous les plugins nécessaires à la diffusion de notre vidéo test sont disponibles sur la raspberry pi et, pour cela, on va lancer la commande <span style="font-family: Courier New, Courier, monospace;"><b>gst-inspect-1.0.</b></span><br />
<br />
<pre class="brush: shell;"># gst-inspect-1.0 |grep test
audiotestsrc: audiotestsrc: Audio test source
videotestsrc: videotestsrc: Video test source
</pre>
<br />
Il est possible d'inspecter chaque élément et de déterminer les propriétés nécessaires de chaque élément de notre chaîne avec la commande <span style="font-family: Courier New, Courier, monospace;"><b>gst-inspect-1.0</b></span>.<br />
Nous utiliserons la propriété <span style="font-family: Courier New, Courier, monospace;"><b>is-live</b></span> de <span style="font-family: Courier New, Courier, monospace;"><b>videotestsrc</b></span> pour nos tests.<br />
Il est également possible de jouer avec le paramètre <span style="font-family: Courier New, Courier, monospace;"><b>pattern</b></span> pour générer différents types de vidéos test.<br />
<br />
<pre class="brush: shell;"># gst-inspect-1.0 videotestsrc
Factory Details:
Rank none (0)
Long-name Video test source
Klass Source/Video
Description Creates a test video stream
Author David A. Schleef <ds schleef.org="">
Plugin Details:
Name videotestsrc
Description Creates a test video stream
Filename /usr/lib/gstreamer-1.0/libgstvideotestsrc.so
Version 1.2.0
License LGPL
Source module gst-plugins-base
Source release date 2013-09-24
Binary package GStreamer Base Plug-ins source release
Origin URL Unknown package origin
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstBaseSrc
+----GstPushSrc
+----GstVideoTestSrc
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-raw
format: { I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
video/x-bayer
format: { bggr, rggb, grbg, gbrg }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
Element Flags:
no flags set
Element Implementation:
Has change_state() function: gst_base_src_change_state
Element has no clocking capabilities.
Element has no indexing capabilities.
Element has no URI handling capabilities.
Pads:
SRC: 'src'
Implementation:
Has getrangefunc(): gst_base_src_getrange
Has custom eventfunc(): gst_base_src_event
Has custom queryfunc(): gst_base_src_query
Has custom iterintlinkfunc(): gst_pad_iterate_internal_links_default
Pad Template: 'src'
Element Properties:
name : The name of the object
flags: readable, writable
String. Default: "videotestsrc0"
parent : The parent of the object
flags: readable, writable
Object of type "GstObject"
blocksize : Size in bytes to read per buffer (-1 = default)
flags: readable, writable
Unsigned Integer. Range: 0 - 4294967295 Default: 4096
num-buffers : Number of buffers to output before sending EOS (-1 = unlimited)
flags: readable, writable
Integer. Range: -1 - 2147483647 Default: -1
typefind : Run typefind before negotiating
flags: readable, writable
Boolean. Default: false
do-timestamp : Apply current stream time to buffers
flags: readable, writable
Boolean. Default: false
pattern : Type of test pattern to generate
flags: readable, writable
Enum "GstVideoTestSrcPattern" Default: 0, "smpte"
(0): smpte - SMPTE 100% color bars
(1): snow - Random (television snow)
(2): black - 100% Black
(3): white - 100% White
(4): red - Red
(5): green - Green
(6): blue - Blue
(7): checkers-1 - Checkers 1px
(8): checkers-2 - Checkers 2px
(9): checkers-4 - Checkers 4px
(10): checkers-8 - Checkers 8px
(11): circular - Circular
(12): blink - Blink
(13): smpte75 - SMPTE 75% color bars
(14): zone-plate - Zone plate
(15): gamut - Gamut checkers
(16): chroma-zone-plate - Chroma zone plate
(17): solid-color - Solid color
(18): ball - Moving ball
(19): smpte100 - SMPTE 100% color bars
(20): bar - Bar
(21): pinwheel - Pinwheel
(22): spokes - Spokes
timestamp-offset : An offset added to timestamps set on buffers (in ns)
flags: readable, writable
Integer64. Range: -9223372036854775808 - 9223372036854775807 Default: 0
is-live : Whether to act as a live source
flags: readable, writable
Boolean. Default: false
k0 : Zoneplate zero order phase, for generating plain fields or phase offsets
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kx : Zoneplate 1st order x phase, for generating constant horizontal frequencies
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
ky : Zoneplate 1st order y phase, for generating contant vertical frequencies
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kt : Zoneplate 1st order t phase, for generating phase rotation as a function of time
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kxt : Zoneplate x*t product phase, normalised to kxy/256 cycles per vertical pixel at width/2 from origin
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kyt : Zoneplate y*t product phase
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kxy : Zoneplate x*y product phase
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kx2 : Zoneplate 2nd order x phase, normalised to kx2/256 cycles per horizontal pixel at width/2 from origin
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
ky2 : Zoneplate 2nd order y phase, normailsed to ky2/256 cycles per vertical pixel at height/2 from origin
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
kt2 : Zoneplate 2nd order t phase, t*t/256 cycles per picture
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
xoffset : Zoneplate 2nd order products x offset
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
yoffset : Zoneplate 2nd order products y offset
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
foreground-color : Foreground color to use (big-endian ARGB)
flags: readable, writable, controllable
Unsigned Integer. Range: 0 - 4294967295 Default: 4294967295
background-color : Background color to use (big-endian ARGB)
flags: readable, writable, controllable
Unsigned Integer. Range: 0 - 4294967295 Default: 4278190080
horizontal-speed : Scroll image number of pixels per frame (positive is scroll to the left)
flags: readable, writable
Integer. Range: -2147483648 - 2147483647 Default: 0
</ds></pre>
<br />
Nous allons utiliser l'encodeur vidéo H264 fourni avec la librairie <a href="http://fr.wikipedia.org/wiki/OpenMAX">OpenMAX</a>.<br />
<br />
H.264, ou MPEG-4 AVC (Advanced Video Coding), ou MPEG-4 Part 10, est une norme de codage vidéo développée conjointement par l'UIT-T Q.6/SG16 Video Coding Experts Group (VCEG) ainsi que l'ISO/CEI Moving Picture Experts Group (MPEG) et est le produit d'un effort de partenariat connu sous le nom Joint Video Team (JVT). La norme UIT-T H.264 et la norme ISO/CEI MPEG-4 Part 10 (ISO/CEI 14496-10) sont techniquement identiques, et la technologie employée est aussi connue sous le nom AVC, pour Advanced Video Coding. (source <a href="http://fr.wikipedia.org/wiki/H.264">wikipedia</a>)<br />
<br />
<pre class="brush: shell; highlights: [11]"># gst-inspect-1.0 |grep omx
omx: omxmpeg2videodec: OpenMAX MPEG2 Video Decoder
omx: omxmpeg4videodec: OpenMAX MPEG4 Video Decoder
omx: omxh263dec: OpenMAX H.263 Video Decoder
omx: omxh264dec: OpenMAX H.264 Video Decoder
omx: omxtheoradec: OpenMAX Theora Video Decoder
omx: omxvp8dec: OpenMAX VP8 Video Decoder
omx: omxmjpegdec: OpenMAX MJPEG Video Decoder
omx: omxvc1dec: OpenMAX WMV Video Decoder
omx: omxh264enc: OpenMAX H.264 Video Encoder
</pre>
<br />
Nous allons utiliser l'encodeur vidéo <a href="http://www.theora.org/">Theora</a>.<br />
<br />
Theora est un format de compression vidéo ouvert et sans brevets promu par la fondation Xiph.org. C'est un des composants de leur projet de format d'encapsulation Ogg, qui a pour but de créer un ensemble de standards ouverts concernant le traitement de signaux multimédia (son, vidéo). Theora fournit la vidéo. (source <a href="http://fr.wikipedia.org/wiki/Theora">wikipedia</a>)<br />
<br />
<pre class="brush: shell; highlights: [7]"># gst-inspect-1.0 |grep theora
rtp: rtptheoradepay: RTP Theora depayloader
rtp: rtptheorapay: RTP Theora payloader
typefindfunctions: video/x-theora: no extensions
theora: theoradec: Theora video decoder
theora: theoraenc: Theora video encoder
theora: theoraparse: Theora video parser
omx: omxtheoradec: OpenMAX Theora Video Decoder
</pre>
<br />
<h4 style="text-align: left;">
Debug</h4>
<br />
Il est possible d'avoir différentes traces de debug supplémentaires de tous les éléments d'une chaîne ou seulement quelques-uns en particulier, grâce à la variable d'environnement GST_DEBUG.<br />
<br />
<pre class="brush: shell;"># GST_DEBUG=1
# gst-launch-1.0 ....
</pre>
<br />
Le numéro correspond au niveau de traces de debug désirées.<br />
<ul style="text-align: left;">
<li>1 : ERROR - Traces de toutes les erreurs fatales</li>
<li>2 : WARNING - Traces de tous les warning </li>
<li>3 : FIXME - Traces de tous les FIXME (morceau de code pas complètement implémenté)</li>
<li>4 : INFO - Traces tous les message d'informations</li>
<li>5 : DEBUG - Traces tous les messages de debug</li>
<li>6 : LOG - Traces tous les messages de log</li>
<li>7 : TRACE - Traces tous les messages</li>
<li>9 : MEMDUMP - Traces tous les messages de memory dump.</li>
</ul>
<div>
Ca peut vite devenir le bordel car si vous tracez tous les messages sur votre console, vous n'allez pas vous y retrouver, donc il est possible de tracer que quelques éléments d'une chaîne. exemple :</div>
<br />
<pre class="brush: shell;"># GST_DEBUG="videotestsrc:7, omxh264enc:1"
# gst-launch-1.0 -v videotestsrc is-live=1 ! omxh264enc ! mpegtsmux ! udpsink host=192.168.1.5 port=9999
</pre>
<br />
Sur cet exemple, je ne vais tracer que tous les messages provenant de l'élément <span style="font-family: Courier New, Courier, monospace;"><b>videotestsrc</b></span> et toutes les erreurs provenant de l'élément <span style="font-family: Courier New, Courier, monospace;"><b>omxh264enc</b></span>.<br />
Ce qui va réduire, considérablement, les messages affichés sur la console.<br />
<br />
<br />
<h3 style="text-align: left;">
Mire + Encodeur vidéo Theora + streaming UDP</h3>
<br />
<br />
<u>Sur le PC avec GStreamer :</u><br />
<br />
Commande à lancer avant celle sur la raspberry pi :<br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v udpsrc port=9998 ! oggdemux ! theoradec ! autovideosink sync=false
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
</pre>
<br />
<u>Sur la raspberry pi :</u><br />
<br />
On peut jouer avec le bitrate (75, 150, 300, ...)<br />
theroaenc : encodeur video<br />
oggmux : conteneur video <br />
<br />
Conteneur video : un format de fichier pouvant contenir divers types de données. Les spécifications du format conteneur décrivent la façon dont sont organisées les données à l'intérieur du fichier. Les conteneurs sont beaucoup utilisés dans le domaine du multimédia ; ils peuvent contenir des flux vidéo et/ou audio, en général compressés à l'aide de codecs normalisés. Des conteneurs plus avancés permettent également de stocker des sous-titres, des éléments de chapitrage, ainsi que d'autres informations sur le média (appelées métadonnées ou tags). (source <a href="http://fr.wikipedia.org/wiki/Format_conteneur">wikipedia</a>)<br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v videotestsrc is-live=1 ! theoraenc bitrate=300 ! video/x-theora, framerate=15/1 ! oggmux ! udpsink host=192.168.1.5 port=9998
</pre>
<br />
La mire apparaît sur le PC avec un saccadement de la vidéo due a une charge d'encodage trop importante sur la raspberry pi :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsWCZXN6k8RwzI5GhSFt9GtzEiMrh0CBaXr0DwL1BygVoeElJSxBlnpjh3Q0r9HIhp5IMR7yk_oNVOiXEa1MCtUABCH1js2ZEoLOfLVvi44ENPdhpW2dyELu8YcsMrxQAvcxL91gvHGHM/s1600/gstreamer_udp_mire_theora_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsWCZXN6k8RwzI5GhSFt9GtzEiMrh0CBaXr0DwL1BygVoeElJSxBlnpjh3Q0r9HIhp5IMR7yk_oNVOiXEa1MCtUABCH1js2ZEoLOfLVvi44ENPdhpW2dyELu8YcsMrxQAvcxL91gvHGHM/s1600/gstreamer_udp_mire_theora_1.png" height="400" width="373" /></a></div>
<br />
la charge CPU de la raspberry pi nous montre que toutes les ressources du processeur sont utilisées pour l'encodage vidéo et l'envoie des trames UDP.<br />
<br />
<pre class="brush: shell; highlights: [5];">Mem: 33192K used, 378276K free, 0K shrd, 1412K buff, 18952K cached
CPU: 99% usr 0% sys 0% nic 0% idle 0% io 0% irq 0% sirq
Load average: 1.16 0.54 0.23 2/52 132
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
122 111 root S 37176 9% 99% gst-launch-1.0 -v videotestsrc is-live=1 ! theoraenc bitrate=300 ! video/x-theora, framerate=15/1 ! oggmux ! udpsink host=192.168.1.5 port=9998
132 127 root R 2348 1% 0% top
126 88 root S 2144 1% 0% /usr/sbin/dropbear
17 2 root SW 0 0% 0% [kworker/0:1]
40 2 root SW< 0 0% 0% [kworker/0:1H]
103 1 root S 20468 5% 0% /usr/sbin/vcfiled
111 110 root S 2348 1% 0% -sh
127 126 root S 2348 1% 0% -sh
108 1 root S 2268 1% 0% /sbin/getty -L ttyAMA0 115200 vt100
</pre>
<br />
Il est également possible d'afficher la mire sur un lecteur vidéo comme VLC :<br />
<br />
Voici le type d'URL à utiliser pour lire le flux vidéo :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLxiSLu9-K9qq00KdstrULybria9k48TTUMbx0G9H3wsK4eDBJgFoSz0ZZ5N6BRD-2NYBW55niy7JW7IXr7O_RxI5eDL80eAKVtwQa_bJckYJIrtEVnI-hI0vyybLb6AXI3pqJy3rOxQk/s1600/vlc_udp_conf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLxiSLu9-K9qq00KdstrULybria9k48TTUMbx0G9H3wsK4eDBJgFoSz0ZZ5N6BRD-2NYBW55niy7JW7IXr7O_RxI5eDL80eAKVtwQa_bJckYJIrtEVnI-hI0vyybLb6AXI3pqJy3rOxQk/s1600/vlc_udp_conf.png" height="265" width="400" /></a></div>
<br />
et vous obtenez le même résultat qu'avec GStreamer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8x9BER8PIIu5356oPTH1a2Vk7g1uw_SOgimuyXcomH7l7P4r3uC7-V79Cu3OtLiRjdRp14r03D3VEreG3ywJ35cf-eQM0hdmNU5KYa79ED0_pIJ3aBcp18JATYyQG4AUJGXtOpu1KzKg/s1600/vlc_udp_mire_theora_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8x9BER8PIIu5356oPTH1a2Vk7g1uw_SOgimuyXcomH7l7P4r3uC7-V79Cu3OtLiRjdRp14r03D3VEreG3ywJ35cf-eQM0hdmNU5KYa79ED0_pIJ3aBcp18JATYyQG4AUJGXtOpu1KzKg/s1600/vlc_udp_mire_theora_1.png" height="400" width="373" /></a></div>
<br />
<br />
<h3 style="text-align: left;">
Mire + Encodeur vidéo H264 + streaming UDP</h3>
<div>
<br />
<br /></div>
<div>
Pour exploiter au mieux les capacités de la raspberry pi, on va encoder la vidéo test avec le GPU de la raspberry pi et ainsi libérer de la charge CPU pour d'autres traitements.</div>
<br />
<u>Sur le PC avec GStreamer :</u><br />
<br />
Commande à lancer avant celle sur la raspberry pi :<br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v udpsrc port=9999 ! decodebin ! autovideosink sync=false
</pre>
<br />
<u>Sur la raspbeery pi :</u><br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v videotestsrc is-live=1 ! omxh264enc ! mpegtsmux ! udpsink host=192.168.1.5 port=9999
</pre>
<br />
La mire apparaît sur le PC sans aucun saccadement maintenant :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeuJVe7-B3HJbNv7dun23k1qXTZz2GPpFPTMnNut6DAsWf03g7N6Eevcq_IK4x3MnfUYdybkCZ97VlLZJqFT5C9p7Lu73D3BGI_rX2xCGvoKJkUJHd8D5iQO8TcSIixCgMWrhlFdl3AYA/s1600/gstreamer_udp_mire_h264_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeuJVe7-B3HJbNv7dun23k1qXTZz2GPpFPTMnNut6DAsWf03g7N6Eevcq_IK4x3MnfUYdybkCZ97VlLZJqFT5C9p7Lu73D3BGI_rX2xCGvoKJkUJHd8D5iQO8TcSIixCgMWrhlFdl3AYA/s1600/gstreamer_udp_mire_h264_1.png" height="400" width="373" /></a></div>
<br />
La charge CPU est maintenant plus acceptable :<br />
<br />
<pre class="brush: shell; highlights: [5];">Mem: 28188K used, 383280K free, 0K shrd, 3852K buff, 12616K cached
CPU: 34% usr 1% sys 0% nic 63% idle 0% io 0% irq 0% sirq
Load average: 0.72 0.42 0.18 1/61 201
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
184 107 root S 99m 25% 35% gst-launch-1.0 -v videotestsrc is-live=1 ! omxh264enc ! mpegtsmux ! udpsink host=192.168.1.5 port=9999
30 2 root SW< 0 0% 1% [VCHIQ-0]
201 197 root R 2348 1% 0% top
196 84 root S 2144 1% 0% /usr/sbin/dropbear
7 2 root SW 0 0% 0% [rcu_preempt]
100 1 root S 20468 5% 0% /usr/sbin/vcfiled
107 106 root S 2348 1% 0% -sh
197 196 root S 2348 1% 0% -sh
105 1 root S 2268 1% 0% /sbin/getty -L ttyAMA0 115200 vt100
1 0 root S 2264 1% 0% init
</pre>
<br />
<br />
<h3 style="text-align: left;">
Mire + Encodeur vidéo H264 + streaming TCP</h3>
<br />
<br />
<u>Sur le PC avec GStreamer :</u><br />
<br />
Le PC va servir de serveur TCP donc il sera nécessaire de le lancer avant le client TCP de la raspberry pi.<br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v tcpserversrc host=192.168.1.5 port=9876 ! decodebin ! autovideosink sync=false
</pre>
<br />
<u>Sur la raspberry pi :</u><br />
<br />
La raspberry pi va être configurée comme client TCP.<br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v videotestsrc is-live=1 ! omxh264enc ! mpegtsmux ! tcpclientsink host=192.168.1.5 port=9876
</pre>
<br />
La mire apparaît sur le PC :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdygs_yDoXCTgC4fz0Iywjq0G0S-zhplcWpuzKWmTm-ovxQMAbZvU35UTr2Cv8OW9ckw3ZjKUVLmgVRFWiCnrxN_KFcw6KLG2qdI54dHs6nfoQ2U6lA1NDxMas7NUxLHlBM82dxTchvFo/s1600/gstreamer_tcp_mire_h264_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdygs_yDoXCTgC4fz0Iywjq0G0S-zhplcWpuzKWmTm-ovxQMAbZvU35UTr2Cv8OW9ckw3ZjKUVLmgVRFWiCnrxN_KFcw6KLG2qdI54dHs6nfoQ2U6lA1NDxMas7NUxLHlBM82dxTchvFo/s1600/gstreamer_tcp_mire_h264_1.png" height="400" width="373" /></a></div>
<br />
<br />
La charge CPU est sensiblement la même qu'en UDP.<br />
<br />
<pre class="brush: shell;">Mem: 28172K used, 383296K free, 0K shrd, 3864K buff, 12704K cached
CPU: 36% usr 2% sys 0% nic 60% idle 0% io 0% irq 0% sirq
Load average: 0.91 0.68 0.35 1/59 262
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
251 107 root S 92996 23% 36% gst-launch-1.0 -v videotestsrc is-live=1 ! omxh264enc ! mpegtsmux ! tcpclientsink host=192.168.1.5 port=9876
30 2 root SW< 0 0% 1% [VCHIQ-0]
262 197 root R 2348 1% 0% top
196 84 root S 2144 1% 0% /usr/sbin/dropbear
7 2 root SW 0 0% 0% [rcu_preempt]
3 2 root SW 0 0% 0% [ksoftirqd/0]
100 1 root S 20468 5% 0% /usr/sbin/vcfiled
107 106 root S 2348 1% 0% -sh
197 196 root S 2348 1% 0% -sh
105 1 root S 2268 1% 0% /sbin/getty -L ttyAMA0 115200 vt100
1 0 root S 2264 1% 0% init
</pre>
<br />
<br />
<h3>
Mire + Encodeur vidéo H264 + streaming RTP/RTCP</h3>
<div>
<br /></div>
<div>
<br /></div>
<div>
RTP (Real-Time Transport Protocol) et RTCP (Real-Time Transport Control Protocol) sont des protocoles de transport de données ayant la particularité d'avoir des propriétés temps-réel.</div>
<div>
Le but du RTP est de fournir au client connecté à celui-ci, une séquence de paquets permettant de reconstituer l'informations originelle (audio ou vidéo) même si les paquets réseaux sont arrivés dans le mauvais ordre.</div>
<div>
Le but du RTCP est de fournir des informations de qualité de service (QoS), qualité de transmission, pertes de paquets etc ... </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGWNaTJzwOlc2BOFZJB68aJl7JZLkr6q18XzsE4OXMilKhQCOK-A3YRy8m9MT-0D7nPqVabX41xz5SnWt5spE0LS0CiAZZeRXiH57uWbDDE1irseHw1bHIV2TN9ksjdMLAWUnTfUDRROU/s1600/RTP_Protocol.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGWNaTJzwOlc2BOFZJB68aJl7JZLkr6q18XzsE4OXMilKhQCOK-A3YRy8m9MT-0D7nPqVabX41xz5SnWt5spE0LS0CiAZZeRXiH57uWbDDE1irseHw1bHIV2TN9ksjdMLAWUnTfUDRROU/s1600/RTP_Protocol.gif" height="137" width="400" /></a></div>
<div>
<br />
Pour lancer une diffusion de notre flux vidéo test avec le protocole RTP/RTCP, nous allons avoir besoin de récupérer le champs <span style="font-family: Courier New, Courier, monospace;"><b>caps</b></span> (long : capabilities) du serveur, décrivant le type de media streamé, et le fournir au client dans sa chaîne.<br />
<br /></div>
<div>
<u>Sur la raspberry pi :</u><br />
<br />
<pre class="brush: shell;"># gst-launch-1.0 -v videotestsrc is-live=1 ! 'video/x-raw, format=I420, width=320, height=240, framerate=(fraction)15/1' ! omxh264enc ! rtph264pay name=pay0 pt=96 config-interval=2 ! udpsink host=192.168.1.5 port=5000
</pre>
<br />
Au niveau des traces sur la console, nous avons quelque chose comme :<br />
<br />
<pre class="brush: shell;">[...]
/GstPipeline:pipeline0/GstRtpH264Pay:pay0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQKD9APEiagA\=\,KO4CXLAA", payload=(int)96, ssrc=(uint)401291925, timestamp-offset=(uint)1224952945, seqnum-offset=(uint)25331
/GstPipeline:pipeline0/GstUDPSink:udpsink0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQKD9APEiagA\=\,KO4CXLAA", payload=(int)96, ssrc=(uint)401291925, timestamp-offset=(uint)1224952945, seqnum-offset=(uint)25331
[...]
</pre>
<br />
Et le caps à récupérer est la dernière ligne : <span style="font-family: Courier New, Courier, monospace;"><b>caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQKD9APEiagA\=\,KO4CXLAA", payload=(int)96, ssrc=(uint)401291925, timestamp-offset=(uint)1224952945, seqnum-offset=(uint)25331</b></span><br />
<br />
<u>Sur le PC avec GStreamer :</u><br />
<br />
<pre class="brush: shell;">gst-launch-1.0 -v udpsrc port=5000 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQKD9APEiagA\=\,KO4CXLAA", payload=(int)96, ssrc=(uint)401291925, timestamp-offset=(uint)1224952945, seqnum-offset=(uint)25331' ! rtph264depay ! decodebin ! autovideosink sync=false
</pre>
<br />
<u>Sur le PC avec VLC :</u><br />
<br />
Pour VLC, pour la réception d'un flux RTP, nous créons un fichier session SDP, par exemple : test.sdp.<br />
<br />
<pre class="brush: shell;">v=0
o=- 1188340656180883 1 IN IP4 127.0.0.1
s=Session streamed by GStreamer
i=server.sh
t=0 0
a=tool:GStreamer
a=type:broadcast
m=video 5000 RTP/AVP 96
c=IN IP4 127.0.0.1
a=rtpmap:96 H264/90000
</pre>
<br />
et il suffit simplement d'ouvrir le fichier SDP avec VLC pour voir apparaître la mire.<br />
<br />
<br />
<h3>
Mire + Encodeur vidéo H264 + Serveur RTSP</h3>
</div>
<div>
<br />
<br /></div>
<div>
Le package gst-rtsp-server fournit quelques exemples et notamment un (test-readme.c) qui nous servira de modèle pour ce petit serveur test, donc a partir de ce fichier source, nous allons créer un petit projet (fichier source et makefile).</div>
<br />
Le Makefile :<br />
<br />
<pre class="brush: shell;">BUILDROOT_PATH = VOTRE CHEMIN VERS BUILDROOT
SYSROOT_PATH = $(BUILDROOT_PATH)/output/host/usr/arm-buildroot-linux-gnueabi/sysroot
CC = $(BUILDROOT_PATH)/output/host/usr/bin/arm-bcm2708-linux-gnueabi-gcc
CFLAGS = -I$(SYSROOT_PATH)/usr/include -I$(SYSROOT_PATH)/usr/include/gstreamer-1.0 -I$(SYSROOT_PATH)/usr/include/glib-2.0 -
I$(SYSROOT_PATH)/usr/lib/glib-2.0/include -I$(BUILDROOT_PATH)/output/build/gst1-rtsp-server-master -W -Wall
LDFLAGS = -L$(SYSROOT_PATH)/usr/lib -lgio-2.0 -lglib-2.0 -lgobject-2.0 -lgstreamer-1.0 -lgstrtspserver-1.0
EXEC = test-readme
OBJS = test-readme.o
all: $(EXEC)
$(EXEC):$(OBJS)
@$(CC) -o $(EXEC) $^ $(LDFLAGS)
%.o:%.c
@echo [CC] $^
@$(CC) -o $@ -c $^ $(CFLAGS)
clean:
@echo [CLEAN]
@rm *.o $(EXEC) -f
</pre>
<br />
Voici le fichier source test-readme.c modifié pour y intégrer l'encodeur openMAX, on remarque que la fonction <span style="font-family: Courier New, Courier, monospace;"><b>gst_rtsp_media_factory_set_launch()</b></span> du serveur va utiliser une chaîne d'éléments comme avec la commande <span style="font-family: Courier New, Courier, monospace;"><b>gst-launch-1.0</b></span>.<br />
<br />
<pre class="brush: c;">int
main (int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* create a server instance */
server = gst_rtsp_server_new ();
/* Configure server to accept connections on the given address */
//gst_rtsp_server_set_address(server, "127.0.0.1");
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points (server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d.
* Each element with pay%d names will be a stream */
factory = gst_rtsp_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory, "( videotestsrc is-live=1 ! video/x-raw, format=I420, width=320, height=240, framerate=(fraction)15/1 ! omxh264enc ! video/x-h264, profile=(string)high, level=(string)4 ! rtph264pay name=pay0 pt=96 config-interval=2 )");
gst_rtsp_media_factory_set_shared (factory, TRUE);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
/* don't need the ref to the mapper anymore */
g_object_unref (mounts);
/* attach the server to the default maincontext */
gst_rtsp_server_attach (server, NULL);
/* start serving */
g_print ("stream ready at rtsp://%s:%s/test\n",
gst_rtsp_server_get_address(server),
gst_rtsp_server_get_service(server));
g_main_loop_run (loop);
return 0;
}
</pre>
<br />
On compile notre petit projet :<br />
<br />
<pre class="brush: shell;"># make
[CC] test-readme.c
</pre>
<br />
puis on le transfert sur la raspberry pi :<br />
<br />
<pre class="brush: shell;"># scp -P 22 test-readme root@192.168.1.10:
</pre>
<br />
On utiliser les traces de debug sur la console :<br />
<br />
<pre class="brush: shell;"># export GST_DEBUG="rtsp*:7"
# ./test-readme
0:00:00.196330000 121 0xe98e00 DEBUG rtspmountpoints rtsp-mount-points.c:131:gst_rtsp_mount_points_init:<gstrtspmountpoints xe98dc0=""> created
0:00:00.200053000 121 0xe98e00 INFO rtspmountpoints rtsp-mount-points.c:326:gst_rtsp_mount_points_add_factory: adding media factory 0xe9f430 for path /test
0:00:00.201302000 121 0xe98e00 DEBUG rtspserver rtsp-server.c:803:gst_rtsp_server_create_socket:<gstrtspserver xe398a0=""> getting address info of 0.0.0.0/8554
0:00:00.210187000 121 0xe98e00 DEBUG rtspserver rtsp-server.c:887:gst_rtsp_server_create_socket:<gstrtspserver xe398a0=""> opened sending server socket
0:00:00.211642000 121 0xe98e00 DEBUG rtspserver rtsp-server.c:915:gst_rtsp_server_create_socket:<gstrtspserver xe398a0=""> listening on server socket 0xea1808 with queue of 5
stream ready at rtsp://0.0.0.0:8554/test
</gstrtspserver></gstrtspserver></gstrtspserver></gstrtspmountpoints></pre>
<br />
Après le lancement du serveur, on se rend compte que lorsqu'aucun client n'est connecté, la raspberry pi n'encode rien et n'envoie aucune donnée.<br />
<br />
<pre class="brush: shell;">Mem: 28168K used, 383300K free, 0K shrd, 6036K buff, 11636K cached
CPU: 0% usr 0% sys 0% nic 99% idle 0% io 0% irq 0% sirq
Load average: 0.03 0.03 0.04 1/50 128
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
128 123 root R 2348 1% 0% top
122 84 root S 2144 1% 0% /usr/sbin/dropbear
39 2 root SW 0 0% 0% [mmcqd/0]
100 1 root S 20468 5% 0% /usr/sbin/vcfiled
121 107 root S 7632 2% 0% ./test-readme
107 106 root S 2348 1% 0% -sh
123 122 root S 2348 1% 0% -sh
105 1 root S 2268 1% 0% /sbin/getty -L ttyAMA0 115200 vt100
1 0 root S 2264 1% 0% init
</pre>
<br />
<u>Client RTSP sur PC avec VLC :</u><br />
<br />
Ouvrir le flux réseau avec l'adresse : rtsp://192.168.1.10:8554/test<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwvtuUZh1pVTo3FJs70w9zdYuxxb1ZLAunx2Eem7Q1O8qZulpKtTF0kzNu5HqQsA98SEP_g3zzt7fnmKIulHulY6cEK10793-PtuvP0t8egi2yPBPzC8LjxZZ5osLaJGZo6HLAEMdnuCg/s1600/vlc_rtsp_conf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwvtuUZh1pVTo3FJs70w9zdYuxxb1ZLAunx2Eem7Q1O8qZulpKtTF0kzNu5HqQsA98SEP_g3zzt7fnmKIulHulY6cEK10793-PtuvP0t8egi2yPBPzC8LjxZZ5osLaJGZo6HLAEMdnuCg/s1600/vlc_rtsp_conf.png" height="265" width="400" /></a></div>
<br />
Ensuite la mire apparaît.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8_6jgts-wvSfe8VBbFwftUO5KFdqG6oTOrJN1SpXPUwlpRGPuPnCgPpfT4d7DlIqHjsQ6AhnT77aFrou0IcUCdHsCLVahqQXjzetqaijt5EKOX2HgPwH3vjRbWXXQjkTY8XzrJ4jj18g/s1600/vlc_rtsp_mire.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8_6jgts-wvSfe8VBbFwftUO5KFdqG6oTOrJN1SpXPUwlpRGPuPnCgPpfT4d7DlIqHjsQ6AhnT77aFrou0IcUCdHsCLVahqQXjzetqaijt5EKOX2HgPwH3vjRbWXXQjkTY8XzrJ4jj18g/s1600/vlc_rtsp_mire.png" height="400" width="373" /></a></div>
<br />
Au niveau des traces du serveur, on voit apparaître les différentes opérations réalisées avant la diffusion de la mire.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtX5PZHwnIAuxfac3bsqtgLQzJFjXgALTHaL3IeFsZwlCBgSGS1dU7daMNQS3CBgli-a6SBdbg2-jEl-eynvUjaFYLZmEMxyf3oV_FNVgRRy_L2_hY6_cv9Z5Pflt3PCC2_1pqIt5JNHM/s1600/RTSP_Operation.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtX5PZHwnIAuxfac3bsqtgLQzJFjXgALTHaL3IeFsZwlCBgSGS1dU7daMNQS3CBgli-a6SBdbg2-jEl-eynvUjaFYLZmEMxyf3oV_FNVgRRy_L2_hY6_cv9Z5Pflt3PCC2_1pqIt5JNHM/s1600/RTSP_Operation.gif" height="320" width="400" /></a></div>
<br />
<br />
<h3 style="text-align: left;">
Utilisation de la Webcam PS3 EyeToy</h3>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCwpYUt8mvhovkYFpPtCvPBWQ-U7uiDTCmLPvtYnNjHCuxM70AQMao2xLO3uoS0RSEU2ImI0joek3R__U0fEKwmfH5o1vn9UjeVQZPbvtM0T-bLCxX0AMVvn3RtzI5LGq911QhfKeQR7s/s1600/ps3eyetoy.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCwpYUt8mvhovkYFpPtCvPBWQ-U7uiDTCmLPvtYnNjHCuxM70AQMao2xLO3uoS0RSEU2ImI0joek3R__U0fEKwmfH5o1vn9UjeVQZPbvtM0T-bLCxX0AMVvn3RtzI5LGq911QhfKeQR7s/s1600/ps3eyetoy.jpg" height="320" width="277" /></a></div>
<br />
La webcam PS3 EyeToy est basé sur un capteur vidéo omnivision OV534, donc il va falloir chargé le bon driver ainsi que ses dépendances.<br />
<br />
<pre class="brush: shell;"># modprobe gspca_ov534
# lsmod
Module Size Used by Not tainted
gspca_ov534 9162 0
gspca_main 20125 1 gspca_ov534
videodev 90333 2 gspca_ov534,gspca_main
media 9512 1 videodev
</pre>
<br />
Pour l'utiliser avec GStreamer, il suffit de remplacer :<br />
<br />
<pre class="brush: shell;">videotestsrc is-live=1
</pre>
<br />
par :<br />
<br />
<pre class="brush: shell;">v4l2src device=/dev/video0 ! videoconvert ! video/x-raw, format=(string)I420, width=640, height=480, framerate=(fraction)30/1
</pre>
<br />
Amusez-vous bien !!!<br />
<br /></div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com3Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-86813779171296024992014-01-03T15:44:00.002+01:002014-01-03T15:44:45.727+01:00Crosstool-NG 1.19.0 et Make 4.0<div dir="ltr" style="text-align: left;" trbidi="on">
Ce petit billet pour faire part des quelques modifications à apporter à la dernière <a href="http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.19.0.tar.bz2">release (1.19.0)</a> de crosstool-NG pour créer une chaîne de compilation croisée pour la raspberry pi sur une distribution arch-linux x86_64.<br />
<br />
Les outils abordés sont :<br />
<br />
<ul style="text-align: left;">
<li>crosstool-NG version 1.19.0</li>
<li>eglibc version 2.16</li>
<li>GNU make version 4.0</li>
</ul>
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">
Gestion de la nouvelle version de GNU make</h3>
<br />
La première erreur est que la version 4.0 de <span style="font-family: Courier New, Courier, monospace;"><b>make</b></span> n'est pas gérée par <span style="font-family: Courier New, Courier, monospace;"><b>eglibc</b></span>, donc il va falloir modifier le fichier configure pour remédier à cette erreur.<br />
<br />
<pre class="brush: shell;">[INFO ] Installing kernel headers: done in 6.93s (at 06:41)
[INFO ] =================================================================
[INFO ] Installing C library headers & start files
...................
[CFG ] checking for arm-bcm2708-linux-gnueabi-gcc... (cached) arm-bcm2708-linux-gnueabi-gcc
[CFG ] checking version of arm-bcm2708-linux-gnueabi-gcc ... 4.8.2, ok
[CFG ] checking for gnumake... no
[CFG ] checking for gmake... no
[CFG ] checking for make... make
[CFG ] checking version of make... 4.0, bad
[CFG ] checking for gnumsgfmt... no
[CFG ] checking for gmsgfmt... no
[CFG ] checking for msgfmt... msgfmt
[CFG ] checking version of msgfmt... 0.18.3, ok
[CFG ] checking for makeinfo... makeinfo
[CFG ] checking version of makeinfo... 5.2, ok
[CFG ] checking for sed... sed
[CFG ] checking version of sed... v. ?.??, bad
[CFG ] checking for arm-bcm2708-linux-gnueabi-readelf... arm-bcm2708-linux-gnueabi-readelf
[CFG ] checking for arm-bcm2708-linux-gnueabi-nm... nm
[CFG ] checking for autoconf... autoconf
[CFG ] checking whether autoconf works... yes
[ERROR] configure: error:
[CFG ] *** These critical programs are missing or too old: make
[CFG ] *** Check the INSTALL file for required versions.
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Installing C library headers & start files'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@257]
[ERROR] >> called from: do_libc_backend_once[scripts/build/libc/glibc-eglibc.sh-common@347]
[ERROR] >> called from: do_libc_backend[scripts/build/libc/glibc-eglibc.sh-common@143]
[ERROR] >> called from: do_libc_start_files[scripts/build/libc/glibc-eglibc.sh-common@60]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@632]
[ERROR] >>
[ERROR] >> For more info on this error, look at the file: 'build.log'
[ERROR] >> There is a list of known issues, some with workarounds, in:
[ERROR] >> '/home/vbenoit/PERSO/raspberry_pi/crosstool-ng/install/share/doc/crosstool-ng/ct-ng.1.19.0/B - Known issues.txt'
[ERROR]
[ERROR] (elapsed: 6:46.20)
</pre>
<br />
Voici le patch (<a href="https://drive.google.com/file/d/0B6WDjVnTAZgFOXRtUWpFZTdBOXc/edit?usp=sharing">eglibc_2_16_make_4.patch</a>) à appliquer au fichier configure de eglibc pour résoudre l'erreur.<br />
<br />
<pre class="brush: shell;">--- a/configure 2014-01-03 14:08:59.027618540 +0100
+++ b/configure 2014-01-03 14:10:24.897615610 +0100
@@ -4936,7 +4936,7 @@
ac_prog_version=`$MAKE --version 2&>1 | sed -n 's/^.*GNU Make[^0-9]*\([0-9][0-9.]*\).*$/\1/p'`
case $ac_prog_version in
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
- 3.79* | 3.[89]*)
+ 3.79* | 3.[89]* | 4.0*)
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
</pre>
<br />
<h3 style="text-align: left;">
Erreur tls_model</h3>
<br />
Une autre erreur peut survenir surtout sur avec une distribution 64 bits arch-linux avec un message d'erreur de ce type :<br />
<br />
<pre class="brush: shell;">[ERROR] configure: error: support for the tls_model attribute is required
</pre>
<br />
Il y aurait quelques conflits avec les options <span style="font-family: Courier New, Courier, monospace;"><b>-mcpu=arm1176jzf-s</b></span> et <span style="font-family: Courier New, Courier, monospace;"><b>-march=armv6z</b></span> qui sont deux attributs redondants. En supprimant le premier de la configuration dans le menuconfig (Target Options -> Emit assembly for CPU et Target Options -> Tune for CPU), cela résout le problème.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmrWxEHjmAJ1k9mvrhZPElDGyEnrifgLKWRM3Qxardj1zATKZmK_2RyW0TREsYr4ZdtH34mCCs18YiZNvapeni4qCsDqYoMszhAP_3Ji8Puc8AhqUjUtrKZSvLc7eRUH5E8w8tJNS6j8A/s1600/ctng_rpi.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmrWxEHjmAJ1k9mvrhZPElDGyEnrifgLKWRM3Qxardj1zATKZmK_2RyW0TREsYr4ZdtH34mCCs18YiZNvapeni4qCsDqYoMszhAP_3Ji8Puc8AhqUjUtrKZSvLc7eRUH5E8w8tJNS6j8A/s1600/ctng_rpi.png" height="640" width="596" /></a></div>
<br />
<br /></div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-81198981336963810852013-12-27T10:59:00.000+01:002014-01-07T09:12:18.916+01:00Gstreamer et Serveur de streaming RTSP sur Raspberry Pi (1ere Partie)<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://img.linuxfr.org/img/687474703a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f7468756d622f642f64622f4773747265616d65722d6c6f676f2e7376672f35333070782d4773747265616d65722d6c6f676f2e7376672e706e67/530px-Gstreamer-logo.svg.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://img.linuxfr.org/img/687474703a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f7468756d622f642f64622f4773747265616d65722d6c6f676f2e7376672f35333070782d4773747265616d65722d6c6f676f2e7376672e706e67/530px-Gstreamer-logo.svg.png" height="91" width="320" /></a></div>
Ce tutoriel va nous permettre de construire, grâce à une raspberry pi, un serveur de streaming vidéo et/ou audio et notamment diffuser un flux vidéo provenant d'une caméra. N'ayant pas encore en ma possession le module caméra de la raspberry pi, je vais utiliser une webcam USB du commerce compatible avec la raspberry pi (<a href="http://elinux.org/RPi_USB_Webcams">USB Webcam</a>).<br />
<br />
Le serveur de streaming que nous allons installer est basé sur le protocole RTSP (Real Time Streaming Protocol). Ce protocole RTSP est implémenté sur la couche 7 du modèle OSI (couche applicative) et utilise les couches de transports RTP/RTCP pour faire circuler les flux de données sur un réseau IP.<br />
L'avantage du RTSP est de diffuser un ou plusieurs flux seulement quand un client se connecte au serveur et ce même client peut interagir avec le flux de données (lecture, pause, retour en arrière, en avant, etc ...).<br />
<br />
Ce tutoriel est divisé en deux billets, Ce billet est consacré à la construction et l'installation d'un serveur RTSP basé sur le framework GStreamer sur notre raspberry pi et le second billet est consacré à l'introduction de GStreamer avec des cas simples d'utilisation et notamment la démonstration de notre serveur RTSP.<br />
<br />
Pour ce billet, nous allons travailler avec :<br />
<ul style="text-align: left;">
<li>Notre environnement de compilation : buildroot-2013.08.1.</li>
<li>Kernel 3.12.0.</li>
<li>Chaîne de compilation croisée construite avec crosstool-NG 1.15.0.</li>
<li>Packages rpi-userland et rpi-firmware.</li>
<li>Framework GStreamer version 1.2.0 et ses plugins standards (base, bad, ugly et good) en version 1.2.0.</li>
<li>Plugin OMX (OpenMAX IL wrapper) version Git, qui nous permettra d'encoder les vidéos grâce aux GPU de la raspberry pi.</li>
<li>Serveur RTSP version Git aussi.</li>
</ul>
<div>
<a name='more'></a><br /></div>
<h3 style="text-align: left;">
Préambule</h3>
<div style="text-align: left;">
<br /></div>
<h4 style="text-align: left;">
Chaîne de compilation croisée</h4>
<div>
<br /></div>
<br />
Pour ce projet, nous n'allons pas utiliser la chaîne de compilation croisée construite avec buildroot (basée sur uclibc) pour la simple raison que j'ai rencontré quelques (voir beaucoup ...) difficultés dans la gestion des threads glib2, que je n'ai pas encore pu résoudre.<br />
<br />
Nous allons utiliser une chaîne de compilation croisée construite avec crosstool-NG déjà créée et se trouvant sur le github de raspberry pi.<br />
<br />
Voici les commandes à utiliser :<br />
<br />
<pre class="brush: shell;"># git clone https://github.com/raspberrypi/tools
# cd tools
# ls arm-bcm2708
arm-bcm2708-linux-gnueabi arm-bcm2708hardfp-linux-gnueabi gcc-linaro-arm-linux-gnueabihf-raspbian
</pre>
<br />
Nous allons utiliser la chaîne de compilation croisée <b><span style="font-family: Courier New, Courier, monospace;">arm-bcm2708hardfp-linux-gnueabi </span></b>pour ce projet.<br />
<br />
Si ce n'est pas déjà fait, ne pas oublier de configurer correctement buildroot pour la raspberry pi avec la commande :<br />
<br />
<pre class="brush: shell;"># make rpi_defconfig
</pre>
<br />
Entrer dans le menu de buildroot:<br />
<br />
<pre class="brush: shell;"># make menuconfig
</pre>
<br />
Sur le menu de buildroot, cocher l'option <b><span style="font-family: Courier New, Courier, monospace;">EABIhf</span></b> pour <span style="font-family: Courier New, Courier, monospace;"><b>Target ABI</b></span> :<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2GPSHgROX0bNaAB4BUf8hxZb_GUYaddwPauKSRp59cojD1IBy-gXqGXS54uFKEqj2gfxCjSVJ0B997k6t1oA1aiuflN6Jv6DDi6FxFI1WkrJK9NbzbwpPNY9yLssduyKO7Fr8ICxIUjQ/s1600/buildroot_ext_crosstool_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2GPSHgROX0bNaAB4BUf8hxZb_GUYaddwPauKSRp59cojD1IBy-gXqGXS54uFKEqj2gfxCjSVJ0B997k6t1oA1aiuflN6Jv6DDi6FxFI1WkrJK9NbzbwpPNY9yLssduyKO7Fr8ICxIUjQ/s1600/buildroot_ext_crosstool_1.png" height="640" width="596" /></a></div>
<br />
<br />
Se rendre dans le sous menu <span style="font-family: Courier New, Courier, monospace;"><b>Toolchain</b></span>. <br />
<br />
<ul style="text-align: left;">
<li>Sur le champ <b><span style="font-family: Courier New, Courier, monospace;">Toolchain type</span></b>, choisir <span style="font-family: Courier New, Courier, monospace;"><b>External Toolchain</b></span></li>
<li>Sur le champ <b><span style="font-family: Courier New, Courier, monospace;">Toolchain origin</span></b>, choisir <span style="font-family: Courier New, Courier, monospace;"><b>Pre-installed toolchain</b></span></li>
<li>Sur le champ <span style="font-family: Courier New, Courier, monospace;"><b>Toolchain path</b></span>, entrer le chemin vers la chaîne de compilation précédemment téléchargée (TOOLS_PATH/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi)</li>
<li>Sur le champ <span style="font-family: Courier New, Courier, monospace;"><b>Toolchain prefix</b></span>, entrer le préfixe <span style="font-family: Courier New, Courier, monospace;"><b>arm-bcm2708hardfp-linux-gnueabi</b></span></li>
<li>Sur le champ <span style="font-family: Courier New, Courier, monospace;"><b>External toolchain C library</b></span>, choisir <b><span style="font-family: Courier New, Courier, monospace;">glibc/eglibc</span></b></li>
<li>Cocher les cases <span style="font-family: Courier New, Courier, monospace;"><b>Toolchain has RPC support?</b></span>, "<b><span style="font-family: Courier New, Courier, monospace;">Toolchain has C++ support?</span></b> et <span style="font-family: Courier New, Courier, monospace;"><b>Enable MMU support</b></span></li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFqE6MJ0qEFo7EMZ-2AA-DsxSzfQHTKfu8A5hNFwdp_kUcD5_SQe59PgNA3LMW7oKP7FhxaL3koFs0eiefNXzdaDpce-KU2TF-h5rOmA-zWU45SxzVethhJUhu812Rmj_F0fLV_mbvb3A/s1600/buildroot_ext_crosstool_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFqE6MJ0qEFo7EMZ-2AA-DsxSzfQHTKfu8A5hNFwdp_kUcD5_SQe59PgNA3LMW7oKP7FhxaL3koFs0eiefNXzdaDpce-KU2TF-h5rOmA-zWU45SxzVethhJUhu812Rmj_F0fLV_mbvb3A/s1600/buildroot_ext_crosstool_2.png" height="640" width="598" /></a></div>
<br />
<br />
L'environnement de compilation est maintenant prêt. On va passer à la suite.<br />
<br />
<h3 style="text-align: left;">
Compilation et Installation de GStreamer et de ses plugins</h3>
<br />
Par défaut, les versions de GStreamer et de ses packages sont 1.0.8 avec cette version de buildroot, il va donc falloir modifier chaque makefile pour changer les versions en 1.2.0. La raison est que la version du serveur RTSP que nous allons utiliser a besoin d'une version de GStreamer >= 1.1.0<br />
<br />
Les packages GStreamer se trouvent dans le dossier package/multimedia.<br />
Les versions 0.10 et 1.0 sont présents dans ce dossier et se différencient avec les noms des packages.<br />
Pour la version 0.10, "gst-plugin-xxxxxxx" ou "gstreamer", et pour la version 1.0, "gst1-plugin-xxxxxxx" ou "gstreamer1". Petite subtilité pour gst-omx qui a une dépendance avec gstreamer 1.0 et non gstreamer 0.10.<br />
<br />
<pre class="brush: shell; highlight: [16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27];"># ls package/multimedia -al
total 180
drwxr-xr-x 39 vbenoit users 4096 18 déc. 13:47 .
drwxr-xr-x 786 vbenoit users 20480 10 déc. 17:52 ..
-rw-r--r-- 1 vbenoit users 2038 18 déc. 13:47 Config.in
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 alsa-utils
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 aumix
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 bellagio
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 faad2
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 ffmpeg
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 flac
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-dsp
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-ffmpeg
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-fsl-plugins
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-omapfb
drwxr-xr-x 2 vbenoit users 4096 13 déc. 21:48 gst-omx
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-plugin-x170
drwxr-xr-x 2 vbenoit users 4096 6 déc. 11:58 gst-plugins-bad
drwxr-xr-x 2 vbenoit users 4096 11 déc. 17:53 gst-plugins-base
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-plugins-good
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gst-plugins-ugly
drwxr-xr-x 2 vbenoit users 4096 11 déc. 19:25 gst1-plugins-bad
drwxr-xr-x 2 vbenoit users 4096 11 déc. 19:24 gst1-plugins-base
drwxr-xr-x 2 vbenoit users 4096 13 déc. 19:05 gst1-plugins-good
drwxr-xr-x 2 vbenoit users 4096 13 déc. 19:47 gst1-plugins-ugly
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 gstreamer
drwxr-xr-x 2 vbenoit users 4096 26 déc. 14:30 gstreamer1
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 lame
drwxr-xr-x 2 vbenoit users 4096 10 déc. 21:53 libvpx
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 madplay
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 mpd
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 mpg123
drwxr-xr-x 2 vbenoit users 4096 13 déc. 20:12 mplayer
-rw-r--r-- 1 vbenoit users 34 17 sept. 13:42 multimedia.mk
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 musepack
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 on2-8170-libs
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 pulseaudio
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 tidsp-binaries
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 vorbis-tools
drwxr-xr-x 2 vbenoit users 4096 17 sept. 13:42 wavpack</pre>
<br />
<h4 style="text-align: left;">
Package gstreamer1</h4>
<br />
Se rendre dans le dossier package/multimedia/gstreamer1 et nous allons modifier la variable GSTREAMER1_VERSION dans le makefile.<br />
<br />
<pre class="brush: shell; highlight: [7, 8];">################################################################################
#
# gstreamer1
#
################################################################################
#GSTREAMER1_VERSION = 1.0.8
GSTREAMER1_VERSION = 1.2.0
GSTREAMER1_SOURCE = gstreamer-$(GSTREAMER1_VERSION).tar.xz
GSTREAMER1_SITE = http://gstreamer.freedesktop.org/src/gstreamer
GSTREAMER1_INSTALL_STAGING = YES
GSTREAMER1_LICENSE_FILES = COPYING
GSTREAMER1_LICENSE = LGPLv2+ LGPLv2.1+
[...]
</pre>
<br />
il va falloir aussi rajouter un patch, nommé <span style="font-family: Courier New, Courier, monospace;"><b>gstreamer1-001-libtheora_lazy.patch</b></span>, qui nous servira pour l'utilisation du plugin theora/ogg (voir la deuxième partie du tutoriel).<br />
Sans ce patch, GStreamer n'arrivera pas à résoudre des symboles inclus dans les librairies tierces de theora.<br />
<br />
<pre class="brush: shell;">--- a/gst/gstplugin.c 2013-07-05 01:50:56.000000000 +0200
+++ b/gst/gstplugin.c 2013-12-10 17:13:02.701218001 +0100
@@ -729,6 +729,8 @@
* */
if (strstr (filename, "libgstpython"))
flags |= G_MODULE_BIND_LAZY;
+ else if(strstr (filename, "libgsttheora"))
+ flags |= G_MODULE_BIND_LAZY;
module = g_module_open (filename, flags);
if (module == NULL) {
</pre>
<br />
<h4 style="text-align: left;">
Package gst1-plugin-bad</h4>
<br />
On fait la même chose avec le plugin bad de GStreamer.<br />
<br />
<pre class="brush: shell; highlight: [7, 8];">################################################################################
#
# gst1-plugins-bad
#
################################################################################
#GST1_PLUGINS_BAD_VERSION = 1.0.8
GST1_PLUGINS_BAD_VERSION = 1.2.0
GST1_PLUGINS_BAD_SOURCE = gst-plugins-bad-$(GST1_PLUGINS_BAD_VERSION).tar.xz
GST1_PLUGINS_BAD_SITE = http://gstreamer.freedesktop.org/src/gst-plugins-bad
GST1_PLUGINS_BAD_LICENSE_FILES = COPYING COPYING.LIB
# Unknown and GPL licensed plugins will append to GST1_PLUGINS_BAD_LICENSE if
# enabled.
GST1_PLUGINS_BAD_LICENSE = LGPLv2+ LGPLv2.1+
GST1_PLUGINS_BAD_AUTORECONF = YES
GST1_PLUGINS_BAD_AUTORECONF_OPT = -I $(@D)/common/m4
</pre>
<br />
<h4 style="text-align: left;">
Package gst1-plugin-base</h4>
<br />
de même avec le plugin base<br />
<br />
<pre class="brush: shell; highlight: [7, 8];">################################################################################
#
# gst1-plugins-base
#
################################################################################
GST1_PLUGINS_BASE_VERSION = 1.2.0
#GST1_PLUGINS_BASE_VERSION = 1.0.8
GST1_PLUGINS_BASE_SOURCE = gst-plugins-base-$(GST1_PLUGINS_BASE_VERSION).tar.xz
GST1_PLUGINS_BASE_SITE = http://gstreamer.freedesktop.org/src/gst-plugins-base
GST1_PLUGINS_BASE_INSTALL_STAGING = YES
GST1_PLUGINS_BASE_LICENSE_FILES = COPYING.LIB
GST1_PLUGINS_BASE_LICENSE = LGPLv2+ LGPLv2.1+
</pre>
<br />
<h4 style="text-align: left;">
Package gst1-plugin-ugly</h4>
<br />
de même avec le plugin ugly<br />
<br />
<pre class="brush: shell; highlight: [7, 8];">################################################################################
#
# gst1-plugins-ugly
#
################################################################################
#GST1_PLUGINS_UGLY_VERSION = 1.0.8
GST1_PLUGINS_UGLY_VERSION = 1.2.0
GST1_PLUGINS_UGLY_SOURCE = gst-plugins-ugly-$(GST1_PLUGINS_UGLY_VERSION).tar.xz
GST1_PLUGINS_UGLY_SITE = http://gstreamer.freedesktop.org/src/gst-plugins-ugly
GST1_PLUGINS_UGLY_LICENSE_FILES = COPYING
# GPL licensed plugins will append to GST1_PLUGINS_UGLY_LICENSE if enabled.
GST1_PLUGINS_UGLY_LICENSE = LGPLv2.1+
</pre>
<br />
<h4 style="text-align: left;">
Package gst1-plugin-good</h4>
<br />
de même avec le plugin good. J'ai également supprimé le patch pour ne pas l'appliquer.<br />
<br />
<pre class="brush: shell; highlight: [7, 8];">################################################################################
#
# gst1-plugins-good
#
################################################################################
#GST1_PLUGINS_GOOD_VERSION = 1.0.8
GST1_PLUGINS_GOOD_VERSION = 1.2.0
GST1_PLUGINS_GOOD_SOURCE = gst-plugins-good-$(GST1_PLUGINS_GOOD_VERSION).tar.xz
GST1_PLUGINS_GOOD_SITE = http://gstreamer.freedesktop.org/src/gst-plugins-good
GST1_PLUGINS_GOOD_LICENSE_FILES = COPYING
GST1_PLUGINS_GOOD_LICENSE = LGPLv2.1+
</pre>
<br />
<h4 style="text-align: left;">
Package Gstreamer OMX</h4>
<br />
La raspberry pi est "designé" autour d'un CPU contenant un GPU (Graphical Processor Unit) (Broadcom VideoCore IV) contenant les decodeurs OpenGL ES 1.1, OpenGL ES 2.0, accélération materielle OpenVG 1.1, Open EGL, OpenMAX. <br />
Ce GPU va nous permettre de dissocier la tâche d'encodage vidéo aux autres traitement de la board (voir la démonstration dans la seconde partie du tutoriel).<br />
<br />
Le package gst-omx de buildroot utilise une version assez ancienne, nous allons recréer un autre package (gst1-omx) pour une version plus récente.<br />
<br />
<pre class="brush: shell;"># cd package/multimedia
# mkdir gst1-omx
# vim gst1-omx.mk
</pre>
<br />
Buildroot gère assez mal les sous-modules Git, nécessaires pour la compilation du package, c'est pourquoi, pour cette version, après avoir téléchargé le package, on lance le script GST1_OMX_RUN_AUTOCONF pour créer le fichier de configuration.<br />
Nous sommes obligés de patcher la version de buildroot avec la variable GST1_OMX_LIBTOOL_PATCH = yes, sinon il va nous faire une belle erreur<br />
de linkage en essayant de linker une librairie de la machine hôte.<br />
<br />
<pre class="brush: shell;">################################################################################
#
# gst1-omx
#
################################################################################
GST1_OMX_VERSION = 8932bef0f3407a5b49f764878197eb24e68542d6
GST1_OMX_SOURCE = gst-omx-$(GST1_OMX_VERSION).tar.gz
GST1_OMX_SITE = http://cgit.freedesktop.org/gstreamer/gst-omx/snapshot/
GST1_OMX_LIBTOOL_PATCH = YES
GST1_OMX_AUTORECONF = YES
GST1_OMX_LICENSE = LGPLv2.1
GST1_OMX_LICENSE_FILES = COPYING
ifeq ($(BR2_PACKAGE_RPI_USERLAND),y)
GST1_OMX_CONF_OPT = \
--with-omx-target=rpi
GST1_OMX_CONF_ENV = \
CFLAGS="$(TARGET_CFLAGS) \
-I$(STAGING_DIR)/usr/include/IL \
-I$(STAGING_DIR)/usr/include/interface/vcos/pthreads \
-I$(STAGING_DIR)/usr/include/interface/vmcs_host/linux \
-Wno-deprecated-declarations"
endif
ifeq ($(BR2_PACKAGE_BELLAGIO),y)
GST1_OMX_CONF_OPT = \
--with-omx-target=bellagio
GST1_OMX_CONF_ENV = \
CFLAGS="$(TARGET_CFLAGS) \
-DOMX_VERSION_MAJOR=1 \
-DOMX_VERSION_MINOR=1 \
-DOMX_VERSION_REVISION=2 \
-DOMX_VERSION_STEP=0"
endif
define GST1_OMX_RUN_AUTOCONF
(cd $(@D); \
mkdir m4; \
rm common -rf; \
git init; \
git remote add project git://anongit.freedesktop.org/gstreamer/gst-omx; \
git fetch project; \
git submodule add git://anongit.freedesktop.org/gstreamer/common common; )
(cd $(@D); \
LIBTOOLIZE=$(LIBTOOLIZE) \
ACLOCAL_FLAGS=$(ACLOCAL_FLAGS) \
ACLOCAL="$(ACLOCAL)" \
AUTOHEADER=$(AUTOHEADER) \
AUTOCONF=$(AUTOCONF) \
AUTOMAKE=$(AUTOMAKE) \
AUTOM4TE=$(HOST_DIR)/usr/bin/autom4te \
NOCONFIGURE=1 \
./autogen.sh --nocheck)
endef
GST1_OMX_PRE_CONFIGURE_HOOKS += GST1_OMX_RUN_AUTOCONF
GST1_OMX_DEPENDENCIES = gstreamer1 gst1-plugins-base libopenmax
$(eval $(autotools-package))
</pre>
<br />
Nous allons ensuite créer le fichier Config.in :<br />
<br />
<pre class="brush: shell;"># vim Config.in
</pre>
<br />
<pre class="brush: shell;">config BR2_PACKAGE_GST1_OMX
bool "gst1-omx"
depends on BR2_PACKAGE_GSTREAMER1 && BR2_PACKAGE_HAS_OPENMAX
select BR2_PACKAGE_GST1_PLUGINS_BASE
help
GStreamer plug-in to use OpenMAX API.
http://cgit.freedesktop.org/gstreamer/gst-omx
comment "gst-omx requires a OpenMAX implementation"
depends on BR2_PACKAGE_GSTREAMER1 && !BR2_PACKAGE_HAS_OPENMAX
</pre>
<br />
puis un patch pour un fichier de configuration a insérer sur le système de fichiers qui servira a indiquer le chemin des librairies pour l'encodeur vidéo.<br />
Le fichier se nommera : gst1-omx-config-files.patch<br />
<br />
<pre class="brush: shell;">Change config files to match default buildroot install
Signed-off-by: Spenser Gilliland <spenser gillilanding.com="">
---
Index: gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6/config/bellagio/gstomx.conf
===================================================================
--- gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6.orig/config/bellagio/gstomx.conf 2013-03-12 04:12:09.000000000 -0500
+++ gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6/config/bellagio/gstomx.conf 2013-05-21 17:50:14.545692908 -0500
@@ -1,6 +1,6 @@
[omxmpeg4videodec]
type-name=GstOMXMPEG4VideoDec
-core-name=/usr/local/lib/libomxil-bellagio.so.0
+core-name=/usr/lib/libomxil-bellagio.so.0
component-name=OMX.st.video_decoder.mpeg4
rank=256
in-port-index=0
@@ -9,7 +9,7 @@
[omxh264dec]
type-name=GstOMXH264Dec
-core-name=/usr/local/lib/libomxil-bellagio.so.0
+core-name=/usr/lib/libomxil-bellagio.so.0
component-name=OMX.st.video_decoder.avc
rank=256
in-port-index=0
@@ -18,7 +18,7 @@
[omxmpeg4videoenc]
type-name=GstOMXMPEG4VideoEnc
-core-name=/usr/local/lib/libomxil-bellagio.so.0
+core-name=/usr/lib/libomxil-bellagio.so.0
component-name=OMX.st.video_encoder.mpeg4
rank=0
in-port-index=0
@@ -27,7 +27,7 @@
[omxaacenc]
type-name=GstOMXAACEnc
-core-name=/usr/local/lib/libomxil-bellagio.so.0
+core-name=/usr/lib/libomxil-bellagio.so.0
component-name=OMX.st.audio_encoder.aac
rank=0
in-port-index=0
Index: gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6/config/rpi/gstomx.conf
==================================================================
--- gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6.orig/config/rpi/gstomx.conf 2013-05-21 17:51:39.965693635 -0500
+++ gst-omx-8932bef0f3407a5b49f764878197eb24e68542d6/config/rpi/gstomx.conf 2013-05-21 17:52:07.781693871 -0500
@@ -1,6 +1,6 @@
[omxmpeg2videodec]
type-name=GstOMXMPEG2VideoDec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -9,7 +9,7 @@
[omxmpeg4videodec]
type-name=GstOMXMPEG4VideoDec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -18,7 +18,7 @@
[omxh263dec]
type-name=GstOMXH263Dec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -27,7 +27,7 @@
[omxh264dec]
type-name=GstOMXH264Dec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -36,7 +36,7 @@
[omxtheoradec]
type-name=GstOMXTheoraDec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -45,7 +45,7 @@
[omxvp8dec]
type-name=GstOMXVP8Dec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -54,7 +54,7 @@
[omxmjpegdec]
type-name=GstOMXMJPEGDec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_decode
rank=256
in-port-index=130
@@ -63,7 +63,7 @@
[omxvc1dec]
type-name=GstOMXWMVDec
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_encode
rank=256
in-port-index=130
@@ -73,7 +73,7 @@
[omxh264enc]
type-name=GstOMXH264Enc
-core-name=/opt/vc/lib/libopenmaxil.so
+core-name=/usr/lib/libopenmaxil.so
component-name=OMX.broadcom.video_encode
rank=256
in-port-index=200
</spenser></pre>
<br />
Ne pas oublier de rajouter dans le fichier Config.in du dossier multimedia la ligne :<br />
<br />
<pre class="brush: shell;">source "package/multimedia/gst1-omx/Config.in"
</pre>
<br />
<h4 style="text-align: left;">
Package Serveur RTSP</h4>
<br />
Ce package va être créé exactement sur le même principe que le package gst-omx surtout pour le makefile.<br />
<br />
<pre class="brush: shell;">################################################################################
#
# gst1-rtsp-server
#
################################################################################
GST1_RTSP_SERVER_VERSION = ab3651d3393d3771975e6f1180ea9adf1fde0605
GST1_RTSP_SERVER_SOURCE = gst-rtsp-server-$(GST1_RTSP_SERVER_VERSION).tar.gz
GST1_RTSP_SERVER_SITE = http://cgit.freedesktop.org/gstreamer/gst-rtsp-server/snapshot
GST1_RTSP_SERVER_LIBTOOL_PATCH = YES
GST1_RTSP_SERVER_AUTORECONF = YES
GST1_RTSP_SERVER_INSTALL_STAGING = YES
GST1_RTSP_SERVER_DEPENDENCIES = gstreamer1
GST1_RTSP_SERVER_CONF_OPT = \
--disable-dependency-tracking \
--disable-libtool-lock \
--disable-nls \
--disable-rpath \
--disable-valgrind
define GST1_RTSP_SERVER_PRE_CONFIG
(cd $(@D); \
mkdir m4; \
rm common -rf; \
git init; \
git remote add project git://anongit.freedesktop.org/gstreamer/gst-rtsp-server; \
git fetch project; \
git submodule add git://anongit.freedesktop.org/gstreamer/common common;)
(cd $(@D); \
LIBTOOLIZE=$(LIBTOOLIZE) \
ACLOCAL_FLAGS=$(ACLOCAL_FLAGS) \
ACLOCAL="$(ACLOCAL)" \
AUTOHEADER=$(AUTOHEADER) \
AUTOCONF=$(AUTOCONF) \
AUTOMAKE=$(AUTOMAKE) \
AUTOM4TE=$(HOST_DIR)/usr/bin/autom4te \
NOCONFIGURE=1 \
./autogen.sh --nocheck)
endef
GST1_RTSP_SERVER_PRE_CONFIGURE_HOOKS += GST1_RTSP_SERVER_PRE_CONFIG
$(eval $(autotools-package))
</pre>
<br />
Le fichier Config.in :<br />
<br />
<pre class="brush: shell;">config BR2_PACKAGE_GST1_RTSP_SERVER
bool "gst1-rtsp-server"
depends on BR2_PACKAGE_GSTREAMER1
help
GStreamer RTSP server
http://gstreamer.freedesktop.org/
</pre>
<br />
finalement, ajouter la ligne suivante dans le fichier Config.in du dossier multimédia :<br />
<br />
<pre class="brush: shell;">source "package/multimedia/gst1-rtsp-server/Config.in"
</pre>
<br />
Finalement, après avoir créer les deux nouveaux packages, nous allons pouvoir les sélectionner dans le menu de buildroot.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHPaT5MXTaOsPUPxDegC6_P8THNU-mrkDw5vMfgWhU0ESUI2PO9qGlvG1Evq3jXTNrnDFNYeR3Kqc9zdFEeGTkvthus9e5QSlHBLo0fvLyOfJxqxSN_gAQ76oyoTAj4kqDx5PMwmhD2tM/s1600/buildroot_ext_crosstool_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHPaT5MXTaOsPUPxDegC6_P8THNU-mrkDw5vMfgWhU0ESUI2PO9qGlvG1Evq3jXTNrnDFNYeR3Kqc9zdFEeGTkvthus9e5QSlHBLo0fvLyOfJxqxSN_gAQ76oyoTAj4kqDx5PMwmhD2tM/s1600/buildroot_ext_crosstool_3.png" height="640" width="598" /></a></div>
<br />
<h4 style="text-align: left;">
Plugins tierces à installer</h4>
<br />
Dans le menu de buildroot, nous allons choisir une liste de plugins a installer sur notre système de fichiers.<br />
Se rendre dans <span style="font-family: Courier New, Courier, monospace;"><b>Target packages</b></span> puis <span style="font-family: Courier New, Courier, monospace;"><b>Audio and video applications</b></span><br />
<br />
dans le sous-menu <span style="font-family: Courier New, Courier, monospace;"><b>gst1-plugin-base</b></span>, choisir :<br />
<br />
<pre class="brush: shell;">[ ] adder
[*] app
[*] audioconvert (mandatory for audio playback)
[*] audiorate
[*] audiotestsrc
[*] encoding
[*] videoconvert
[ ] gio
[*] playback
[*] audioresample (mandatory for audio playback)
[*] subparse
[*] tcp
-*- typefind
[*] videotestsrc
[*] videorate
[*] videoscale (mandatory for video playback)
[*] volume (mandatory for audio playback)
*** plugins with external dependencies ***
[ ] alsa (mandatory for audio playback)
[ ] tremor
[*] ogg (*.ogg audio/video)
[ ] pango font renderer
[*] theora (*.ogg video)
[*] vorbis (*.ogg audio)
</pre>
<br />
dans le sous-menu <span style="font-family: Courier New, Courier, monospace;"><b>gst1-plugin-good</b></span>, choisir :<br />
<br />
<pre class="brush: shell;">[*] jpeg (JPEG support)
[*] png (PNG support)
*** dependency-less plugins ***
[ ] alpha
[ ] apetag
[ ] audiofx
[*] audioparsers
[ ] auparse
[*] autodetect
[*] avi (*.avi video)
[ ] cutter
[ ] debugutils
[ ] deinterlace
[ ] effectv
[ ] equalizer
[*] flv
[*] flx
[ ] goom
[ ] goom2k1
[ ] icydemux
[ ] id3demux (*.mp3 audio)
[ ] imagefreeze
[*] interleave
[*] isomp4
[ ] law
[*] level
[ ] matroska
[ ] monoscope
[ ] multifile
[ ] multipart
[ ] replaygain
[*] rtp
[*] rtpmanager
[*] rtsp
[ ] shapewipe
[ ] smpte
[ ] spectrum
[*] udp
[ ] videobox
[*] videocrop
[*] videofilter
[*] videomixer
[ ] wavenc
[*] wavparse (*.wav audio)
[*] y4m
*** plugins with external dependencies ***
[ ] ossaudio (OSS audio)
[ ] oss4 (Open Sound System 4)
[*] v4l2
[ ] cairo
[ ] flac (libFLAC)
[ ] gdkpixbuf
[ ] pulseaudio
[ ] souphttpsrc (http client)
[ ] speex
[ ] vpx (webm)
[ ] vpx (webm)
[ ] wavpack (*.wv audio)
</pre>
<br />
dans le sous-menu <span style="font-family: Courier New, Courier, monospace;"><b>gst1-plugin-bad</b></span>, choisir :<br />
<br />
<pre class="brush: shell;">[*] adpcmdec
[*] adpcmenc
[*] aiff
[*] asfmux
[ ] audiovisualizers
[ ] autoconvert
[ ] bayer
[*] camerabin2
[ ] cdxaparse
[*] coloreffects
[*] dataurisrc
[ ] dccp
[*] debugutils
[ ] dtmf
[ ] dvdsuboverlay
[ ] dvdspu
[ ] faceoverlay
[ ] festival
[ ] fieldanalysis
[ ] freeverb
[ ] frei0r
[ ] gaudieffects
[ ] geometrictransform
[ ] gdp
[ ] hdvparse
[ ] hls
[ ] id3tag
[ ] inter
[ ] interlace
[ ] ivfparse
[ ] jp2kdecimator
[*] jpegformat
[*] librfb
[ ] liveadder
[*] mpegdemux
[*] mpegtsdemux
[*] mpegtsmux
[*] mpegpsmux
[ ] mve
[ ] mxf
[*] nuvdemux
[ ] patchdetect
[ ] pcapparse
[*] pnm
[*] rawparse
[ ] real
[ ] removesilence
[*] rtpmux
[ ] rtpvp8
[ ] scaletempo
[*] sdi
[*] sdp
[ ] segmentclip
[ ] siren
[ ] smooth
[*] speed
[*] subenc
[ ] stereo
[ ] tta
[ ] videofilters
[ ] videomeasure
[ ] videoparsers
[ ] videosignal
[ ] vmnc
[ ] y4m
*** plugins with external dependencies ***
[ ] shm
[ ] vcd
[ ] apexsink
[*] bz2
[ ] cdaudio
[ ] celt
[ ] curl
[ ] decklink
*** decklink requires a toolchain with C++ support enabled **
[ ] directfb
[ ] wayland
[ ] faad
[ ] fbdev
[ ] libmms
*** libmms requires a toolchain with WCHAR and threading supp
[ ] mpeg2enc
[ ] mpg123
[ ] musepack
[ ] neon
[ ] opencv
[ ] opus
[ ] rsvg
[ ] eglgles
[ ] sdl
[ ] sndfile
*** gst-plugins-bad-plugin-sndfile requires a toolchain with
[ ] dvb
</pre>
<br />
dans le sous-menu <span style="font-family: Courier New, Courier, monospace;"><b>gst1-plugin-ugly</b></span>, choisir :<br />
<br />
<pre class="brush: shell;">[ ] asfdemux
[ ] dvdlpcmdec
[ ] dvdsub
[ ] xingmux
[*] realmedia
*** plugins with external dependencies (there may be more available)
[ ] dvdread
[*] lame (*.mp3 audio encoder)
[*] mad (*.mp3 audio)
[*] mpeg2dec
</pre>
<br />
<h3 style="text-align: left;">
Conclusion</h3>
<div>
<br /></div>
<div>
Une fois toutes ces étapes effectuées, nous pouvons construire notre système de fichiers avec la commande <span style="font-family: Courier New, Courier, monospace;"><b>make</b></span> :</div>
<br />
<pre class="brush: shell;"># make</pre>
<br />
Nous allons pouvoir passer à la <a href="http://colocsbar.blogspot.fr/2014/01/gstreamer-et-serveur-de-streaming-rtsp.html">deuxième partie</a> du tutoriel pour vérifier le bon fonctionnement de notre serveur RTSP et des plugins GStreamer installés.<br />
<br /></div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com2Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-81348994990392934442013-12-05T14:49:00.001+01:002013-12-05T14:49:14.502+01:00Raspberry pi et Hotspot Wifi avec le DWA-121 <div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZzO8N8-l7cP3hAsdO3g3FcgaNZmLMT4NpUO_6rLr-tReptJ6_XF4E4fNNVS3ZWbcmsLfTB7qs4ku9QIUo44LHF_-8IVayJrfHsj5XPVQsuoiMp0FuMOpBIrVSsHXIiAA3QKKu_rGheJQ/s1600/sticker1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZzO8N8-l7cP3hAsdO3g3FcgaNZmLMT4NpUO_6rLr-tReptJ6_XF4E4fNNVS3ZWbcmsLfTB7qs4ku9QIUo44LHF_-8IVayJrfHsj5XPVQsuoiMp0FuMOpBIrVSsHXIiAA3QKKu_rGheJQ/s200/sticker1.png" height="162" width="200" /></a></div>
Ce billet est consacré à la transformation d'une raspberry pi en hotspot wifi grâce au dongle wifi DWA-121.<br />
J'ai déjà présenté ce dongle et comment l'interfacer avec une raspberry pi dans <a href="http://colocsbar.blogspot.fr/2013/02/dongle-wifi-dwa-121-et-raspberry-pi.html">un précédent billet</a>.<br />
On va reprendre tout ça pour l'utiliser avec le nouveau noyau linux 3.12.0.<br />
<br />
J'utilise le terme "hotspot" mais il faudrait plus utiliser le terme "point d'accès" puisque je n'aborderai pas la partie partage de connexion Internet grâce aux iptables. De nombreux tutoriels existent sur le net sur le partage de connexion.<br />
<br />
Les outils principaux abordés sur ce billet seront :<br />
<ul style="text-align: left;">
<li><b>8192cu.ko </b>: Driver pour le dongle DWA-121</li>
<li><b>wireless tools (iwconfig, iwlist, ...) </b>: Utilitaires pour la gestion du wifi.</li>
<li><b>hostapd</b> : Utilitaire de création de point d'accès wifi.</li>
<li><b>dhcpd</b> : démon de serveur dhcp permettant l'attribution d'adresses IP aux appareils se connectant à la raspberry pi.</li>
</ul>
<br />
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">
Préambule</h3>
<br />
Pour commencer, après avoir construit un environnement complet grâce à l'outil buildroot-2013.08.1 (si ce n'est pas le cas, veuillez vous reporter vers le billet précédent), nous allons installer la chaîne de compilation croisée dans le <span style="font-family: Courier New, Courier, monospace;">PATH</span> pour pouvoir compiler les outils nécessaires à l'utilisation du dongle wifi.<br />
<br />
Pour compiler le package dhcp server sur buildroot, il faut impérativement avoir une chaîne de compilation croisée avec l'option IPv6 coché.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9K-hBuIiJN7aYRpZ1RjKD3eo3wr-w96HaOhH_KU3_-tkw5GW6r3b4shUUXOhcfQvrJVZf4p6x-FCw4fg2cDT2AzoMt1NXJZwvjk8MMxQYuDVVajuI7c2_ECGrFg7oJEphvneVJcu4L7s/s1600/toolchain_ipv6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9K-hBuIiJN7aYRpZ1RjKD3eo3wr-w96HaOhH_KU3_-tkw5GW6r3b4shUUXOhcfQvrJVZf4p6x-FCw4fg2cDT2AzoMt1NXJZwvjk8MMxQYuDVVajuI7c2_ECGrFg7oJEphvneVJcu4L7s/s1600/toolchain_ipv6.png" height="640" width="596" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
A la racine de buildroot, on va se rendre dans le dossier d'installation de la chaîne de compilation croisée :<br />
<br />
<pre class="brush: shell"># cd output/host/usr/bin
</pre>
<br />
puis exporter le nouveau PATH :<br />
<br />
<pre class="brush: shell"># export PATH=$PATH:$PWD
</pre>
<br />
Ca va nous permettre d'avoir accès aux binaires de compilation plus facilement.<br />
<br />
Le dongle wifi DWA-121 est basé sur un chipset realtek rtl8192cu et les sources drivers constructeurs sont nécessaires à son bon fonctionnement. L'archive est disponible sur <a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PNid=21&PFid=48&Level=5&Conn=4&DownTypeID=3&GetDown=false&Downloads=true#2772">le site web de realtek</a>. C'est la version 4.0.2_9000 compatible avec les noyaux linux 2.6.18 à 3.9 (cette dernière information va avoir son importance dans la suite du billet).<br />
<br />
désarchiver le fichier en dehors de buildroot.<br />
<br />
<pre class="brush: shell"># unzip RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip
# cd RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911
# ls
ReleaseNotes.pdf android_ref_codes_JB_4.1 android_reference_codes document hardware_wps_pbc readme.txt wpa_supplicant_hostapd
WiFi_Direct_User_Interface android_ref_codes_JB_4.2 android_reference_codes_ICS_nl80211 driver install.sh wireless_tools
</pre>
<br />
Les dossiers importants sont :<br />
<ul style="text-align: left;">
<li><b>driver</b> : Contenant les sources pour la compilation du driver pour le dongle wifi.</li>
<li><b>wireless_tools</b> : Contenant les sources des utilitaires, nécessaires pour la configuration d'une connexion wifi et autres.</li>
<li><b>wpa_supplicant_hostapd</b> : Contenant les sources des outils pour la création et la configuration d'un point d'accès wifi.</li>
</ul>
<br />
<div>
<h3 style="text-align: left;">
Compilation du driver</h3>
<br />
On va commencer par la compilation du driver, rendez-vous dans le dossier <span style="font-family: Courier New, Courier, monospace;">driver</span> et désarchiver le fichier tarball :<br />
<br />
<pre class="brush: shell"># tar xvzf rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911.tar.gz
# cd rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911
# ls
Kconfig Makefile clean core hal ifcfg-wlan0 include os_dep runwpa wlan0dhcp
</pre>
<br />
Plusieurs fichiers vont être à modifier, à commencer par le makefile.<br />
<br />
On va rajouter une règle de compilation pour notre plateforme (raspberry pi) :<br />
<br />
<pre class="brush: shell; highlight: [5];">CONFIG_PLATFORM_I386_PC = n
CONFIG_PLATFORM_TI_AM3517 = n
CONFIG_PLATFORM_ANDROID_X86 = n
CONFIG_PLATFORM_JB_X86 = n
CONFIG_PLATFORM_ARM_BCM2708 = y
CONFIG_PLATFORM_ARM_S3C2K4 = n
CONFIG_PLATFORM_ARM_PXA2XX = n
</pre>
<br />
et les différentes informations concernant le prefix de la chaîne de compilation croisée ainsi que le chemin du noyau linux utilisé :<br />
<br />
<pre class="brush: shell; highlight: [9, 10, 11, 12, 13, 14, 15];">ifeq ($(CONFIG_PLATFORM_ARM_S3C6K4), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-none-linux-gnueabi-
KVER := 2.6.34.1
KSRC ?= /usr/src/linux-2.6.34.1
endif
ifeq ($(CONFIG_PLATFORM_ARM_BCM2708), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-buildroot-linux-uclibcgnueabi-
KVER := 3.12.0
KSRC ?= <buildroot_path>/output/build/linux-rpi-3.12.y
endif
ifeq ($(CONFIG_PLATFORM_RTD2880B), y)
EXTRA_CFLAGS += -DCONFIG_BIG_ENDIAN -DCONFIG_PLATFORM_RTD2880B
ARCH:=
CROSS_COMPILE:=
KVER:=
KSRC:=
endif
</buildroot_path></pre>
<br />
Ce n'est pas tout, en préambule, je vous avez dit que le driver était compatible que pour les versions de noyaux comprises entre 2.6.18 et 3.9 alors que nous souhaitons le compiler pour une version de noyau 3.12.<br />
<br />
La raison est que les fonctions pour créer des entrées (informations systèmes) dans le dossier <span style="font-family: Courier New, Courier, monospace;"><b>proc</b></span> sont dépréciées depuis la version 3.10 du noyau linux. Ces fonctions (create_proc_entry(), create_proc_read_entry(), etc ...) sont utilisées dans le fichier <span style="font-family: Courier New, Courier, monospace;"><b>os_dep/linux/os_intfs.c</b></span>.<br />
<br />
Je vous fournit un <a href="https://drive.google.com/file/d/0B6WDjVnTAZgFdE9jS09FUDZUMjQ/edit?usp=sharing">patch correctif</a> pour résoudre ce problème. J'ai fait le barbare et supprimer les fonctions de création de ses entrées qui ne sont pas nécessaires.<br />
Le patch comprend aussi les modifications à faire dans le Makefile.<br />
<br />
Copier le patch à la racine du dossier contenant les sources du driver et appliquer la commande :<br />
<br />
<pre class="brush: shell">patch -p1 < rtl8192c_proc_remove.patch
</pre>
<br />
Ne pas oublier de changer le chemin de votre noyau 3.12.0 dans le makefile.<br />
Il ne reste plus qu'à lancer la commande de compilation et le driver 8192cu.ko devrait apparaître<br />
<br />
<pre class="brush: shell"># make
[...]
# file 8192cu.ko
8192cu.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=49a3ca8f2bfd3a6eaea5068f710dc46069e4eb8f, not stripped
</pre>
<br />
Ce driver, ainsi compilé, sera à copier sur le système de fichiers.</div>
<br />
<br />
<h3 style="text-align: left;">
Outils wifi</h3>
<br />
Nous allons maintenant nous rendre dans le dossier <span style="font-family: Courier New, Courier, monospace;">wireless_tools</span> contenant les sources des outils wifi.<br />
<br />
Décompressez l'archive :<br />
<br />
<pre class="brush: shell"># cd wireless_tools
# tar xvzf wireless_tools.30.rtl.tar.gz
# cd wireless_tools.30.rtl.tar.gz
</pre>
<br />
Nous allons modifier le makefile pour cross-compiler les outils :<br />
<br />
<pre class="brush: shell; highlight: [11, 12, 13, 14, 15];">##
## Please check the configurion parameters below
##
## Installation directory. By default, go in /usr/local.
## Distributions should probably use /, but they probably know better...
ifndef PREFIX
PREFIX = /usr/local
endif
## Compiler to use (modify this for cross compile).
CC = arm-buildroot-linux-uclibcgnueabi-gcc
## Other tools you need to modify for cross compile (static lib only).
AR = arm-buildroot-linux-uclibcgnueabi-ar
RANLIB = arm-buildroot-linux-uclibcgnueabi-ranlib
## Uncomment this to build tools using static version of the library.
## Mostly useful for embedded platforms without ldd, or to create
## a local version (non-root).
## Standard distros should comment that option to save space and to
## build libiw.so used by third parties...
BUILD_STATIC = y
</pre>
<br />
Pour compiler les outils, lancer la commande :<br />
<br />
<pre class="brush: shell;"># make
</pre>
<br />
Les outils compilés sont :<br />
<br />
<ul style="text-align: left;">
<li><b>iwconfig</b> : configure une interface réseau sans-fil.</li>
<li><b>iwevent</b> : affiche les événements d'une interface réseau sans-fil.</li>
<li><b>iwgetid</b> : rapporte l'ESSID, NWID ou l'Adresse de l'AP/Cell (Point d'Accès/Cellule) du réseau sans fil.</li>
<li><b>iwlist</b> : affichage d'informations détaillées d'une interface réseau sans-fil.</li>
<li><b>iwpriv</b> : traite les paramètres et attributs spécifiques à chaque pilote.</li>
<li><b>iwspy</b> : fixe une liste d'adresses à surveiller sur une interface réseau sans-fil.</li>
</ul>
<br />
Ces outils compilés sont à copier sur le système de fichiers dans le dossier <span style="font-family: Courier New, Courier, monospace;">/usr/bin</span>.<br />
<br />
<br />
<h3 style="text-align: left;">
Outil de création de point d'accès : hostapd</h3>
<div style="text-align: left;">
<br /></div>
<h4 style="text-align: left;">
Compilation de l'exécutable</h4>
<br />
Hostapd est l'outil permettant de créer et de configurer un point d'accès wifi. Cet utilitaire est disponible parmi les packages buildroot mais nous n'utiliseront pas cette version pour la simple raison que les chipsets realtek ne sont pas supportés avec cette version standard.<br />
Avec son driver, realtek fournit une version modifiée de Hostapd supportant ses chipset.<br />
Nous allons compiler les sources modifiées puis installer le binaire sur le système de fichiers.<br />
<br />
Entrez dans le dossier <span style="font-family: Courier New, Courier, monospace;"><b>wpa_supplicant_hostapd</b></span> puis décompressez l'archive :<br />
<br />
<pre class="brush: shell"># cd wpa_supplicant_hostapd
# tar xvzf wpa_supplicant_hostapd-0.8_rtw_r7475.20130812.tar.gz
# cd wpa_supplicant_hostapd-0.8_rtw_r7475.20130812
# cd hostapd
</pre>
<br />
voici le fichier de configuration standard (fichier defconfig) :<br />
<br />
<pre class="brush: shell"># Example hostapd build time configuration
#
# This file lists the configuration options that are used when building the
# hostapd binary. All lines starting with # are ignored. Configuration option
# lines must be commented out complete, if they are not to be included, i.e.,
# just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cass, these lines should use += in order not
# to override previous values of the variables.
# Driver interface for Host AP driver
CONFIG_DRIVER_HOSTAP=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
# Driver interface for madwifi driver
#CONFIG_DRIVER_MADWIFI=y
#CFLAGS += -I../../madwifi # change to the madwifi source directory
# Driver interface for drivers using the nl80211 kernel interface
#CONFIG_DRIVER_NL80211=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
#LIBS += -L/usr/local/lib
#LIBS_p += -L/usr/local/lib
#LIBS_c += -L/usr/local/lib
# Driver interface for no driver (e.g., RADIUS server only)
#CONFIG_DRIVER_NONE=y
</pre>
<br />
et celui modifié par realtek (fichier .config) :<br />
<br />
<pre class="brush: shell; highlight: [14]"># Example hostapd build time configuration
#
# This file lists the configuration options that are used when building the
# hostapd binary. All lines starting with # are ignored. Configuration option
# lines must be commented out complete, if they are not to be included, i.e.,
# just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cass, these lines should use += in order not
# to override previous values of the variables.
# Driver interface for Host AP driver
#CONFIG_DRIVER_HOSTAP=y
CONFIG_DRIVER_RTW=y
# Driver interface for wired authenticator
#CONFIG_DRIVER_WIRED=y
# Driver interface for madwifi driver
#CONFIG_DRIVER_MADWIFI=y
#CFLAGS += -I../../madwifi # change to the madwifi source directory
# Driver interface for drivers using the nl80211 kernel interface
#CONFIG_DRIVER_NL80211=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CONFIG_SUPPORT_RTW_DRIVER=y
#CFLAGS += -I/usr/local/include
#LIBS += -L/usr/local/lib
#LIBS_p += -L/usr/local/lib
#LIBS_c += -L/usr/local/lib
# Driver interface for no driver (e.g., RADIUS server only)
#CONFIG_DRIVER_NONE=y
</pre>
<br />
Il n'y aura qu'un seul driver compilé avec cette version modifié de hostapd. le nom du driver a utiliser dans le fichier de configuration est : rtl871xdrv<br />
<br />
Voici le morceau de code du fichier source <span style="font-family: Courier New, Courier, monospace;"><b>src/drivers/driver_rtw.c</b></span> : <br />
<br />
<pre class="brush: shell; highlight: [2];">const struct wpa_driver_ops wpa_driver_rtw_ops = {
.name = "rtl871xdrv",
.hapd_init = rtl871x_driver_init_ops,
.hapd_deinit = rtl871x_driver_deinit_ops,
.hapd_send_eapol = rtl871x_send_eapol_ops,
.get_hw_feature_data = rtl871x_get_hw_feature_data_ops,
.sta_remove = rtl871x_sta_remove_ops,
.set_beacon = rtl871x_set_beacon_ops,
.set_key = rtl871x_set_key_ops,
.sta_deauth = rtl871x_sta_deauth_ops,
.sta_disassoc = rtl871x_sta_disassoc_ops,
.set_ap_wps_ie = rtl871x_set_ap_wps_ie,
.flush = rtl871x_sta_flush_ops,
.set_rts = rtl871x_set_rts_threshold,
.set_frag = rtl871x_set_frag_threshold,
};
</pre>
<br />
Il n'y a pas besoin de modifier le makefile, entrez juste la commande :<br />
<br />
<pre class="brush: shell"># CC=arm-buildroot-linux-uclibcgnueabi-gcc make
# file hostapd
hostapd: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
</pre>
<br />
<h4 style="text-align: left;">
Fichier de configuration</h4>
<br />
L'utilitaire hostapd s'utilise avec un fichier de configuration (hostapd.conf) à installer sur le système de fichiers dans le dossier <span style="font-family: Courier New, Courier, monospace;"><b>/etc/hostapd/</b></span><br />
<br />
Voici un fichier de configuration exemple permettant de créer un point d'accès avec une sécurité de connexion WPA.<br />
<br />
Deux paramètres sont à modifier :<br />
<ul style="text-align: left;">
<li><b>ssid</b> : Le nom du réseau qui sera afficher sur les appareils souhaitant se connecter à la raspberry pi</li>
<li><b>wpa_passphrase</b> : La clé réseau pour la connexion</li>
</ul>
<br />
Vous trouverez sur internet de nombreux exemples de fichiers de configuration (conf avec sécurité WEP, WPA2, EAP, etc ...). Il faut toujours que le paramètre driver soit <span style="font-family: Courier New, Courier, monospace;"><b>rtl871xdrv</b></span><br />
<br />
<pre class="brush: shell"># AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
# management frames); ath0 for madwifi
interface=wlan0
# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd);
# default: hostap). nl80211 is used with all Linux mac80211 drivers.
# Use driver=none if building hostapd as a standalone RADIUS server that does
# not control any wireless/wired driver.
driver=rtl871xdrv
##### IEEE 802.11 related configuration #######################################
# SSID to be used in IEEE 802.11 management frames
ssid=rpi_hotspot
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# Default: IEEE 802.11b
hw_mode=g
# Channel number (IEEE 802.11)
# (default: 0, i.e., not set)
# Please note that some drivers (e.g., madwifi) do not use this value from
# hostapd and the channel will need to be configuration separately with
# iwconfig.
channel=6
# Station MAC address -based authentication
# Please note that this kind of access control requires a driver that uses
# hostapd to take care of management frame processing and as such, this can be
# used with driver=hostap or driver=nl80211, but not with driver=madwifi.
# 0 = accept unless in deny list
# 1 = deny unless in accept list
# 2 = use external RADIUS server (accept/deny lists are searched first)
macaddr_acl=0
# IEEE 802.11 specifies two authentication algorithms. hostapd can be
# configured to allow both of these or only one. Open system authentication
# should be used with IEEE 802.1X.
# Bit fields of allowed authentication algorithms:
# bit 0 = Open System Authentication
# bit 1 = Shared Key Authentication (requires WEP)
auth_algs=1
# Send empty SSID in beacons and ignore probe request frames that do not
# specify full SSID, i.e., require stations to know SSID.
# default: disabled (0)
# 1 = send empty (length=0) SSID in beacon and ignore probe request for
# broadcast SSID
# 2 = clear SSID (ASCII 0), but keep the original length (this may be required
# with some clients that do not support empty SSID) and ignore probe
# requests for broadcast SSID
ignore_broadcast_ssid=0
##### WPA/IEEE 802.11i configuration ##########################################
# Enable WPA. Setting this variable configures the AP to require WPA (either
# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
# RADIUS authentication server must be configured, and WPA-EAP must be included
# in wpa_key_mgmt.
# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
# and/or WPA2 (full IEEE 802.11i/RSN):
# bit0 = WPA
# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)
wpa=2
# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
# so the PSK changes when ASCII passphrase is used and the SSID is changed.
wpa_passphrase=je_suis_un_con
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
# added to enable SHA256-based stronger algorithms.
wpa_key_mgmt=WPA-PSK
# Set of accepted cipher suites (encryption algorithms) for pairwise keys
# (unicast packets). This is a space separated list of algorithms:
# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
# Group cipher suite (encryption algorithm for broadcast and multicast frames)
# is automatically selected based on this configuration. If only CCMP is
# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
# TKIP will be used as the group cipher.
wpa_pairwise=TKIP
# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)
rsn_pairwise=CCMP
</pre>
<br />
<h4 style="text-align: left;">
Utilisation de l'utilitaire</h4>
<br />
Pour lancer l'exécutable, il suffit de lancer la commande :<br />
<br />
<pre class="brush: shell"># hostapd -B -P /var/run/hostapd.pid /etc/hostapd/hostapd.conf
</pre>
<br />
Les paramètres :<br />
<ul style="text-align: left;">
<li>-B : permet de lancer l'exécutable en tant que démon</li>
<li>-P <pid_file> : permet de définir le chemin du fichier process_id</pid_file></li>
</ul>
<br />
Lorsqu'on lance la commande, différentes traces de debugs apparaissent et la LED bleue du dongle clignote signifiant que le démon est opérationnel :<br />
<br />
<pre class="brush: shell">Configuration file: /etc/hostapd/hostapd.conf
drv->ifindex=3
l2_sock_recv==l2[ 3490.422354] _rtw_pwr_wakeup call ips_leave....
_sock_xmit=0x0xd[ 3490.428112] ==>ips_leave cnts:1
91c28
[ 3490.433486] ===> rtw_ips_pwr_up..............
[ 3490.437992] ===> ips_netdrv_open.........
[ 3490.447772] ===> FirmwareDownload91C() fw:Rtl819XFwImageArray_TSMC
[ 3490.454572] FirmwareDownload92C accquire FW from embedded image
[ 3490.460541] fw_ver=v88, fw_subver=2, sig=0x88c0
[ 3490.508549] fw download ok!
[ 3490.511382] Set RF Chip ID to RF_6052 and RF type to 1T1R.
[ 3491.009448] IQK:Start!!!
[ 3491.024204] Path A IQK Success!!
[ 3491.035699] Path A IQK Success!!
[ 3491.044340] IQK: final_candidate is 0
[ 3491.048043] IQK: RegE94=102 RegE9C=12 RegEA4=fc RegEAC=2 RegEB4=0 RegEBC=0 RegEC4=0 RegECC=0
Path A IQ Calibration Success !
[ 3491.180505] pdmpriv->TxPowerTrackControl = 1
[ 3491.190242] rtl8192cu_hal_init in 740ms
[ 3491.217821] <=== rtw_ips_pwr_up.............. in 780ms
[ 3491.223824] ==> ips_leave.....LED(0x00028080)...
[ 3491.228477] set_mode = IW_MODE_MASTER
[ 3491.233752] rtw_hostapd_sta_flush
[ 3491.237428] hw_var_set_opmode()-4234 mode = 3
[ 3491.242936] rtw_sta_flush(wlan0)
[ 3491.246187] issue_deauth to ff:ff:ff:ff:ff:ff
+rtl871x_sta_dea[ 3491.250925] rtw_set_encryption
uth_ops, ff:ff:ff:ff:ff:[ 3491.256106] clear default encryption keys, keyid=0
ff is deauth, reason=2
[ 3491.262960] rtw_set_encryption
rtl871x_set_key_[ 3491.267239] clear default encryption keys, keyid=1
ops
rtl871x_set_key_ops[ 3491.274616] rtw_set_encryption
rtl871x_set_ke[ 3491.278520] clear default encryption keys, keyid=2
y_ops
rtl871x_set_key_[ 3491.285754] rtw_set_encryption
ops
[ 3491.289989] clear default encryption keys, keyid=3
Using interface wlan0 with hwaddr c8:be:19:86:be:51 and ssid 'rpi_hotspot'
rtl871x_set_wps_[ 3491.469863] rtw_set_wps_assoc_resp, len=14
assoc_resp_ie
rtl871x_[ 3491.475890] rtw_set_wps_beacon, len=14
set_wps_beacon_i[ 3491.481049] rtw_set_wps_probe_resp, len=14
e
rtl871x_set_wps_probe_resp_ie
rtl871x_[ 3491.488651] rtw_set_encryption
set_key_ops
[ 3491.493725] rtw_set_encryption, set group_key, CCMP
[ 3491.499166] set_group_key
rtl871x_set_beac[ 3491.503652] rtw_set_beacon, len=83
on_ops
[ 3491.508302] rtw_check_beacon_data, len=69
[ 3491.516077] SetHwReg8192CU, 5126, RCR= 7000228e
[ 3491.535195] CH=6, BW=0, offset=0
[ 3491.539444] HW_VAR_BASIC_RATE: BrateCfg(0x15d)
[ 3491.553744] update_bmc_sta, mask=0x6000000f, arg=0x81
[ 3491.559941] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
rtl871x_set_hidd[ 3491.567560] rtw_set_hidden_ssid(wlan0) ignore_broadcast_ssid:0, rpi_hotspot,11
en_ssid ignore_broadcast_ssid:0, rpi_hotspot,11
rtl871x_set_acl
# [ 3496.233839] rtl8192c_dm_RF_Saving(): RF_Normal
</pre>
<br />
<h3 style="text-align: left;">
Utilitaire serveur DHCP</h3>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Le serveur DHCP (Dynamic Host Configuration Protocol) va permettre à la raspberry pi d'affecter automatiquement une adresse IP et un masque de sous-réseau aux périphériques souhaitant se connecter à celle-ci.</div>
<div style="text-align: left;">
<br /></div>
<h4 style="text-align: left;">
Fonctionnement</h4>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
(<a href="http://fr.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">Extrait de wikipedia</a>)<br />
<br /></div>
<br />
<li style="margin-bottom: 0.1em;">L’ordinateur équipé de carte réseau, mais dépourvu d’adresse IP, envoie en diffusion Broadcast un datagramme (<span class="lang-en" lang="en" xml:lang="en"><i>DHCP DISCOVER</i></span>) qui s’adresse au <span class="nowrap" style="white-space: nowrap;">port 67</span> de n’importe quel serveur à l’écoute sur ce port. Ce datagramme comporte entre autres l’adresse physique (MAC) du client.</li>
<br />
<li style="margin-bottom: 0.1em;">Tout serveur DHCP ayant reçu ce datagramme, s’il est en mesure de proposer une adresse sur le réseau auquel appartient le client, envoie une offre DHCP (<span class="lang-en" lang="en" xml:lang="en"><i>DHCP OFFER</i></span>) à l’attention du client (sur son <span class="nowrap" style="white-space: nowrap;">port 68</span>), identifié par son adresse physique. Cette offre comporte l’adresse IP du serveur, ainsi que l’adresse IP et le masque de sous-réseau qu’il propose au client. Il se peut que plusieurs offres soient adressées au client.</li>
<br />
<li style="margin-bottom: 0.1em;">Le client retient une des offres reçues (la première qui lui parvient), et diffuse sur le réseau un datagramme de requête DHCP (<span class="lang-en" lang="en" xml:lang="en"><i>DHCP REQUEST</i></span>). Ce datagramme comporte l’adresse IP du serveur et celle qui vient d’être proposée au client. Elle a pour effet de demander au serveur choisi l’assignation de cette adresse, l’envoi éventuel des valeurs des paramètres, et d’informer les autres serveurs qui ont fait une offre qu’elle n’a pas été retenue.</li>
<br />
<li style="margin-bottom: 0.1em;">Le serveur DHCP élabore un datagramme d'accusé de réception (<i>DHCP ACK</i> pour <i>acknowledgement</i>) qui assigne au client l'adresse IP et son masque de sous-réseau, la durée du bail de cette adresse (dont découlent deux valeurs T1 et T2 qui déterminent le comportement du client en fin de bail), et éventuellement d'autres paramètres (adresse IP de la passerelle par défaut, adresses IP des serveurs DNS et adresses IP des serveurs NBNS, ...).</li>
<br />
<br />
<h4 style="text-align: left;">
Installation</h4>
<br />
Le serveur dhcp est un package de busybox qui est accessible depuis buildroot en cochant la case : <span style="font-family: Courier New, Courier, monospace;">Show packages that are also provided by busybox </span><span style="font-family: Arial, Helvetica, sans-serif;">dans le menu</span><span style="font-family: Courier New, Courier, monospace;"> Target Packages --></span><br />
<br />
<pre class="brush: shell"># make menuconfig
</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyrEZ2vUO9UM4UKoI-4MCc1xw3nHVJ7LgUDvn4YZ7cbOjcfhdSl2KH9agAkA2WFoqI59DXohONzzOsnAn1Xka76ZmoSWdFlXRp0CQaNRScfbnFtC7XYc3EIW1-kHE93ga7iUfrCjamfeU/s1600/buildroot_show_busybox_others.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyrEZ2vUO9UM4UKoI-4MCc1xw3nHVJ7LgUDvn4YZ7cbOjcfhdSl2KH9agAkA2WFoqI59DXohONzzOsnAn1Xka76ZmoSWdFlXRp0CQaNRScfbnFtC7XYc3EIW1-kHE93ga7iUfrCjamfeU/s1600/buildroot_show_busybox_others.png" height="640" width="598" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Ensuite se rendre dans le sous-menu <span style="font-family: Courier New, Courier, monospace;">Networking applications --></span> et choisir le package <span style="font-family: Courier New, Courier, monospace;">isc dhcp</span> et <span style="font-family: Courier New, Courier, monospace;">dhcp server</span>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ST7cCQd0rrmK5cEOCH-ov97n7uFn2Dd9TdvIc-cB73zbqKJkjHPdLGvx6MMK6eUBY8Znn05xUltsu5TzKsIrUehbIg_S3fRmfALQLFD4iPUxtMqaK8GEPoto9prz2hAb2___qofLrf0/s1600/buildroot_dhcp_server.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7ST7cCQd0rrmK5cEOCH-ov97n7uFn2Dd9TdvIc-cB73zbqKJkjHPdLGvx6MMK6eUBY8Znn05xUltsu5TzKsIrUehbIg_S3fRmfALQLFD4iPUxtMqaK8GEPoto9prz2hAb2___qofLrf0/s1600/buildroot_dhcp_server.png" height="640" width="598" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Il suffit de taper la commande make pour compiler l'éxecutable et l'installer sur le système de fichiers :<br />
<br />
<pre class="brush: shell"># make
</pre>
<br />
<h4 style="text-align: left;">
Configuration</h4>
<br />
Le fichier de configuration se trouve sur le système de fichiers : <span style="font-family: Courier New, Courier, monospace;"><b>/etc/dhcp/dhcpd.conf</b></span><br />
<span style="font-family: Courier New, Courier, monospace;"><b><br />
</b></span> <br />
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica, sans-serif;">Il existe, bien entendu, une tripotée de configurations différentes, en voici un exemple :</span></div>
<br />
<pre class="brush: shell"># cat dhcpd.conf
# Sample configuration file for ISC dhcpd for Debian
#
# $Id: dhcpd.conf,v 1.1.1.1 2002/05/21 00:07:44 peloy Exp $
#
# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;
# option definitions common to all supported networks...
option domain-name "benserv-rpi";
option domain-name-servers 8.8.8.8, 8.8.4.4;
default-lease-time 3600;
max-lease-time 7200;
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.10.255;
option routers 192.168.10.254;
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.10 192.168.10.100;
}
</pre>
<br />
Le serveur DHCP assignera au client une adresse IP comprise entre 192.168.10.10 et 192.168.10.100 pour une durée de 3600 secondes. Le client peut spécifier une période de temps spécifique, dans ce cas, le temps d'allocation maximum est de 7200 secondes.<br />
<br />
Le serveur va également informer le client qu'il doit utiliser:<br />
<br />
<ul style="text-align: left;">
<li>un masque de sous réseau à 255.255.255.0</li>
<li>une adresse de multi-diffusion à 192.168.10.255</li>
<li>une adresse de passerelle à 192.168.10.254</li>
<li>des serveurs DNS à 8.8.8.8 et 8.8.4.4</li>
</ul>
<br />
<ul style="text-align: left;">
</ul>
<div>
<br /></div>
<h3 style="text-align: left;">
Script d'initialisation</h3>
<div>
<br /></div>
<div>
Pour automatiser les différentes étapes permettant la mise en oeuvre d'un point d'accès, on va créer un script d'initialisation qui se lancera au démarrage du système. Ce script est à créer dans /etc/init.d.</div>
<br />
On va l'appeler S70wifi pour l'activation du wifi.<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# Start the wifi....
#
VENDOR_ID="2001"
PRODUCT_ID="3308"
INTERFACE="wlan0"
result_lsusb=""
case "$1" in
start)
result_lsusb=`lsusb -d "${VENDOR_ID}":"${PRODUCT_ID}"`
if [ "${result_lsusb}" != "" ]; then
# activation du driver 8192cu.ko
insmod /lib/modules/3.12.0/kernel/drivers/net/wireless/rtl8192cu/8192cu.ko
# attribution d'une adresse IP passerelle pour l'interface réseau sans-fil
/sbin/ip a add 192.168.10.254/24 dev wlan0
# activation de l'interface réseau sans-fil
/sbin/ip link set dev wlan0 up
fi
;;
stop)
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre>
<br />
Le script de lancement du serveur dhcp est directement installé sur le système de fichier, il suffit simplement de modifier la variable INTERFACES à wlan0<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# $Id: dhcp3-server.init.d,v 1.4 2003/07/13 19:12:41 mdz Exp $
#
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="wlan0"
# It is not safe to start if we don't have a default configuration...
#echo "/etc/init.d/dhcp-server not yet configured! - Aborting..."
#exit 1;
test -f /usr/sbin/dhcpd || exit 0
case "$1" in
start)
echo -n "Starting DHCP server: "
test -d /var/lib/dhcp/ || mkdir -p /var/lib/dhcp/
test -f /var/lib/dhcp/dhcpd.leases || touch /var/lib/dhcp/dhcpd.leases
start-stop-daemon -S -x /usr/sbin/dhcpd -- -cf /etc/dhcp/dhcpd.conf -q $INTERFACES
echo "."
;;
stop)
echo -n "Stopping DHCP server: dhcpd3"
start-stop-daemon -K -x /usr/sbin/dhcpd
echo "."
;;
restart | force-reload)
$0 stop
sleep 2
$0 start
if [ "$?" != "0" ]; then
exit 1
fi
;;
*)
echo "Usage: /etc/init.d/dhcp-server {start|stop|restart|force-reload}"
exit 1
esac
exit 0
</pre>
<br />
et finalement le script de lancement de l'utilitaire hostapd avec le script <span style="font-family: Courier New, Courier, monospace;"><b>/etc/init.d/S81hostapd</b></span> :<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# Start Hostapd....
#
test -f /usr/bin/hostapd || exit 0
case "$1" in
start)
echo -n "Starting hostapd: "
start-stop-daemon -S -x /usr/bin/hostapd -- -B -P /var/run/hostapd.pid /etc/hostapd/hostapd.conf
;;
stop)
echo -n "Stopping hostapd: "
start-stop-daemon -K -x /usr/bin/hostapd
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre>
<br />
<h3 style="text-align: left;">
Conclusion</h3>
<br />
Vous voila avec un point d'accès complètement fonctionnel, Je me suis servi d'un topic sur le forum de raspberry pi (<a href="http://www.raspberrypi.org/phpBB3/viewtopic.php?p=270652#p270652">ici</a>).<br />
J'avais trouvé les explications un peu trop légères sur comment faire et je souhaitais expliquer, plus en détail, comment obtenir une version de hostpad fonctionnel.<br />
<br />
Amusez-vous bien ...</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-52804603220451637232013-12-02T20:41:00.000+01:002013-12-02T21:15:58.628+01:00Afficheur Alphanumérique (bonus python)<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s1600/RPI_LCD.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s1600/RPI_LCD.png" height="200" width="580" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Dans un précédent billet, on a vu comment s'interfacer avec l'afficheur LCD 2x16 caractères depuis un code écrit en C. On va maintenant s'intéresser à un module python pour afficher des informations sur l'afficheur.<br />
L'un des principaux avantages du python par rapport au langage C est que l'on a pas besoin de compiler le code pour le lancer sur la raspberry pi, donc moins galère pour faire du prototypage.<br />
<br />
La base de l'environnement embarqué de travail est :<br />
<br />
<ul style="text-align: left;">
<li>buildroot-2013.08.1</li>
<li>kernel 3.12.0</li>
<li>chaîne de compilation croisée : buildroot-uclibc</li>
</ul>
<br />
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">
Installation de python 3</h3>
<div>
<br /></div>
<div>
Tant qu'à faire, autan utiliser la dernière version de python. :)</div>
<div>
Le package python 3 est déjà présent sur l'environnement buildroot, il faut simplement le sélectionner dans via le menu et le tour est joué.</div>
<br />
<pre class="brush: shell"># make menuconfig
</pre>
<br />
Puis de lancer la compilation avec la commande <b>make</b> :<br />
<br />
<pre class="brush: shell"># make
</pre>
<br />
<h3 style="text-align: left;">
Modification d'un package buildroot</h3>
<br />
Pour s'interfacer avec le bus I2C via un module python, on va utiliser le package <span style="font-family: Courier New, Courier, monospace;"><b>i2c-tools</b></span> version 3.1.0 déjà présent dans les packages buildroot, mais la librairie python <span style="font-family: Courier New, Courier, monospace;"><b>smbus</b></span> n'est pas compilée par défaut, il va falloir l'activer et modifier le makefile pour faire fonctionner tout ça.<br />
<br />
Tout d'abord télécharger les fichiers correctifs (<a href="https://drive.google.com/file/d/0B6WDjVnTAZgFd2Y0NUhDdng1Zms/edit?usp=sharing">i2c-tools.tar.gz</a>) à désarchiver et à insérer dans le dossier package/i2c-tools :<br />
<br />
<pre class="brush: shell"># rm package/i2c-tools
# tar i2c-tools.tar.gz -C package
# ls package/i2c-tools
Config.in i2c-tools-001-smbusmodule.patch i2c-tools.mk
</pre>
<br />
Cette archive comprend :<br />
<ul style="text-align: left;">
<li><b>Config.in</b> : Le fichier de configuration pour le menu buildroot</li>
<li><b>i2c-tools-001-smbusmodule.patch</b> : Un patch du fichier source smbusmodule.c pour faire fonctionner smbus avec python 3</li>
<li><b>i2c-tools.mk</b> : Le fichier de fabrication des exécutables pour jouer avec les ports I2C présents et du module python.</li>
</ul>
Les lignes surlignées sont celles rajoutées par rapport au fichier original.<br />
<br />
<pre class="brush: shell; highlight: [12, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35];">####################################################################
#
# i2c-tools
#
####################################################################
I2C_TOOLS_VERSION = 3.1.0
I2C_TOOLS_SOURCE = i2c-tools-$(I2C_TOOLS_VERSION).tar.bz2
I2C_TOOLS_SITE = http://dl.lm-sensors.org/i2c-tools/releases
I2C_TOOLS_DEPENDENCIES = python3 host-python3
# LDSHARED and PYTHON VAR ENV from $(HOST_DIR)/usr/bin/python3 -m sysconfig
define I2C_TOOLS_BUILD_CMDS
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D)
(cd $(@D)/py-smbus; \
PYTHONXCPREFIX="$(STAGING_DIR)/usr" \
CC="$(TARGET_CC)" \
CFLAGS="-fno-strict-aliasing -pthread -Wno-unused-result -DNDEBUG -g -fwrapv -O3 -Wall -O2 -I$(STAGING_DIR)/usr/include/python3.3m $(CFLAGS)" \
CPPFLAGS="$(CPPFLAGS) -I../include" \
LDFLAGS="-L$(STAGING_DIR)/lib -L$(STAGING_DIR)/usr/lib" \
LDSHARED="$(TARGET_CC) -pthread -shared $(LDFLAGS) -Wl,-rpath,-L$(STAGING_DIR)/usr/lib" \
$(HOST_DIR)/usr/bin/python3 setup.py build)
endef
define I2C_TOOLS_INSTALL_TARGET_CMDS
for i in i2cdump i2cget i2cset i2cdetect; \
do \
$(INSTALL) -m 755 -D $(@D)/tools/$$i $(TARGET_DIR)/usr/bin/$$i; \
done
(cd $(@D)/py-smbus; \
PYTHONPATH="$(TARGET_DIR)/usr/lib/python3.3/site-packages" \
$(HOST_DIR)/usr/bin/python3 setup.py install --prefix=$(TARGET_DIR)/usr)
endef
$(eval $(generic-package))
</pre>
<br />
Une fois la modification faite, il suffit de selectionner le package i2c-tools dans le menu de buildroot grâce à la commande :<br />
<br />
<pre class="brush: shell"># make menuconfig
</pre>
<br />
Puis de lancer la commande :<br />
<br />
<pre class="brush: shell"># make
</pre>
<br />
Normalement, sur le système de fichiers, vous devriez avoir les fichiers dans le dossier <span style="font-family: Courier New, Courier, monospace;"><b>/usr/lib/python3.3/site-packages</b></span> :<br />
<br />
<ul style="text-align: left;">
<li>smbus.cpython-33m.so : La librairie compilée</li>
<li>smbus-1.1-py3.3.egg-info : Le module python smbus</li>
</ul>
<div>
<br /></div>
<h3 style="text-align: left;">
Python 3 et module I2C</h3>
<div>
<br /></div>
<div>
Pour pouvoir utiliser le nouveau module fraîchement installé, il faut activer le module i2c sur la raspberry pi, pour ceci, la commande modprobe va nous permettre de lancer les modules :</div>
<br />
<pre class="brush: shell"># modprobe -a i2c-bcm2708 i2c-dev
</pre>
<br />
Ce qui va permettre de créer les nœuds <span style="font-family: Courier New, Courier, monospace;"><b>/dev/i2c-0</b></span> et <b><span style="font-family: Courier New, Courier, monospace;">/dev/i2c-1.</span></b><br />
<div>
</div>
Ensuite pour tester si le bus I2C est fonctionnel, il faut lancer l'exécutable de détection :<br />
<pre class="brush: shell"># i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --
</pre>
<br />
Notre module LCD est bien vu par la raspberry pi à l'adresse 0x76 sur le bus 0<br />
<br />
L'utilisation du module est simple, voici un premier exemple :<br />
<br />
<pre class="brush: python">#!/usr/bin/python3
from smbus import SMBus
# Adresse de notre module LCD
lcd_addr = 0x76
# Utilisation du bus 0
bus = SMBus(0)
# Clear LCD display
bus.write_i2c_block_data(lcd_addr, 0x01, 0x02)
</pre>
<br />
Suivant la messagerie codée sur le micro-contrôleur PIC pour la gestion de l'écran LCD, j'ai codé cette petite librairie permettant d'avoir accès aux fonctionnalités.<br />
<br />
fichier i2c_lib.py :<br />
<br />
<pre class="brush: python">#############################################################
# Importation de modules externes :
import smbus
from time import *
#############################################################
# Class et Methods :
class i2c_device:
""" I2C Class interface
"""
def __init__(self, addr, port=0):
self.addr = addr
self.bus = smbus.SMBus(port)
def write_cmd(self, cmd):
""" Write a single command
"""
self.bus.write_byte(self.addr, cmd)
sleep(0.01)
def write_cmd_arg(self, cmd, data):
""" Write a command and argument
"""
self.bus.write_byte_data(self.addr, cmd, data)
sleep(0.01)
def write_block_data(self, cmd, data):
""" Write a block of data
"""
self.bus.write_block_data(self.addr, cmd, data)
sleep(0.01)
def write_i2c_datas(self, cmd, datas):
""" Write datas
"""
if isinstance(datas, list) and isinstance(cmd, int):
self.bus.write_i2c_block_data(self.addr, cmd, datas)
sleep(0.01)
def read(self):
""" Read a single byte
"""
return self.bus.read_byte(self.addr)
def read_data(self, cmd):
""" Read
"""
return self.bus.read_byte_data(self.addr, cmd)
def read_block_data(self, cmd):
""" Read a block of data
"""
return self.bus.read_block_data(self.addr, cmd)
</pre>
<br />
fichier lcd_2x16.py :<br />
<br />
<pre class="brush: python">#############################################################
# Importation de modules externes :
import sys
sys.path.append(".")
from i2c_lib import i2c_device
#############################################################
# Class et Methods :
class lcd_2x16:
""" Classe de contrôle de l'affichage de l'écran alpha 2x16 caractères
via le bus i2c
------------------------------//-------
| Frame Id | Frame Size | Frame datas |
------------------------------//-------
Identifiants :
--------------
0x01 : Clear Display
0x02 : Return home
0x03 : Set Cursor
0x04 : Put character
0x05 : Put string
0x06 : Control Display
"""
LCD_ID_CLEAR_DISPLAY = 0x01
LCD_ID_RETURN_HOME = 0x02
LCD_ID_SET_CURSOR = 0x03
LCD_ID_PUT_CHAR = 0x04
LCD_ID_PUT_STR = 0x05
LCD_ID_CONTROL_DISPLAY = 0x06
def __init__(self, addr=0x76, port=0):
self.i2c_lib_obj = i2c_device(addr, port)
def clear_display(self):
""" Efface les informations ecrites sur l'écran LCD
"""
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_CLEAR_DISPLAY, [0x02])
def return_home(self):
""" Retourne le curseur à la position Row = 1, column = 1
"""
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_RETURN_HOME, [0x02])
def set_cursor(self, row, column):
""" Deplace le curseur à la position souhaitée
"""
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_SET_CURSOR, [0x04, row, column])
def put_char(self, char):
""" Insert un caractère à la position courante du curseur
"""
if isinstance(char, str) and len(char) is 1:
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_PUT_CHAR, [0x03, ord(char)])
else:
print('Error with argument ...')
def put_str(self, string):
""" Insert une chaîne de caractères à la position courante du curseur
"""
if isinstance(string, str) and len(string) <= 16:
str_len = 2 + len(string)
lst_str = [ord(char) for char in string]
lst_str.insert(0, len(string) + 2)
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_PUT_STR, lst_str)
def control_display(self, display, cursor, blink):
""" Change les paramètres de l'écran
"""
self.i2c_lib_obj.write_i2c_datas(self.LCD_ID_CONTROL_DISPLAY, [0x05, display, cursor, blink])
</pre>
<br />
Il suffit d'importer le module <b><span style="font-family: Courier New, Courier, monospace;">lcd_2x16.py</span></b> dans vos sources et d'instancier la classe lcd_2x16 pour interagir avec l'écran LCD.<br />
<br />
Amusez-vous bien ...
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-62267576699601954432013-11-29T13:50:00.001+01:002013-11-29T13:50:14.587+01:00Buildroot 2013.08.1 & Raspberry Pi<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihGJ8QW9djLKQRHm_zEIpk1_92HW4hV8-CS9IKd9rXeP0OQmhcKW1PYarWNbI7Mv8CreM41y6CLld2iQPN_ACx8CvcwtaXGSW3vg-ghG5TS0tWgTT5wKSwR1lP5yfFJS9C64H8yNFXfJ8/s1600/buildroot.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihGJ8QW9djLKQRHm_zEIpk1_92HW4hV8-CS9IKd9rXeP0OQmhcKW1PYarWNbI7Mv8CreM41y6CLld2iQPN_ACx8CvcwtaXGSW3vg-ghG5TS0tWgTT5wKSwR1lP5yfFJS9C64H8yNFXfJ8/s320/buildroot.jpg" width="320" /></a></div>
Après plusieurs mois d'absence et un nouvel hobby qui prend du temps: être Papa ;-) je reviens pour compléter mon blog sur les systèmes embarqués.<br />
<br />
Ce billet sera simplement consacré à la création d'un environnement embarqué complet à partir de la dernière version de buildroot 2013.08.1.<br />
<br />
Cette nouvelle version de buildroot va apporter beaucoup plus de simplicité que les précédentes versions ...<br />
<br />
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">
Au revoir Crosstool-NG, bonjour Buildroot toolchain ...</h3>
<div>
<br /></div>
<div>
La dernière version de buildroot (2013.08.1) est téléchargeable <a href="http://buildroot.uclibc.org/downloads/buildroot-2013.08.1.tar.gz">ici</a>.</div>
<div>
Après décompression, si on inspecte le dossier <span style="font-family: Courier New, Courier, monospace;"><b>configs</b></span> comprenant toutes les configurations fournies avec l'environnement, on se rend compte qu'il existe le fichier : <span style="font-family: Courier New, Courier, monospace; font-weight: bold;">rpi_defconfig</span><span style="font-family: Arial, Helvetica, sans-serif;">.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<pre class="brush: shell"># tar xvzf buildroot-2013.08.1.tar.gz
# cd buildroot-2013.08.1
# cd configs/
# ls
arm_foundationv8_defconfig atngw100_defconfig fdi3250_defconfig pandaboard_defconfig qemu_ppc_mpc8544ds_defconfig
armadeus_apf27_defconfig atstk100x_defconfig freescale_mpc8315erdb_defconfig phy3250_defconfig qemu_ppc_virtex_ml507_defconfig
armadeus_apf28_defconfig beaglebone_defconfig freescale_p1010rdb_defconfig qemu_arm_nuri_defconfig qemu_sh4_r2d_defconfig
armadeus_apf9328_defconfig calao_qil_a9260_defconfig gnublin_defconfig qemu_arm_versatile_defconfig qemu_sparc_ss10_defconfig
at91rm9200df_defconfig calao_snowball_defconfig integrator926_defconfig qemu_arm_vexpress_defconfig qemu_x86_64_defconfig
at91sam9260dfc_defconfig calao_tny_a9g20_lpw_defconfig kb9202_defconfig qemu_microblazebe_mmu_defconfig qemu_x86_defconfig
at91sam9260eknf_defconfig calao_usb_a9260_defconfig mini2440_defconfig qemu_microblazeel_mmu_defconfig rpi_defconfig
at91sam9261ek_defconfig calao_usb_a9263_defconfig mx53loco_defconfig qemu_mips64_malta_defconfig s6lx9_microboard_defconfig
at91sam9263ek_defconfig calao_usb_a9g20_lpw_defconfig nitrogen6x_defconfig qemu_mips_malta_defconfig sheevaplug_defconfig
at91sam9g20dfc_defconfig cubieboard_defconfig olimex_imx233_olinuxino_defconfig qemu_mipsel_malta_defconfig telit_evk_pro3_defconfig
at91sam9g45m10ek_defconfig ea3250_defconfig openblocks_a6_defconfig qemu_ppc_g3beige_defconfig
</pre>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span><br />
Nous allons utiliser cette config validée par les devs de buildroot.<br />
Cette version de buildroot a la particularité d'avoir supprimé la gestion de la chaîne de compilation croisée par l'outil externe crosstool-ng et dispose de son propre outil de création de chaîne de compilation basé sur une uclibc (micro-c libc).<br />
<br />
<pre class="brush: shell"># make rpi_defconfig
mkdir -p /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/lxdialog
make CC="/usr/bin/gcc" HOSTCC="/usr/bin/gcc" obj=/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config -C support/kconfig -f Makefile.br conf
make[1]: Entering directory '/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/support/kconfig'
/usr/bin/gcc -DCURSES_LOC="<ncurses .h="">" -DLOCALE -I/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config -DCONFIG_=\"\" -MM *.c > /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/.depend 2>/dev/null || :
/usr/bin/gcc -DCURSES_LOC="<ncurses .h="">" -DLOCALE -I/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config -DCONFIG_=\"\" -c conf.c -o /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/conf.o
/usr/bin/gcc -DCURSES_LOC="<ncurses .h="">" -DLOCALE -I/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config -DCONFIG_=\"\" -I. -c /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/zconf.tab.c -o /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/zconf.tab.o
In file included from /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/zconf.tab.c:2500:0:
./confdata.c: In function ‘conf_split_config’:
./confdata.c:849:6: attention : assignment makes pointer from integer without a cast [enabled by default]
dir = dirname(_name);
^
/usr/bin/gcc -DCURSES_LOC="<ncurses .h="">" -DLOCALE -I/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config -DCONFIG_=\"\" /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/conf.o /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/zconf.tab.o -o /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/conf
rm /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/output/build/buildroot-config/zconf.tab.c
make[1]: Leaving directory '/home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/support/kconfig'
#
# configuration written to /home/vbenoit/PERSO/raspberry_pi/buildroot/buildroot_python/.config
#
</ncurses></ncurses></ncurses></ncurses></pre>
<br />
puis faire un petit make pour la génération de l'environnement complet. N'hésitez pas à aller chercher un café, ça peut prendre du temps.<br />
<br />
<pre class="brush: shell"># make
</pre>
<br />
<h3 style="text-align: left;">
finalement ...</h3>
<br />
En inspectant le dossier <span style="font-family: Courier New, Courier, monospace;"><b>output/images</b></span>, on retrouve deux fichiers et un dossier :<br />
<br />
<ul style="text-align: left;">
<li><b>zImage</b> : Le noyau linux a copier dans la partition boot (fat32) de la carte SD.</li>
<li><b>rootfs.tar</b> : Le système de fichiers archivé à désarchiver dans la partition rootfs (ext4) de la carte SD.</li>
<li><b>rpi-firmware</b> : Les binaires a copier dans la partition boot (fat32) de la carte SD.</li>
</ul>
<br />
Voila, pas plus, pas moins. Amusez-vous bien.</div>
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com5Toulouse, France43.604652 1.444209000000000743.420672 1.1214855000000008 43.788632 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-5466100043579003642013-03-13T18:30:00.000+01:002013-03-13T18:55:35.269+01:00Cortex M4 - Premiers Pas avec des outils Opensource<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: left;">
<a href="http://dangerousprototypes.com/forum/download/file.php?id=8639&t=1" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="http://dangerousprototypes.com/forum/download/file.php?id=8639&t=1" width="200" /></a></div>
Je suis parti à la découverte des micros Cortex M4 lors de l'achat d'une carte de démonstration STM32F3 discovery pour une dizaine d'euros.<br />
<br />
Cette "demo board" embarque plusieurs choses très intéressantes, notamment, un MCU STM32F303VCT6 32 bits Cortex M4, un ST-LINK v2 (outil de programmation et de debug), un Gyroscope, Un compas avec un accéléromètre, plusieurs leds et boutons et deux connecteurs mini USB. Bref, tout pour commencer à s’amuser.<br />
<br />
<br />
<br />
<br />
Un programme de démonstration tourne déjà sur la carte et permet de s'amuser avec les différents composants (Chenillard, gyroscope et accéléromètre avec la roue de Leds).<br />
<br />
Après lecture de la documentation téléchargeable sur le site de <a href="http://www.st.com/web/en/catalog/tools/PF254044?s_searchtype=keyword">ST microelectronics</a>. J'ai fait particulièrement attention aux différents outils de développement proposés avec la carte. 4 choix possibles :<br />
<br />
<ul style="text-align: left;">
<li><a href="http://www.tasking.com/products/arm/">Altium®, TASKINGTM VX-toolset</a> : Outil payant (environ 1500 euros) avec version d'essai.</li>
<li><a href="http://www.atollic.com/index.php/truestudio">ARM®, Atollic TrueSTUDIO®</a> : Outil payant avec version d'essai.</li>
<li><a href="https://www.iar.com/en/Products/IAR-Embedded-Workbench/">IAR, EWARM (IAR Embedded Workbench®)</a> : Outil payant avec version d'essai 30 jours.</li>
<li><a href="http://www.keil.com/arm/mdk.asp">Keil, MDK-ARM</a> : Outil payant avec version d'essai.</li>
</ul>
<br />
Vous l'aurez compris, j'ai choisi la cinquième option. Elle consiste à utiliser des outils Open source pour toute la chaîne de développement.<br />
<br />
Ce premier post sur le cortex M4 va consister à montrer les différents outils nécessaires au développement, à la programmation et au débogage.<br />
<br />
<ul style="text-align: left;">
<li>Création d'une chaîne de compilation croisée GNU custom pour le micro.</li>
<li>Création d'un Template de compilation (Makefile, etc ...).</li>
<li>Utilisation et comparaison avec une chaîne de compilation croisée GNU téléchargeable.</li>
<li>Installation et utilisation de l'outil de programmation sous linux (non-officiel) et sous windows (officiel)</li>
<li>Installation et utilisation de l'outil OpenOCD pour le débogage.</li>
</ul>
<div>
<a name='more'></a><br /></div>
<h3 style="text-align: left;">
CMSIS : Qu'est ce que c'est ?</h3>
<br />
Avant de répondre à cette question <strike>existentielle</strike>, on va revenir sur <a href="http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stm32f3discovery_fw.zip">l'archive</a> fournie par ST avec la démo board. Elle fournit les sources de la démo installée sur la carte ainsi que différents exemples sur l'utilisation et l'interfaçage des périphériques du micro.<br />
<br />
<pre class="brush: shell"># cd STM32F3-Discovery_FW_V1.1.0
# ls -al
total 100
drwxrwxr-x 6 sinseman44 sinseman44 4096 2013-02-25 19:30 ./
drwxr-xr-x 17 sinseman44 sinseman44 4096 2013-02-27 21:27 ../
drwxrwxr-x 2 sinseman44 sinseman44 4096 2013-02-25 19:30 _htmresc/
drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 Libraries/
-r--r--r-- 1 sinseman44 sinseman44 17797 2012-09-07 13:14 MCD-ST Liberty SW License Agreement V2.pdf
drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 Project/
-r--r--r-- 1 sinseman44 sinseman44 39158 2012-09-27 15:05 Release_Notes.html
drwxrwxr-x 3 sinseman44 sinseman44 4096 2013-02-25 19:30 Utilities/
</pre>
<br />
Dans le dossier Libraries, contient le fameux dossier CMSIS, ainsi que le dossier <i>STM32F30x_StdPeriph_Driv</i> contenant les drivers (sources) des périphériques présents sur la carte et le dossier <i>STM32_USB-FS-Device_Driv</i> contenant la librairie de la pile de communication USB de la carte.<br />
<br />
<pre class="brush: shell"># cd Libraries
total 20
drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 ./
drwxrwxr-x 6 sinseman44 sinseman44 4096 2013-02-25 19:30 ../
drwxrwxr-x 9 sinseman44 sinseman44 4096 2013-02-25 19:28 CMSIS/
drwxrwxr-x 4 sinseman44 sinseman44 4096 2013-02-25 19:28 STM32F30x_StdPeriph_Driver/
drwxrwxr-x 4 sinseman44 sinseman44 4096 2013-02-25 19:28 STM32_USB-FS-Device_Driver/
</pre>
<br />
J'ai voulu m’intéresser plus particulièrement au dossier CMSIS parce qu'il a une particularité très intéressante.<br />
CMSIS pour <i>ARM Cortex Microcontroller Software Interface Standard</i> est une couche d'abstraction bas niveau, comprenez hardware, indépendante du constructeur pour les séries de micro contrôleur Cortex. Ce qui signifie, que quelque soit le constructeur de micro contrôleur Cortex M0, Cortex M3 ou Cortex M4 (ST, NXP, etc ...), la couche d'abstraction CMSIS sera, à un ou deux détails près, la même.<br />
Dans le cas de travaux hobbyistes, tels que les miens, ce n'est pas très important, mais pour des sociétés voulant changer de micro contrôleur sur leurs cartes en passant d'un fabricant à un autre pour des raisons de pérennité ou pour passer sur une série plus puissante, cela peut considérablement réduire les coûts de développement.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://mcuoneclipse.files.wordpress.com/2013/02/cmsis-version-3-block-diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="http://mcuoneclipse.files.wordpress.com/2013/02/cmsis-version-3-block-diagram.png" width="400" /></a></div>
<br />
Dans le dossier CMSIS, se trouve les sous dossiers :<br />
<br />
<ul style="text-align: left;">
<li><i>CMSIS-CORE</i> : offre une interface avec l'architecture matérielle du micro contrôleur ainsi que les registres, les définitions des noms, des adresses. Il contient, également, une interface indépendante pour les noyaux temps réel (RTOS) qui inclus des définitions de débogage.</li>
<li><i>CMSIS-DSP</i> : Suite de sources, codées en C, de nombreuses fonctions pour le traitement de signaux basée sur l'architecture Cortex.</li>
<li><i>CMSIS-RTOS API</i> : Interface de programmation standardisé pour les OS temps réel (Thread control, resource, time management, ...)</li>
<li><i>CMSIS-SVD</i> (System View Description) : Fichiers XML contenant une vue complete du micro contrôleur incluant les périphériques externes.</li>
</ul>
<div>
<br /></div>
<h3 style="text-align: left;">
Chaîne de compilation croisée custom</h3>
<br />
Pour construire notre chaîne de compilation, on va se servir de l'outil <a href="http://crosstool-ng.org/">Crosstool-NG</a>. Pour ceux qui suivent ce blog, il fait partie de la suite de logiciels contenue dans buildroot.<br />
Cet outil a pour but de construire une chaîne de compilation croisée en fonction des différents paramètres donnés.<br />
<br />
Je vous file le fichier de <a href="https://docs.google.com/file/d/0B6WDjVnTAZgFRWk3aXpweFZhQVE/edit?usp=sharing">config</a>.<br />
<br />
L'archive de l'outil (<a href="http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.18.0.tar.bz2">crosstool-ng-1.18.0.tar.bz2</a>) doit être téléchargée puis installée :<br />
<pre class="brush: shell"># tar xvjf crosstool-ng-1.18.0.tar.bz2
# cd crosstool-ng-1.18.0
# ./bootstrap
# ./configure
# make
# make install
</pre>
<br />
Puis dans le dossier d'installation de Crosstool-NG, lancer l'outil :<br />
<pre class="brush: shell"># cd <CROSSTOOL_NG_INSTALL_PATH>
# cd bin</pre>
<pre class="brush: shell">=> Pour ceux qui ont téléchargé le fichier de config
# mv cortexM4_config .config</pre>
<pre class="brush: shell"># ./ct-ng menuconfig
</pre>
<br />
L'un des sous dossiers important est <i>Target options</i> :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibjTru7xjkVxjRSaopvnzkhPDugskTBd8Xqwxw9jdaePXn6LBAE2P7Jdk6TSUIFUYjEy3Y4QTZjo2NgsKnG50ZwxsF5NbSFx1pf8ikQ3Y4gjM3DcccxuKomKJWvNqVkhTWxOqGc_rJnZs/s1600/ctng_cortexM4_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibjTru7xjkVxjRSaopvnzkhPDugskTBd8Xqwxw9jdaePXn6LBAE2P7Jdk6TSUIFUYjEy3Y4QTZjo2NgsKnG50ZwxsF5NbSFx1pf8ikQ3Y4gjM3DcccxuKomKJWvNqVkhTWxOqGc_rJnZs/s640/ctng_cortexM4_1.png" width="580" /></a></div>
<br />
Ce sous dossier permet de configurer l'architecture matérielle du micro contrôleur.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHPunel6odit8e9gGMwlLrIqaY8DFKNR4GUAjRAGBcPR2xLzFXcYfqHPWoYig5IRxzFuOL2lKFhgI6A7vjIvuO61n8PFewxa4-OFy50PClCtQC3S3AjxkIkE76NiHQYTj-SnmIupz7xq0/s1600/ctng_cortexM4_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="388" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHPunel6odit8e9gGMwlLrIqaY8DFKNR4GUAjRAGBcPR2xLzFXcYfqHPWoYig5IRxzFuOL2lKFhgI6A7vjIvuO61n8PFewxa4-OFy50PClCtQC3S3AjxkIkE76NiHQYTj-SnmIupz7xq0/s640/ctng_cortexM4_2.png" width="580" /></a></div>
<br />
Le sous dossier <i>Operating System</i> :<br />
<br />
<b>bare-metal</b> signifie que le software est exécuté directement depuis la mémoire vive, sur le système, au lieu d'être chargé en tant que tâche d'un OS.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGLUBzCTDl-Xhlriqsf-7jdk3spolbR3qzKvkfeqv5Djhw8Cx_ayKTL7VsM44B9OGh4_Q57Z0DrFXQSHforx5i70eB_0YNe8pHSW12gV6D3IrkVBSJfogQoGt4LZkjLqjov89tCFo3YjY/s1600/ctng_cortexM4_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGLUBzCTDl-Xhlriqsf-7jdk3spolbR3qzKvkfeqv5Djhw8Cx_ayKTL7VsM44B9OGh4_Q57Z0DrFXQSHforx5i70eB_0YNe8pHSW12gV6D3IrkVBSJfogQoGt4LZkjLqjov89tCFo3YjY/s640/ctng_cortexM4_3.png" width="580" /></a></div>
<br />
Le sous dossier <i>C compiler</i> :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaL56vUfyPUXCqWYQEY7d0egErtRtBvKUqjDUp_17-wSfnAQAYKeJ9KFGjGUpygSiLKbuzOhtrngu6LmG7lOz4JfR1CRkNo7P_VNXjpkT5It9mQjtUHW5Vzb8RNMvjSpgxcP1Dlm9ne-I/s1600/ctng_cortexM4_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaL56vUfyPUXCqWYQEY7d0egErtRtBvKUqjDUp_17-wSfnAQAYKeJ9KFGjGUpygSiLKbuzOhtrngu6LmG7lOz4JfR1CRkNo7P_VNXjpkT5It9mQjtUHW5Vzb8RNMvjSpgxcP1Dlm9ne-I/s640/ctng_cortexM4_4.png" width="580" /></a></div>
<br />
Après la configuration, il suffit de lancer la commande pour construire la chaîne de compilation :<br />
<pre class="brush: shell"># ./ct-ng build
</pre>
<br />
(Attention, cette étape peut-être longue, quelques dizaines de minutes, en fonction des capacités de votre ordinateur)<br />
<br />
Une fois la compilation faite, voici le dossier d'installation de cette nouvelle chaîne :<br />
<pre class="brush: shell"># cd <x-tools>
total 320
dr-xr-xr-x 8 sinseman44 sinseman44 4096 2013-02-27 18:40 ./
drwxr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 16:34 ../
dr-xr-xr-x 6 sinseman44 sinseman44 4096 2013-02-27 17:58 arm-unknown-eabi/
dr-xr-xr-x 2 sinseman44 sinseman44 12288 2013-02-27 18:40 bin/
-r--r--r-- 1 sinseman44 sinseman44 278144 2013-02-27 18:40 build.log.bz2
dr-xr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 18:40 include/
dr-xr-xr-x 4 sinseman44 sinseman44 4096 2013-02-27 18:40 lib/
dr-xr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 18:31 libexec/
dr-xr-xr-x 4 sinseman44 sinseman44 4096 2013-02-27 18:40 share/
</pre>
<br />
<h3 style="text-align: left;">
Template de compilation</h3>
<br />
Le Template va permettre de créer un projet générique ou il n'y aura plus qu'à y insérer les sources du projet et à modifier le makefile. Il est basé sur un déjà existant, adapté pour l'occasion : <br />
<br />
<div id="repo1">
</div>
<script>
$('#repo1').repo({ user: 'mblythe86', name: 'stm32f3-discovery-basic-template' });
</script><br />
<br />
Voici l'arborescence de notre Template nécessaire pour la compilation :<br />
<br />
<ul style="text-align: left;">
<li>dossier <i>Device</i> : contient le code de démarrage de la carte ainsi que le script de linkage</li>
<li>dossier <i>extra</i> : contient les utilitaires nécessaires pour le flashage et le débogage du projet</li>
<li>dossier <i>src</i> : contient les fichiers sources du projet</li>
<li>dossier <i>inc</i> : contient les headers des fichiers sources</li>
<li>Makefile : fichier de compilation</li>
</ul>
<br />
Le dossier <i>Libraries</i> a volontairement disparu puisque je vais utiliser les librairies fournies avec la démo board de chez ST.<br />
<br />
Voici l'arborescence après compilation :<br />
<ul style="text-align: left;">
<li>dossier <i>Device</i> : contient le code de démarrage de la carte ainsi que le script de linkage</li>
<li>dossier <i>extra</i> : contient les utilitaires nécessaires pour le flashage et le débogage du projet</li>
<li>dossier <i>bins</i> : contient les binaires (fichier HEX, fichier ELF, fichier BIN, fichier MAP, etc ...) générés du projet.</li>
<li>dossier <i>inc</i> : contient les headers des fichiers sources</li>
<li>dossier <i>deps</i> : contient les dépendances générées lors de la compilation</li>
<li>dossier <i>objs</i> : contient les fichiers objets générés lors de la compilation</li>
<li>dossier <i>src</i> : contient les fichiers sources du projet</li>
<li>Makefile : fichier de compilation</li>
<li>libstm32f3.a : librairie statique compilée des sources des périphériques du micro</li>
</ul>
<div style="text-align: left;">
<br /></div>
<h4 style="text-align: left;">
Quelques explications sur le fichier de linkage et le code de démarrage :</h4>
<br />
La séquence de démarrage pour un système "<i>bare-metal</i>" de type ARM est contenu dans un fichier startup.s. Toutes les séquences d'initialisation bas niveau pour le CPU, la carte, écrite en C ou en assembleur, sont présents.<br />
Le script de linkage regroupe les informations du code de démarrage, et définit la "map" mémoire du système cible. Il a comme extention .ld.<br />
<br />
Pour les plus courageux, voici un peu de documentation (<a href="https://docs.google.com/file/d/0B6WDjVnTAZgFbmJiZk9rZ1ZMVXc/edit?usp=sharing">Building_bare-metal_ARM_with_GNU.pdf</a>) sur le sujet.<br />
<br />
Maintenant le fichier de compilation, Makefile. Il faut modifier les variables :<br />
<br />
<ul>
<li><b>SRCS</b> : contient les noms des fichiers sources à compiler.</li>
<li><b>SRCS_PERIPH</b> : contient les noms des fichiers sources des drivers des différents périphériques de la démo board.</li>
<li><b>PROJ_NAME</b> : Le nom du projet qui sera utilisé comme nom de binaires.</li>
<li><b>STD_PERIPH_LIB</b> : Le chemin des librairies fournies avec la démo board.</li>
<li><b>LDSCRIPT_INC</b> : Le chemin du script de linkage.</li>
<li><b>OPENOCD_BOARD_DIR</b> : Le chemin des scripts de configuration de carte pour OpenOCD.</li>
<li><b>OPENOCD_PROC_FILE</b> : Le chemin des directives de lancement d'OpenOCD.</li>
<li><b>TOOLCHAIN</b> : Le chemin de la chaîne de compilation croisée.</li>
<li><b>TOOLCHAIN_TARGET</b> : Le préfixe de la chaîne de compilation croisée.</li>
</ul>
<div>
<br /></div>
<br />
<pre class="brush: bash"># put your *.c source files here, make should handle the rest!
SRCS = main.c errno.c stm32f3_discovery.c system_stm32f30x.c
# Periph driver sources
SRCS_PERIPH = stm32f30x_adc.c stm32f30x_can.c stm32f30x_comp.c stm32f30x_crc.c \
stm32f30x_dac.c stm32f30x_dbgmcu.c stm32f30x_dma.c \
stm32f30x_exti.c stm32f30x_flash.c stm32f30x_gpio.c \
stm32f30x_i2c.c stm32f30x_iwdg.c stm32f30x_misc.c stm32f30x_opamp.c \
stm32f30x_pwr.c stm32f30x_rcc.c stm32f30x_rtc.c stm32f30x_spi.c \
stm32f30x_syscfg.c stm32f30x_tim.c stm32f30x_usart.c \
stm32f30x_wwdg.c usb_core.c usb_init.c usb_int.c usb_mem.c \
usb_regs.c usb_sil.c
# all the files will be generated with this name (main.elf, main.bin, main.hex, etc)
PROJ_NAME=blink_led
# Location of the Libraries folder from the STM32F3 Standard Peripheral Library
STD_PERIPH_LIB=<PATH_TO_LIBRARIES_FILES>/STM32F3-Discovery_FW_V1.1.0/Libraries
# Location of the linker scripts
LDSCRIPT_INC=Device/ldscripts
# location of OpenOCD Board .cfg files (only used with 'make program')
OPENOCD_BOARD_DIR=<PATH_TO_OPENOCD_BOARD_SCRIPT>
# Configuration (cfg) file containing programming directives for OpenOCD
OPENOCD_PROC_FILE=extra/stm32f3-openocd.cfg
# toolchain path
TOOLCHAIN=<PATH_TO_TOOLCHAIN>/gcc-arm-none-eabi-4_7-2012q4/bin
TOOLCHAIN_TARGET=$(TOOLCHAIN)/arm-none-eabi-
# that's it, no need to change anything below this line!
###################################################
CC = $(TOOLCHAIN_TARGET)gcc
GDB = $(TOOLCHAIN_TARGET)gdb
OBJCOPY = $(TOOLCHAIN_TARGET)objcopy
OBJDUMP = $(TOOLCHAIN_TARGET)objdump
SIZE = $(TOOLCHAIN_TARGET)size
LIB = libstm32f3.a
CFLAGS = -Wall -g -std=c99 -Os
#CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb
#CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections -Wl,-Map=bins/$(PROJ_NAME).map
###################################################
vpath %.a $(STD_PERIPH_LIB)
vpath %.c $(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/src
vpath %.c $(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/src
vpath %.c src
ROOT=$(shell pwd)
CFLAGS += -Iinc
CFLAGS += -I$(STD_PERIPH_LIB)
CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Device/ST/STM32F30x/Include
CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Include
CFLAGS += -I$(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/inc
CFLAGS += -I$(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/inc
CFLAGS += -DUSE_STDPERIPH_DRIVER
STARTUP = Device/startup_stm32f30x.s # add startup file to build
OBJS = $(addprefix objs/,$(SRCS:.c=.o))
DEPS = $(addprefix deps/,$(SRCS:.c=.d))
OBJS_PERIPH = $(addprefix objs/,$(SRCS_PERIPH:.c=.o))
DEPS_PERIPH = $(addprefix deps/,$(SRCS_PERIPH:.c=.d))
###################################################
.PHONY: all lib proj program debug clean reallyclean
all: $(LIB) proj
-include $(DEPS)
$(LIB): $(OBJS_PERIPH)
@echo [AR] $@
@$(AR) -r $@ $(OBJS_PERIPH)
proj: bins/$(PROJ_NAME).elf
dirs:
@mkdir -p deps objs bins
@touch dirs
objs/%.o : %.c dirs
@echo [OBJ] $<
@$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF deps/$(*F).d
bins/$(PROJ_NAME).elf: $(OBJS)
@$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(STARTUP) -L$(STD_PERIPH_LIB) -L. -lstm32f3 -L$(LDSCRIPT_INC) -Tstm32f3.ld
@$(OBJCOPY) -O ihex bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).hex
@$(OBJCOPY) -O binary bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).bin
@$(OBJDUMP) -St bins/$(PROJ_NAME).elf > bins/$(PROJ_NAME).lst
@$(SIZE) bins/$(PROJ_NAME).elf
program: all
@openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown
debug: program
@$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf
clean:
@echo [CLEAN]
@find ./ -name '*~' | xargs rm -f
@rm -rf objs
@rm -rf deps
@rm -rf bins
@rm -f dirs
@rm -f $(LIB)
reallyclean: clean
@$(MAKE) -C $(STD_PERIPH_LIB) clean
</pre>
<br />
Deux étapes sont nécessaires pour la compilation du projet, la première, compilation des sources des drivers périphériques et création d'une librairie statique et la deuxième, compilation des sources du projet et linkage avec la librairie statique.<br />
<br />
Différentes sous-commandes sont présentes, dans ce Makefile, pour faciliter la compilation du projet, la programmation du micro contrôleur et le débogage de celui-ci.<br />
<br />
Compilation du projet :<br />
<pre class="brush: bash"># make clean all
</pre>
<br />
Programmation de la cible :<br />
<pre class="brush: bash"># make program
</pre>
<br />
Débogage de la cible :<br />
<pre class="brush: bash"># make debug
</pre>
<br />
<h3 style="text-align: left;">
Chaîne de compilation croisée GNU</h3>
<br />
Bien sur, il n'est pas nécessaire de créer sa propre chaîne de compilation, il est possible d'en télécharger une. Vous en trouverez sur le site de Launchpad.net, rubrique <a href="https://launchpad.net/gcc-arm-embedded">GNU Tools for ARM embedded processors</a>. Les avantages de télécharger la chaîne sont, premièrement, de l'installer sur l'OS que vous souhaitez (Windows, Mac ou Linux), deuxièmement, de pouvoir l'utiliser sur de nombreux micros, tel que Cortex M0, M3, M4, etc ...<br />
<br />
Pour connaître toutes les architectures supportées par la chaîne de compilation croisée, il suffit de lancer la commande :<br />
<br />
<pre class="brush: shell">./arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-r/thumb;@mthumb@march=armv7-r
armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16
armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16
armv7-r/thumb/softfp;@mthumb@march=armv7-r@mfloat-abi=softfp@mfpu=vfpv3-d16
armv7-r/thumb/fpu;@mthumb@march=armv7-r@mfloat-abi=hard@mfpu=vfpv3-d16</pre>
<br />
Les différents types d'architectures sont :<br />
<ul>
<li>Architecture ARMv6-M : Cortex-M0, Cortex-M0+ et Cortex-M1</li>
<li>Architecture ARMv7-M : Cortex-M3</li>
<li>Architecture ARMv7E-M : Cortex-M4</li>
<li>Architecture ARMv7-R : Cortex-R4 (processeur temps-réel)</li>
</ul>
<br />
<br />
Cependant, cela implique quelques modifications du Makefile du Template pour préciser le type de micro, ainsi que les options qui vont avec.<br />
<br />
<pre class="brush: shell; highlight: [47, 48];"># put your *.c source files here, make should handle the rest!
SRCS = main.c errno.c stm32f3_discovery.c system_stm32f30x.c
# Periph driver sources
SRCS_PERIPH = stm32f30x_adc.c stm32f30x_can.c stm32f30x_comp.c stm32f30x_crc.c \
stm32f30x_dac.c stm32f30x_dbgmcu.c stm32f30x_dma.c \
stm32f30x_exti.c stm32f30x_flash.c stm32f30x_gpio.c \
stm32f30x_i2c.c stm32f30x_iwdg.c stm32f30x_misc.c stm32f30x_opamp.c \
stm32f30x_pwr.c stm32f30x_rcc.c stm32f30x_rtc.c stm32f30x_spi.c \
stm32f30x_syscfg.c stm32f30x_tim.c stm32f30x_usart.c \
stm32f30x_wwdg.c usb_core.c usb_init.c usb_int.c usb_mem.c \
usb_regs.c usb_sil.c
# all the files will be generated with this name (main.elf, main.bin, main.hex, etc)
PROJ_NAME=blink_led
# Location of the Libraries folder from the STM32F3 Standard Peripheral Library
STD_PERIPH_LIB=<PATH_TO_LIBRARIES_FILES>/STM32F3-Discovery_FW_V1.1.0/Libraries
# Location of the linker scripts
LDSCRIPT_INC=Device/ldscripts
# location of OpenOCD Board .cfg files (only used with 'make program')
OPENOCD_BOARD_DIR=<PATH_TO_OPENOCD_BOARD_SCRIPT>
# Configuration (cfg) file containing programming directives for OpenOCD
OPENOCD_PROC_FILE=extra/stm32f3-openocd.cfg
# toolchain path
TOOLCHAIN=<PATH_TO_TOOLCHAIN>/gcc-arm-none-eabi-4_7-2012q4/bin
TOOLCHAIN_TARGET=$(TOOLCHAIN)/arm-none-eabi-
# that's it, no need to change anything below this line!
###################################################
CC = $(TOOLCHAIN_TARGET)gcc
GDB = $(TOOLCHAIN_TARGET)gdb
OBJCOPY = $(TOOLCHAIN_TARGET)objcopy
OBJDUMP = $(TOOLCHAIN_TARGET)objdump
SIZE = $(TOOLCHAIN_TARGET)size
LIB = libstm32f3.a
CFLAGS = -Wall -g -std=c99 -Os
CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections -Wl,-Map=bins/$(PROJ_NAME).map
###################################################
vpath %.a $(STD_PERIPH_LIB)
vpath %.c $(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/src
vpath %.c $(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/src
vpath %.c src
ROOT=$(shell pwd)
CFLAGS += -Iinc
CFLAGS += -I$(STD_PERIPH_LIB)
CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Device/ST/STM32F30x/Include
CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Include
CFLAGS += -I$(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/inc
CFLAGS += -I$(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/inc
CFLAGS += -DUSE_STDPERIPH_DRIVER
STARTUP = Device/startup_stm32f30x.s # add startup file to build
OBJS = $(addprefix objs/,$(SRCS:.c=.o))
DEPS = $(addprefix deps/,$(SRCS:.c=.d))
OBJS_PERIPH = $(addprefix objs/,$(SRCS_PERIPH:.c=.o))
DEPS_PERIPH = $(addprefix deps/,$(SRCS_PERIPH:.c=.d))
###################################################
.PHONY: all lib proj program debug clean reallyclean
all: $(LIB) proj
-include $(DEPS)
$(LIB): $(OBJS_PERIPH)
@echo [AR] $@
@$(AR) -r $@ $(OBJS_PERIPH)
proj: bins/$(PROJ_NAME).elf
dirs:
@mkdir -p deps objs bins
@touch dirs
objs/%.o : %.c dirs
@echo [OBJ] $<
@$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF deps/$(*F).d
bins/$(PROJ_NAME).elf: $(OBJS)
@$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(STARTUP) -L$(STD_PERIPH_LIB) -L. -lstm32f3 -L$(LDSCRIPT_INC) -Tstm32f3.ld
@$(OBJCOPY) -O ihex bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).hex
@$(OBJCOPY) -O binary bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).bin
@$(OBJDUMP) -St bins/$(PROJ_NAME).elf > bins/$(PROJ_NAME).lst
@$(SIZE) bins/$(PROJ_NAME).elf
program: all
@openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown
debug: program
@$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf
clean:
@echo [CLEAN]
@find ./ -name '*~' | xargs rm -f
@rm -rf objs
@rm -rf deps
@rm -rf bins
@rm -f dirs
@rm -f $(LIB)
reallyclean: clean
@$(MAKE) -C $(STD_PERIPH_LIB) clean
</pre>
<br />
<h3 style="text-align: left;">
Programmation du micro</h3>
<div style="text-align: left;">
<br />
La sonde JTAG est directement intégrée sur la carte de démo via un micro stlink v2. Sous windows, les drivers de cette sonde sont directement téléchargeable sur le site de chez ST. Par contre sous linux, c'est un peu plus galère, surtout si vous utilisez, comme moi, une machine virtuelle.<br />
Sur virtualbox, ça ne fonctionne juste pas !!! Par contre, sur VMWare, cela fonctionne moyennant un ajout dans les règles udev.<br />
<br />
Dans le dossier <i>/etc/udev/rules.d</i>, il faut rajouter la règle <i>S49-stlinkv2.rules</i> :<br />
<pre class="brush: shell;"># cd /etc/udev/rules.d/
# sudo touch S49-stlinkv2.rules
# vim touch S49-stlinkv2.rules
</pre>
<br />
et copier le texte ci-dessous :<br />
<pre class="brush: shell;"># stm32 discovery boards, with onboard st/linkv2
# ie, STM32L, STM32F4.
# STM32VL has st/linkv1, which is quite different
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \
MODE:="0666", \
SYMLINK+="stlinkv2_%n"
# If you share your linux system with other users, or just don't like the
# idea of write permission for everybody, you can replace MODE:="0666" with
# OWNER:="yourusername" to create the device owned by you, or with
# GROUP:="somegroupname" and mange access using standard unix groups.
</pre>
<br />
<br /></div>
<h4 style="text-align: left;">
Windows</h4>
<br />
Le logiciel windows s'appelle STM32 ST-LINK Utility et permet de programmer les cibles STM32 Cortex sans trop de soucis. Après avoir installer les drivers de la sonde JTAG, il suffit de lancer le logiciel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi05yPbG1aDJ9tyrcEZptu-TzzlT8BdUlRPC3IidyCzLip2PZp4WouinjSoBIHDuKmbwdI27MFHPIW92_UbBYyX62Xb2lX0LE3Rn1C0FSgphSpYhPnuSPWeZZ6q4LG_cTmTR77HuG2kdRY/s1600/stlink_windows_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi05yPbG1aDJ9tyrcEZptu-TzzlT8BdUlRPC3IidyCzLip2PZp4WouinjSoBIHDuKmbwdI27MFHPIW92_UbBYyX62Xb2lX0LE3Rn1C0FSgphSpYhPnuSPWeZZ6q4LG_cTmTR77HuG2kdRY/s640/stlink_windows_1.png" width="580" /></a></div>
<br />
L'onglet Target permet de connecter la carte puis de la programmer. Il accepte comme fichier d'entrée le binaire "<i>.HEX</i>".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPsElGyALj0UpJm1eotGH1Wk_TnqBWnh1jLTZ1dqiHCoKzIC0F5Mhyphenhyphenwir3N1nbS_Hm-DlaKoBfCij97UlAdzlBq2inz9PTJ2gDmdq0Of64r1p5Zgb0JwfmYeTUgepmDZ2weVvsB3FnE7g/s1600/stlink_windows_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="530" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPsElGyALj0UpJm1eotGH1Wk_TnqBWnh1jLTZ1dqiHCoKzIC0F5Mhyphenhyphenwir3N1nbS_Hm-DlaKoBfCij97UlAdzlBq2inz9PTJ2gDmdq0Of64r1p5Zgb0JwfmYeTUgepmDZ2weVvsB3FnE7g/s640/stlink_windows_2.png" width="580" /></a></div>
<br />
Je ne vais pas trop m'attarder sur le logiciel Windows. Passons maintenant aux choses sérieuses.<br />
<br />
<h4 style="text-align: left;">
Linux</h4>
<div>
<br /></div>
<br />
Le premier outil utilisé pour la programmation du micro s'appelle <i>stlink</i>, du même nom que la sonde JTAG de la carte. Les sources disponibles sous github (ci-dessous) permettent de compiler les outils sous Linux.<br />
<br />
Repository des utilitaires de programmation pour la sonde JTAG stlink v2 pour les micros cortex de chez STM32 :<br />
<br />
<div id="repo">
</div>
<script>
$('#repo').repo({ user: 'texane', name: 'stlink' });
</script><br />
Installation des outils :<br />
<pre class="brush: shell;"># sudo apt-get install libusb-1.0 libusb-1.0-dev pkg-config autotools
# git clone git://github.com/texane/stlink.git stlink
# cd stlink
# ./autogen.sh
# ./configure
# make
</pre>
<br />
Deux utilitaires sont compilés :<br />
<ul style="text-align: left;">
<li><i>st-flash : </i>un outil de manipulation de la flash</li>
<li><i>st-utils : </i>un serveur GDB (non abordé dans ce tutoriel)</li>
</ul>
<br />
Voici quelques exemples de commandes pour le flashage du binaire fraîchement compilé :<br />
<br />
Commande de lecture de 4096 octets de la flash du micro, à partir de l'adresse 0x8000000, dans le fichier out.bin<br />
<pre class="brush: shell;"># ./st−flash read out.bin 0x8000000 4096
</pre>
<br />
Commande d'écriture du fichier in.bin dans la flash du micro à l'adresse 0x8000000<br />
<pre class="brush: shell;"># ./st−flash write in.bin 0x8000000
</pre>
<br />
PS : L'adresse 0x8000000 correspond à l'adresse de début de la plage mémoire (0x8000000 à 0x8040000 => 256 KOctets) de la flash interne du micro d'après le mapping mémoire de la datasheet.<br />
<br />
<h3 style="text-align: left;">
OpenOCD (Open On-Chip Debugger)</h3>
<br />
OpenOCD est un logiciel qui permet de débugger/programmer un code s'exécutant sur un processeur en utilisant l'interface JTAG. Ce logiciel libre fait l'intermédiaire entre le logiciel de debug et l'interface matérielle qui permet l'accès au JTAG.<br />
<br />
Il offre trois interfaces d'utilisation :<br />
<ul style="text-align: left;">
<li>Un serveur GDB, permettant l'utilisation de gnu debugger</li>
<li>Une interface telnet pour passer directement des commandes</li>
<li>Une interface TCL, permettant d'utiliser ce langage de script</li>
</ul>
<br />
OpenOCD reconnait de nombreux adaptateur JTAG :<br />
<ul style="text-align: left;">
<li>Interfaces parallèles</li>
<li>Interface USB (FTDI, ...)</li>
</ul>
<br />
<h4 style="text-align: left;">
Installation de l'outil </h4>
<br />
Récupération des sources d'openocd :<br />
<pre class="brush: shell;"># git clone git://git.code.sf.net/p/openocd/code openocd-code
</pre>
<br />
Compilation et installation :<br />
<pre class="brush: shell;"># ./bootstrap
# ./configure --enable-maintainer-mode --enable-stlink
# make
# make install
</pre>
<br />
<h4 style="text-align: left;">
Programmation grâce à OpenOCD et au Template du projet</h4>
<br />
<br />
On reprend en détail la partie programmation du micro avec le makefile :<br />
<br />
<pre class="brush: shell;">program: all
@openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown
</pre>
<br />
Il lance l'utilitaire OpenOCD avec comme configuration de carte <i>stm32f3discovery.cfg</i>, comme directives de programmation <i>stm32f3-openocd.cfg</i> et deux commandes (première pour la programmation et la deuxième pour la fermeture de la communication).<br />
<br />
le fichier stm32f3-openocd.cfg, on retrouve, comme sur l'autre outil, une écriture en flash à l'adresse de début 0x08000000 :<br />
<pre class="brush: shell;">init
proc stm_flash {IMGFILE} {
reset halt
sleep 100
wait_halt 2
flash write_image erase $IMGFILE 0x08000000
sleep 100
verify_image $IMGFILE 0x08000000
sleep 100
reset run
}
proc stm_erase {} {
reset halt
sleep 100
stm32f1x mass_erase 0
sleep 100
}
</pre>
<br />
Pour programmer le micro avec le programme fraîchement compilé, on lance la commande :<br />
<pre class="brush: shell;"># make program
Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : Target voltage: 2.878032
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
stm_erase
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800040c msp: 0x20008000
auto erase enabled
Info : device id = 0x10036422
Info : flash size = 256kbytes
wrote 4096 bytes from file /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.bin in 0.938627s (4.262 KiB/s)
verified 2216 bytes in 0.278803s (7.762 KiB/s)
shutdown command invoked
</pre>
<br />
<br />
<h4 style="text-align: left;">
Débogage grâce à OpenOCD et au Template du projet</h4>
<br />
<span style="background-color: red;">Attention : Le débogage, pour le moment n'est possible que si on utilise la chaîne de compilation croisée téléchargée sur le site de Launchpad, suite à un bug sur la version de GDB de crosstool-NG.</span><br />
<br />
On reprend en détail la partie débogage du micro avec le makefile :<br />
<pre class="brush: shell;">debug: program
@$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf
</pre>
<br />
Il lance la commande de débogage arm-none-eabi-gdb avec comme fichier de configuration gdb-cmds et le binaire à déboguer.<br />
GDB communique avec OpenOCD de deux façons différentes :<br />
<ul style="text-align: left;">
<li>une connexion par socket TCP/IP.</li>
<ul>
<li>exemple : <i>target remote localhost:3333</i></li>
</ul>
<li>une connexion par pipe. Ça a l'avantage que GDB à la main sur OpenOCD et peut l'arrêter à tout moment.</li>
<ul>
<li>exemple : <i>target remote | openocd -c "gdb_port pipe; log_output openocd.log"</i></li>
</ul>
</ul>
<br />
Le fichier de configuration gdb-cmds :<br />
<pre class="brush: shell;">target remote | openocd -f /usr/share/openocd/scripts/board/stm32f0discovery.cfg -c "gdb_port pipe; log_output openocd.log"
monitor reset halt
load
</pre>
<br />
La commande à lancer pour le débogage est la suivante :<br />
<pre class="brush: shell;">#make debug
Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : Target voltage: 2.900648
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
stm_erase
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000458 msp: 0x20008000
auto erase enabled
Info : device id = 0x10036422
Info : flash size = 256kbytes
wrote 4096 bytes from file /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.bin in 1.038872s (3.850 KiB/s)
verified 2216 bytes in 0.353893s (6.115 KiB/s)
shutdown command invoked
GNU gdb (GNU Tools for ARM Embedded Processors) 7.4.1.20121207-cvs
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-linux-gnu --target=arm-none-eabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.elf...done.
Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
0x00000000 in ?? ()
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800040c msp: 0x20008000
Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x6d4 lma 0x8000188
Loading section .data, size 0x4c lma 0x800085c
Start address 0x800040d, load size 2216
Transfer rate: 2 KB/sec, 738 bytes/write.
(gdb) b main
Breakpoint 1 at 0x80001a0: file src/main.c, line 30.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at src/main.c:30
30 {
</pre>
<br />
La petite astuce qui tue pour avoir le multi-windows sous GDB : CTRL x puis a :<br />
<pre class="brush: shell;">┌──src/main.c───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│22 } │
│23 │
│24 /** │
│25 * @brief Main program. │
│26 * @param None │
│27 * @retval None │
│28 */ │
│29 int main(void) │
B+>│30 { │
│31 /* SysTick end of count event each 10ms */ │
│32 RCC_GetClocksFreq(&RCC_Clocks); │
│33 SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); │
│34 │
│35 /* Initialize LEDs and User Button available on STM32F3-Discovery board */ │
│36 STM_EVAL_LEDInit(LED3); │
│37 STM_EVAL_LEDInit(LED4); │
│38 STM_EVAL_LEDInit(LED5); │
│39 STM_EVAL_LEDInit(LED6); │
│40 STM_EVAL_LEDInit(LED7); │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
remote Remote target In: main Line: 30 PC: 0x80001a0
(gdb) cont
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at src/main.c:30
(gdb) </pre>
<br />
<br />
<br /></div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.4206725 1.1214855000000008 43.7886315 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-82125028715560267082013-02-24T16:14:00.003+01:002013-02-24T16:14:37.606+01:00Dongle wifi DWA-121 et Raspberry Pi<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://di1-1.shoppingshadow.com/images/pi/c6/7b/a5/111233580-260x260-0-0_dongle+d+link+d+link+dwa+121+dwa+121+adaptateur+mi.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="http://di1-1.shoppingshadow.com/images/pi/c6/7b/a5/111233580-260x260-0-0_dongle+d+link+d+link+dwa+121+dwa+121+adaptateur+mi.jpg" width="200" /></a></div>
Mon dernier achat est un dongle WIFI. Avant cet achat compulsif, j'ai vérifié dans la<a href="http://elinux.org/RPi_VerifiedPeripherals#USB_Wi-Fi_Adapters"> liste fournie sur le wiki de raspberry pi</a>, quel modèle acheter. C'est déjà pas forcément facile avec du matériel certifié alors si on part dans l'inconnu, c'est encore plus galère....<br />
<br />
L'heureux élu est le dongle DWA-121 de la marque D-LINK.<br />
<br />
Le but de ce tutoriel est de configurer le dongle wifi sur une distribution de type buildroot (oubliez network-manager et tout ce qui va avec ....)<br />
<br />
<br />
Pour ce tutoriel, nous allons :<br />
<br />
<ul style="text-align: left;">
<li>Utiliser l'outil de configuration wifi : <a href="http://fr.wikipedia.org/wiki/Wpa_supplicant">wpa_supplicant</a></li>
<li>Compiler, installer et charger le driver de chez realtek : <a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=277&DownTypeID=3&GetDown=false&Downloads=true#2772">8192cu</a></li>
<li>Compiler et installer les outils sans fil fournis avec le driver</li>
<li>Créer un script pour la configuration du dongle au lancement du système de fichiers.</li>
</ul>
<div>
<a name='more'></a><br /></div>
Lors de l’insertion du dongle wifi sur la raspberry pi, voici les informations indiquant qu'il est bien reconnu par le système :<br />
<pre class="brush: shell"># dmesg
[...]
[258285.789273] usb 1-1.2: new high-speed USB device number 4 using dwc_otg
[258285.911171] usb 1-1.2: New USB device found, idVendor=2001, idProduct=3308
[258285.918191] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[258285.926230] usb 1-1.2: Product: 802.11n WLAN Adapter
[258285.931734] usb 1-1.2: Manufacturer: Realtek
[258285.936151] usb 1-1.2: SerialNumber: 00e04c000001
[258285.998142] cfg80211: Calling CRDA to update world regulatory domain
</pre>
<br />
et les informations sur le bus USB :<br />
<pre class="brush: shell; highlight: [5];"># lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 2001:3308 D-Link Corp. DWA-121 802.11n Wireless N 150 Pico Adapter [Realtek RTL8188CUS]
</pre>
<br />
<h3 style="text-align: left;">
Outil de configuration : wpa_supplicant</h3>
<br />
L'outil est disponible dans le menuconfig de buildroot (<i>Package selection for target -> Network Applications</i>) :<br />
<pre class="brush: shell"># make menuconfig
</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8_ivE4JE2WImJfSZ7aI1TX83Cnpkqlws9t0Dr0SK3VRHBmJwex3jfQaU_4utQbrPx0-A10g1tEJABG4ky4MANMMzi9VtYKBb7hv4MnwJstvR-XHBX_8VCdeQNNzOvDSjmx2Qh_IUxtnA/s1600/buildroot_wpa_supplicant.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="331" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8_ivE4JE2WImJfSZ7aI1TX83Cnpkqlws9t0Dr0SK3VRHBmJwex3jfQaU_4utQbrPx0-A10g1tEJABG4ky4MANMMzi9VtYKBb7hv4MnwJstvR-XHBX_8VCdeQNNzOvDSjmx2Qh_IUxtnA/s640/buildroot_wpa_supplicant.png" width="580" /></a></div>
<br />
Après avoir intégrer les outils au système de fichiers, il faut éditer les fichiers de configuration <i>/etc/wpa.conf</i> et <i>/etc/network/interfaces</i> et entrer les bons paramètres en fonction de votre routeur wifi :<br />
<br />
le fichier de configuration wpa.conf :<br />
<pre class="brush: shell">#On indique tout d'abord où se situe le programme (socket avec wpa_cli...)
ctrl_interface=/var/run/wpa_supplicant
#On protège l'accès à wpa_supplicant en l'attribuant à un groupe
#Le groupe peut être un identifiant (gid) ou un nom de groupe
#Par défaut le gid est à 0 pour signifier que c'est le root qui protège l'accès.
ctrl_interface_group=0
eapol_version=2
#On définit le mode de sélection du point d'accès (AP : Access Point)
#1 : Configuration classique
#0 : Utilisé pour le protocole IEEE 802.1X (et les réseaux établis).
#2 : Associe les points d'accès dans un mode sécurisé. !!!Utilisé pour le mode Ad-Hoc!!!
# Associe le SSID (nom de votre réseau) mais pas le BSSID (n° attribué à votre carte réseau).
# A utiliser si vous avez une clef installée sous NDIS(WRAPPER) pour utiliser pleinement votre réseau :
# dans ce cas le block network devra comprendre les informations 'key_mgmt', 'pairwise', 'group' et les variables de protocole.
ap_scan=1
network={
ssid="ma freebox"
#psk: clef WPA (256bits)
# ="mon mot de passe" : entre guillemets pour un mot de passe 'texte' (entre 8 et 63caractères compris)
psk="mon mot de passe"
#proto: protocole
# =WPA : WPA(1) (WPA/IEEE 802.11i/D3.0)
# =RSN : WPA2 (IEEE 802.11i) (par défaut)
proto=RSN WPA
#key_mgmt: encryption
# =WPA-PSK : WPA 'pre-shared key' (requièrt une clef PSK)
# =WPA-EAP : WPA utilisant une authentification EAP (peut utiliser un programme externe (Xsupplicant)).
# =IEEE8021X : IEEE 802.1X utulisant une authentification EAP et, optionnellement la génération de clefs WEP dynamiques.
# =NONE : Pas de WPA : clef WEP ou connexion directe.
# =WPA-NONE : Pour réseaux Ad-Hoc (possibilité de groupage TKIP ou CCMP(AES))
key_mgmt=WPA-PSK WPA-EAP
#pairwise: !A ne pas confondre avec le 'group' qui est plus connu!
# =CCMP : AES (CBC-MAC : RFC 3610, IEEE 802.11i/D7.0)
# =TKIP : (IEEE 802.11i/D7.0)
# =NONE : Utilisé pour le mode ad-hoc principalement
pairwise=CCMP TKIP
#auth_alg: système d'authentification du réseau
# =OPEN : pour WPA et WPA2
# =SHARED : pour WEP
# =LEAP : pour LEAP sur réseau EAP
auth_alg=OPEN
}
</pre>
<br />
le fichier d'interfaces réseaux :<br />
<pre class="brush: shell"># Configure Loopback
auto lo
iface lo inet loopback
# Configure eth0
auto eth0
iface eth0 inet dhcp
# Configure wlan0
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa.conf
</pre>
<br />
<h3 style="text-align: left;">
Driver Realtek RTL8192</h3>
<br />
Sur le noyau linux 3.2.27, les drivers pour le dongle sont déjà présents et chargés automatiquement grâce au démon <i>udevd</i>, mais le driver <i>rtl8192cu.ko</i> semble buggé (problème d'écriture synchrone, à priori), c'est pourquoi j'ai décidé de repartir des drivers fournis par le constructeur realtek (<i>8192cu.ko</i>), qui d'après ce que j'ai pu voir en traînant sur le web, une version complètement différentes (plus limité, pas de mode moniteur pour les connaisseurs) de celui fourni avec le noyau linux, mais suffisant pour une utilisation standard d'interface réseau.<br />
<br />
Fil d'un post trouvé sur le forum raspberry pi : <a href="http://www.raspberrypi.org/phpBB3/viewtopic.php?f=71&t=24951">rtl8192cu module for Edimax EW-7811n Wifi dongle</a><br />
<br />
Voici l'état du système d'origine :<br />
<pre class="brush: shell"># cd /lib/modules/3.2.27/kernel/drivers/net/wireless/rtlwifi
# ls -l
| drwxr-xr-x 2 root root 4.0K Feb 23 18:36 ./
| drwxr-xr-x 4 root root 4.0K Feb 23 18:36 ../
| drwxr-xr-x 2 root root 4.0K Feb 23 18:36 rtl8192c/
+--> -rw------- 1 root root 64K Feb 23 18:36 rtl8192c-common.ko
|drwxr-xr-x 2 root root 4.0K Feb 23 19:06 rtl8192cu/
+--> -rw------- 1 root root 113K Feb 23 18:36 rtl8192cu.ko
|-rw------- 1 root root 85K Feb 23 18:36 rtlwifi.ko
</pre>
<br />
et les drivers déjà chargés sur le système :<br />
<pre class="brush: shell; highlight: [3,4,5,6,7];"># lsmod
Module Size Used by
rtl8192cu 97581 1
rtl8192c_common 53692 1 rtl8192cu
rtlwifi 64628 1 rtl8192cu
mac80211 203510 3 rtlwifi,rtl8192c_common,rtl8192cu
cfg80211 143188 2 mac80211,rtlwifi
i2c_dev 4657 2
ipv6 237083 14
spidev 4274 0
i2c_bcm2708 3019 0
spi_bcm2708 3969 0
</pre>
<br />
<h4 style="text-align: left;">
Compilation et insertion du nouveau driver</h4>
<br />
Il faut, dans un premier temps, télécharger <a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=277&DownTypeID=3&GetDown=false&Downloads=true#2772">les drivers linux</a> sur le site de realtek puis décompresser les sources et entrer dans le sous dossier driver.<br />
<br />
<pre class="brush: shell">drwxrwxr-x 6 sinseman44 sinseman44 4096 2013-02-24 14:57 ./
drwxrwxr-x 3 sinseman44 sinseman44 4096 2013-02-23 19:19 ../
-rw-r--r-- 1 sinseman44 sinseman44 116 2012-07-30 14:51 clean
drwxrwxr-x 3 sinseman44 sinseman44 12288 2013-02-24 14:57 core/
drwxrwxr-x 3 sinseman44 sinseman44 4096 2013-02-24 14:57 hal/
-rw-r--r-- 1 sinseman44 sinseman44 54 2012-07-30 14:51 ifcfg-wlan0
drwxrwxr-x 3 sinseman44 sinseman44 16384 2013-02-23 19:19 include/
-rw-r--r-- 1 sinseman44 sinseman44 110 2012-07-30 14:51 Kconfig
-rw-r--r-- 1 sinseman44 sinseman44 14760 2013-02-23 19:56 Makefile
drwxrwxr-x 3 sinseman44 sinseman44 4096 2013-02-24 14:57 os_dep/
-rw-r--r-- 1 sinseman44 sinseman44 294 2012-07-30 14:51 wlan0dhcp
</pre>
<br />
On va modifier le Makefile pour configurer correctement notre driver et intégrer la cible raspberry pi (ne pas oublier de mettre la chaîne de compilation croisée dans le PATH) :<br />
<br />
<pre class="brush: shell; highlight: [3];">[...]
CONFIG_PLATFORM_I386_PC = n
CONFIG_PLATFORM_ARM_BCM2708 = y
CONFIG_PLATFORM_TI_AM3517 = n
CONFIG_PLATFORM_ANDROID_X86 = n
CONFIG_PLATFORM_ARM_S3C2K4 = n
CONFIG_PLATFORM_ARM_PXA2XX = n
CONFIG_PLATFORM_ARM_S3C6K4 = n
CONFIG_PLATFORM_MIPS_RMI = n
CONFIG_PLATFORM_RTD2880B = n
CONFIG_PLATFORM_MIPS_AR9132 = n
[...]
</pre>
<br />
<pre class="brush: shell; highlight: [10,11,12,13,14,15,16];">ifeq ($(CONFIG_PLATFORM_ANDROID_X86), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/)
ARCH := $(SUBARCH)
CROSS_COMPILE := /media/DATA-2/android-x86/ics-x86_20120130/prebuilt/linux-x86/toolchain/i686-unknown-linux-gnu-4.2.1/bin/i686-unknown-linux-gnu-
KSRC := /media/DATA-2/android-x86/ics-x86_20120130/out/target/product/generic_x86/obj/kernel
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_BCM2708), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-unknown-linux-gnueabi-
KVER := 3.2.27
KSRC ?= <BUILDROOT_PATH>/output/build/linux-rpi-3.2.27
endif
ifeq ($(CONFIG_PLATFORM_ARM_PXA2XX), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-none-linux-gnueabi-
KVER := 2.6.34.1
KSRC ?= /usr/src/linux-2.6.34.1
endif
</pre>
<br />
ensuite, il suffit d'entrer la commande <i>make </i>pour compiler notre driver :<br />
<pre class="brush: shell;"># make
[...]
# ls -al
-rw-r--r-- 1 sinseman44 sinseman44 631805 2013-02-24 15:09 8192cu.ko
</pre>
<br />
On transfert ce driver sur notre cible dans le dossier des drivers <i>/lib/modules/3.2.27/kernel/drivers/net/wireless/rtlwifi/rtl8192cu.</i><br />
<i><br />
</i> <br />
<h4 style="text-align: left;">
Compilation des outils fournis par le driver</h4>
<div>
<br />
Les outils fournis avec le driver sont les suivants :</div>
<div>
<ul style="text-align: left;">
<li><a href="http://pwet.fr/man/linux/administration_systeme/iwconfig">iwconfig</a> : outil similaire à ifconfig mais pour les interfaces réseaux sans fil.</li>
<li><a href="http://www.delafond.org/traducmanfr/man/man8/iwlist.8.html">iwlist</a> : affiche des informations additionnelles sur les interfaces réseaux. </li>
<li><a href="http://man.developpez.com/man8/iwpriv.8.php">iwpriv</a> : outil traite les paramètres et attributs privés de chaque pilote.</li>
<li><a href="http://www.delafond.org/traducmanfr/man/man8/iwspy.8.html">iwspy</a> : outil permettant d'obtenir des statistiques depuis un noeud donné.</li>
<li><a href="http://www.delafond.org/traducmanfr/man/man8/iwgetid.8.html">iwgetid</a> : rapporte l'ESSID ou Le nom du point d'accès d'un réseau sans fil.</li>
<li><a href="http://www.delafond.org/traducmanfr/man/man8/iwevent.8.html">iwevent</a> : affiche les évènements sans fil</li>
</ul>
</div>
<div>
<br />
Dans le dossier wireless_tools, on va modifier le makefile pour cross-compiler les outils :</div>
<pre class="brush: shell; highlight: [7, 8, 9, 10, 11];">## Installation directory. By default, go in /usr/local.
## Distributions should probably use /, but they probably know better...
ifndef PREFIX
PREFIX = /usr/local
endif
## Compiler to use (modify this for cross compile).
CC = arm-unknown-linux-gnueabi-gcc
## Other tools you need to modify for cross compile (static lib only).
AR = arm-unknown-linux-gnueabi-ar
RANLIB = arm-unknown-linux-gnueabi-ranlib
## Uncomment this to build tools using static version of the library.
## Mostly useful for embedded platforms without ldd, or to create
## a local version (non-root).
## Standard distros should comment that option to save space and to
## build libiw.so used by third parties...
BUILD_STATIC = y
</pre>
<br />
On compile les outils à l'aide de la commande <i>make </i>et on les transfère sur la cible dans le dossier <i>/usr/sbin </i>:<br />
<pre class="brush: shell;"># make
</pre>
<br />
<h4 style="text-align: left;">
Test du driver compilé</h4>
<br />
On va dans un premier temps retirer le driver <i>rtl8192cu.ko</i> du noyau linux 3.2.27 pour qu'il ne soit pas chargé par notre système puis dans un deuxième temps, charger notre nouveau driver <i>8192cu.ko</i> :<br />
<pre class="brush: shell;"># cd /lib/modules/3.2.27/kernel/drivers/net/wireless/rtlwifi/rtl8192cu
# rmmod rtl8192cu.ko
# mv rtl8192cu.ko rtl8192cu.ko.origin
# insmod 8192cu.ko
</pre>
<br />
Voici les nouveaux drivers chargés par le système :<br />
<pre class="brush: shell; highlight: [4];"># lsmod
Module Size Used by
ipv6 237083 14
8192cu 537834 0
rtl8192c_common 53692 0
rtlwifi 64628 0
mac80211 203510 2 rtlwifi,rtl8192c_common
cfg80211 143188 2 mac80211,rtlwifi
spidev 4274 0
spi_bcm2708 3969 0
i2c_bcm2708 3019 0
</pre>
<br />
Grâce à l'outil <i>iwconfig</i>, l'interface sans fil <i>wlan0</i> apparaît :<br />
<br />
<pre class="brush: shell;"># iwconfig
lo no wireless extensions.
wlan0 unassociated Nickname:"<wifi>"
Mode:Auto Frequency=2.412 GHz Access Point: Not-Associated
Sensitivity:0/0
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality:0 Signal level:0 Noise level:0
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
eth0 no wireless extensions.
</wifi></pre>
<br />
On lance ensuite l'outil <i>wpa_supplicant </i>avec les bons paramètres :<br />
<pre class="brush: shell;">/usr/sbin/wpa_supplicant -B -Dwext -c /etc/wpa.conf -iwlan0
</pre>
<br />
L'interface réseau <i>wlan0</i> apparaît dans la liste, mais sans adresse IP configurée et la LED bleue du dongle s'allume et clignote :<br />
<pre class="brush: shell; highlight: [20, 21, 22, 23, 24, 25, 26];"># ifconfig
eth0 Link encap:Ethernet HWaddr B8:27:EB:XX:XX:XX
inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::ba27:ebff:fe91:ec1c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1187 errors:0 dropped:1 overruns:0 frame:0
TX packets:2513 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:149219 (145.7 KiB) TX bytes:386962 (377.8 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
wlan0 Link encap:Ethernet HWaddr C8:BE:19:XX:XX:XX
inet6 addr: fe80::cabe:19ff:fe86:be51/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3631 errors:0 dropped:3683 overruns:0 frame:0
TX packets:323 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:633128 (618.2 KiB) TX bytes:29376 (28.6 KiB)
</pre>
<br />
L'outil <i>iwconfig </i>permet de vérifier que le dongle est bien associé au routeur wifi :<br />
<br />
<pre class="brush: shell;"># iwconfig
lo no wireless extensions.
wlan0 IEEE 802.11bgn ESSID:"ma freebox" Nickname:"<wifi>"
Mode:Managed Frequency:2.432 GHz Access Point: F4:CA:E5:XX:XX:XX
Bit Rate:150 Mb/s Sensitivity:0/0
Retry:off RTS thr:off Fragment thr:off
Encryption key:****-****-****-****-****-****-****-**** Security mode:open
Power Management:off
Link Quality=100/100 Signal level=100/100 Noise level=0/100
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
eth0 no wireless extensions.
</wifi></pre>
<br />
On va faire une requête DHCP pour récupérer l'adresse IP :<br />
<pre class="brush: shell; highlight: [14]"># dhclient wlan0 -v
Internet Systems Consortium DHCP Client 4.1-ESV-R6
Copyright 2004-2012 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/wlan0/c8:be:19:86:be:51
Sending on LPF/wlan0/c8:be:19:86:be:51
Sending on Socket/fallback
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
DHCPREQUEST on wlan0 to 255.255.255.255 port 67
DHCPOFFER from 192.168.1.254
DHCPACK from 192.168.1.254
bound to 192.168.1.32 -- renewal in 17679 seconds.
</pre>
<br />
et finalement configurer l'adresse IP de notre interface wlan0 :<br />
<pre class="brush: shell;"># ifconfig wlan0 192.168.1.32 netmask 255.255.255.0
</pre>
<br />
On peut maintenant pinger cette nouvelle interface sans fil.<br />
<br />
<h3 style="text-align: left;">
Script de démarrage</h3>
<br />
Une fois le dongle testé et fonctionnel, on peut créer un script de démarrage pour automatiser les tâches. Dans le dossier, sur la cible, <i>/etc/init.d/</i>, nous allons créer le script <b>S39wifi </b>:<br />
<br />
<pre class="brush: shell;">#!/bin/sh
#
# Start the wifi....
#
VENDOR_ID="2001"
PRODUCT_ID="3308"
INTERFACE="wlan0"
result_lsusb=""
case "$1" in
start)
result_lsusb=`lsusb -d "${VENDOR_ID}":"${PRODUCT_ID}"`
if [ "${result_lsusb}" != "" ]; then
insmod /lib/modules/3.2.27/kernel/drivers/net/wireless/rtlwifi/rtl8192cu/8192cu.ko
/usr/sbin/wpa_supplicant -B -Dwext -c /etc/wpa.conf -i"${INTERFACE}"
fi
;;
stop)
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre>
<br />
Il suffit de redémarrer la raspberry pi pour que le dongle wifi soit automatiquement configuré et fonctionnel avec son adresse IP.<br />
<br /></div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com6Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-56957161108619011212013-02-19T20:15:00.001+01:002013-02-21T10:21:29.623+01:00Afficheur Alphanumérique (partie 3)<div dir="ltr" style="text-align: left;" trbidi="on"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s1600/RPI_LCD.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s640/RPI_LCD.png" width="580" /></a><br />
<br />
On va maintenant s’intéresser à l'interfaçage de la carte micro-contrôleur avec la raspberry pi.<br />
<br />
<br />
<a name='more'></a><br />
<br />
<h3 style="text-align: left;">Activation et vérification de l'I²C</h3><div dir="ltr" style="text-align: left;" trbidi="on"></div><br />
Lors du démarrage de la raspberry pi, il est important que le driver I²C soit chargé<br />
<br />
<pre class="brush: shell; highlight: [4];">[ 15.669863] Freeing init memory: 132K
[ 15.891808] EXT4-fs (mmcblk0p2): re-mounted. Opts: user_xattr,acl,barrier=1,data=ordered
[ 16.350619] udevd[59]: starting version 182
[ 16.655836] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79)
[ 16.748663] bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)
[ 16.816541] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79)
[ 18.934210] smsc95xx 1-1.1:1.0: eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1
[ 22.859421] NET: Registered protocol family 10
[ 31.422506] Console: switching to colour dummy device 80x30
[ 31.536753] bcm2708_fb_check_var info(c78b5000) 720x480 (720x480), 691200, 16
[ 31.536774] bcm2708_fb_check_var var(c68ebdc8) 1x1 (1x1), 16, 345600
[ 31.536792] bcm2708_fb_set_par info(c78b5000) 1x1 (1x1), 691200, 16
[ 31.553110] BCM2708FB: start = c8826000,49385000 width=1, height=1, bpp=16, pitch=32 size=512 success=0
[ 32.899219] eth0: no IPv6 routers present</pre><br />
Il faut chargé le driver <i>i2c-dev.ko</i> pour créer les noeuds <i>/dev/i2c-0</i> et <i>/dev/i2c-1</i><br />
<br />
<pre class="brush: shell"># modprobe i2c-dev
# lsmod
Module Size Used by
i2c_dev 4657 0
ipv6 237083 14
spidev 4274 0
spi_bcm2708 3969 0
i2c_bcm2708 3019 0
</pre><br />
Pour vérifier si le microcontrôleur est bien connecté au bus I²C, on va utiliser l'utilitaire <i>i2cdetect</i> qui va nous donner tous les esclaves connectés à la raspberry pi.<br />
<br />
<pre class="brush: shell"># i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] Y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --
</pre><br />
On remarque que l'esclave avec l'adresse <b>0x76 </b>(le micro-contrôleur PIC16F876A) est bien vu par la raspberry pi.<br />
<br />
<h3 style="text-align: left;">Programme de test</h3><br />
Voici un petit programme de test sur la raspberry pi pour valider la communication I²C, elle permet d'afficher l'heure et la date du système :<br />
<br />
Le fichier source :<br />
<pre class="brush: c">/**
* Objet :
* --------------------------------------------------------------------------------
* Fichier : test_raspberry_lcd.c
* --------------------------------------------------------------------------------
* Version : 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
/***********************************/
/* Includes des fichiers du projet */
/***********************************/
/**********************************/
/* Constantes internes au fichier */
/**********************************/
#define syslog_info(format, ...) syslog(LOG_INFO, format, ##__VA_ARGS__)
#define syslog_debug(format, ...) syslog(LOG_DEBUG, format, ##__VA_ARGS__)
#define syslog_err(format, ...) syslog(LOG_ERR, format, ##__VA_ARGS__)
#define syslog_warning(format, ...) syslog(LOG_WARNING, format, ##__VA_ARGS__)
/**********************************/
/* Structures internes au fichier */
/**********************************/
typedef char char_t;
typedef float float32_t;
typedef double float64_t;
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
int32_t main(int32_t __attribute__((unused)) argc,
char_t __attribute__((unused)) *argv[]) {
int32_t i32_ret = -1;
int32_t i32_fd_i2c = -1;
char_t pi8_buf[16];
int i32_adapter_nr = 0; /* probably dynamically determined */
int i32_addr = 0x76; /* The I2C address */
char_t sz_filename[20];
// initialise buffer
memset(pi8_buf, 0, sizeof(pi8_buf));
memset(sz_filename, 0, sizeof(sz_filename));
sprintf(sz_filename, "/dev/i2c-%d", i32_adapter_nr);
// openlog is not necessary
syslog_info("[TEST_RASPBERRY_I2C] Start process ...");
// Open i2c dev node
i32_fd_i2c = open(sz_filename, O_RDWR);
if(i32_fd_i2c == -1) {
syslog_err("[TEST_RASPBERRY_I2C] open : %m");
return -1;
}
/* else nothing to do */
i32_ret = ioctl(i32_fd_i2c, I2C_SLAVE, i32_addr);
if (i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] ioctl : %m");
return -1;
}
/* else nothing to do */
// Clear display
pi8_buf[0] = 0x01;
pi8_buf[1] = 0x02;
// write I²C frame
i32_ret = write(i32_fd_i2c, pi8_buf, 2);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] write : %m");
close(i32_fd_i2c);
return -1;
}
/* else nothing to do */
sleep(1);
while(1) {
memset(pi8_buf, 0, sizeof(pi8_buf));
// Return Home
pi8_buf[0] = 0x02;
pi8_buf[1] = 0x02;
// write I²C frame
i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] write : %m");
close(i32_fd_i2c);
return -1;
}
/* else nothing to do */
usleep(50000);
st_time = time(NULL);
pst_dateheure = localtime(&st_time);
memset(pi8_buf, 0, sizeof(pi8_buf));
pi8_line1_ptr = &pi8_buf[0];
// String hour
*pi8_line1_ptr = 0x05;
pi8_line1_ptr ++;
*pi8_line1_ptr = 14;
pi8_line1_ptr ++;
sprintf(pi8_line1_ptr, " %02d:%02d:%02d", pst_dateheure->tm_hour, pst_dateheure->tm_min, pst_dateheure->tm_sec);
// write I²C frame
i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] write : %m");
close(i32_fd_i2c);
return -1;
}
/* else nothing to do */
usleep(100000);
memset(pi8_buf, 0, sizeof(pi8_buf));
// go to line 2, column 1
pi8_buf[0] = 0x03;
pi8_buf[1] = 0x04;
pi8_buf[2] = 2;
pi8_buf[3] = 1;
// write I²C frame
i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] write : %m");
close(i32_fd_i2c);
return -1;
}
/* else nothing to do */
usleep(50000);
memset(pi8_buf, 0, sizeof(pi8_buf));
pi8_line1_ptr = &pi8_buf[0];
// String date
*pi8_line1_ptr = 0x05;
pi8_line1_ptr ++;
*pi8_line1_ptr = 15;
pi8_line1_ptr ++;
sprintf(pi8_line1_ptr, " %02d/%02d/%04d", pst_dateheure->tm_mday, (pst_dateheure->tm_mon + 1), (pst_dateheure->tm_year + 1900));
// write I²C frame
i32_ret = write(i32_fd_i2c, pi8_buf, pi8_buf[1]);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] write : %m");
close(i32_fd_i2c);
return -1;
}
/* else nothing to do */
usleep(50000);
}
// Close i2c dev node
i32_ret = close(i32_fd_i2c);
if(i32_ret == -1) {
syslog_err("[TEST_RASPBERRY_I2C] close : %m");
return -1;
}
/* else nothing to do */
return 0;
}
</pre><br />
Et le makefile :<br />
<pre class="brush: shell">CC = arm-unknown-linux-gnueabi-gcc
CFLAGS = -I../buildroot_test_a_del/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/include -W -Wall
LDFLAGS = -L../buildroot_test_a_del/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/lib -pthread -lrt
EXEC = test_raspberry_lcd
OBJS = test_raspberry_lcd.o
all: $(EXEC)
$(EXEC):$(OBJS)
@$(CC) -o $(EXEC) $^ $(LDFLAGS)
%.o:%.c
@echo [CC] $^
@$(CC) -o $@ -c $^ $(CFLAGS)
clean:
@echo [CLEAN]
@rm *.o $(EXEC) -f
</pre><br />
On lance la compilation du programme de test avec la commande <i>make </i>et on vérifie que l’exécutable est bien compilé pour notre cible (raspberry pi).<br />
<pre class="brush: shell"># file test_raspberry_lcd
test_raspberry_lcd: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.2.25, not stripped
</pre><br />
On lance l’exécutable de test avec la commande :<br />
<pre class="brush: shell"># ./test_raspberry_lcd
</pre><br />
<h4 style="text-align: left;">Résultat</h4><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVxx1ekZOTMe6PvzZxnKdMzMEX9o6GtdNqiIBrIjlqKVuvx57BQXadrfVfhHHvOnqcpCji5T18O7UQGyQOODvsBNCnX0vBt4ItopJAH6FoMk4embtOSxDTiU0dTxr7XL38So_jAnjuqLA/s1600/RPI_LCD_017.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVxx1ekZOTMe6PvzZxnKdMzMEX9o6GtdNqiIBrIjlqKVuvx57BQXadrfVfhHHvOnqcpCji5T18O7UQGyQOODvsBNCnX0vBt4ItopJAH6FoMk4embtOSxDTiU0dTxr7XL38So_jAnjuqLA/s400/RPI_LCD_017.jpg" width="400" /></a></div><div><br />
</div><div><br />
</div><h3 style="text-align: left;">Quelques photos</h3><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlkfvIj1piKVHYAE0SqyAeziPkzI4CcZeNECW092hwhjjOSxkH-ij2tLSOi6wpBc1Yn3P1OazFinOV-hKMHIQD87lDWn8QZjs7DAvXWeZMBM5eGjj7ylvj2cyXUdgJEuEr4RytsV46Xg0/s1600/RPI_LCD_001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlkfvIj1piKVHYAE0SqyAeziPkzI4CcZeNECW092hwhjjOSxkH-ij2tLSOi6wpBc1Yn3P1OazFinOV-hKMHIQD87lDWn8QZjs7DAvXWeZMBM5eGjj7ylvj2cyXUdgJEuEr4RytsV46Xg0/s400/RPI_LCD_001.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBh9Lq3x70ID9hlRVQ2-GwGGyGDwbL7shmZjwT7Jdvhrtm8yGXzpS8DKi36AhV74j00NtFjXn15NeymkKcgOHa8QaPYNYw5QX3p_w2FQN_7UDmmPpI2VT-N2G6FaN1Sn05bJT0O2bFoyA/s1600/RPI_LCD_006.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBh9Lq3x70ID9hlRVQ2-GwGGyGDwbL7shmZjwT7Jdvhrtm8yGXzpS8DKi36AhV74j00NtFjXn15NeymkKcgOHa8QaPYNYw5QX3p_w2FQN_7UDmmPpI2VT-N2G6FaN1Sn05bJT0O2bFoyA/s400/RPI_LCD_006.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzBGxe4i_p0rue3nTQQtpziU5aiBbe-x1fF3xSw4O_rMBhtU8no7yejCwtrD3PyDXGzQv3UyMNuWnAAxnkzF2_248qCsGcCniSO-B5JKf0OVvyOQJ8JLqjz3nGc9QgeJ9_IvUqPkLWr74/s1600/RPI_LCD_003.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzBGxe4i_p0rue3nTQQtpziU5aiBbe-x1fF3xSw4O_rMBhtU8no7yejCwtrD3PyDXGzQv3UyMNuWnAAxnkzF2_248qCsGcCniSO-B5JKf0OVvyOQJ8JLqjz3nGc9QgeJ9_IvUqPkLWr74/s400/RPI_LCD_003.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQdyL18_ZeS9pVwH9q3p1i2ZK-KEW2loNNcbqSkTWY1lUnUH28Yl1bnfVCPDkIDOiVl9hSYJobLcRV_dbxrRPqQW7slwauXjBVb2oyKd34LMPamtLIbryzm1VjI2PwVwxIgcimmUEeXIM/s1600/RPI_LCD_010.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQdyL18_ZeS9pVwH9q3p1i2ZK-KEW2loNNcbqSkTWY1lUnUH28Yl1bnfVCPDkIDOiVl9hSYJobLcRV_dbxrRPqQW7slwauXjBVb2oyKd34LMPamtLIbryzm1VjI2PwVwxIgcimmUEeXIM/s400/RPI_LCD_010.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJFq5plM8z4nji7dg1j-JG73ruotghO75SeX-YGsP4jvuDI9RuPxwY_rpDeTyjS68lxWI8TdGl2P0WAPnGaJh8-w9hZPfxXOMEmtmPBl5rl4UhUoBjlwQu8S_QKT8c7SoNhSq8urDbKT4/s1600/RPI_LCD_016.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJFq5plM8z4nji7dg1j-JG73ruotghO75SeX-YGsP4jvuDI9RuPxwY_rpDeTyjS68lxWI8TdGl2P0WAPnGaJh8-w9hZPfxXOMEmtmPBl5rl4UhUoBjlwQu8S_QKT8c7SoNhSq8urDbKT4/s400/RPI_LCD_016.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNdE75yXNofYdl9z_bNlpNqhtAv1ROJIFE9CoV-Rr8b1JeNamlxd0bE4YcsEZA_D3qmq7xz8q1XddCVBSh2Uc-3o4DXR9XB_FdmYrR1CrVc0z39PnjiHoMyC3u7bG8MEF7jIPQ8seqDA/s1600/RPI_LCD_011.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNdE75yXNofYdl9z_bNlpNqhtAv1ROJIFE9CoV-Rr8b1JeNamlxd0bE4YcsEZA_D3qmq7xz8q1XddCVBSh2Uc-3o4DXR9XB_FdmYrR1CrVc0z39PnjiHoMyC3u7bG8MEF7jIPQ8seqDA/s1600/RPI_LCD_011.jpg" width="300" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
Lien vers la première partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-1.html">Afficheur alphanumérique (Partie 1)</a><br />
Lien vers la deuxième partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-2.html">Afficheur alphanumérique (Partie 2)</a><br />
<br />
<br />
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-64484910974788976022013-02-19T20:15:00.000+01:002013-02-19T20:26:19.763+01:00Afficheur Alphanumérique (partie 2)<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s1600/RPI_LCD.png" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s640/RPI_LCD.png" height="180" width="580" /></a><br />
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<br />
<h3 style="text-align: left;">
Architecture Logicielle</h3>
<div>
<br /></div>
<div>
L'architecture logicielle de la carte contrôleur est relativement simple. </div>
<div>
On reçoit des trames provenant du bus I²C via le handler d'interruption et les empiler dans une file d'attente (FIFO), ensuite, périodiquement, on dépile la file d'attente et traite les trames enregistrées pour afficher les informations sur l'écran LCD.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3_e9xAU6coJyT5Qn-3Lp_7KyHCzwkVvWkL433VXUT7s7GZOwMQXabT5Ku5ohyNp7hL6F5OeF4ooCsaBblFNmft6SdDWxnEAizBQBAxm4Uiqr8vr0N8dg86SOBPnodnK4c_ScbB2ykXhs/s1600/archi_logiciel_rpi_controleur_lcd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3_e9xAU6coJyT5Qn-3Lp_7KyHCzwkVvWkL433VXUT7s7GZOwMQXabT5Ku5ohyNp7hL6F5OeF4ooCsaBblFNmft6SdDWxnEAizBQBAxm4Uiqr8vr0N8dg86SOBPnodnK4c_ScbB2ykXhs/s400/archi_logiciel_rpi_controleur_lcd.png" height="306" width="400" /></a></div>
<br /></div>
<br />
<a name='more'></a><br />
<br />
Voici les sources du contrôleur PIC16f876A, versionnées sous Github :<br />
<br />
<div id="repo">
</div>
<script>
$('#repo').repo({ user: 'sinseman44', name: 'pic16f_lcd_controller' });
</script><br />
<h3 style="text-align: left;">
Dialogue avec le bus I²C</h3>
<div>
<br /></div>
<div>
<h4 style="text-align: left;">
Initialisation</h4>
<br />
Le micro-contrôleur doit être initialisé en tant qu'esclave sur le bus I²C, à une adresse particulière, ici, 0x76.<br />
D'après la datasheet du micro, de nombreux registres (cinq pour être exact) doivent être configurés pour faire fonctionner l'I²C.<br />
<ul style="text-align: left;">
<li>MSSP Control Register (SSPCON) - Registre de configuration et de controle</li>
<li>MSSP Control Register 2 (SSPCON2) - Registre de configuration et de contrôle</li>
<li>MSSP Status Register (SSPSTAT) - Registre d'états</li>
<li>Serial Receive/Transmit Buffer Register (SSPBUF) - Buffer de réception et transmission de données</li>
<li>MSSP Address Register (SSPADD) - Registre d'adresse de l'esclave</li>
</ul>
<br />
<pre class="brush: c">#define PIC16F876A_I2C_SLAVE_ADDR 0x76
#define SCL RC3
#define SDA RC4
int8_t i2c_init(void) {
// Synchronous Serial Port Disable bit
SSPEN = 0;
// Set RC3 as Input
TRISC3 = 1;
// Set RC4 as Input
TRISC4 = 1;
// Synchronous Serial Port Mode Select bit
// 0110 => I2C Slave mode, 7-bit address
SSPM3 = 0;
SSPM2 = 1;
SSPM1 = 1;
SSPM0 = 0;
// Set the Slave address
SSPADD = PIC16F876A_I2C_SLAVE_ADDR << 1; // 7 bits address = Bits 7654 321
// CKP: SCK Release Control bit
CKP = 1;
// Synchronous Serial Port Enable bit
SSPEN = 1;
SSPCON2 = 0x01;
//SMP: Slew Rate Control bit
SMP = 1;
//enable I²C interrupt
SSPIE = 1;
// clear SSPIF interrupt flag
SSPIF = 0;
return RET_OK;
}
</pre>
</div>
<div>
<br />
<h4 style="text-align: left;">
Fonctionnement</h4>
<br /></div>
<div>
L'envoi et la réception d'une trame I²C correspond à un schéma type de base :<br />
<br />
<ul style="text-align: left;">
<li>Bit de START</li>
<li>Octet d'adresse + bit de lecture ou d'écriture</li>
<li>Octet(s) de données</li>
<li>Bit de STOP</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-9hCCG2Omn1b1DTf9qJMtF9uIfYy__pMnfcLgSM6rnLZ3yZM2R4pEVB5zQhMGSY7cKE7tYAgV5itkws-div4yUoPz2M1xPtNIHR6vrDEc0NzpZPBcahLWtRngMnnloMPGBG6Py135rFs/s1600/I2C_read.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-9hCCG2Omn1b1DTf9qJMtF9uIfYy__pMnfcLgSM6rnLZ3yZM2R4pEVB5zQhMGSY7cKE7tYAgV5itkws-div4yUoPz2M1xPtNIHR6vrDEc0NzpZPBcahLWtRngMnnloMPGBG6Py135rFs/s640/I2C_read.jpg" height="185" width="580" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEoJfAe7tg8G_fc4B92ZbOATsFxnuVVMWQsbCShm3VeqG_ISJf-oT_TxdHP3TEPlI19Bhh4Up5Md0EZ5OrRPsVUvdzjYuOvTY-AnqexsJDxS_0NP1fVPvWM_GZ5z52NheTrozD-RjMWoc/s1600/I2C_write.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEoJfAe7tg8G_fc4B92ZbOATsFxnuVVMWQsbCShm3VeqG_ISJf-oT_TxdHP3TEPlI19Bhh4Up5Md0EZ5OrRPsVUvdzjYuOvTY-AnqexsJDxS_0NP1fVPvWM_GZ5z52NheTrozD-RjMWoc/s640/I2C_write.jpg" height="178" width="580" /></a></div>
<br />
Les différents bits du registre de status permettent de renseigner le programme sur le type d'opération en cours :<br />
<ol style="text-align: left;">
<li>Opération d'écriture du maître (lecture de l'esclave), le dernier octet reçu est une adresse.</li>
<ol>
<li>Bit 0 : Buffer full bit = 1</li>
<li>Bit 2 : Read or Write bit = 0</li>
<li>Bit 3 : Start bit = 1</li>
<li>Bit 5 : Data or Address bit = 0</li>
</ol>
<li>Opération d'écriture du maître (lecture de l'esclave), le dernier octet reçu est une donnée.</li>
<ol>
<li>Bit 0 : Buffer full bit = 1</li>
<li>Bit 2 : Read or Write bit = 0</li>
<li>Bit 3 : Start bit = 1</li>
<li>Bit 5 : Data or Address bit = 1</li>
</ol>
<li>Opération de lecture du maître (écriture de l'esclave), le dernier octet reçu est une adresse.</li>
<ol>
<li>Bit 0 : Buffer full bit = 0</li>
<li>Bit 2 : Read or Write bit = 1</li>
<li>Bit 3 : Start bit = 1</li>
<li>Bit 5 : Data or Address bit = 0</li>
</ol>
<li>Opération de lecture du maître (écriture de l'esclave), le dernier octet reçu est une donnée.</li>
<ol>
<li>Bit 0 : Buffer full bit = 0</li>
<li>Bit 2 : Read or Write bit = 1</li>
<li>Bit 3 : Start bit = 1</li>
<li>Bit 5 : Data or Address bit = 1</li>
</ol>
</ol>
<div>
<br /></div>
</div>
<div>
J'ai opté pour un fonctionnement du bus I²C en interruption, ce qui signifie que dès qu'il y a une activité sur le bus, le programme entre dans la routine d'interruption, regarde le type d'opération en cours et enregistre les données dans la file d'attente, si nécessaire.</div>
<div>
<br />
<br />
<h3 style="text-align: left;">
Dialogue avec l'écran LCD 2x16 caractères</h3>
<div>
<br /></div>
<h4 style="text-align: left;">
Initialisation</h4>
<br />
Deux modes d'initialisation sont possibles, mode 4 bits et mode 8 bits. Pour économiser quelques entrées du micro, j'ai choisi le premier mode (4 bits).<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvmRADwzmRRaBik3zUKLfVdmCCIW2gDc0xH3YYGdnpd5lDFUb85SSHvBhEk6b04SAPivscpQldLk3kb9fFvQ_NAXSFehnJC9aLmSfKPvv1wfFgjl1D_p3IsxZcEKlBxpqG3hYkdjy6Gh8/s1600/hd44780_init.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvmRADwzmRRaBik3zUKLfVdmCCIW2gDc0xH3YYGdnpd5lDFUb85SSHvBhEk6b04SAPivscpQldLk3kb9fFvQ_NAXSFehnJC9aLmSfKPvv1wfFgjl1D_p3IsxZcEKlBxpqG3hYkdjy6Gh8/s400/hd44780_init.png" height="400" width="395" /></a></div>
<br />
L'organigramme est assez simple pour l'initialisation, On réalise une attente de 15 ms puis on met les broches DB5 et DB4 à l'état haut, tout en laissant les autres à l'état bas.<br />
Il faut toujours envoyer une impulsion positive d'au moins 450 ns, après la mise à l'état haut.<br />
On réalise ensuite, une attente de 4.1 ms, suivie de la mise à l'état haut des broches DB5 et DB4.<br />
Comme précédemment, on fait une impulsion d'au moins 450 ns pour valider la commande.<br />
On réalise, pour finir, une attente de 100 us, suivie de la mise à l'état haut des broches DB5 et DB4 puis une attente de validation.<br />
<br />
<pre class="brush: c">int8_t lcd_init(void) {
int8_t i8_ret = 0;
ADCON1 = 0x06;
// make the corresponding PORTA pin an output
TRISA = 0;
// clear all output pins
PORTA = 0;
// clear all three output pins
LCD_RS = 0;
LCD_EN = 0;
// Wait for more than 15 ms after VCC rises to 4.5 V
__delay_ms(15);
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 1 1
LCD_D4 = 1;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
// Il faut toujours envoyer une impulsion positive d'au moins 450ns,
// après la mise à l'état haut des broches DB5 et DB4, sur la broche EN.
LCD_EN = 1;
NOP();
LCD_EN = 0;
// Wait for more than 4.1 ms
__delay_ms(5);
LCD_EN = 1;
NOP();
LCD_EN = 0;
// Wait for more than 100 μs
__delay_us(200);
LCD_EN = 1;
NOP();
LCD_EN = 0;
__delay_us(200);
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 1 0 => interface four bits mode
LCD_D4 = 0;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_EN = 1;
NOP();
LCD_EN = 0;
__delay_ms(5);
// => Set interface length
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 1 0
// 0 0 N F * *
lcd_write_byte(0x28);
// => Display On, Cursor On, Cursor Blink Off
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 0 0
// 0 0 1 0 0 0
lcd_write_byte(0x08);
// => Clear screen
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 0 0
// 0 0 0 0 0 1
lcd_write_byte(0x01);
// => Set entry Mode
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 0 0
// 0 0 0 1 D S
lcd_write_byte(0x06);
// RS R/W DB7 DB6 DB5 DB4
// 0 0 0 0 0 0
// 0 0 1 D C B
lcd_write_byte(0x0C);
// erase display
lcd_clear_display();
return i8_ret;
}
</pre>
<br />
la primitive d'écriture pour l'écran LCD est la suivante :<br />
<br />
<pre class="brush: c">int8_t lcd_write_byte(const uint8_t /* in */ ui8_byte) {
LCD_D4 = (ui8_byte >> 4) & 0x01;
LCD_D5 = (ui8_byte >> 5) & 0x01;
LCD_D6 = (ui8_byte >> 6) & 0x01;
LCD_D7 = (ui8_byte >> 7) & 0x01;
LCD_EN = 1;
NOP();
LCD_EN = 0;
if(LCD_RS == 1) {
__delay_us(200);
}
else {
__delay_ms(5);
}
LCD_D4 = ui8_byte & 0x01;
LCD_D5 = (ui8_byte >> 1) & 0x01;
LCD_D6 = (ui8_byte >> 2) & 0x01;
LCD_D7 = (ui8_byte >> 3) & 0x01;
LCD_EN = 1;
NOP();
LCD_EN = 0;
if(LCD_RS == 1) {
__delay_us(200);
}
else {
__delay_ms(5);
}
return RET_OK;
}
</pre>
<br />
<h4 style="text-align: left;">
fonctionnement</h4>
<br />
De nombreuses commandes permettent de jouer avec l'écran (récapitulées dans ce tableau, tiré de la datasheet) :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWtMciVRf-HdaCn-YLPYadKbapPDpN-ZFORJYlnLsOUQBTaiq3zZBl_zAlhRywvGj0ITvcWcnyr4OQzhgfQGRVpRUf-jOMmteY5ntlXdrg3NG0MMckT7NluRI15_pyCrTToEUmUmkYTdg/s1600/hd44780_instructions_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWtMciVRf-HdaCn-YLPYadKbapPDpN-ZFORJYlnLsOUQBTaiq3zZBl_zAlhRywvGj0ITvcWcnyr4OQzhgfQGRVpRUf-jOMmteY5ntlXdrg3NG0MMckT7NluRI15_pyCrTToEUmUmkYTdg/s640/hd44780_instructions_1.png" height="522" width="580" /></a></div>
<br />
toutes les commandes envoyées à l'écran sont basées sur la primitive d'écriture, exemples :<br />
<br />
Effacer l'écran :<br />
<br />
<pre class="brush: c">void lcd_clear_display(void) {
LCD_RS = 0;
lcd_write_byte(0x01);
}
</pre>
<br />
Retourner au début de l'écran :<br />
<br />
<pre class="brush: c">void lcd_return_home(void) {
LCD_RS = 0;
lcd_write_byte(0x02);
}
</pre>
<br />
Ecrire un caractère sur l'écran :<br />
<br />
<pre class="brush: c">void lcd_put_char(const char_t /* in */ i8_char) {
LCD_RS = 1; // write character
lcd_write_byte(i8_char);
LCD_RS = 0;
}</pre>
<br /></div>
<h3 style="text-align: left;">
File d'attente : FiFo</h3>
<br />
J'ai mis en place une file d'attente statique de type FiFo (First In, First Out), ce qui signifie que les premières données empilées dans la mémoire seront les premières à être dépilées et une fois arrivé au bout de la file d'attente, on boucle sur le début de la file d'attente. Elle est statique car la mémoire d'un micro-contrôleur est limitée, donc on déclare une taille figée de FiFo (64 octets).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmLXJUt7oQnfgJuNdKKyrqAmuLezWkmt-lM7-RIeuUaLgSHmdvgedLeAJWxSZtcuf6sU4OlxkGd4Rs4gq9BjrkNhg0rN4NSmrbYEenV_aPTZ8nL-6dOeN7772npoCwrBCobfxrBfU1maw/s1600/fifo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmLXJUt7oQnfgJuNdKKyrqAmuLezWkmt-lM7-RIeuUaLgSHmdvgedLeAJWxSZtcuf6sU4OlxkGd4Rs4gq9BjrkNhg0rN4NSmrbYEenV_aPTZ8nL-6dOeN7772npoCwrBCobfxrBfU1maw/s320/fifo.gif" height="142" width="320" /></a></div>
<br />
Concrètement, on a un tableau d'octets déclaré et deux pointeurs (un de lecture et un d'écriture) qui vont se balader sur ce tableau, avec comme contrainte que le pointeur de lecture ne dépasse jamais le pointeur d'écriture.<br />
<br />
<pre class="brush: c">#define FIFO_MAX_SIZE 64 /*!< Buffer size max */
uint8_t gpui8_buffer[FIFO_MAX_SIZE]; /*!< Static buffer */
void fifo_init(void) {
uint8_t ui8_idx = 0;
// initialise buffer
for(ui8_idx = 0; ui8_idx < FIFO_MAX_SIZE; ui8_idx ++) {
gpui8_buffer[ui8_idx] = 0;
}
// initialise pointers
gpui8_read_buf = &gpui8_buffer[0];
gpui8_write_buf = &gpui8_buffer[0];
gb_flag_cur_state_buf = BUFFER_STAT_EMPTY;
return;
}
</pre>
<br />
<h3 style="text-align: left;">
Messagerie I²C</h3>
<br />
Une messagerie simple a été conçue pour avoir accès aux fonctions principales de l'afficheur LCD et afficher la plupart des informations à l'écran.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguSqyLaWhRwOYxzb6tNaOAK49x9EXCWClyX9hkaB84BJpLxnxSp_9XtUnQW1zeBf7-dEpF8UpY1v3qVVDNdN3Fe17HHRb1xEuuqX7dj_O0Y8o4MwhTxT8cINuC9EWAwtMqaT425pKqEKg/s1600/trame_i2c_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguSqyLaWhRwOYxzb6tNaOAK49x9EXCWClyX9hkaB84BJpLxnxSp_9XtUnQW1zeBf7-dEpF8UpY1v3qVVDNdN3Fe17HHRb1xEuuqX7dj_O0Y8o4MwhTxT8cINuC9EWAwtMqaT425pKqEKg/s640/trame_i2c_1.png" height="580" width="580" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3ZSU-vEfJFHxZt6QGpbVvq78xtFKDJ5lTAtpoon0Gx2HY7DJzO8Opkv1mhCL3VlSQMOtBZKHeM7gW_sf78E-Qi2I8RASs8RCRDCsuzRaE4NwAIV9UWGjEH26Hu2NwgR5lmt51vdmbmpk/s1600/trame_i2c_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3ZSU-vEfJFHxZt6QGpbVvq78xtFKDJ5lTAtpoon0Gx2HY7DJzO8Opkv1mhCL3VlSQMOtBZKHeM7gW_sf78E-Qi2I8RASs8RCRDCsuzRaE4NwAIV9UWGjEH26Hu2NwgR5lmt51vdmbmpk/s640/trame_i2c_2.png" height="328" width="580" /></a></div>
<br />
Lien vers la première partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-1.html">Afficheur alphanumérique (Partie 1)</a><br />
Lien vers la troisième partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-3.html">Afficheur alphanumérique (Partie 3)</a><br />
</div>
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-16389698844030343002013-02-19T20:14:00.000+01:002013-02-19T20:23:55.769+01:00Afficheur Alphanumérique (partie 1)<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s1600/RPI_LCD.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqPHjLlVOOmIfOAou0JjoKy-q9-MZgzAO8V-W95k0tmeCO0EHMLP_Vqg9Glnl8DwkYKG7UfO_jusPIN9hmwh1Hiy8zmbj-Y6Mx6Fmlm305hF51Sv8oZrQfCyfZuo7dqhbOtibHYM3KdU/s640/RPI_LCD.png" height="180" width="580" /></a></div>
<h2 style="text-align: left;">
Préambule</h2>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
Ce projet consiste à interfacer un afficheur alphanumérique 2x16 caractères avec la raspberry pi. Il va pouvoir indiquer différentes informations sur l'état de la raspberry pi en fonctionnement (exemples : information sur la mémoire, le micro processeur, les process, etc ...).<br />
<br />
Ça a l'air d'être à la mode d'interfacer un afficheur à la raspberry pi. Vous trouverez sur la toile, de nombreux tutoriels pour le faire directement.<br />
Je vais complexifier un peu la chose, rien de bien méchant, je vous rassure ;-)</div>
<div style="text-align: left;">
L'afficheur va être contrôlé avec un micro contrôleur 8bits de la marque Microchip (Pic 16f876a) et dialoguera avec la raspberry pi via le bus I2C. Cela permettra d'appréhender la communication entre 2 micros via un bus série.</div>
<div style="text-align: left;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh55HfFdK_wE4MbZue-wgRlRtnB06NEmFJA1oRhmL19XNn0Xceqd_Eu0qkwV7NuUK2-9ArZdGzW_bCl8c3Xxj5JZiytVvmuJDooU2dbM4TOxk6YxFIAbdO9zHoAnTAfXT9gcqZ0Usy5meo/s1600/arch_raspi_lcd_controller.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh55HfFdK_wE4MbZue-wgRlRtnB06NEmFJA1oRhmL19XNn0Xceqd_Eu0qkwV7NuUK2-9ArZdGzW_bCl8c3Xxj5JZiytVvmuJDooU2dbM4TOxk6YxFIAbdO9zHoAnTAfXT9gcqZ0Usy5meo/s640/arch_raspi_lcd_controller.png" height="234" width="580" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Architecture générale du projet</td></tr>
</tbody></table>
<br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
J'ai choisi ce micro contrôleur 8 bits parce qu'il est possible :</div>
<ul style="text-align: left;">
<li>d'écrire le programme en C (je suis pas un grand fan de l'assembleur)</li>
<li>de compiler le programme sous Linux à l'aide du compilateur <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en542849">HI-TECH C compiler</a> (il existe, de plus, une version demo et lite)</li>
<li>de le faire évoluer pour d'autres fonctionnalités.</li>
<li>de pouvoir découvrir de nouveaux aspects des systèmes embarqués.</li>
<li>de réduire les coûts de développement (quelques euros, voir dizaines d'euros avec le programmateur)</li>
</ul>
<br />
Le premier billet va illustrer les différents éléments de ce projet. <br />
Le second billet va aborder les différents modules du micro contrôleur PIC 16f876a à mettre en place et finalement, le dernier billet montrera l'interface avec la raspberry pi.<br />
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">
Bus I²C</h3>
<br />
<a href="http://www.logotypes101.com/logos/198/8643E037CDE60120742A6EAAF3C78FC2/i2c_Bus.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.logotypes101.com/logos/198/8643E037CDE60120742A6EAAF3C78FC2/i2c_Bus.png" height="100" width="100" /></a>Le bus I2C est un bus de données série synchrone bidirectionnel half-duplex.<br />
Plusieurs équipements, soient maîtres, soient esclaves, peuvent être connectés au bus.<br />
Les échanges ont toujours lieu entre un seul maître et un (ou tous les) esclave(s), toujours à l'initiative du maître (jamais de maître à maître ou d'esclave à esclave).<br />
<br />
La connexion est réalisée par l'intermédiaire de 2 lignes :<br />
<ul>
<li>SDA (Serial Data Line) : ligne de données bidirectionnelle,</li>
<li>SCL (Serial Clock Line) : ligne d'horloge de synchronisation bidirectionnelle.</li>
</ul>
Les 2 lignes sont tirées au niveau de tension V<sub>DD</sub> à travers des résistances de pull-up (R<sub>P</sub>).<br />
Le nombre maximal d'équipements n'est pas spécifié, mais est donné pour une capacité du bus (C<sub>B</sub>) maximum (qui dépend de la vitesse du bus).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.praxisbuch.net/embedded-linux/images/iicconcept.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.praxisbuch.net/embedded-linux/images/iicconcept.png" height="105" width="400" /></a></div>
<br />
<br />
<a href="http://fr.wikipedia.org/wiki/I2C">source Wikipédia </a><br />
<br />
<div>
<h3 style="text-align: left;">
Level Shifter I²C</h3>
<h3 style="text-align: left;">
</h3>
<div style="text-align: left;">
D'après la <a href="http://elinux.org/RPi_Low-level_peripherals">documentation</a> du raspberry pi, les GPIOs fonctionnent avec un niveau logique à 3,3v (circuit CMOS) alors qu'une partie des composants (c'est le cas du micro contrôleur PIC 16f876a) utilisant le bus I²C, fonctionnent avec un niveau logique à 5v (circuit TTL), il va falloir adapter le niveau logique 3,3v en niveau logique 5v pour éviter toute incompatibilité entre les deux équipements et garantir une bonne communication.<br />
<br />
Philips, le concepteur du bus I²C, a anticipé ce genre de problème et a pondu une note d'application pour le résoudre.</div>
<br />
<iframe height="450" src="https://docs.google.com/file/d/0B6WDjVnTAZgFMGpYRVA5OTlrRnM/preview" width="580"></iframe><br />
<br />
<div style="text-align: left;">
<br />
Le schéma du shifter est basique, 2 <a href="http://fr.wikipedia.org/wiki/Transistor_%C3%A0_effet_de_champ_%C3%A0_grille_m%C3%A9tal-oxyde">mosfets à canal N</a> et 4 résistances de pull-up et le tour est joué.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-fWHkwwNqo3q79pHnKGFwpVTYFkQBYP8Bn-yGA6ngFdEnR_xBHaaqe7eqDMzLiUJrgfxib74XwSsFwfA4Q-a4bY6KGBpriGCPApsXhRYr4Rp2V9uredssGGyK6SXJxeWCSTk5zIPn1F0/s1600/i2c_shifter_level.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-fWHkwwNqo3q79pHnKGFwpVTYFkQBYP8Bn-yGA6ngFdEnR_xBHaaqe7eqDMzLiUJrgfxib74XwSsFwfA4Q-a4bY6KGBpriGCPApsXhRYr4Rp2V9uredssGGyK6SXJxeWCSTk5zIPn1F0/s640/i2c_shifter_level.png" height="361" width="580" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h4 style="text-align: left;">
Explications</h4>
<u><br />
</u> <u>État 1 :</u> En mode repos, les deux cotés de la ligne sont à l'état haut via les résistances de pull-up. Les broches <i>gate</i> et <i>source</i> du MOS-FET sont à 3,3v, donc la tension <i>Vgs</i> est en dessous de la tension de seuil (<i>Vth</i>), le MOS-FET ne conduit pas (bloqué).<br />
<br />
<u>État 2 :</u> La raspberry pi "prend la main sur la ligne" (mise à l'état bas). La broche <i>source</i> du MOS-FET descend à 0v, alors que la broche <i>gate</i> reste à 3,3v, donc la tension <i>Vgs </i>augmente jusqu'à la tension de seuil (<i>Vth</i>), le MOS-FET devient conducteur (passant). De l'autre coté de la ligne, elle est mise à l'état bas via la conduction du MOS-FET.<br />
<br />
<u>État 3 : </u> Le micro contrôleur 8bits "prend la main sur la ligne" (mise à l'état bas). A travers la diode présente entre le <i>drain</i> et la <i>source</i> (non visible sur le schéma ci-dessus), la tension <i>Vgs</i> est mise à zéro jusqu'à ce que le MOS-FET devienne conducteur et à ce moment là, les deux cotés de la ligne sont à l'état bas à travers la conduction du MOS-FET.<br />
<br />
<br />
Le site de vente de composants électronique <a href="https://www.sparkfun.com/products/8745?"><i>sparkfun</i></a> vend ce montage tout fait.<br />
<br />
A noter que ce petit circuit peut s'appliquer à d'autres tensions (tout en gardant à l'esprit que la tension la plus faible doit être reliée à la broche <i>gate</i>) et d'autres utilisations autre que le bus I²C.<br />
<br />
<h3 style="text-align: left;">
LCD Alphanumérique 2x16 </h3>
<br />
L'afficheur est contrôlé via le contrôleur HD44780 permettant de piloter un dispositif d'affichage par cristaux liquides. Il peut communiquer avec l’extérieur soit avec une liaison série, soit avec une liaison parallèle et 2 modes de communication sont possibles (4 ou 8 bits).<br />
<br />
Dans notre cas, ce sera une liaison parallèle en mode 4 bits.<br />
<br />
<h4 style="text-align: left;">
La différence entre les 2 modes de communication :</h4>
<div style="text-align: left;">
<br /></div>
<u>mode 8 bits :</u><br />
<br />
C'est le mode initial de l'afficheur, les données sont échangées via les broches D0 à D7.<br />
<br />
<u>mode 4 bits :</u><br />
<br />
Afin de limiter le nombre de broches nécessaires pour commander l'afficheur, on peut travailler en mode 4 bits ou les données sont échangées via les broches D4 à D7 (les broches D0 à D3 sont mises à la masse).<br />
<br />
<h4 style="text-align: left;">
Schéma de câblage :</h4>
<div style="text-align: left;">
<br /></div>
<ul style="text-align: left;">
<li>La broche R/W est mise à la masse puisque l'on souhaite seulement écrire sur l'afficheur.</li>
<li>Les broches DB0 à DB3 sont mis à la masse car on va l'utiliser en mode 4 bits</li>
<li>Le potentiomètre RV1 va servir à régler le contraste de l'affichage</li>
</ul>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7CGo8_byE10ubSeq0BxqOu8bWO2dcX9t_9SKzGbeqkqmYousNfizl5GLTB7xEdyLqP3sR9NZBzntFpAJ6ht7v9469gGW5DZfqo4VoGffmL8IyFoLRvi9uvhy5D0EEbjtYM8VFZzrlSLQ/s1600/hd44780_schema.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7CGo8_byE10ubSeq0BxqOu8bWO2dcX9t_9SKzGbeqkqmYousNfizl5GLTB7xEdyLqP3sR9NZBzntFpAJ6ht7v9469gGW5DZfqo4VoGffmL8IyFoLRvi9uvhy5D0EEbjtYM8VFZzrlSLQ/s400/hd44780_schema.png" height="361" width="400" /></a></div>
<br />
<br />
Datasheet du contrôleur HD44780 :<br />
<br />
<iframe height="450" src="https://docs.google.com/file/d/0B6WDjVnTAZgFd0xjZHc0Y3JPN3M/preview" width="580"></iframe><br />
<br />
<br />
<h3 style="text-align: left;">
micro contrôleur 8 bits</h3>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://robot-eseo.fr/partenaires/2010-2011/MICROCHIP_logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://robot-eseo.fr/partenaires/2010-2011/MICROCHIP_logo.png" height="75" width="125" /></a></div>
<div style="text-align: left;">
Le micro contrôleur PIC16f876a va jouer le rôle de contrôleur LCD en interprétant les messages I²C arrivant de la raspberry pi pour afficher les informations sur l'écran.<br />
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
Caractéristiques du pic16f876a :</h4>
<br />
20 MHz (max), environ 220 ko de mémoire flash, 2944 octets de RAM, 2048 octets d'eeprom, modules SPI, I²C, UART, PWM, Convertisseur Analogique Numérique, 4 ports d'entrées sorties multiplexés.<br />
<br />
<h4 style="text-align: left;">
Schéma de câblage :</h4>
<br />
<ul style="text-align: left;">
<li>La tension de fonctionnement du micro contrôleur est 5v. </li>
<li>Le filtrage <i>RC</i> sur la broche <i>MCLR</i> permet de mettre en œuvre un mécanisme de protection lors du reset du système.</li>
<li>DB4 à DB7, RS et ENABLE sont les signaux provenant de l'afficheur LCD.</li>
<li>L'oscillateur de 8 MHz câblé permet d'utiliser le micro contrôleur en mode HS (High Speed)</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVVVp37AbKdAqu0M24dyY1O7eLuJ3fMRmTrwn0j8JClLiNZDI0XXZ17js3R1tpt74kEvbWfa5E0dJhyjfwTHYLbb9Yw_c6YbEK6HDjMqWDZs1C9RsQOyd5qQndwtVrjV-DqaWUqO8BUUo/s1600/pic16f876a_schema_cablage.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVVVp37AbKdAqu0M24dyY1O7eLuJ3fMRmTrwn0j8JClLiNZDI0XXZ17js3R1tpt74kEvbWfa5E0dJhyjfwTHYLbb9Yw_c6YbEK6HDjMqWDZs1C9RsQOyd5qQndwtVrjV-DqaWUqO8BUUo/s640/pic16f876a_schema_cablage.png" height="465" width="580" /></a></div>
<br />
<br />
<br /></div>
<div style="text-align: left;">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
La datasheet du PIC16f876a :<br />
<br />
<iframe height="450" src="https://docs.google.com/file/d/0B6WDjVnTAZgFbzR4RnlXQWtHcWM/preview" width="580"></iframe><br />
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br />
<h3 style="text-align: left;">
Schéma électrique </h3>
<br />
Schéma électrique de la carte d'extension<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPUcIjuOeABH1P6ARhD-QTuFwncWQEsWRDXmYKwzd4NHW8v1ePWWKXeiMU4yPZjwk6wdrz1olRNwXvlRRhy-WvBLu1UDh0_9_aS5npyZ3HmvIHX_xY2hRY8lbaD3u49zEHUeKVdU_ybxM/s1600/schema_rpilcd.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPUcIjuOeABH1P6ARhD-QTuFwncWQEsWRDXmYKwzd4NHW8v1ePWWKXeiMU4yPZjwk6wdrz1olRNwXvlRRhy-WvBLu1UDh0_9_aS5npyZ3HmvIHX_xY2hRY8lbaD3u49zEHUeKVdU_ybxM/s640/schema_rpilcd.png" height="467" width="580" /></a></div>
<br /></div>
<div style="text-align: left;">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Lien vers la deuxième partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-2.html">Afficheur alphanumérique (Partie 2)</a><br />
Lien vers la troisième partie du tutoriel : <a href="http://colocsbar.blogspot.fr/2013/02/afficheur-alphanumerique-partie-3.html">Afficheur alphanumérique (Partie 3)</a></div>
</div>
</div>
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-45540689076186508792013-02-09T12:16:00.001+01:002013-02-09T12:16:09.185+01:00Alertes [LE BON COIN]<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUj4NGAiMDqcCGyp25pJLBHKfxKH0gIkg2w4hJjtVop15dcIDU6byJq_DPxUf6thpM3IpTrg1_WzNc_aqX6oll9DQwjdU5y0Qv-OjO_YZTJdndOJBsRlZRUsspILF0-vAbN7REK4teWSo/s1600/alerte_le_bon_coin.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="53" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUj4NGAiMDqcCGyp25pJLBHKfxKH0gIkg2w4hJjtVop15dcIDU6byJq_DPxUf6thpM3IpTrg1_WzNc_aqX6oll9DQwjdU5y0Qv-OjO_YZTJdndOJBsRlZRUsspILF0-vAbN7REK4teWSo/s1600/alerte_le_bon_coin.png" width="580" /></a></div>
<br />
<br />
<br />
<br />
Vous connaissez, surement, l'un des sites de recherche d'objets neufs ou d'occasions le plus connu, <b>Le bon coin</b>. Il est vrai que l'on peut y faire de bonnes affaires, en achetant ou en vendant à peu près tout ce que l'on veut ou en proposant tous types de services.<br />
Il m'arrive, assez régulièrement, de fréquenter ce site, surtout quand je suis à la recherche de choses bien précise.<br />
N'ayant pas la possibilité de me rendre régulièrement sur le site, tout au long d'une journée, j'ai imaginé ce soft qui a pour but d'effectuer la recherche à ma place à une date précise ou un intervalle de temps programmé. Le résultat de cette recherche est ensuite envoyé par email si de nouveaux éléments sont trouvés.<br />
Une interface web est accessible depuis n'importe quel navigateur, afin de faciliter la gestion (Ajout, suppression et configuration) de mes recherches.<br />
<br />
Ce programme, sous licence GPL, écrit entièrement en <i>python, </i>utilise différentes sources tierces pour atteindre mon but :<br />
<br />
<ul style="text-align: left;">
<li><b><a href="http://www.cherrypy.org/">CherryPy</a> </b>: Création et gestion d'un serveur Web minimaliste</li>
<li><b><a href="http://genshi.edgewall.org/">Genshi</a> </b>: Template pour la gestion des pages Web</li>
<li><b><a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> </b>: Analyse d'une page internet</li>
<li><b><a href="http://docs.python.org/2/library/xml.dom.minidom.html">Minidom</a></b> : Gestion des fichiers XML qui jouera le rôle de base de données</li>
<li><a href="http://packages.python.org/APScheduler/"><b>APScheduler</b></a> : Gestion d'un ordonnanceur/planificateur de tâches</li>
</ul>
<div>
<a name='more'></a><br /></div>
<div>
<h3 style="text-align: left;">
Installation</h3>
<br />
Télécharger l'archive <a href="https://docs.google.com/file/d/0B6WDjVnTAZgFblVvRnZoU0FEcUU/edit?usp=sharing">alertes_lbc-0.1.tar.gz</a> puis décompressez la. Pour une installation facile, avec toutes les dépendances, il faudra avoir le package <i>python-setuptools</i>.<br />
<br />
<pre class="brush: shell"># tar xvzf alertes_lbc-0.1.tar.gz
# sudo apt-get install python-setuptools
# cd alertes_lbc-0.1
# sudo python setup.py install
</pre>
<br />
setuptools installera les dépendances manquantes nécessaires à l'utilisation du soft.<br />
<br />
<h3 style="text-align: left;">
Exécution</h3>
<br />
Le soft, <i>alertes.py</i>, se trouve dans le dossier source de l'archive. Il est possible d'avoir de l'aide avec la commande :<br />
<br />
<pre class="brush: shell"># ./alertes.py --help
Usage: alertes.py [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-l LIBELLE, --libelle=LIBELLE
Libellé d'une nouvelle alerte le bon coin
-u URL, --url=URL Url de recherche du site le bon coin
-e EMAIL, --email=EMAIL
Email d'envoi des résultats
Recherche à une date précise:
Format JJ/MM/AAAA HH:mm AAAA = Année MM = mois JJ = Jour HH = Heure
mm = minute
-d DATE, --date=DATE
Date précise de format : JJ/MM/AAAA HH:mm
Recherche à un intervalle de temps:
-j FREQ_DAY, --jour=FREQ_DAY
Intervalle de X jours entre chaque recherche
-H FREQ_HOUR, --heure=FREQ_HOUR
Intervalle de X heures entre chaque recherche
-M FREQ_MINUTE, --minute=FREQ_MINUTE
Intervalle de X minutes entre chaque recherche
Option pour l'interface Web:
--sans-serveur-web Ne pas démarrer le serveur web
-n SERVER_HOST, --server-host=SERVER_HOST
L'adresse IP pour le serveur web
-p SERVER_PORT, --server-port=SERVER_PORT
Le port d'écoute du serveur
</pre>
<br />
Deux paramètres principaux sont à renseigner pour lancer le soft :<br />
<br />
<ul style="text-align: left;">
<li>l'adresse IP du serveur, par défaut, localhost</li>
<li>Le port du serveur</li>
</ul>
<br />
Exemple :<br />
<pre class="brush: shell"># ./alertes.py -n "0.0.0.0" -p 3456
[09/Feb/2013:10:40:10] ENGINE Bus STARTING
[09/Feb/2013:10:40:10] ENGINE Started monitor thread '_TimeoutMonitor'.
[09/Feb/2013:10:40:10] ENGINE Started monitor thread 'Autoreloader'.
[09/Feb/2013:10:40:11] ENGINE Serving on 0.0.0.0:3456
[09/Feb/2013:10:40:11] ENGINE Bus STARTED
</pre>
<br />
Je lance l'écoute du serveur web sur toutes les adresses IP du réseau sur le port 3456.<br />
ouvrez un navigateur web et entrez <b>http://IP:PORT</b> dans la barre d'adresse, et on obtient cette page.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHgx7BJ1GIOyyDqRZdvPL2HJrMkPO1Jn7eFPJ4XeagJexFN00cIfZy0PgQocVJcqEVZInuIbtro7kKwonfI2_irUNP5soVypVnPQcnpmKPFf2tJuUWUT5pL9O11WWl10zy1pxbL_3QUYs/s1600/alerte_le_bon_coin_2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHgx7BJ1GIOyyDqRZdvPL2HJrMkPO1Jn7eFPJ4XeagJexFN00cIfZy0PgQocVJcqEVZInuIbtro7kKwonfI2_irUNP5soVypVnPQcnpmKPFf2tJuUWUT5pL9O11WWl10zy1pxbL_3QUYs/s640/alerte_le_bon_coin_2.png" width="580" /></a></div>
<br />
<br /></div>
<div>
<br />
Le <i>header </i>de la page permet de naviguer sur le serveur :<br />
<br />
<ul style="text-align: left;">
<li><b>Accueil</b> : Page d’accueil du serveur, récapitulatif des alertes en cours</li>
<li><b>Ajouter</b> : Page d'ajout de nouvelles alertes</li>
<li><b>Supprimer</b> : Page de suppression d'une ou plusieurs alertes</li>
<li><b>Configuration</b> : Page de configuration pour l'envoi d'email</li>
</ul>
<br />
Le corps de la page principale donne un récapitulatif des alertes enregistrées, chaque alerte est représentée par un <b>libellé</b>, <b>l'URL </b>le bon coin de la recherche, <b>l'email </b>d'envoi des résultats, <b>l'heure et la date</b> de création de l'alerte et la <b>fréquence </b>de recherche.<br />
<br />
<h4 style="text-align: left;">
La page Ajouter</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76hKL8UcGuhb4x71wf33rnrMDvqk_i2D3zYm1BeWq2tsp9Nst7pq0AydbrTDTvTbYsbzW8kwmnZVjLMfeafHb6skXNZk6ggrBf1TbxcjwLT3xH0sb5TRM4uhEnJFYpbtdCK6R1Fh4UsE/s1600/alerte_le_bon_coin_3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi76hKL8UcGuhb4x71wf33rnrMDvqk_i2D3zYm1BeWq2tsp9Nst7pq0AydbrTDTvTbYsbzW8kwmnZVjLMfeafHb6skXNZk6ggrBf1TbxcjwLT3xH0sb5TRM4uhEnJFYpbtdCK6R1Fh4UsE/s640/alerte_le_bon_coin_3.png" width="580" /></a></div>
<br />
Sur cette page, on va renseigner les champs nécessaires pour notre alerte.<br />
<br />
<ul style="text-align: left;">
<li>Libellé : Nom de l'alerte</li>
<li>Lien URL : Le lien URL le bon coin de notre recherche</li>
<li>Email : L'adresse email pour l'envoi des résultats</li>
<li>Date Unique ou Intervalle de temps</li>
</ul>
<div>
<b><br />
</b> <b>Exemple d'utilisation :</b><br />
<br />
Sur le site internet : le bon coin, je saisi ma recherche complète, et je clique sur le bouton CHERCHER.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9CCFuDfFnIWBP7raJ5hI4H_J5Ptabdbi2UukWzT8NuWrQ3ZywTjsEc4E9Zv-0yKKrcHGjbyr1giGhCpb1ypZYpffht0iJf7z7kA9nnQByS26tu-qhcn3vNudkvI32m8QA-SIv7DEsxxE/s1600/alerte_le_bon_coin_4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9CCFuDfFnIWBP7raJ5hI4H_J5Ptabdbi2UukWzT8NuWrQ3ZywTjsEc4E9Zv-0yKKrcHGjbyr1giGhCpb1ypZYpffht0iJf7z7kA9nnQByS26tu-qhcn3vNudkvI32m8QA-SIv7DEsxxE/s640/alerte_le_bon_coin_4.png" width="580" /></a></div>
<br />
La deuxième étape consiste à copier le lien internet de la recherche puis de coller le lien sur notre page ajouter et de renseigner les autres champs. Ici, j'ai configuré une recherche toutes les heures.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVbSNNlZHxX454AAv-JCG5vmcsBgZy4z8BOiQRtgXW5O-ReL43HtIHBnm7vhbEyBeXhfgeOHa9fh9ogHlYWflPfPmnjtcf1jScEESnX5L6Rsb7tEwgginaccutTZs3yZqh2eqrlMzM1U/s1600/alerte_le_bon_coin_5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVbSNNlZHxX454AAv-JCG5vmcsBgZy4z8BOiQRtgXW5O-ReL43HtIHBnm7vhbEyBeXhfgeOHa9fh9ogHlYWflPfPmnjtcf1jScEESnX5L6Rsb7tEwgginaccutTZs3yZqh2eqrlMzM1U/s640/alerte_le_bon_coin_5.png" width="580" /></a></div>
<br />
On clique sur le bouton <i>Ajout</i>, et la page principale ré-apparaît avec le récapitulatif de la recherche.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWsZNEMbxr8EzcDe3hHLMQ4w9YgnNa39oPt7IPQIGcm0Fwrh7U1Cr6rCjW_xYST7VkG82TAs_CddmS1my192f-4zTkVsIUPPcLQI6oOTZ1M3TtFoqyaqLDBQyFwBhuValcz3FdFrs6gKM/s1600/alerte_le_bon_coin_6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWsZNEMbxr8EzcDe3hHLMQ4w9YgnNa39oPt7IPQIGcm0Fwrh7U1Cr6rCjW_xYST7VkG82TAs_CddmS1my192f-4zTkVsIUPPcLQI6oOTZ1M3TtFoqyaqLDBQyFwBhuValcz3FdFrs6gKM/s640/alerte_le_bon_coin_6.png" width="580" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h4 style="text-align: left;">
La page Configuration </h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBO1GdcIaxW74BgdqnHg-jF06DUj7ZrAR8zwpDiJvWfQnlxX9fXRHX3ja2S3gFPZYQuBfXA4BU8_nglpFE-Qw0OQ-khIjMJ45BS9rEVUTp2JbN8ovulYFbnPFQbxO__sipmx2v-TtJ_s/s1600/alerte_le_bon_coin_7.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBO1GdcIaxW74BgdqnHg-jF06DUj7ZrAR8zwpDiJvWfQnlxX9fXRHX3ja2S3gFPZYQuBfXA4BU8_nglpFE-Qw0OQ-khIjMJ45BS9rEVUTp2JbN8ovulYFbnPFQbxO__sipmx2v-TtJ_s/s640/alerte_le_bon_coin_7.png" width="580" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Sur cette page, on va renseigner les différents champs, puis appuyer sur le bouton <i>Configurer </i>pour valider les paramètres :<br />
<br />
<ul style="text-align: left;">
<li>serveur smtp (exemple : smtp.free.fr, smtp.gmail.com, smtp.orange.fr)</li>
<li>port smtp (exemple : 587)</li>
<li>Sécurité d'email : </li>
<ul>
<li>Aucune, dans ce cas là, on ne renseigne pas les champs login et password</li>
<li>STARTTLS, on va devoir renseigner le login et le password</li>
</ul>
</ul>
Le mot de passe est enregistré crypté dans la base de donnée.<br />
<br />
Exemple de configuration :<br />
<br />
<ul style="text-align: left;">
<li>Gmail :</li>
<ul>
<li>serveur : smtp.gmail.com</li>
<li>port : 587</li>
<li>sécurité : STARTTLS</li>
<li>login : adresse email gmail</li>
<li>password : mot de passe de connexion</li>
</ul>
</ul>
<div>
<br /></div>
<h4 style="text-align: left;">
La page Supprimer</h4>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMSvJbkE_D-6KIFAfB_tUogkeB-FFzDrkZagtU1bx2QlSD5GWbeefwWh_TWTUB0TY3k0KTQS59dVyMwG4GIX6ed9z2Lw4a9p10MIgg-4b4Lvu_gDDB0arKlPncZObKd4Aw6UkI5vxdyMk/s1600/alerte_le_bon_coin_8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMSvJbkE_D-6KIFAfB_tUogkeB-FFzDrkZagtU1bx2QlSD5GWbeefwWh_TWTUB0TY3k0KTQS59dVyMwG4GIX6ed9z2Lw4a9p10MIgg-4b4Lvu_gDDB0arKlPncZObKd4Aw6UkI5vxdyMk/s640/alerte_le_bon_coin_8.png" width="580" /></a></div>
<br />
Pour supprimer une annonce, il suffit de cocher l'alerte ou les alertes à supprimer puis de cliquer sur le bouton <i>Supprimer</i>.<br />
<br />
<h3 style="text-align: left;">
Conclusion</h3>
<br />
Profitez-en, tant que les sources sont disponibles car ce genre d'outils ne plait pas beaucoup à ce site ... ;-)<br />
<br /></div>
</div>
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com5Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-10072567183078109442013-01-06T22:03:00.002+01:002013-01-06T22:03:08.852+01:00Monitoring & Raspberry Pi<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://github.com/nicolargo/glances/raw/master/doc/glances-white-256.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://github.com/nicolargo/glances/raw/master/doc/glances-white-256.png" width="200" /></a></div>
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Voici un petit outil de supervision, créé par Nicolargo dont voici le lien du blog : <a href="http://blog.nicolargo.com/">blog de nicolargo</a>. Cet outil s'appelle <a href="http://nicolargo.github.com/glances">Glances</a>, et permet surveiller son système en mode console depuis un terminal. Cet outil est développé en python et utilise différentes librairies python, notamment <b>psutil</b> qui récupère les informations systèmes de la raspberry pi.<br />
<br />
<br />
<br />
<br />
<br />
Les différentes statistiques sont classées et visibles grâce à différentes couleurs :<br />
<br />
<ul style="border: 0pt none; list-style-type: square; margin: 0.5em 0em 0.5em 2em; outline: invert none 0pt; padding: 0pt; text-align: left; vertical-align: baseline;">
<li><span style="color: lime;">VERT</span> : la statistique est OK</li>
<li><span style="color: blue;">BLEU </span>: la statistique est à surveiller</li>
<li><span style="color: purple;">VIOLET </span>: la statistique est en alerte</li>
<li><span style="color: red;">ROUGE </span>: la statistique est critique</li>
</ul>
<br />
De nombreux raccourci clavier permettent d'activer ou désactiver différentes fonctions, de trier certaines statistiques, etc ...<br />
<br />
Voici un petit screenshot de cet utilitaire :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRHy70PBm0zMepWl-7C_GKGkARDCUHNxJv7v7urdcJwk57VU4puLlre-0KATLWkPb4fFuvpYDFN8JEwrsLzY3qHy_hOW4yZImScrFTLei_1IuG7XqCUG5hjeuTnZ-8dokWTa9vUIJ28sY/s1600/glances_raspberrypi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRHy70PBm0zMepWl-7C_GKGkARDCUHNxJv7v7urdcJwk57VU4puLlre-0KATLWkPb4fFuvpYDFN8JEwrsLzY3qHy_hOW4yZImScrFTLei_1IuG7XqCUG5hjeuTnZ-8dokWTa9vUIJ28sY/s640/glances_raspberrypi.png" width="580" /></a></div>
<br />
<a name='more'></a><br />
<br />
Deux nouveaux paquets sont à installer dans le dossier <i>package</i> de buildroot :<br />
<br />
<pre class="brush: shell"># mkdir -p BUILDROOT_PATH/package/python-psutil
# mkdir -p BUILDROOT_PATH/package/glances
</pre>
<br />
<h4 style="text-align: left;">
Python-psutil</h4>
<br />
Le dossier python-psutil contient le fichier de configuration et son makefile :<br />
<br />
<pre class="brush: shell"># ls -al BUILDROOT_PATH/package/python-psutil
total 108
drwxr-xr-x 2 sinseman44 sinseman44 4096 2013-01-05 23:23 ./
drwxr-xr-x 553 sinseman44 sinseman44 77824 2013-01-06 18:45 ../
-rw-r--r-- 1 sinseman44 sinseman44 469 2013-01-05 11:09 Config.in
-rw-r--r-- 1 sinseman44 sinseman44 1136 2013-01-05 23:23 python-psutil.mk
</pre>
<br />
Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_PYTHON_PSUTIL
bool "python-psutil"
depends on BR2_PACKAGE_PYTHON
help
psutil is a module providing an interface for retrieving information on all running processes
and system utilization (CPU, memory, disks, network, users) in a portable way by using Python,
implementing many functionalities offered by command line tools such as
(ps, top, df, kill, free, lsof, netstat, ifconfig, nice, etc ...)
http://code.google.com/p/psutil
</pre>
<br />
python-psutil.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# python-psutil
#
#############################################################
PYTHON_PSUTIL_VERSION = 0.6.1
PYTHON_PSUTIL_SOURCE = psutil-$(PYTHON_PSUTIL_VERSION).tar.gz
PYTHON_PSUTIL_SITE = http://psutil.googlecode.com/files
PYTHON_PSUTIL_DEPENDENCIES = python
define PYTHON_PSUTIL_BUILD_CMDS
(cd $(@D); $(HOST_DIR)/usr/bin/python setup.py build_py)
(cd $(@D); \
PYTHONXCPREFIX="$(STAGING_DIR)/usr/" \
CC="$(TARGET_CC) -pthread" \
LDSHARED="$(TARGET_CC) -pthread -shared -Wl,-O1,--sort-common,--as-needed" \
CFLAGS="-fno-strict-aliasing -I$(STAGING_DIR)/usr/include/python2.7 $(CFLAGS)" \
LDFLAGS="-L$(STAGING_DIR)/lib -L$(STAGING_DIR)/usr/lib $(LDFLAGS)" \
"$(HOST_DIR)"/usr/bin/python setup.py build_ext \
--include-dirs="$(STAGING_DIR)"/usr/include \
--library-dirs="$(STAGING_DIR)"/usr/lib)
endef
define PYTHON_PSUTIL_INSTALL_TARGET_CMDS
(cd $(@D); PYTHONPATH=$(TARGET_DIR)/usr/lib/python$(PYTHON_VERSION_MAJOR)/site-packages \
$(HOST_DIR)/usr/bin/python setup.py install --prefix=$(TARGET_DIR)/usr)
endef
$(eval $(generic-package))
</pre>
<br />
<h4 style="text-align: left;">
Glances </h4>
<br />
Le dossier glances contient le fichier de configuration et son makefile :<br />
<br />
<pre class="brush: shell"># ls -al BUILDROOT_PATH/package/glances
total 108
drwxr-xr-x 2 sinseman44 sinseman44 4096 2013-01-06 18:43 ./
drwxr-xr-x 553 sinseman44 sinseman44 77824 2013-01-06 18:45 ../
-rw-r--r-- 1 sinseman44 sinseman44 244 2013-01-06 18:38 Config.in
-rw-r--r-- 1 sinseman44 sinseman44 1101 2013-01-06 18:43 glances.mk
</pre>
<br />
Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_GLANCES
bool "glances"
depends on BR2_PACKAGE_PYTHON_PSUTIL
depends on BR2_PACKAGE_PYTHON_SETUPTOOLS
help
Glances is a CLI curses based monitoring tool for GNU/Linux and BSD OS
http://nicolargo.github.com/glances
</pre>
<br />
glances.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# glances
#
#############################################################
GLANCES_VERSION = ebf8cf92d2520b2d5f815e6531b1a628f1e0dd6f
GLANCES_SITE_METHOD = git
GLANCES_SITE = https://github.com/nicolargo/glances.git
GLANCES_DEPENDENCIES = python
define GLANCES_BUILD_CMDS
(cd $(@D); $(HOST_DIR)/usr/bin/python setup.py build_py)
(cd $(@D); \
PYTHONXCPREFIX="$(STAGING_DIR)/usr/" \
CC="$(TARGET_CC) -pthread" \
LDSHARED="$(TARGET_CC) -pthread -shared -Wl,-O1,--sort-common,--as-needed" \
CFLAGS="-fno-strict-aliasing -I$(STAGING_DIR)/usr/include/python2.7 $(CFLAGS)" \
LDFLAGS="-L$(STAGING_DIR)/lib -L$(STAGING_DIR)/usr/lib $(LDFLAGS)" \
"$(HOST_DIR)"/usr/bin/python setup.py build_ext \
--include-dirs="$(STAGING_DIR)"/usr/include \
--library-dirs="$(STAGING_DIR)"/usr/lib)
endef
define GLANCES_INSTALL_TARGET_CMDS
(cd $(@D); PYTHONPATH=$(TARGET_DIR)/usr/lib/python$(PYTHON_VERSION_MAJOR)/site-packages \
$(HOST_DIR)/usr/bin/python setup.py install --prefix=$(TARGET_DIR)/usr)
endef
$(eval $(generic-package))
</pre>
<br />
Il faut ensuite modifier le fichier de configuration général pour l'intégrer à buildroot :<br />
<br />
<pre class="brush: shell; highlight: [17,18];"># vim BUILDROOT_PATH/package/Config.in
270 if BR2_PACKAGE_PYTHON
271 menu "external python modules"
272 source "package/python-dpkt/Config.in"
273 source "package/python-id3/Config.in"
274 source "package/python-mad/Config.in"
275 source "package/python-netifaces/Config.in"
276 source "package/python-nfc/Config.in"
277 source "package/python-pygame/Config.in"
278 source "package/python-serial/Config.in"
279 source "package/python-setuptools/Config.in"
280 source "package/python-cheetah/Config.in"
281 source "package/python-openssl/Config.in"
282 source "package/python-sqlite/Config.in"
283 source "package/python-yenc/Config.in"
284 source "package/python-cherrypy/Config.in"
285 source "package/python-psutil/Config.in"
286 source "package/glances/Config.in"
287 endmenu
288 endif
289 source "package/ruby/Config.in"
290 source "package/tcl/Config.in"
291 endmenu
</pre>
<br />
Une fois les modifications effectuées, selectionner l'utilitaire dans la section <i>Interpreter languages and scripting -> external python modules</i>, à l'aide de la commande :<br />
<br />
<pre class="brush: shell"># make menuconfig
</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9tXGf6QJfrPW7EWeNDKRusOBNIybEtDgDvTr2Q5-i698MePPp4MhDBF2ZRqQtlJR01AQL7a9DM1ZuE_r34U4mi8fAMlGM8mbf_Y2KN77TWby_97t0vmqK73iI08jSE2xzPnWnsOexy_g/s1600/buildroot_glances.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="456" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9tXGf6QJfrPW7EWeNDKRusOBNIybEtDgDvTr2Q5-i698MePPp4MhDBF2ZRqQtlJR01AQL7a9DM1ZuE_r34U4mi8fAMlGM8mbf_Y2KN77TWby_97t0vmqK73iI08jSE2xzPnWnsOexy_g/s640/buildroot_glances.png" width="580" /></a></div>
<br />
Compilation de l'utilitaire et intégration de celui-ci au système de fichiers :<br />
<br />
<pre class="brush: shell"># make
</pre>
<br />
<h4 style="text-align: left;">
Utilisation</h4>
<br />
l'option "-t" permet de choisir le temps de rafraîchissement (en seconde) qui est par défaut de 1 seconde.<br />
<br />
<pre class="brush: shell"># python /usr/bin/glances -t 5
</pre>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaYwsxxDn1Xw7ENzZm4n8VMqEITBAoOehumygo_HcmZu-gZGQdpcy4Q0icSzhxkdqr7uvov99FGKfpdqO-kopwfh2WnMDKmGi3iLvZ-HZXLPlqzj_6HN4uTsgVP-ryOUR3P-mCGDYnzYI/s1600/glances_raspberrypi_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="352" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaYwsxxDn1Xw7ENzZm4n8VMqEITBAoOehumygo_HcmZu-gZGQdpcy4Q0icSzhxkdqr7uvov99FGKfpdqO-kopwfh2WnMDKmGi3iLvZ-HZXLPlqzj_6HN4uTsgVP-ryOUR3P-mCGDYnzYI/s640/glances_raspberrypi_2.png" width="580" /></a></div>
<br />
<br /></div>
</div>
Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-1583510161276941782012-12-29T12:39:00.000+01:002013-01-06T18:25:09.162+01:00Raspberry PI mod C64<div dir="ltr" style="text-align: left;" trbidi="on"><div class="separator" style="clear: both; text-align: center;"><a href="http://www.amolag.com/wp-content/uploads/2012/03/me64er-logo.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.amolag.com/wp-content/uploads/2012/03/me64er-logo.jpg" /></a></div><a href="http://www.madgrin.com/wp-content/uploads/2007/12/commodore-logo-thumb.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br />
</a><br />
<br />
On m'a refiler 2 commodores 64 pour "essayer" de les réparer et d'en faire un fonctionnel. Donc je me suis retrouvé avec 2 châssis pour une seule carte électronique, et j'ai eu l'idée en parcourant différents site web d'électronique, DIY, blog, etc ... de me faire un <b>RPI mod C64</b>.<br />
<br />
<br />
<br />
<br />
Le cahier des charges de ce projet est relativement simple, utiliser un châssis + clavier de commodore 64 pour jouer à des jeux de commodore 64 mais sur une Raspberry Pi, et pour rajouter un peu plus de fun dans tout ça, pouvoir l'utiliser en tant que média center.<br />
<br />
Voici le résultat final :<br />
<br />
<ul style="text-align: left;"><li>2 interrupteurs, le premier pour l'alimentation électrique et le second pour changer de mode (émulateur ou media center)</li>
<li>1 led d'état du contrôleur de clavier</li>
</ul><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhONChyphenhyphenKVCxIJsZZQW_kkrSPpqJau_iSCI7rmxPpiNujUX2xXMjKz8DQyXuM9aOOCkK924z0pzQ6oQqhcX_4tpTLSlx6BWiALxJDXZkC7YDjDAo2NCu8dmRztu1vQDlzZjdaW-TWI3FoGQ/s1600/20121226_100514.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhONChyphenhyphenKVCxIJsZZQW_kkrSPpqJau_iSCI7rmxPpiNujUX2xXMjKz8DQyXuM9aOOCkK924z0pzQ6oQqhcX_4tpTLSlx6BWiALxJDXZkC7YDjDAo2NCu8dmRztu1vQDlzZjdaW-TWI3FoGQ/s320/20121226_100514.jpg" height="240" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"></div>et l'intérieur de la bête :<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnfXAm1niWHNpohr2U4v5x43l2HDiMxRvvhphWWp-BhwHDOdUyiNzvy7aFOclIx3WMlLx_HTUuN-DsurlLpaVbLWovOMelaJbWnp7HhlZwASW5IaMdhOKHtE8IIK6oL_Ekf5_H_EPSZFc/s1600/20121225_204800.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnfXAm1niWHNpohr2U4v5x43l2HDiMxRvvhphWWp-BhwHDOdUyiNzvy7aFOclIx3WMlLx_HTUuN-DsurlLpaVbLWovOMelaJbWnp7HhlZwASW5IaMdhOKHtE8IIK6oL_Ekf5_H_EPSZFc/s320/20121225_204800.jpg" height="240" width="320" /></a></div><br />
<br />
Les différentes grandes étapes du projet sont :<br />
<ul style="text-align: left;"><li>Compiler XBMC (media center) pour buildroot et l'intégrer au système de fichiers</li>
<li>Compiler Vice C64 (émulateur commodore C64) pour buildroot et l'intégrer au système de fichiers</li>
<li>Créer un programme qui contrôle le démarrage et l'arrêt du mediacenter/émulateur en fonction de la position d'un switch</li>
<li>Créer une carte contrôleur pour la gestion du clavier C64 en USB.</li>
</ul><br />
<br />
<a name='more'></a><br />
<h3 style="text-align: left;">XBMC pour Buildroot</h3><br />
Histoire de ne pas ré-inventer la roue, j'ai trouvé sur github, XBMC intégré sur buildroot (une ancienne version).<br />
<br />
Je suis reparti de <a href="https://github.com/huceke/buildroot-rbp">ces sources</a> et je les ai adaptées pour mon buildroot, pour vous fournir un <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFY0dxVjNLcm5wZFE">patch</a> à appliquer à buildroot.<br />
<br />
<pre class="brush: shell"># cd BUILDROOT_PATH
# patch -p1 < buildroot_raspberrypi_xbmc.patch
</pre><br />
Que contient ce patch ?<br />
<ul style="text-align: left;"><li>Toutes les libraires nécessaires à la compilation et à l'utilisation de XBMC.</li>
<li>Le script d'initialisation pour le démarrage du binaire xbmc.</li>
<li>La modification des makefiles pour certains utilitaires à compiler sur la machine hôte.</li>
<li>La modification du defconfig de buildroot.</li>
</ul><br />
Menu de configuration de buildroot :<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj98ZA-CjSnRE_S0LBZkydMfHTvCyNA5UIdQwI4QszZj5F_HiOzTrHR7z52Ig2ea61s14JG6RrDbqa3SZPjiSt0Okg628yDpFxlH-hOHyg_wHL_Wtr0zr11qbd5gEDyM_YUorfiSNNlFAk/s1600/buildroot_xbmc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj98ZA-CjSnRE_S0LBZkydMfHTvCyNA5UIdQwI4QszZj5F_HiOzTrHR7z52Ig2ea61s14JG6RrDbqa3SZPjiSt0Okg628yDpFxlH-hOHyg_wHL_Wtr0zr11qbd5gEDyM_YUorfiSNNlFAk/s640/buildroot_xbmc.png" height="444" width="580" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuNC_53fFAENuEgV8ZMbKUq8wiyB58huzLmVOALhMpUqOn3RCCKQk-yQx8ZkUg-g8Y7OHI-iQ1jT84gAwCLJErY0dpgDgsKrGiArH4oeNIokse3S4crI-zsqXh1zFXzjmQGRhobYQrXGI/s1600/buildroot_xbmc_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuNC_53fFAENuEgV8ZMbKUq8wiyB58huzLmVOALhMpUqOn3RCCKQk-yQx8ZkUg-g8Y7OHI-iQ1jT84gAwCLJErY0dpgDgsKrGiArH4oeNIokse3S4crI-zsqXh1zFXzjmQGRhobYQrXGI/s640/buildroot_xbmc_2.png" height="490" width="580" /></a></div><br />
<br />
<strike>PS : Il se peut qu'il y ai un petit problème de compilation sur un des modules. je fournirai (plus tard) un patch pour résoudre ce souci.</strike><br />
<br />
Une des libraires de XBMC (libcec) à besoin d'être patchée (<a href="https://docs.google.com/open?id=0B6WDjVnTAZgFcHJkYVBWQW0yV1E">libcec-001_fix_bool_t_modification.patch</a>) pour une bonne compilation. Ce patch est à copier dans le dossier BUILDROOT_PATH/package/xbmc/libcec.<br />
<br />
<pre class="brush: shell"># ls -al package/xbmc/libcec
total 44
drwxr-xr-x 2 sinseman44 sinseman44 4096 2013-01-06 12:05 .
drwxr-xr-x 28 sinseman44 sinseman44 4096 2012-12-02 14:35 ..
-rw-r--r-- 1 sinseman44 sinseman44 200 2012-12-01 15:57 Config.in
-rw-r--r-- 1 sinseman44 sinseman44 1825 2013-01-06 12:03 libcec-001-fix_bool_t_modification.patch
-rw-r--r-- 1 sinseman44 sinseman44 680 2012-12-06 08:42 libcec.mk
</pre><br />
Ce patch contient les informations suivantes (modification de bool en bool_t, donc true en VC_TRUE et false en VC_FALSE) :<br />
<br />
<pre class="brush: diff">diff -ruN libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp output/build/libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp
--- libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp 2012-11-09 16:39:39.000000000 +0100
+++ output/build/libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterCommunication.cpp 2013-01-06 11:51:56.934356002 +0100
@@ -264,7 +264,7 @@
if (bStartListening)
{
// enable passive mode
- vc_cec_set_passive(true);
+ vc_cec_set_passive(VC_TRUE);
// register the callback
vc_cec_register_callback(((CECSERVICE_CALLBACK_T)rpi_cec_callback), (void*)this);
@@ -320,7 +320,7 @@
UnregisterLogicalAddress();
// disable passive mode
- vc_cec_set_passive(false);
+ vc_cec_set_passive(VC_FALSE);
if (!g_bHostInited)
{
diff -ruN libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp output/build/libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp
--- libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp 2012-11-09 16:39:39.000000000 +0100
+++ output/build/libcec-600d5e54c86d494933fac1fe4a9b2826b8008280/src/lib/adapter/RPi/RPiCECAdapterMessageQueue.cpp 2013-01-06 11:50:55.090356002 +0100
@@ -182,7 +182,7 @@
LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
#endif
- int iReturn = vc_cec_send_message((uint32_t)command.destination, (uint8_t*)&payload, iLength, bIsReply);
+ int iReturn = vc_cec_send_message((uint32_t)command.destination, (uint8_t*)&payload, iLength, (bool_t)bIsReply);
#endif
if (iReturn != VCHIQ_SUCCESS)
</pre><br />
<br />
L'autre patch (<a href="https://docs.google.com/open?id=0B6WDjVnTAZgFMWRUakpfeS1pU2s">xbmc-001_texturepacker_raspberrypi.patch</a>) est pour xbmc et plus précisément le fichier Configure.in et est à copier dans le dossier BUILDROOT_PATH/package/xbmc/xbmc :<br />
<br />
<pre class="brush: shell"># ls -al package/xbmc/xbmc
total 68
drwxr-xr-x 2 sinseman44 sinseman44 4096 2013-01-06 17:39 ./
drwxr-xr-x 28 sinseman44 sinseman44 4096 2012-12-02 14:35 ../
-rw-r--r-- 1 sinseman44 sinseman44 775 2012-12-01 15:57 advancedsettings.xml
-rw-r--r-- 1 sinseman44 sinseman44 2303 2012-12-05 14:19 Config.in
-rwxr-xr-x 1 sinseman44 sinseman44 662 2012-12-01 15:57 S99xbmc*
-rw-r--r-- 1 sinseman44 sinseman44 787 2013-01-06 17:35 xbmc-001_texturepacker_raspberrypi.patch
-rw-r--r-- 1 sinseman44 sinseman44 3657 2012-12-05 14:21 xbmc.mk
</pre><br />
Que contient ce patch ?<br />
Il permet de configurer le makefile correctement pour la compilation de TexturePacker (USE_TEXTUREPACKER_NATIVE_ROOT est une option renseignée dans le makefile (xbmc.mk) de xbmc présent dans le sous dossier package de buildroot).<br />
<br />
<pre class="brush: diff">diff -ruN output/build/xbmc-130bd4ee55688a8ae49a04256308831363d2c58f/configure.in xbmc-130bd4ee55688a8ae49a04256308831363d2c58f/configure.in
--- output/build/xbmc-130bd4ee55688a8ae49a04256308831363d2c58f/configure.in 2012-10-24 22:40:47.000000000 +0200
+++ xbmc-130bd4ee55688a8ae49a04256308831363d2c58f/configure.in 2013-01-06 15:15:14.234355994 +0100
@@ -670,7 +670,7 @@
use_cpu=arm1176jzf-s
use_hardcoded_tables="yes"
use_alsa="no"
- USE_TEXTUREPACKER_NATIVE_ROOT="$TEXTUREPACKER_NATIVE_ROOT"
+# USE_TEXTUREPACKER_NATIVE_ROOT="$TEXTUREPACKER_NATIVE_ROOT"
ARCH="arm"
AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_ARMEL -DTARGET_RASPBERRY_PI")
AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer])
</pre><br />
<br />
<h4 style="text-align: left;">Userland</h4><br />
Userland est un un jeu des librairies tierces (présent dans le patch de XBMC) nécessaires à l'utilisation de la raspberry pi (VideoCore, OMXplayer, etc ...) et notamment pour XBMC. Anciennement, ces librairies étaient téléchargées, pré-compilées, et installées sur le système de fichiers. Maintenant, elles sont cross-compilées depuis buildroot.<br />
<br />
Le fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_USERLAND
bool "Raspberry Pi Userland drivers"
help
These are the binary VideoCore drivers from Broadcom.
https://github.com/raspberrypi/userland.git
</pre><br />
Le makefile useland.mk :<br />
<br />
<pre class="brush: shell">############################################################
#
# Userland
#
############################################################
USERLAND_VERSION = 83e1597d57766a4dddcf11960289a6bd49d3d1ce
USERLAND_SITE_METHOD = git
USERLAND_SITE = https://github.com/raspberrypi/userland.git
USERLAND_INSTALL_STAGING = YES
USERLAND_INSTALL_TARGET = YES
$(eval $(cmake-package))
</pre><br />
Le script d'initialisation S90vcfield :<br />
<br />
<pre class="brush: shell">#! /bin/sh
### BEGIN INIT INFO
# Provides: vcfiled
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Required-Start: udev
# Required-Stop: udev
# Short-Description: VideoCore file server daemon
### END INIT INFO
# Author: Luke Diamand <luked broadcom.com="broadcom.com">
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="VideoCore file server daemon"
NAME=vcfiled
VCROOT=/opt/vc
DAEMON=$VCROOT/sbin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME/$NAME
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
#. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
#. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
#[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
echo "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) echo "0" ;; #[ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) echo "1" ;; #[ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
#[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
echo "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) echo "0" ;; #[ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) echo "1" ;; #[ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
#log_daemon_msg "Restarting $DESC" "$NAME"
echo "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) echo "0" ;; #log_end_msg 0 ;;
1) echo "1" ;; #log_end_msg 1 ;; # Old process is still running
*) echo "1" ;; #log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
echo "1" #log_end_msg 1
;;
esac
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
</luked>
</pre><br />
<h3 style="text-align: left;">Vice 2.3 C64 pour Buildroot</h3><br />
voici le <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFMFRnZFZ6aHpZWHM">patch</a> à appliquer à buildroot pour insérer l'émulateur aux autres outils.<br />
<br />
<pre class="brush: shell"># cd BUILDROOT_PATH
# patch -p1 < buildroot_raspberrypi_vice_c64.patch
</pre><br />
Que contient ce patch ?<br />
<ul style="text-align: left;"><li>Le nouveau package (Config.in et vice.mk)</li>
<li>La modification du defconfig de buildroot.</li>
</ul><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaN719pVpfPYPYoqe5vGXc2fLAXeMDyt2gQVXdwLRES0UELe1SgDKYUO4LQL7S5ogU5n9431eZH9E20ptqAOOtnGYbls2VkTwH70iX5r-3e7TL-Zh25cCqEszmj6O6xYzxZsyZQcrPi60/s1600/buildroot_vice.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaN719pVpfPYPYoqe5vGXc2fLAXeMDyt2gQVXdwLRES0UELe1SgDKYUO4LQL7S5ogU5n9431eZH9E20ptqAOOtnGYbls2VkTwH70iX5r-3e7TL-Zh25cCqEszmj6O6xYzxZsyZQcrPi60/s640/buildroot_vice.png" height="550" width="580" /></a></div><br />
<br />
<h4 style="text-align: left;">Utilitaire framebuffer : fbset</h4><br />
je rajoute également un <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFMXJCdXlWSm5icnc">script d'initialisation</a> (S89fbmodes) nécessaire pour l'utilisation de l'émulateur (à inserer dans le dossier <b>/etc/init.d</b>), pour la création du fichier fb.modes dans le dossier <b>/etc</b>, qui, nativement, n'est pas présent sur le système de base.<br />
<br />
Pour ceci, il est nécessaire de cocher dans le menuconfig de buildroot l'utilitaire fbset<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQXRPcH5FT2hPv41huyjR_eVJZeSI67w23L2K76ldV5OhDfJYQ7B6n23QWcwpyUp3vQW1CKGYMFRTEgAdQ2pdU1688ks5_-1Nc5-HAESLyz_QrRThMxL1scnKiCtvJTZ7iV7sOYSjm-hw/s1600/buildroot_fbset.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQXRPcH5FT2hPv41huyjR_eVJZeSI67w23L2K76ldV5OhDfJYQ7B6n23QWcwpyUp3vQW1CKGYMFRTEgAdQ2pdU1688ks5_-1Nc5-HAESLyz_QrRThMxL1scnKiCtvJTZ7iV7sOYSjm-hw/s640/buildroot_fbset.png" height="328" width="580" /></a></div><br />
<a href="http://pwet.fr/man/linux/formats/fb_modes">fb.modes</a> est un fichier contenant tous les modes vidéos possibles.<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# fb.modes ..
#
FB_MODE_PATH="/etc/fb.modes"
case "$1" in
start)
echo "Initialisation of fb.modes for Vice C64 emulator ..."
if [ ! -f "${FB_MODE_PATH}" ]; then
/usr/sbin/fbset -s > "${FB_MODE_PATH}"
fi
;;
stop)
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre><br />
le plus simple est de mettre ce script d'initialisation dans le dossier <b>BUILDROOT_PATH/board/raspberrypi</b>, puis de modifier le script <b>post-build.sh</b> (dans ce même dossier) qui l’insérera dans le système de fichiers à la compilation.<br />
<br />
<pre class="brush: shell">$ cp -a S89fbmodes BUILDROOT_PATH/board/raspberrypi
$ cd BUILDROOT_PATH/board/raspberrypi
$ vim post-build.sh
</pre><br />
<pre class="brush: shell; highlight: [20,22];">TARGETDIR=$1
# Set root password to 'root'. Password generated with
# mkpasswd, from the 'whois' package in Debian/Ubuntu.
sed -i 's%^root::%root:8kfIfYHmcyQEE:%' $TARGETDIR/etc/shadow
# Point /bin/sh to /bin/bash
ln -T -s /bin/bash $TARGETDIR/bin/sh
# Package the /boot partition
tar -czf $TARGETDIR/../images/boot.tar.gz --exclude=Image -C $TARGETDIR/boot/ .
# add a corrected, and lightweight inittab
cp board/raspberrypi/inittab $TARGETDIR/etc/inittab
# add eth0 dhcp entry into /etc/network/interfaces
cp board/raspberrypi/interfaces $TARGETDIR/etc/network/
# make sure that ntpdate is run before sshd is started
cp board/raspberrypi/S41ntpdate $TARGETDIR/etc/init.d/
cp board/raspberrypi/S89fbmodes $TARGETDIR/etc/init.d/
chmod a+x $TARGETDIR/etc/init.d/S41ntpdate
chmod a+x $TARGETDIR/etc/init.d/S89fbmodes
</pre><br />
<h3 style="text-align: left;">Processus Controle</h3><br />
Les fonctions principales de ce processus (<a href="https://docs.google.com/open?id=0B6WDjVnTAZgFQTQxcDUwaHduZjA">controle-0.1.tar.gz</a>) sont le lancement d'un binaire (émulateur ou média center) en fonction de l'état de l'interrupteur et la surveillance ces processus (relance en cas de crash), écriture dans le syslog pour le debug.<br />
<ul style="text-align: left;"><li>Le thread principal se charge de lancer les applications (scripts de start/stop) grâce à la fonction <a href="http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/system.3.html">system</a>.</li>
<li>Le thread secondaire, quant à lui, surveille l'état des processus en testant la valeur de leur PID, grâce à l'appel de l'utilitaire <a href="http://pwet.fr/man/linux/administration_systeme/pidof">pidof</a>.</li>
</ul><br />
Voici l'organisation du système de fichiers pour le bon fonctionnement du processus <i>controle</i>.<br />
<ul style="text-align: left;"><li>le processus controle se trouve dans le dossier <b>/usr/bin/</b></li>
<li>les scripts de lancement et d'arrêt des 2 fonctionnalités se trouve dans le dossier <b>/usr/share/controle/scripts</b> (S99vice et S99xbmc)</li>
<li>le script d'initialisation de controle se trouve dans <b>/etc/init.d/</b></li>
</ul><div style="text-align: left;"><br />
<h4 style="text-align: left;">Compilation du processus</h4><br />
La première étape est d'enregister la chaîne de compilation croisée dans le PATH du terminal :<br />
<br />
<pre class="brush: shell">$ export PATH=$PATH:BUILDROOT_PATH/output/host/usr/bin
</pre><br />
ensuite, grâce au makefile (CFLAGS et LDFLAGS doivent être modifiés avec les chemins adéquats à votre buildroot) présent dans l'archive,<br />
<br />
<pre class="brush: shell">CC = arm-unknown-linux-gnueabi-gcc
CFLAGS = -IBUILDROOT_PATH/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/include -W -Wall
LDFLAGS = -LBUILDROOT_PATH/output/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/lib -pthread -lrt
EXEC = controle_process
OBJS = controle_process.o
all: $(EXEC)
$(EXEC):$(OBJS)
@$(CC) -o $(EXEC) $^ $(LDFLAGS)
%.o:%.c
@echo [CC] $^
@$(CC) -o $@ -c $^ $(CFLAGS)
clean:
@echo [CLEAN]
@rm *.o $(EXEC) -f
</pre><br />
on peut lancer la commande make pour compiler le programme :<br />
<br />
<pre class="brush: shell">$ make
[CC] controle_process.c
</pre><br />
On vérifie que le binaire est bien cross-compilé :<br />
<br />
<pre class="brush: shell">$ file controle_process
controle_process: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.0.39, not stripped
</pre><br />
</div><h4 style="text-align: left;">Gestion d'une IO</h4><div style="text-align: left;"><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Voici le schéma électrique de la gestion de l'entrée de cette GPIO :</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw21xPLrAWBBx0UdQasaoLRHtaeeo5oAM4mxTrWkVb1iQu_FF3NfKlr8_oV9JcZyLioDiZpLH1eZ-5WCCDdke_jKNWc2Gr4jzDENBsXLR_zZ1em-Q8JhaBNyjV4_p9jsHrAYMFB6prS1c/s1600/gpio17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw21xPLrAWBBx0UdQasaoLRHtaeeo5oAM4mxTrWkVb1iQu_FF3NfKlr8_oV9JcZyLioDiZpLH1eZ-5WCCDdke_jKNWc2Gr4jzDENBsXLR_zZ1em-Q8JhaBNyjV4_p9jsHrAYMFB6prS1c/s320/gpio17.png" height="320" width="252" /></a></div><br />
Le montage final :<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3-Az9bO0eQGJKPcWR0lRllMOdI-ccjOXUKHkLSUmns1AQA3OYDwgd1LAoz7aj3IQSSeZkczHjrfNdjAwL5EEFtxvq1v0I3OxclOYCSl7GiwYQnw5h5th7l5X70nh569xshLvkWHdGOUE/s1600/20121223_105211.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3-Az9bO0eQGJKPcWR0lRllMOdI-ccjOXUKHkLSUmns1AQA3OYDwgd1LAoz7aj3IQSSeZkczHjrfNdjAwL5EEFtxvq1v0I3OxclOYCSl7GiwYQnw5h5th7l5X70nh569xshLvkWHdGOUE/s320/20121223_105211.jpg" height="240" width="320" /></a></div><br />
<h4>Script d'initialisation de controle</h4><div><br />
Le script d'initialisation configure une IO en entrée (GPIO 17) qui sera ensuite surveillée par le processus controle, puis lance le processus en mode daemon.</div><br />
<pre class="brush: shell">#!/bin/sh
#
# Controle ..
#
GPIO_PATH="/sys/class/gpio"
GPIO_NUM="17"
GPIO_NAME="gpio${GPIO_NUM}"
export HOME=/root
case "$1" in
start)
echo "configuration of gpio ..."
if [ ! -d "${GPIO_PATH}"/"${GPIO_NAME}" ]; then
echo "${GPIO_NUM}" > "${GPIO_PATH}"/export
fi
if [ -d "${GPIO_PATH}"/"${GPIO_NAME}" ]; then
echo "in" > "${GPIO_PATH}"/"${GPIO_NAME}"/direction
fi
echo "Starting controle ..."
start-stop-daemon --background -m -S -q -p /var/run/controle_process.pid --exec /usr/bin/controle_process
;;
stop)
echo "Stopping controle ..."
start-stop-daemon -K -q -p /var/run/controle_process.pid --exec /usr/bin/controle_process
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre><br />
</div><h4 style="text-align: left;">Scripts de lancement/d'arrêt de Vice c64 et xbmc</h4><br />
S99vice :<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# Vice C64 emulator
#
case "$1" in
start)
echo "Start Vice C64 emulator ..."
/usr/bin/x64 &
;;
stop)
echo "Stop Vice C64 emulator ..."
/usr/bin/pkill x64
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre><br />
S99xbmc :<br />
<br />
<pre class="brush: shell">#!/bin/sh
#
# XBMC mediacenter
#
case "$1" in
start)
echo "Start XBMC mediacenter ..."
/usr/lib/xbmc/xbmc.bin -standalone -fs &
;;
stop)
echo "Stop XBMC mediacenter ..."
/usr/bin/pkill xbmc.bin
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre><br />
<h4 style="text-align: left;">Carte Contrôleur clavier</h4><br />
Le clavier du commodore 64 n'utilise qu'une broche de 20 pins pour être interfacé (1 pin pour la masse, 2 pins non connectées, 1 pin pour restorer le clavier et 16 pins pour les 64 touches). Le but de cette carte d'interface est de connecter le clavier en USB sur la raspberry pi, via une <a href="http://www.rennes.supelec.fr/ren/fi/elec/docs/usb/hid.html">interface HID</a> (Human Interface Device).<br />
Le micro-contrôleur utilisé est un pic18f4550 qui gère l'USB et l'alimentation électrique de la carte est réalisé via le bus USB connecté à la raspberry pi (bus-powered). J'ai utilisé le compilateur <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en542861">HI-TECH</a> picc18 sous linux et la stack USB opensource fourni par <a href="http://www.microchip.com/">Microchip</a>.<br />
<br />
L'installation, l'utilisation du compilateur pic de chez HI-TECH, le flashage d'un micro pic16f/pic18f, fera l'objet d'un autre billet sur les micro-contrôleurs.<br />
<br />
Voici le schéma de principe :<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PbINucj6tuONvUjfo16sUcL5BThRuXGj90U-RzCcMFv1-VB1BI55C_DO5RDxVkzpXInxz3xOQmkrsuFHAKwQzcQfH19ashNPAODjrOTu9QPe6qpE1V7XDKu0gWA4z2aDco3rEU67gts/s1600/schema_cablage_clavier_c64.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PbINucj6tuONvUjfo16sUcL5BThRuXGj90U-RzCcMFv1-VB1BI55C_DO5RDxVkzpXInxz3xOQmkrsuFHAKwQzcQfH19ashNPAODjrOTu9QPe6qpE1V7XDKu0gWA4z2aDco3rEU67gts/s640/schema_cablage_clavier_c64.png" height="403" width="580" /></a></div><br />
Les colonnes (PIN 5 à PIN 12) vont être reliées en entrée et positionnées à l'état haut (+5v) via une résistance de pull-up, du micro-contrôleur et les lignes (PIN 13 à PIN 20) vont être reliées en sortie.<br />
La théorie est de placer respectivement chaque ligne à l'état bas (GND) et de vérifier quelle colonne est aussi à l'état bas pour connaitre la touche qui a été appuyée.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRgfSi2UT9DiRsfk7zEk9QEUygcfz4yow8xHRTxOZeK51gCc3TygC-sgu3ByLMhB9fIQpxHCoyo8FY2GkfJgra31ODnB8LHG7ehmVwCjpFw6P9v81XQTbghVnidnCaN1uw2akZ9ap_KRI/s1600/principe_bouton.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRgfSi2UT9DiRsfk7zEk9QEUygcfz4yow8xHRTxOZeK51gCc3TygC-sgu3ByLMhB9fIQpxHCoyo8FY2GkfJgra31ODnB8LHG7ehmVwCjpFw6P9v81XQTbghVnidnCaN1uw2akZ9ap_KRI/s200/principe_bouton.png" height="200" width="188" /></a></div><br />
Voici le schéma électrique de la carte contrôleur :<br />
<br />
<iframe height="480" src="https://docs.google.com/file/d/0B6WDjVnTAZgFamZLNFRyajVHVWM/preview" width="580"></iframe><br />
<br />
Voici la datasheet du micro-contrôleur pic18F4550 :<br />
<br />
<iframe height="480" src="https://docs.google.com/file/d/0B6WDjVnTAZgFcFloWEtWX1VWUWs/preview" width="580"></iframe><br />
<br />
Je me suis largement inspiré du site web <a href="http://www.waitingforfriday.com/index.php/C64_VICE_Front-End">waitingforfriday.com</a> pour réaliser cette carte.<br />
<br />
<h3 style="text-align: left;">Conclusion</h3><div><div style="text-align: left;"><br />
</div><h4 style="text-align: left;">Point 1 :</h4></div><div>Le clavier du commodore 64 n'a que deux touches pour la gestion des flèches de directions (BAS et DROITE, nativement et L-SHIFT + BAS = HAUT et L-SHIFT + DROITE = GAUCHE), j'ai du remapper d'autres touches pour pouvoir naviguer dans les différents menu de XBMC puisque je n'ai pas réussi à utiliser la combinaison L-SHIFT + DROITE/BAS.</div><div><br />
</div><div>sur le système de fichier de la raspberry pi :</div><br />
<pre class="brush: shell"># cd /usr/share/xbmc/system/keymaps
</pre><br />
Supprimer toutes les configurations (fichiers XML) qui ne vous intéresse pas, pour ne garder que keyboard.xml, mouse.xml et remote.xml. Une <a href="http://wiki.xbmc.org/index.php?title=HOW-TO:Modify_keyboard.xml">page wiki de XMBC</a> explique comment modifier ces fichiers de configuration.<br />
<br />
<h4 style="text-align: left;">Point 2 :</h4>J'en ai profiter pour rajouter le client de téléchargement sur newsgroup : SABnzbd (voir précédent billet) et suite à une charge réseau importante, je me suis rendu compte que la raspberry pi plantait. Pour remédier à ce problème.<br />
<br />
dans buildroot, on va rajouter un fichier sysctl.conf. Le paramètre <b>vm.min_free_kbytes</b> permet de forcer le manager de mémoire virtuelle à garder un minimum de mémoire libre (Ko). par défault, il était à 1Ko, je le passe à 8Ko.<br />
<br />
<pre class="brush: shell"># cd BUILDROOT_PATH/board/raspberrypi/
# touch sysctl.conf
# echo "vm.min_free_kbytes=8192" > sysctl.conf
</pre><br />
Ce fichier va être copié à la compilation sur le système de fichiers<br />
<br />
<pre class="brush: shell; highlight: [19,20];"># vim post-build.sh
TARGETDIR=$1
# Set root password to 'root'. Password generated with
# mkpasswd, from the 'whois' package in Debian/Ubuntu.
sed -i 's%^root::%root:8kfIfYHmcyQEE:%' $TARGETDIR/etc/shadow
# Point /bin/sh to /bin/bash
ln -T -s /bin/bash $TARGETDIR/bin/sh
# Package the /boot partition
tar -czf $TARGETDIR/../images/boot.tar.gz --exclude=Image -C $TARGETDIR/boot/ .
# add a corrected, and lightweight inittab
cp board/raspberrypi/inittab $TARGETDIR/etc/inittab
# add eth0 dhcp entry into /etc/network/interfaces
cp board/raspberrypi/interfaces $TARGETDIR/etc/network/
# copy raspberrypi special conf
cp board/raspberrypi/sysctl.conf $TARGETDIR/etc/sysctl.conf
# make sure that ntpdate is run before sshd is started
cp board/raspberrypi/S41ntpdate $TARGETDIR/etc/init.d/
cp board/raspberrypi/S89fbmodes $TARGETDIR/etc/init.d/
chmod a+x $TARGETDIR/etc/init.d/S41ntpdate
chmod a+x $TARGETDIR/etc/init.d/S89fbmodes
</pre><br />
On va ensuite modifier le script d'initialisation de controle pour qu'au démarrage, la carte prenne en compte ce nouveau paramètre. (A noter que sur ce script l'export du paramètre TZ permet de mettre à jour l'heure française).<br />
<br />
<pre class="brush: shell; highlight: [16,17];"># vim S95controle
#!/bin/sh
#
# Controle ..
#
GPIO_PATH="/sys/class/gpio"
GPIO_NUM="17"
GPIO_NAME="gpio${GPIO_NUM}"
export HOME=/root
export TZ=MET-1METDST
case "$1" in
start)
echo "configuration des parametres de la carte"
/sbin/sysctl -p /etc/sysctl.conf
echo "configuration of gpio ..."
if [ ! -d "${GPIO_PATH}"/"${GPIO_NAME}" ]; then
echo "${GPIO_NUM}" > "${GPIO_PATH}"/export
fi
if [ -d "${GPIO_PATH}"/"${GPIO_NAME}" ]; then
echo "in" > "${GPIO_PATH}"/"${GPIO_NAME}"/direction
fi
echo "Starting controle ..."
echo "HOME = ${HOME}"
start-stop-daemon --background -m -S -q -p /var/run/controle_process.pid --exec /usr/bin/controle_process
#/bin/sh -c "/usr/bin/controle_process &"
;;
stop)
echo "Stopping controle ..."
start-stop-daemon -K -q -p /var/run/controle_process.pid --exec /usr/bin/controle_process
#/bin/sh -c "killall controle_process"
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
</pre><br />
Une modification du fichier cmdline.txt présent sur la partition de boot pour y rajouter de nouveaux paramètres. Voici la ligne complète du fichier cmdline.txt<br />
<br />
<pre class="brush: shell">sdhci-bcm2708.enable_llm=1 sdhci-bcm2708.sync_after_dma=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
</pre><br />
<h4 style="text-align: left;">Point 3 :</h4>Je n'ai pas réussi à lancer l'émulateur C64 en mode plein écran, malgré mon fichier fb.modes bien configuré avec les paramètres correspondants à ma TV. Je continue à investiguer sur la librairie SDL utilisée par l'émulateur.<br />
<br />
<br />
Voici quelques photos du montage de ce projet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwD6cIitF2Y5QoWLMUC0kdOVc16JCLd_A6cpMJ8cCng78J_U70zFI4Zo0pf3p3xDSiSd6njGPN5YZ6DMyCC_wiYHNVb-VYpo1BnvH2khY4sfrOeEbAvM4WAETGuCGkuKupZT7nTmGAp2o/s1600/20121217_215537.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwD6cIitF2Y5QoWLMUC0kdOVc16JCLd_A6cpMJ8cCng78J_U70zFI4Zo0pf3p3xDSiSd6njGPN5YZ6DMyCC_wiYHNVb-VYpo1BnvH2khY4sfrOeEbAvM4WAETGuCGkuKupZT7nTmGAp2o/s320/20121217_215537.jpg" height="240" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZzPJWrueh0zGEHC-XvbDNhQm8bwOW7uAArPu6kfTMhb0T2fYkoet8v-jA_eoLMNhHMLE6IhAJAJYzQaZ4jEfAzS4GHWpexh6fE2WzQryUrcHyGOsB-q-8YtVaTAcxAyLK7qWiMt2pke4/s1600/20121220_205901.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZzPJWrueh0zGEHC-XvbDNhQm8bwOW7uAArPu6kfTMhb0T2fYkoet8v-jA_eoLMNhHMLE6IhAJAJYzQaZ4jEfAzS4GHWpexh6fE2WzQryUrcHyGOsB-q-8YtVaTAcxAyLK7qWiMt2pke4/s320/20121220_205901.jpg" height="320" width="240" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPNPP7_mjK9fxg07Bw86oSSweyxRO-Cwk7GFq_p5651nHzLDYpq_DErPam7qlihC0os3hfb0t-O1zDLZ1wB3bPLZ71xs_NFzV3ilS4siH7MRhb9crsWJOOyoqOB2tNJUF9uTKMZgMrmBk/s1600/20121220_215759.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPNPP7_mjK9fxg07Bw86oSSweyxRO-Cwk7GFq_p5651nHzLDYpq_DErPam7qlihC0os3hfb0t-O1zDLZ1wB3bPLZ71xs_NFzV3ilS4siH7MRhb9crsWJOOyoqOB2tNJUF9uTKMZgMrmBk/s320/20121220_215759.jpg" height="240" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMhB4z23REm8_fYQOGUTo5w5r3jb82BKHc3m_GPRgaFmxtHKnLb1s2LUTD74XSprAA93qC5cgRIAaK6Jvipya8w7ED5093Jx1QVTCwQMDaiNpz4mQOKs7X4yga5exC1Y4nQcmNl8cvWRU/s1600/20121224_183036.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMhB4z23REm8_fYQOGUTo5w5r3jb82BKHc3m_GPRgaFmxtHKnLb1s2LUTD74XSprAA93qC5cgRIAaK6Jvipya8w7ED5093Jx1QVTCwQMDaiNpz4mQOKs7X4yga5exC1Y4nQcmNl8cvWRU/s320/20121224_183036.jpg" height="240" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEighLLJ_GTyNGDZtxJZVuWZK3I7Gt4MlC0BJ6LTpePerFang7l7Jppj8NyOOzgdnXDf1TJNCS8Yp_GuPcgio-lVY1Xu4NtevBPaaeXNKPDKpgM2JiZheClAcHbys-acHBpKM32SyqQjAb0/s1600/20121224_183049.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEighLLJ_GTyNGDZtxJZVuWZK3I7Gt4MlC0BJ6LTpePerFang7l7Jppj8NyOOzgdnXDf1TJNCS8Yp_GuPcgio-lVY1Xu4NtevBPaaeXNKPDKpgM2JiZheClAcHbys-acHBpKM32SyqQjAb0/s320/20121224_183049.jpg" height="240" width="320" /></a></div><br />
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.444209000000000743.420674500000004 1.1214855000000008 43.7886295 1.7669325000000007tag:blogger.com,1999:blog-3014712466464327072.post-6096630734128531082012-12-02T13:16:00.000+01:002012-12-02T13:16:03.733+01:00Buildroot 2012.08 update<div dir="ltr" style="text-align: left;" trbidi="on">Il y a eu quelques évolutions sur la dernière version de buildroot et ses différents composants, du coup, certaines petites modifications sont nécessaires par rapport au tutoriel que j'ai pu vous présenter précédemment.<br />
J'ai essayé de faire les choses proprement et je vous ai pondu un patch à appliquer à la version de buildroot pour pouvoir générer notre système sans trop de souci.<br />
<br />
<br />
<a name='more'></a><br />
<br />
Voici les différentes étapes :<br />
<br />
Récupération de la dernière version :<br />
<br />
<pre class="brush: shell"># git clone git://github.com/nezticle/RaspberryPi-BuildRoot.git Buildroot
Cloning into Buildroot...
remote: Counting objects: 87162, done.
remote: Compressing objects: 100% (27518/27518), done.
remote: Total 87162 (delta 59287), reused 87111 (delta 59245)
Receiving objects: 100% (87162/87162), 28.13 MiB | 1.00 MiB/s, done.
Resolving deltas: 100% (59287/59287), done.
</pre><br />
Récupération du patch à appliquer : <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFaG9ONmZ4SGNZUjA">Buildroot_patch</a><br />
<br />
Une fois le patch récupéré, on le copie à la base de Buildroot<br />
<br />
Application du patch :<br />
<pre class="brush: shell"># patch -p1 < raspberrypi_buildroot_base.patch
patching file board/raspberrypi/crosstool.config.eglibc
patching file board/raspberrypi/inittab
patching file configs/raspberrypi_sinseman44_defconfig
patching file linux/linux.mk
patching file package/Config.in
patching file package/raspberrypi/VideoCore/S99vcfield
patching file package/raspberrypi/VideoCore/VideoCore.mk
patching file package/raspberrypi/bootloader/bootloader.mk
patching file package/raspberrypi/mkimage/mkimage.mk
patching file package/raspberrypi/raspberrypi.mk
</pre><br />
Maintenant, on peut continuer avec le tutoriel : <a href="http://colocsbar.blogspot.fr/2012/06/on-va-faire-du-custom-partie-1.html">On va faire du custom (partie 1)</a> <br />
Il n'est plus nécessaire de télécharger les fichiers de configs et l'inittab à mettre dans le dossier board/raspberrypi.<br />
<br />
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-17481222900021424222012-09-26T12:43:00.000+02:002012-10-19T18:10:26.168+02:00Newsgroups & SABnzbd<div dir="ltr" style="text-align: left;" trbidi="on"><br />
<h2 style="text-align: left;">Avant-propos :</h2><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg65hsHDF_qvJr05YuftvWwba7vVWg9FU-IA6R993Oa1Yrdubmzyp-XuBvaN1iFPUyvDwvDuP22C4PKAHCw3b92DVUI9-JIiDmfxMDGoCpuocfesVScO7c15FRLsaHHPNPXaBRww7Q7Sk/s1600/sabnzbd_logo-300x82.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="84" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg65hsHDF_qvJr05YuftvWwba7vVWg9FU-IA6R993Oa1Yrdubmzyp-XuBvaN1iFPUyvDwvDuP22C4PKAHCw3b92DVUI9-JIiDmfxMDGoCpuocfesVScO7c15FRLsaHHPNPXaBRww7Q7Sk/s320/sabnzbd_logo-300x82.png" width="320" /></a></div>Il est possible de télécharger des fichiers (légaux ou pas, ce n'est pas le débat ;-)) grâce à différents outils. Nous allons nous intéresser aux newsgroups<b> </b>et à un des lecteurs de news existants sur la toile, SABnzbd<b>.</b><br />
<b>SABnzbd</b> est un lecteur de groupes de discussion multi-platforme open source. Il a l'avantage de pouvoir être utilisé en tant que service, configurable via une page internet et simplifie le téléchargement de fichiers.<br />
Il est écrit en python, ce qui va nous permettre de comprendre comment installer python et ses modules (internes et externes) sur la raspberry pi et les utiliser.<br />
<br />
<h2 style="text-align: left;">Pré-requis :</h2>SABnzbd requiert différents paquets avant l'installation de celui-ci :<br />
<ul style="text-align: left;"><li><b>Python</b> (version 2.5.x, 2.6.x, 2.7.x (recommandé)) - Pas encore la version 3.0</li>
<li>La librairie python <b>Cheetah</b> (moteur de <i>templates</i>)</li>
<li>La librairie python <b>yEnc</b> (encodage/décodage)</li>
<li>La librairie python <b>sqlite</b></li>
<li>La librairie python <b>openssl</b></li>
<li>La librairie python<b> CherryPi </b></li>
<li>binaire <b>par2 et unrar</b></li>
</ul><br />
Les différents modules python demandés ne sont, nativement, pas présents sur buildroot, donc il va falloir<span style="font-family: Arial, Arial, Helvetica;"> les</span> installer. <br />
<h2 style="text-align: left;"><a name='more'></a><br />
</h2><h2 style="text-align: left;">Installation de Python et de ses modules :</h2><br />
<h3 style="text-align: left;">Python 2.7</h3><br />
Python est un paquet, nativement, présent dans le menuconfig de buildroot, dans le sous menu "langages interpréteur ...". En le sélectionnant, le menu des modules python apparaît.<br />
<br />
<pre class="brush: shell"># make menuconfig
Package Selection for the target --->
Interpreter languages and scripting --->
[*] python
</pre><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrYtLPANNpl6zAghs3_kNoM_OY47V3wsIdFURZLR_pJzOUpEyz2sTsKvhLtYfA9K7ubcv4yHwumuoDmQ2TmBGKMeoImKXHi2a2i9LeQ6kGuAeeipiT3B4aEJhuuldkLT7D6yWse1gjKmw/s1600/buildroot_python.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="347" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrYtLPANNpl6zAghs3_kNoM_OY47V3wsIdFURZLR_pJzOUpEyz2sTsKvhLtYfA9K7ubcv4yHwumuoDmQ2TmBGKMeoImKXHi2a2i9LeQ6kGuAeeipiT3B4aEJhuuldkLT7D6yWse1gjKmw/s640/buildroot_python.png" width="580" /></a></div><br />
<br />
<h3 style="text-align: left;">Librairie python <a href="http://www.cheetahtemplate.org/">Cheetah</a></h3><br />
L'archive <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFT2RkMy1MMFRId0U">python-cheetah.tar.gz</a> réunit le dossier (python-cheetah) et les fichiers (<i>Config.in</i> et <i>python-cheetah.mk</i>) permettant l'installation de ce module sur le système de fichiers.<br />
<br />
fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_PYTHON_CHEETAH
bool "python-cheetah"
depends on BR2_PACKAGE_PYTHON
help
Cheetah is an open source template engine and code generation tool.
http://pypi.python.org/pypi/Cheetah/2.4.4
</pre><br />
<br />
fichier python-cheetah.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# python-cheetah
#
#############################################################
PYTHON_CHEETAH_VERSION = 2.4.4
PYTHON_CHEETAH_SOURCE = Cheetah-$(PYTHON_CHEETAH_VERSION).tar.gz
PYTHON_CHEETAH_SITE = http://pypi.python.org/packages/source/C/Cheetah
PYTHON_CHEETAH_DEPENDENCIES = python
define PYTHON_CHEETAH_BUILD_CMDS
(cd $(@D); $(HOST_DIR)/usr/bin/python setup.py build_py)
(cd $(@D); \
PYTHONXCPREFIX="$(STAGING_DIR)/usr/" \
CC="$(TARGET_CC) -pthread" \
LDSHARED="$(TARGET_CC) -pthread -shared -Wl,-O1,--sort-common,--as-needed" \
CFLAGS="-fno-strict-aliasing -I$(STAGING_DIR)/usr/include/python2.7 $(CFLAGS)" \
LDFLAGS="-L$(STAGING_DIR)/lib -L$(STAGING_DIR)/usr/lib $(LDFLAGS)" \
"$(HOST_DIR)"/usr/bin/python setup.py build_ext \
--include-dirs="$(STAGING_DIR)"/usr/include \
--library-dirs="$(STAGING_DIR)"/usr/lib)
endef
define PYTHON_CHEETAH_INSTALL_TARGET_CMDS
#~ (cd $(@D); $(HOST_DIR)/usr/bin/python setup.py install --prefix=$(TARGET_DIR)/usr)
(cd $(@D); PYTHONPATH=$(TARGET_DIR)/usr/lib/python$(PYTHON_VERSION_MAJOR)/site-packages \
$(HOST_DIR)/usr/bin/python setup.py install --prefix=$(TARGET_DIR)/usr)
endef
$(eval $(call GENTARGETS))
</pre><br />
Contrairement à des modules python dits "pures", Cheetah a une partie (_<i>namemapper.c</i>) de sa librairie codée en C. C'est pourquoi, nous avons besoin du cross-compilateur pour compiler la librairie, avec la définition des différents chemins.<br />
<br />
Pour l'installer sous buildroot, nous allons, dans un premier temps, décompresser l'archive dans le dossier package, puis compléter la configuration générale des paquets (Config.in).<br />
<br />
<pre class="brush: c; highlight: [12];"># tar xzf python-cheetah.tar.gz -C BUILDROOT_PATH/package
# vim BUILDROOT_PATH/package/Config.in
menu "external python modules"
source "package/python-dpkt/Config.in"
source "package/python-id3/Config.in"
source "package/python-mad/Config.in"
source "package/python-netifaces/Config.in"
source "package/python-pygame/Config.in"
source "package/python-serial/Config.in"
source "package/python-setuptools/Config.in"
source "package/python-cheetah/Config.in"
endmenu
# make
</pre><br />
<h3 style="text-align: left;">Librairie python OpenSSL, <a href="http://www.golug.it/yenc.html">yEnc</a> et <a href="http://pypi.python.org/pypi/pysqlite">Sqlite3</a></h3><br />
Pour les archives <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFcjhTU3FJVXNob0k">python-openssl.tar.gz</a>, <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFeFZUZ2pueGVkdGc">python-sqlite.tar.gz</a> et <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFazhIb3Y1ZkZGVjQ">python-yenc.tar.gz</a>, "même combat" que pour la librairie Cheetah.<br />
<br />
<pre class="brush: shell; highlight: [15, 16, 17];"># tar xzf python-yenc.tar.gz -C BUILDROOT_PATH/package
# tar xzf python-sqlite.tar.gz -C BUILDROOT_PATH/package
# tar xzf python-openssl.tar.gz -C BUILDROOT_PATH/package
# vim BUILDROOT_PATH/package/Config.in
menu "external python modules"
source "package/python-dpkt/Config.in"
source "package/python-id3/Config.in"
source "package/python-mad/Config.in"
source "package/python-netifaces/Config.in"
source "package/python-pygame/Config.in"
source "package/python-serial/Config.in"
source "package/python-setuptools/Config.in"
source "package/python-cheetah/Config.in"
source "package/python-openssl/Config.in"
source "package/python-sqlite/Config.in"
source "package/python-yenc/Config.in"
endmenu
# make
</pre><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisDcmzz_JClGubrEm5cWnxDTlI8PCokbCcYc4wXVRPBkB0_9cezBv5Khw_LVsFXJLMOROxFnKCfoH1xSgwBh7wWxccCgN2APktAO6DgyhN_STXDMFsnYncmnWnd5hjVtgg9Szs0KOQ8Pk/s1600/buildroot_python_external.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="352" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisDcmzz_JClGubrEm5cWnxDTlI8PCokbCcYc4wXVRPBkB0_9cezBv5Khw_LVsFXJLMOROxFnKCfoH1xSgwBh7wWxccCgN2APktAO6DgyhN_STXDMFsnYncmnWnd5hjVtgg9Szs0KOQ8Pk/s640/buildroot_python_external.png" width="580" /></a></div><br />
<br />
<h3 style="text-align: left;">Librairie <a href="http://www.cherrypy.org/">CherryPy</a></h3><br />
La librairie python CherryPy est, quant à elle, entièrement en python, donc une variante simplifiée du makefile pour l'installation de celle-ci sur le système de fichiers.<br />
<br />
L'archive <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFV1RmSG9UZWFPa1U">python-cherrypy.tar.gz</a> devra être décompressée dans le sous dossier "<i>package</i>" et il faudra modifier le fichier de configuration général.<br />
<br />
Fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_PYTHON_CHERRYPY
bool "python-cherrypy"
depends on BR2_PACKAGE_PYTHON
help
CherryPy allows developers to build web applications in much the same way
they would build any other object-oriented Python program.
This results in smaller source code developed in less time.
http://www.cherrypy.org/
</pre><br />
Fichier python-cherrypy.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# python-cherrypy
#
#############################################################
PYTHON_CHERRYPY_VERSION = 3.2.2
PYTHON_CHERRYPY_SOURCE = CherryPy-$(PYTHON_CHERRYPY_VERSION).tar.gz
PYTHON_CHERRYPY_SITE = http://download.cherrypy.org/cherrypy/$(PYTHON_CHERRYPY_VERSION)
PYTHON_CHERRYPY_DEPENDENCIES = python
define PYTHON_CHERRYPY_BUILD_CMDS
(cd $(@D); $(HOST_DIR)/usr/bin/python setup.py build)
endef
define PYTHON_CHERRYPY_INSTALL_TARGET_CMDS
(cd $(@D); PYTHONPATH=$(TARGET_DIR)/usr/lib/python$(PYTHON_VERSION_MAJOR)/site-packages \
$(HOST_DIR)/usr/bin/python setup.py install --prefix=$(TARGET_DIR)/usr)
endef
$(eval $(call GENTARGETS))
</pre><br />
Le fichier de configuration général :<br />
<br />
<pre class="brush: shell; highlight: [15];"># vim BUILDROOT_PATH/package/Config.in
menu "external python modules"
source "package/python-dpkt/Config.in"
source "package/python-id3/Config.in"
source "package/python-mad/Config.in"
source "package/python-netifaces/Config.in"
source "package/python-pygame/Config.in"
source "package/python-serial/Config.in"
source "package/python-setuptools/Config.in"
source "package/python-cheetah/Config.in"
source "package/python-openssl/Config.in"
source "package/python-sqlite/Config.in"
source "package/python-yenc/Config.in"
source "package/python-cherrypy/Config.in"
endmenu
</pre><br />
<h3 style="text-align: left;">Binaire Par2</h3><br />
<span style="font-family: Arial, Arial, Helvetica;">Les fichiers "*.par" sont des fichiers de flux de données redondants au cas ou un des fichiers venaient à être perdu ou corrompu. type de fichiers très utilisé dans les newsgroups.</span><br />
<span style="font-family: Arial, Arial, Helvetica;"><br />
</span> <span style="font-family: Arial, Arial, Helvetica;">L'archive <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFRjQ0ckVjYml1QlU">par2cmdline.tar.gz</a> est, comme les autres paquets, destinée à être ajoutée dans le sous dossier "package" de buildroot, puisque nativement, il n'est pas présent.</span><br />
<span style="font-family: Arial, Arial, Helvetica;">Cette archive contient les deux fichiers principaux (<i>Config.in</i> et <i>par2cmdline.mk</i>) et un patch pour une compilation sans accros.</span><br />
<br />
fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_PAR2CMDLINE
bool "par2cmdline"
help
Providing a tool to apply the data-recovery capability concepts of RAID-like systems
to the posting & recovery of multi-part archives on Usenet.
</pre><br />
fichier par2cmdline.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# par2cmdline
#
#############################################################
PAR2CMDLINE_VERSION = 0.4
PAR2CMDLINE_SOURCE = par2cmdline-$(PAR2CMDLINE_VERSION).tar.gz
PAR2CMDLINE_SITE = http://sourceforge.net/projects/parchive/files/par2cmdline/$(PAR2CMDLINE_VERSION)
PAR2CMDLINE_INSTALL_STAGING = YES
# avoid enable static option in makefile
SHARED_STATIC_LIBS_OPTS = --enable-shared
$(eval $(call AUTOTARGETS))
</pre><br />
Patch :<br />
<br />
<pre class="brush: diff">diff -ruN par2cmdline-0.4/reedsolomon.cpp par2cmdline-0.4_modif/reedsolomon.cpp
--- par2cmdline-0.4/reedsolomon.cpp 2003-05-26 20:01:31.000000000 +0200
+++ par2cmdline-0.4_modif/reedsolomon.cpp 2012-09-13 11:37:13.000000000 +0200
@@ -51,7 +51,7 @@
}
}
-bool ReedSolomon<galois8>::SetInput(const vector<bool> &present)
+template <> bool ReedSolomon<galois8>::SetInput(const vector<bool> &present)
{
inputcount = (u32)present.size();
@@ -80,7 +80,7 @@
return true;
}
-bool ReedSolomon<galois8>::SetInput(u32 count)
+template <> bool ReedSolomon<galois8>::SetInput(u32 count)
{
inputcount = count;
@@ -101,7 +101,7 @@
return true;
}
-bool ReedSolomon<galois8>::Process(size_t size, u32 inputindex, const void *inputbuffer, u32 outputindex, void *outputbuffer)
+template <> bool ReedSolomon<galois8>::Process(size_t size, u32 inputindex, const void *inputbuffer, u32 outputindex, void *outputbuffer)
{
// Look up the appropriate element in the RS matrix
Galois8 factor = leftmatrix[outputindex * (datapresent + datamissing) + inputindex];
@@ -189,7 +189,7 @@
// Set which of the source files are present and which are missing
// and compute the base values to use for the vandermonde matrix.
-bool ReedSolomon<galois16>::SetInput(const vector<bool> &present)
+template <> bool ReedSolomon<galois16>::SetInput(const vector<bool> &present)
{
inputcount = (u32)present.size();
@@ -233,7 +233,7 @@
// Record that the specified number of source files are all present
// and compute the base values to use for the vandermonde matrix.
-bool ReedSolomon<galois16>::SetInput(u32 count)
+template <> bool ReedSolomon<galois16>::SetInput(u32 count)
{
inputcount = count;
@@ -267,7 +267,7 @@
return true;
}
-bool ReedSolomon<galois16>::Process(size_t size, u32 inputindex, const void *inputbuffer, u32 outputindex, void *outputbuffer)
+template <> bool ReedSolomon<galois16>::Process(size_t size, u32 inputindex, const void *inputbuffer, u32 outputindex, void *outputbuffer)
{
// Look up the appropriate element in the RS matrix
</pre><br />
<h3 style="text-align: left;">Binaire unrar</h3><br />
Les sources du binaire <b>unrar </b>sont un peu particulières, puisqu'il ne s'agit que d'un simple makefile pour la compilation, l'installation ou la suppression de celui-ci (un peu ce que l'on pourrait trouver dans un projet perso)<br />
<br />
Makefile de Unrar :<br />
<br />
<br />
<pre class="brush: shell">COMPILE=$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES)
LINK=$(CXX)
WHAT=UNRAR
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
LIB_OBJ=filestr.o scantree.o dll.o
OBJECTS=rar.o strlist.o strfn.o pathfn.o savepos.o smallfn.o global.o file.o filefn.o filcreat.o \
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
resource.o match.o timefn.o rdwrfn.o consio.o options.o ulinks.o errhnd.o rarvm.o secpassword.o \
rijndael.o getbits.o sha1.o extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
.cpp.o:
$(COMPILE) -D$(WHAT) -c $<
all: unrar
install: install-unrar
uninstall: uninstall-unrar
clean:
@rm -f *.o *.bak *~
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
@rm -f unrar
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
$(STRIP) unrar
sfx: WHAT=SFX_MODULE
sfx: clean $(OBJECTS)
@rm -f default.sfx
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
$(STRIP) default.sfx
lib: WHAT=RARDLL
lib: CXXFLAGS+=$(LIBFLAGS)
lib: clean $(OBJECTS) $(LIB_OBJ)
@rm -f libunrar.so
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
install-unrar:
install -D unrar $(DESTDIR)/bin/unrar
uninstall-unrar:
rm -f $(DESTDIR)/bin/unrar
install-lib:
install libunrar.so $(DESTDIR)/lib
uninstall-lib:
rm -f $(DESTDIR)/lib/libunrar.so
</pre><br />
Le makefile (unrar.mk), fourni avec l'archive <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFX2hWemtXT0hnNDA">unrar.tar.gz</a> a placer dans le sous-dossier "<i>package</i>", va être basé sur l'utilisation de ce makefile.<br />
<br />
Fichier unrar.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# unrar
#
#############################################################
UNRAR_VERSION = 4.2.4
UNRAR_SOURCE = unrarsrc-$(UNRAR_VERSION).tar.gz
UNRAR_SITE = http://www.rarlab.com/rar
UNRAR_INSTALL_STAGING = YES
define UNRAR_BUILD_CMDS
$(MAKE) CXX="$(TARGET_CXX)" CXXFLAGS="-O2" DEFINES="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE" STRIP="$(TARGET_STRIP)" --makefile=makefile.unix -C $(@D) all
endef
define UNRAR_INSTALL_STAGING_CMDS
$(MAKE) DESTDIR="$(STAGING_DIR)/usr" --makefile=makefile.unix -C $(@D) install
endef
define UNRAR_INSTALL_TARGET_CMDS
$(MAKE) DESTDIR="$(TARGET_DIR)/usr" --makefile=makefile.unix -C $(@D) install
endef
$(eval $(call GENTARGETS))
</pre><br />
avec l'appel de macros pour la compilation et l'installation du binaire sur notre système de fichiers.<br />
<br />
<h2 style="text-align: left;">Installation de SABnzbd</h2>Avec les sources de SABnzbd, il n'y a pas d'installation, à proprement parlé. On peut lancer le binaire depuis n'importe quel dossier de notre système.<br />
<br />
Pour cela, on va reconstruire notre système de fichiers avec les nouveaux binaires, et librairies et démarrer la raspberry pi.<br />
<br />
Transfert de l'archive de SABnzbd sur la raspberry pi :<br />
<br />
<pre class="brush: shell"># scp SABnzbd-0.7.3-src.tar.gz root@RASPI_IP_ADDR:
# mkdir -p /usr/bin/sabnzbd
# tar xzf SABnzbd-0.7.3-src.tar.gz -C /usr/bin/sabnzbd
</pre><br />
Si la décompression de l'archive sur la raspberry pi ne fonctionne pas, c'est qu'il manque quelques paquets de gestions d'archives dans busybox.<br />
<br />
Pour l'utilisation, lancer la commande :<br />
<br />
<pre class="brush: shell"># python /usr/bin/sabnzbd/SABnzbd-0.7.3/SABnzbd.py -s -d RASPI_IP_ADDR:8888
</pre><br />
L'option "<i>-d</i>" permet d'utiliser le binaire en tant que service (daemon)<br />
<br />
Ouvrez votre navigateur favori et entrez l'adresse <b>RASPI_IP_ADDR:8888, </b>vous devriez avoir l'assistant de configuration de SABnzbd<b>.</b><br />
<b> </b> <b> </b> <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGVOLSmdvbinqLgbFwQHA3Uv9lKv_HT3dWeOWDYgmrQzxr2QRdRrmSeVxCs0HTZbbDAZPz0rq2yJgRbbvytCDXA95SMy-INdaYzWCyNYSnnfpnqWIiacbgsQTgSBtcjymof5HTU0v_fYA/s1600/sabnzbd_wizard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGVOLSmdvbinqLgbFwQHA3Uv9lKv_HT3dWeOWDYgmrQzxr2QRdRrmSeVxCs0HTZbbDAZPz0rq2yJgRbbvytCDXA95SMy-INdaYzWCyNYSnnfpnqWIiacbgsQTgSBtcjymof5HTU0v_fYA/s640/sabnzbd_wizard.png" width="580" /></a></div><br />
Une fois, la configuration terminée, la fenêtre classique de téléchargement s'ouvre. Vous trouverez sur la toile, un tas de tutoriels pour une configuration plus poussée.<br />
<br />
Vous pouvez écrire un script pour le lancement automatique du binaire au démarrage de la carte (cf billet mediatomb). <br />
<br />
Amusez-vous bien avec ... <br />
<br />
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-75537049654515776072012-09-12T17:08:00.001+02:002012-10-19T15:10:35.389+02:00Serveur UPnP et Raspberry Pi<div dir="ltr" style="text-align: left;" trbidi="on"><br />
<h2 style="text-align: left;">Préambule</h2><br />
Pour ce billet de rentrée, je vais expliquer comment intégrer un serveur UPnP (Universal Plug & Play) à notre Raspberry Pi. Le serveur UPnP servira à partager tous types de documents multimédia sur un réseau (audio, image et vidéo).<br />
Il est biensur possible d'utiliser le fameux <a href="http://www.xbmc.fr/">media center XBMC</a> (porté pour la raspberry pi) pour partager et visualiser les documents, mais dans mon cas, je souhaite quelque chose de leger, de facile à administrer et j'ai toujours pas envie de brancher ma RasPi sur ma télévision. ;-).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAwhsyFmSR-urb8-T_dErWqcOm7dH1HOjwIo67POswn6jl5wm3X79bcMYZPW94rjHYg1I1zmJ_EGYRy8rT2SSSUZ3MoECN0QtJ6q6sMeWeV-uZur0bcRkVAB1gmqk9qUdMZaAMjnuWae0/s1600/mediatomb.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAwhsyFmSR-urb8-T_dErWqcOm7dH1HOjwIo67POswn6jl5wm3X79bcMYZPW94rjHYg1I1zmJ_EGYRy8rT2SSSUZ3MoECN0QtJ6q6sMeWeV-uZur0bcRkVAB1gmqk9qUdMZaAMjnuWae0/s1600/mediatomb.png" /></a></div>Je me suis tourné vers le serveur GPL UPnP <a href="http://mediatomb.cc/">MediaTomb</a>. Il me permet entre autre d'administrer mon serveur via une page web, de faire du transcodage, de faire des miniatures et pleins de bonnes choses encore.<br />
<br />
<br />
Nativement, le packge MediaTomb n'est pas présent dans l'environnement Buildroot, on va commencer par ajouter ce paquet à buildroot pour le configurer, le compiler et l'installer sur notre cible.<br />
<br />
<br />
<a name='more'></a><br />
<br />
<h2 style="text-align: left;">Installation de nos paquets</h2><div style="text-align: left;"><br />
</div><h3 style="text-align: left;">libMP4v2</h3><div style="text-align: left;"><br />
</div><div style="text-align: left;">Avant d'attaquer l'ajout de mediatomb, on va commencer par une libraire <a href="http://code.google.com/p/mp4v2">MP4v2</a>, non présente dans l'environnement Buildroot. Cette librairie sert à la manipulation de fichiers au format MP4 (dérivé du format Apple QuickTime).</div><div style="text-align: left;"><br />
</div><div style="text-align: left;">Je vous fourni le tarball <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFYVFXSlJ1b1BOeGM">libmp4v2.tar.gz</a> util à la création de notre paquet dans l'environnement buildroot. Dans cette archive, deux fichiers sont présents :</div><ul style="text-align: left;"><li>Config.in : Fichier de description de notre application</li>
<li>libmp4v2.mk : Makefile de téléchargement, configuration, compilation et installation de notre executable.</li>
</ul> On va décompresser cette archive dans le sous dossier package de buildroot<br />
<div style="text-align: left;"><br />
<pre class="brush: shell"># tar xvzf libmp4v2.tar.gz -C BUILDROOT_PATH/package/
</pre><br />
Le fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_LIBMP4V2
bool "libmp4v2"
help
The MP4v2 library provides an API to create and
modify mp4 files as defined by ISO-IEC:14496-1:2001 MPEG-4 Systems.
This file format is derived from Apple's QuickTime file format that
has been used as a multimedia file format in a variety of platforms and applications.
http://code.google.com/p/mp4v2/
</pre><br />
Le fichier libmp4v2.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# libmp4v2
#
#############################################################
LIBMP4V2_VERSION = 2.0.0
LIBMP4V2_SOURCE = mp4v2-$(LIBMP4V2_VERSION).tar.bz2
LIBMP4V2_SITE = http://mp4v2.googlecode.com/files
LIBMP4V2_INSTALL_STAGING = YES
LIBMP4V2_INSTALL_TARGET = YES
define LIBMP4V2_UNINSTALL_TARGET_CMDS
rm -f $(TARGET_DIR)/usr/bin/mp4*
rm -f $(TARGET_DIR)/usr/lib/libmp4v2*
endef
define LIBMP4V2_UNINSTALL_STAGING_CMDS
rm -f $(STAGING_DIR)/usr/bin/mp4*
rm -rf $(STAGING_DIR)/usr/include/mp4v2
rm -f $(STAGING_DIR)/usr/lib/libmp4v2*
endef
$(eval $(call AUTOTARGETS))
</pre><br />
Je vous conseille d'aller voir <a href="http://buildroot.uclibc.org/downloads/manual/manual.html#_adding_new_packages_to_buildroot">la documentation de buildroot</a> concernant l'ajout de nouveaux paquets.<br />
<br />
Il va falloir ensuite indiquer à buildroot qu'un nouveau paquet à été créé, pour cela, on va modifier le fichier de configuration général (Config.in) du sous dossier package et lui rajouter la ligne surligné dans la section multimedia. <br />
<br />
<pre class="brush: shell; highlight: [11];">menu "Multimedia"
source "package/libdvdread/Config.in"
source "package/libdvdnav/Config.in"
source "package/libmms/Config.in"
source "package/libmpeg2/Config.in"
source "package/libogg/Config.in"
source "package/libplayer/Config.in"
source "package/libtheora/Config.in"
source "package/live555/Config.in"
source "package/mediastreamer/Config.in"
source "package/libmp4v2/Config.in"
endmenu
</pre><br />
L'installation de cette librairie est finie (nous n'avons pas besoin lancer une compilation pour le moment, ce sera fait lors de la compilation de mediatomb puisque c'est une dépendance de celui-ci), nous allons passer à l'installation de notre serveur dans buildroot. Le principe d'installation va être exactement identique que pour cette librairie.<br />
<br />
<h3 style="text-align: left;">mediatomb</h3><div style="text-align: left;">Je vous fourni le tarball <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFdUlrLV9ZU3kteXc">mediatomb.tar.gz</a> util à la création de notre paquet dans l'environnement buildroot. Dans cette archive, trois fichiers sont présents :</div><ul style="text-align: left;"><li>Config.in : Fichier de description de notre application</li>
<li>mediatomb.mk : Makefile de téléchargement, configuration, compilation et installation de notre executable.</li>
<li>mediatomb.patch : Patch qui sera appliqué par buildroot lors de la compilation du serveur </li>
</ul> On va décompresser cette archive dans le sous dossier package de buildroot<br />
<br />
<pre class="brush: shell"># tar xvzf mediatomb.tar.gz -C BUILDROOT_PATH/package/
</pre><br />
Le fichier Config.in :<br />
<br />
<pre class="brush: shell">config BR2_PACKAGE_MEDIATOMB
bool "mediatomb"
select BR2_PACKAGE_SQLITE
select BR2_PACKAGE_EXPAT
help
MediaTomb is an open source (GPL) UPnP MediaServer with a nice web user interface,
it allows you to stream your digital media through your home network
and listen to/watch it on a variety of UPnP compatible devices.
MediaTomb implements the UPnP MediaServer V 1.0 specification that can be found on http://www.upnp.org/.
The current implementation focuses on parts that are required by the specification,
however we look into extending the functionality to cover the optional parts of the spec as well.
MediaTomb should work with any UPnP compliant MediaRenderer,
please tell us if you experience difficulties with particular models,
also take a look at the Supported Devices list for more information.
</pre><br />
Le fichier mediatomb.mk :<br />
<br />
<pre class="brush: shell">#############################################################
#
# mediatomb
#
#############################################################
MEDIATOMB_VERSION = 0.12.1
MEDIATOMB_SOURCE = mediatomb-$(MEDIATOMB_VERSION).tar.gz
MEDIATOMB_SITE = http://downloads.sourceforge.net/mediatomb
MEDIATOMB_INSTALL_STAGING = YES
# avoid enable static option in makefile
SHARED_STATIC_LIBS_OPTS = --enable-shared
# sqlite3 paths ugly !!!
MEDIATOMB_CONF_OPT = \
--disable-rpl-malloc \
--enable-pthread-lib \
--disable-mysql \
--disable-libmagic \
--disable-lastfmlib \
--disable-id3lib \
--with-search=$(STAGING_DIR)/usr/include \
--with-sqlite3-h=$(BUILD_DIR)/sqlite-$(SQLITE_VERSION) \
--with-sqlite3-libs=$(TARGET_DIR)/usr/lib \
--with-expat-h=$(BASE_DIR)/host/usr/include \
--with-expat-libs=$(STAGING_DIR)/usr/lib
ifeq ($(BR2_PACKAGE_CURL),y)
MEDIATOMB_CONF_OPT += \
--enable-curl \
--with-curl-cfg=$(BASE_DIR)/host/usr/arm-unknown-linux-gnueabi/sysroot/usr/bin/curl-config
MEDIATOMB_DEPENDENCIES += libcurl
endif
ifeq ($(BR2_PACKAGE_LIBEXIF),y)
MEDIATOMB_CONF_OPT += \
--with-libexif-h=$(STAGING_DIR)/usr/include \
--with-libexif-libs=$(STAGING_DIR)/usr/lib
MEDIATOMB_DEPENDENCIES += libexif
else
MEDIATOMB_CONF_OPT += \
--disable-libexif
endif
ifeq ($(BR2_PACKAGE_TAGLIB),y)
MEDIATOMB_CONF_OPT += \
--with-taglib-cfg=$(STAGING_DIR)/usr/bin/taglib-config
MEDIATOMB_DEPENDENCIES += taglib
else
MEDIATOMB_CONF_OPT += \
--disable-taglib
endif
ifeq ($(BR2_PACKAGE_ZLIB),y)
MEDIATOMB_CONF_OPT += \
--with-zlib-h=$(BASE_DIR)/host/usr/include
--with-zlib-libs=$(STAGING_DIR)/usr/lib
MEDIATOMB_DEPENDENCIES += zlib
else
MEDIATOMB_CONF_OPT += \
--disable-zlib
endif
ifeq ($(BR2_PACKAGE_LIBMP4V2),y)
MEDIATOMB_CONF_OPT += \
--with-libmp4v2-h=$(STAGING_DIR)/usr/include
--with-libmp4v2-libs=$(STAGING_DIR)/usr/lib
MEDIATOMB_DEPENDENCIES += libmp4v2
else
MEDIATOMB_CONF_OPT += \
--disable-libmp4v2
endif
$(eval $(call AUTOTARGETS))
</pre><br />
Sans oublier d'ajouter notre paquet à buildroot avec la modification du fichier de configuration générale des paquets (Config.in) dans le sous dossier package :<br />
<br />
<pre class="brush: shell; highlight: [12];">menu "Multimedia"
source "package/libdvdread/Config.in"
source "package/libdvdnav/Config.in"
source "package/libmms/Config.in"
source "package/libmpeg2/Config.in"
source "package/libogg/Config.in"
source "package/libplayer/Config.in"
source "package/libtheora/Config.in"
source "package/live555/Config.in"
source "package/mediastreamer/Config.in"
source "package/libmp4v2/Config.in"
source "package/mediatomb/Config.in"
endmenu
</pre><br />
Ce paquet fait appel à de nombreuses dépendances, 2 sont obligatoires et automatique cochées (sqlite3 et libexpat) lors de l'activation de celui-ci, les autres dépendances sont fortement recommandées, donc il va falloir cocher préalablement, les paquets :<br />
<ul style="text-align: left;"><li>curl</li>
<li>zlib</li>
<li>taglib</li>
<li>libmp4v2</li>
<li>libexif</li>
</ul><br />
Pour choisir les paquets, Entrer la commande à la racine de buildroot :<br />
<br />
<pre class="brush: shell"># make menuconfig
</pre><br />
Le paquet mediatomb fraichement créé dans buildoot se trouve dans le sous menu "multimedia" de "library'. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMykRQVZ0wOgi0MUmN1W4_2Velj3JL1iFl4eo-2T96v5rPdr-buXHLdsPzlATF4dkMdIeB160PYTO8hasMGiVgdFZzHmqRzDrgmbPalF2ioBWbmBa0ZMJkuOA6K4NoD4VdweAqb7Tdo0/s1600/buildroot_mediatomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMykRQVZ0wOgi0MUmN1W4_2Velj3JL1iFl4eo-2T96v5rPdr-buXHLdsPzlATF4dkMdIeB160PYTO8hasMGiVgdFZzHmqRzDrgmbPalF2ioBWbmBa0ZMJkuOA6K4NoD4VdweAqb7Tdo0/s640/buildroot_mediatomb.png" width="580" /></a></div><br />
Il ne reste plus qu'à compiler et installer le tout :<br />
<pre class="brush: shell"># make
</pre><br />
A la fin de la configuration du paquet, un rapport est affiché :<br />
<br />
<pre class="brush: shell">CONFIGURATION SUMMARY ----
sqlite3 : yes
mysql : disabled
libjs : missing
libmagic :
inotify : no
libexif : yes
id3lib : disabled
taglib : yes
libmp4v2 : yes
ffmpeg : yes
ffmpegthumbnailer : missing
lastfmlib : disabled
external transcoding : yes
curl : yes
YouTube : yes
libextractor : disabled
db-autocreate : yes
</pre><br />
Une fois la compilation terminée, nous pouvons vérifier que le serveur est bien installé :<br />
<br />
<pre class="brush: shell"># ls -al BUILDROOT_PATH/output/target/usr/bin/mediatomb
-rwxr-xr-x 1 sinseman44 sinseman44 1153596 2012-09-11 19:14 mediatomb
</pre><br />
et les fichiers de configuration :<br />
<br />
<pre class="brush: shell"># ls -al BUILDROOT_PATH/output/target/usr/share/mediatomb
drwxrwxr-x 4 sinseman44 sinseman44 4096 2012-09-11 19:14 .
drwxrwxr-x 25 sinseman44 sinseman44 4096 2012-09-11 19:14 ..
drwxrwxr-x 2 sinseman44 sinseman44 4096 2012-09-11 19:14 js
-rw-r--r-- 1 sinseman44 sinseman44 1362 2012-09-11 19:14 mappings.xml
-rw-r--r-- 1 sinseman44 sinseman44 3820 2012-09-11 19:14 mysql.sql
-rw-r--r-- 1 sinseman44 sinseman44 2933 2012-09-11 19:14 sqlite3.sql
drwxrwxr-x 4 sinseman44 sinseman44 4096 2012-09-11 19:14 web
</pre><br />
Je vous conseille d'aller voir un ancien tutoriel, pour la mise à jour du système de fichiers sur la carte SD avec les nouvelles applications fraichement installées.<br />
<br />
<h2 style="text-align: left;">Utilisation de mediatomb</h2><div style="text-align: left;">Sur notre carte, on peut vérifier le bon fonctionnement de notre serveur à l'aide de la commande :</div><br />
<pre class="brush: shell"># /usr/bin/mediatomb --version
MediaTomb UPnP Server version 0.12.1 - http://mediatomb.cc/
===============================================================================
Copyright 2005-2010 Gena Batsyan, Sergey Bostandzhyan, Leonhard Wimmer.
MediaTomb is free software, covered by the GNU General Public License version 2
</pre><h3 style="text-align: left;">Lancement du serveur à la main</h3><br />
On peut démarrer le serveur "à la main" (voir l'aide pour les différentes options) :<br />
<br />
<pre class="brush: shell"># /usr/bin/mediatomb -d -e eth0 -p 8080
Running mediatomb to start UPnP server
1970-01-01 00:09:53 INFO: Loading configuration from: /root/.mediatomb/config.xml
1970-01-01 00:09:53 INFO: Checking configuration...
1970-01-01 00:09:53 INFO: Setting filesystem import charset to ANSI_X3.4-1968
1970-01-01 00:09:53 INFO: Setting metadata import charset to ANSI_X3.4-1968
1970-01-01 00:09:53 INFO: Setting playlist charset to ANSI_X3.4-1968
1970-01-01 00:09:53 WARNING: You enabled the YouTube feature, which allows you
to watch YouTube videos on your UPnP device!
Please check http://www.youtube.com/t/terms
By using this feature you may be violating YouTube
service terms and conditions!
1970-01-01 00:09:53 INFO: Configuration check succeeded.
</pre><br />
il va démarrer en mode démon, sur l'interface réseau eth0, avec l'interface web sur le port 8080.<br />
Pour avoir accès à l'interface web, ouvrer votre navigateur web favori et entrer l'adresse : <span style="color: red;">http://RASPI_IP_ADDR:8080 <span style="color: black;">(en remplaçant RASPI_IP_ADDR par celle qui va bien)</span></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUQAZ7wQwsnst4bVpV02vh3byPNIwJEDcqr-IWeBOj5Iaj03eCRQF451Kg3e5AekADgG66osNfDyfSVBZx6F3RywQGCzz599bxV_Llvt07CasyV4KA8964ZJ3gSZM60skesrbfht7ZMaU/s1600/mediatomb_web.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUQAZ7wQwsnst4bVpV02vh3byPNIwJEDcqr-IWeBOj5Iaj03eCRQF451Kg3e5AekADgG66osNfDyfSVBZx6F3RywQGCzz599bxV_Llvt07CasyV4KA8964ZJ3gSZM60skesrbfht7ZMaU/s640/mediatomb_web.png" width="580" /></a></div><br />
<br />
<h3 style="text-align: left;">Lancement du serveur au démarrage de la carte</h3><br />
Copier le script <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFWEUwZDhMRUNjcVE">S51upnpd</a> dans le sous-dossier <i>board/raspberrypi </i>de buildroot<i> </i>et modifier le script post-build.sh dans ce même sous-dossier, et rajouter la ligne surlignée :<br />
<br />
<pre class="brush: shell">TARGETDIR=$1
# Set root password to 'root'. Password generated with
# mkpasswd, from the 'whois' package in Debian/Ubuntu.
sed -i 's%^root::%root:8kfIfYHmcyQEE:%' $TARGETDIR/etc/shadow
# Generate boot config files
echo "dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" > $TARGETDIR/boot/cmdline.txt
echo "disable_overscan=1" > $TARGETDIR/boot/config.txt
echo "arm_freq=800" >> $TARGETDIR/boot/config.txt
# Point /bin/sh to /bin/bash
ln -T -s /bin/bash $TARGETDIR/bin/sh
# Package the /boot partition
tar -czf $TARGETDIR/../images/boot.tar.gz --exclude=Image -C $TARGETDIR/boot/ .
# add a corrected, and lightweight inittab
#cp board/raspberrypi/inittab $TARGETDIR/etc/inittab
# add eth0 dhcp entry into /etc/network/interfaces
cp board/raspberrypi/interfaces $TARGETDIR/etc/network/
# make sure that ntpdate is run before sshd is started
cp board/raspberrypi/S41ntpdate $TARGETDIR/etc/init.d/
<b>cp board/raspberrypi/S51upnpd $TARGETDIR/etc/init.d/</b>
chmod a+x $TARGETDIR/etc/init.d/S41ntpdate
</pre><br />
Ce script vous permettra de faire la même chose que la ligne de commande lancée précedement mais automatique au démarrage du système. Je vous conseille d'aller jeter un coup d'oeil à la documentation de mediatomb pour plus d'infos (utilisation avec une télévision connectée et/ou une console type PS3 ou XBOX 360, etc ...).<br />
<br />
Amusez-vous bien avec ...</div></div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-81800742422030913552012-07-17T15:53:00.002+02:002012-10-19T15:35:20.905+02:00Integrer un driver au noyau linux<div dir="ltr" style="text-align: left;" trbidi="on">Avant de proposer la deuxième partie de mon tutoriel sur la gestion d'une entrée GPIO à travers un driver Linux, je vais montrer comment intégrer le driver de led, précédemment créé, directement dans les sources du noyau pour pouvoir le compiler et l'installer en même temps que les autres modules.<br />
<br />
Je rappelle que le fichier source du module est disponible sous github.<br />
<div style="color: #6fa8dc;"><br />
</div><div style="color: #0b5394;"><b>git://github.com/sinseman44/rpiled.git</b></div><br />
Mon noyau Linux ayant été compilé avec l’environnement buildroot. les sources du kernel se trouve dans le dossier <i>buildroot/output/build/linux-HEAD</i>.<br />
A partir de ce dossier parent, je vais copier le fichier source du module (raspberrypi_test_led.c) dans la partie <i>drivers/gpio</i>.<br />
<br />
Dans ce dossier, 2 fichiers vont être modifiés pour l'intégration (Kconfig et Makefile).<br />
Le premier Kconfig, fichier d'interface permettant de sélectionner via le menuconfig, les modules à installer avec le noyau :<br />
<br />
<pre class="brush: shell; highlight: [14, 15, 16, 17, 18];">menuconfig GPIOLIB
bool "GPIO Support"
depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB
select GENERIC_GPIO
help
This enables GPIO support through the generic GPIO library.
You only need to enable this, if you also want to enable
one or more of the GPIO drivers below.
If unsure, say N.
if GPIOLIB
config RPI_GPIO_LED
tristate "Raspberry Pi led GPIO"
depends on GPIOLIB
help
driver to test a led connected to the raspberry pi
config DEBUG_GPIO
bool "Debug GPIO calls"
depends on DEBUG_KERNEL
help
Say Y here to add some extra checks and diagnostics to GPIO calls.
These checks help ensure that GPIOs have been properly initialized
before they are used, and that sleeping calls are not made from
non-sleeping contexts. They can make bitbanged serial protocols
slower. The diagnostics help catch the type of setup errors
that are most common when setting up new platforms or boards.
</pre><br />
Il y a deux possibilités pour la compilation soit statique, le noyau va construire le fichier objet et inclure le module directement l'image finale, soit dynamique, le driver va être compilé en module et c'est à l'utilisateur de charger/décharger par la suite le module sur le système embarqué.<br />
Certains drivers ont la variable <b>bool</b> à la place de <b>tristate</b>, dans ce cas, le driver est soit compilé en statique, soit pas. La variable <b>tristate</b>, laisse le choix à l'utilisateur de compiler le driver en statique (X), en module (M) ou pas du tout. <br />
<br />
La capture d'écran montre que notre driver va être compilé en module.<br />
<br />
<pre class="brush: shell"># make linux26-menuconfig</pre><br />
menu<i> device drivers -> GPIO support</i><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoXujYdze1HX0sE7Jx3QCzpPzmBPZbD4MVUrFpYEIURnDg39Iz3AMhpHC3TOUurV3F3yjXnu-Mf71MV8NAaYj2Pc0PEViwUaRYfw79W-7rOHxaMLLLIKGH91BK59hPqG-c2g4sID9fWhA/s1600/buildroot_screenshot_rpiled.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoXujYdze1HX0sE7Jx3QCzpPzmBPZbD4MVUrFpYEIURnDg39Iz3AMhpHC3TOUurV3F3yjXnu-Mf71MV8NAaYj2Pc0PEViwUaRYfw79W-7rOHxaMLLLIKGH91BK59hPqG-c2g4sID9fWhA/s640/buildroot_screenshot_rpiled.png" width="580" /></a></div><br />
Le deuxième fichier à modifier est le Makefile :<br />
<br />
<pre class="brush: shell; highlight: [6];"><pre class="brush: c; ">[ ... ]
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_RPI_GPIO_LED) += raspberrypi_test_led.o
</pre>Il ne reste plus qu'à utiliser les commandes de compilation :
<pre class="brush: shell"># make</pre>Le module, une fois compilé, va être installé sur le système de fichiers et visible dans le dossier <i>lib/modules/3.1.9/kernel/drivers/gpio</i>.
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com1Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-71388280815840304002012-07-16T11:31:00.001+02:002012-10-19T15:43:51.755+02:00On va jouer avec les GPIOs (partie 1)<div dir="ltr" style="text-align: left;" trbidi="on">La carte raspberry pi offre la possibilité d'interagir (facilement) avec quelques entrées/sorties (connecteur 2x13 pins présents sur un coté de la carte). Ce tutoriel va se concentrer sur l'utilisation d'une entrée (partie 1) et d'une sortie (partie 2) pour montrer les différentes possibilités que nous offrent cette carte.<br />
<div style="text-align: left;"><br />
</div><div style="text-align: left;"><h4 style="text-align: left;"> <u><i>Petit rappel (<a href="http://elinux.org/RPi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29">wiki raspberry pi</a>) :</i></u></h4></div><br />
Les GPIOs sont présentes sur le connecteur 2x13 pins, avec d'autres signaux, tels que les alimentations +3,3v et +5v et la masse.<br />
Certaines de ces GPIOs (0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 18, 21) sont multiplexées avec d'autres fonctionnalités (Ex : GPIO 14 est multiplexé avec la transmission UART, soit on l'utilise en tant que GPIO ou en tant que transmission UART, mais pas les deux en même temps). <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1UDhpEH2jwAjIMTjR1aL99iO2J-o-4zUx3eddA6WnhsZflaNt84_DnoUhe_0bAvDWiF9fqASwJvNj85tdu-WY4LSUIMrSLXNEjQJQld4cA2bKA9TvkpeSK9fVrpDnCWrS-OkLDCAkes8/s1600/254px-GPIOs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1UDhpEH2jwAjIMTjR1aL99iO2J-o-4zUx3eddA6WnhsZflaNt84_DnoUhe_0bAvDWiF9fqASwJvNj85tdu-WY4LSUIMrSLXNEjQJQld4cA2bKA9TvkpeSK9fVrpDnCWrS-OkLDCAkes8/s320/254px-GPIOs.png" width="138" /></a></div><br />
Pour ce billet, je vais me concentrer sur deux GPIOs (la 17 en sortie, reliée à une led et la 18 en entrée, reliée au bouton poussoir).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq-kZzB0zj-8em4RJC8bmr-lzLuCznRCjOq1XhaLp0YFeCb0aZttYnVz5TibnyQKyXn2sdDO_udBWTJDYeorFOEV9rIMENtnLx5GYJZPfAmmXYUSBoVXjTDDFXjtRYSPwMQEUfzQAIyLE/s1600/20120704_214421.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq-kZzB0zj-8em4RJC8bmr-lzLuCznRCjOq1XhaLp0YFeCb0aZttYnVz5TibnyQKyXn2sdDO_udBWTJDYeorFOEV9rIMENtnLx5GYJZPfAmmXYUSBoVXjTDDFXjtRYSPwMQEUfzQAIyLE/s320/20120704_214421.jpg" width="320" /></a></div><br />
Le schéma de câblage est du plus basique. Une LED standard orange, avec une tension à ses bornes de 2,1v et une résistance de 60 Ohms pour fournir les 20 mA nécessaires. Une résistance de tirage d'une centaine d'ohms pour la liaison avec le bouton poussoir.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCg-_mT_igJORODA6qPwAxMRxEyCgCIon7_PHWpZgxk04lSNEPz-CT8hY4Weg-Vi3LPD6Li3dW718FkqJ5iG1QSJZgVZev3bns2PJP8dj4v5C97AHZUTkAegPtfQEe8lOBi85ZVytlzwU/s1600/schematique_gpio_test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCg-_mT_igJORODA6qPwAxMRxEyCgCIon7_PHWpZgxk04lSNEPz-CT8hY4Weg-Vi3LPD6Li3dW718FkqJ5iG1QSJZgVZev3bns2PJP8dj4v5C97AHZUTkAegPtfQEe8lOBi85ZVytlzwU/s320/schematique_gpio_test.png" width="317" /></a> </div><div class="separator" style="clear: both; text-align: center;"> <u><i><br />
</i></u></div><h3 style="text-align: left;"> <u><i>Accès aux GPIOs depuis l'espace utilisateur :</i></u></h3><br />
On va commencer à jouer avec les GPIOs depuis l'espace utilisateur, puisque il est possible d'interagir avec chaque GPIO du système depuis l'interface <i>/sys/class/gpio</i>.<br />
<br />
<pre class="brush: shell">[raspberry_pi]# cd /sys/class/gpio/
[raspberry_pi]# ls -al
drwxr-xr-x 2 root root 0 Jan 1 1970 .
drwxr-xr-x 27 root root 0 Jan 1 1970 ..
--w------- 1 root root 4096 Jul 4 18:39 export
lrwxrwxrwx 1 root root 0 Jan 1 1970 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
--w------- 1 root root 4096 Jan 1 1970 unexport
[raspberry_pi]# echo 17 > export
[raspberry_pi]# ls -al
drwxr-xr-x 2 root root 0 Jan 1 1970 .
drwxr-xr-x 27 root root 0 Jan 1 1970 ..
--w------- 1 root root 4096 Jul 4 18:39 export
lrwxrwxrwx 1 root root 0 Jul 4 18:39 gpio17 -> ../../devices/virtual/gpio/gpio17
lrwxrwxrwx 1 root root 0 Jan 1 1970 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
--w------- 1 root root 4096 Jan 1 1970 unexport
</pre><br />
Au démarrage du système, les GPIOs sont configurées par le noyau et de ce fait, non visible depuis l'espace utilisateur. Pour les rendre visible, il suffit de les exporter en indiquant le numéro de la pin souhaitée.<br />
<br />
<pre class="brush: shell">[raspberry_pi]# ls gpio17
active_low direction power subsystem uevent value
[raspberry_pi]# cat gpio17/direction
in
</pre><br />
On va configurer la GPIO17 en sortie et allumer (ou éteindre) la led grâce au fichier <i>value</i>.<br />
<br />
<pre class="brush: shell">[raspberry_pi]# echo out > gpio17/direction
[raspberry_pi]# cat gpio17/direction
out
[raspberry_pi]# cat gpio17/value
0
[raspberry_pi]# echo 1 > gpio17/value (la LED s'allume)
[raspberry_pi]# cat gpio17/value
1
[raspberry_pi]# echo 0 > gpio17/value (la LED s'éteint)
[raspberry_pi]# cat gpio17/value
0
</pre><br />
On va configurer la GPIO18 en entrée et vérifier l'état du bouton grâce au fichier <i>value</i>.<br />
<br />
<pre class="brush: shell">[raspberry_pi]# echo in > gpio18/direction
[raspberry_pi]# cat gpio18/direction
in
[raspberry_pi]# cat gpio18/value
0
(on appuie sur le bouton)
[raspberry_pi]# cat gpio18/value
1
(on relâche le bouton)
[raspberry_pi]# cat gpio18/value
0
</pre><h3 style="text-align: left;"> <br />
</h3><h3 style="text-align: left;"> <u><i>Accès aux GPIOs depuis l'espace noyau :</i></u></h3><h4 style="text-align: left;"> </h4><h4 style="text-align: left;"> Préambule</h4>Je conseille, surtout un peu de lecture (pour les plus courageux), sur l'utilisation des GPIOs dans un driver Linux. Cette documentation nommée, <i>gpio.txt</i>, se trouve dans les sources du noyau,<i> LINUX_PATH/Documentation/gpio.txt</i>.<br />
<br />
<h4 style="text-align: left;"> Pilotage d'une LED </h4>Grâce aux drivers, nous avons la possibilité de contrôler un périphérique avec des interactions (ou pas) depuis l'espace utilisateur. Pour cet exemple, je vais contrôler une LED via le driver (Activation, désactivation et clignotement).<br />
Ce driver est présent sur github à cette adresse : <br />
<div style="color: blue;"><b><br />
</b></div><div style="color: #3d85c6;"><b>git://github.com/sinseman44/rpiled.git</b></div><br />
La récupération des sources et du module (déjà compilé) se fera via la commande :<br />
<br />
<pre class="brush: shell"># git clone git://github.com/sinseman44/rpiled.git
Cloning into rpiled...
remote: Counting objects: 10, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 10 (delta 1), reused 10 (delta 1)
Receiving objects: 100% (10/10), 8.58 KiB, done.
Resolving deltas: 100% (1/1), done.
# ls
Makefile raspberrypi_test_led.c raspberrypi_test_led.ko README
</pre><div style="text-align: left;"><br />
</div><div style="text-align: left;">Pour ceux qui veulent re-compiler leur module, passer au chapitre suivant, sinon passer directement au chapitre "utilisation du module.</div><h4 style="text-align: left;"> </h4><h4 style="text-align: left;"> Compilation du module</h4>(La chaîne de compilation croisée a été préalablement installée dans le <b>PATH</b>)<br />
<br />
Dans ce tutoriel, le module est compilé en dehors du noyau linux, un guide est fourni dans les docs du noyau linux, chapitre "<i>How to build external modules</i>" dans <i>LINUX_PATH/Documentations/kbuild/modules.txt</i>. Un makefile est fourni dans le package pour la compilation de celui-ci.<br />
<br />
Pour obtenir un module à partir de ce code source, il va falloir le compiler en utilisant les sources du noyau et le compilateur croisée :<br />
<div style="text-align: left;"><br />
<pre class="brush: shell"># cd rpiled
# make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi-
</pre><br />
On indique l'architecture de la cible et la chaîne de compilation croisée.<br />
A la sortie de compilation, plusieurs fichiers se sont créés ainsi que le module, <i style="color: red;">raspberrypi_test_led.ko</i> :<br />
<br />
<pre class="brush: shell"># ls -al
drwxr-xr-x 3 sinseman44 sinseman44 4096 2012-07-13 14:25 ./
drwxr-xr-x 5 sinseman44 sinseman44 4096 2012-07-11 10:24 ../
-rw-r--r-- 1 sinseman44 sinseman44 212 2012-07-05 09:04 Makefile
-rw-r--r-- 1 sinseman44 sinseman44 95 2012-07-13 14:25 modules.order
-rw-r--r-- 1 sinseman44 sinseman44 0 2012-07-13 14:25 Module.symvers
-rw-r--r-- 1 sinseman44 sinseman44 14927 2012-07-13 14:01 raspberrypi_test_led.c
-rw-r--r-- 1 sinseman44 sinseman44 11627 2012-07-13 14:25 raspberrypi_test_led.ko
-rw-r--r-- 1 sinseman44 sinseman44 519 2012-07-13 14:25 .raspberrypi_test_led.ko.cmd
-rw-r--r-- 1 sinseman44 sinseman44 1711 2012-07-13 14:25 raspberrypi_test_led.mod.c
-rw-r--r-- 1 sinseman44 sinseman44 3808 2012-07-13 14:25 raspberrypi_test_led.mod.o
-rw-r--r-- 1 sinseman44 sinseman44 18669 2012-07-13 14:25 .raspberrypi_test_led.mod.o.cmd
-rw-r--r-- 1 sinseman44 sinseman44 8544 2012-07-13 14:25 raspberrypi_test_led.o
-rw-r--r-- 1 sinseman44 sinseman44 22213 2012-07-13 14:25 .raspberrypi_test_led.o.cmd
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-07-13 14:25 .tmp_versions/
</pre><br />
</div><h4 style="text-align: left;"> Utilisation du module </h4><br />
Maintenant que le module est compilé, on le transfert sur la carte, via le réseau ethernet, avec la commande :<br />
<br />
<pre class="brush: shell"># scp raspberrypi_test_led.ko root@ADRESSE_IP_DE_LA_CARTE:
</pre><br />
Sur la carte, on charge le module :<br />
<br />
<pre class="brush: shell"># insmod raspberrypi_test_led.ko
</pre><br />
On peut vérifier que le module est bien chargé sur notre système grâce à la commande :<br />
<br />
<pre class="brush: shell"># lsmod
Module Size Used by Not tainted
raspberrypi_test_led 3200 0
</pre><br />
différentes informations sur le module peuvent être affichées :<br />
<br />
<pre class="brush: shell"># modinfo raspberrypi_test_led.ko
filename: raspberrypi_test_led.ko
description: LED driver on raspberry PI
author: Sinseman44 <sinseman44@gmail.com>
license: GPL
vermagic: 3.1.9 preempt mod_unload modversions ARMv6
depends:
</sinseman44@gmail.com></pre><br />
<h4 style="text-align: left;"> Accès au périphérique via le sysfs</h4><br />
Lors du chargement du module, une nouvelle classe est créée dans le sysfs, avec l'accès au périphérique en fonction de l'action souhaitée.<br />
<ul style="text-align: left;"><li>led_value (R/W) : lecture et écriture de l'état de la LED</li>
<li>led_blink (R/W) : Activation et désactivation du clignotement de la LED</li>
<li>led_timer (R/W) : lecture et écriture de la vitesse (0 à 999) de clignotement (millisecondes)</li>
</ul><br />
<pre class="brush: shell"># ls -al /sys/class/rpiled/rpiled/
total 0
drwxr-xr-x 3 root root 0 Jul 14 10:26 .
drwxr-xr-x 3 root root 0 Jul 14 10:26 ..
-r--r--r-- 1 root root 4096 Jul 14 10:26 dev
-rw-r--r-- 1 root root 4096 Jul 14 10:28 led_blink
-rw-r--r-- 1 root root 4096 Jul 14 10:28 led_timer
-rw-r--r-- 1 root root 4096 Jul 14 10:28 led_value
drwxr-xr-x 2 root root 0 Jul 14 10:28 power
lrwxrwxrwx 1 root root 0 Jul 14 10:28 subsystem -> ../../../../class/rpiled
-rw-r--r-- 1 root root 4096 Jul 14 10:28 uevent
</pre><br />
Lecture de l'état de la LED :<br />
<br />
<pre class="brush: shell"># cat /sys/class/rpiled/rpiled/led_value
state of LED : 1
</pre><br />
Activation ou désactivation (écriture) de la LED :<br />
<br />
<pre class="brush: shell"># echo 0 > /sys/class/rpiled/rpiled/led_value
# cat /sys/class/rpiled/rpiled/led_value
state of LED : 0
</pre><br />
Lecture de l'état de clignotement de la LED :<br />
<br />
<pre class="brush: shell"># cat /sys/class/rpiled/rpiled/led_blink
off
</pre><br />
Activation ou désactivation du clignotement de la LED :<br />
<br />
<pre class="brush: shell"># echo on > /sys/class/rpiled/rpiled/led_blink
# cat /sys/class/rpiled/rpiled/led_blink
on
</pre><br />
Lecture de la vitesse de clignotement de la LED :<br />
<br />
<pre class="brush: shell"># cat /sys/class/rpiled/rpiled/led_timer
blink led timer (ms) : 1
</pre><br />
Changement de vitesse de clignotement de la LED :<br />
<br />
<pre class="brush: shell"># echo 500 > /sys/class/rpiled/rpiled/led_timer
# cat /sys/class/rpiled/rpiled/led_timer
blink led timer (ms) : 500</pre><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/YiWI9NFSEL0?feature=player_embedded' frameborder='0'></iframe> </div><h4 style="text-align: left;"> </h4><h4 style="text-align: left;"> Accès au périphérique via un nœud dans /dev</h4>Au chargement du module, un nœud nommé <b>rpiled</b> va être créé dans le dossier <i>dev</i> avec comme numéro de majeur 252 et numéro de mineur 0. Ce nœud va servir à l'utilisateur pour interagir avec le périphérique via une application (utilisation des méthodes <i>open, read, close</i>). exemple :
<pre class="brush: shell"># cat /dev/rpiled
</pre><h3 style="text-align: left;"> Conclusion</h3>Maintenant que le gestion d'une GPIO en sortie est traitée (driver et application), nous allons nous intéresser à la gestion d'une GPIO en entrée (bouton poussoir) à l'aide d'un driver Linux. </div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com1Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-28929370622265705762012-07-01T21:56:00.000+02:002012-10-19T15:45:47.207+02:00On va faire du custom (Partie 2)<div dir="ltr" style="text-align: left;" trbidi="on">Après avoir compiler nos différents éléments, nous allons maintenant les insérer sur une carte SD. avant cela, nous allons la formater suivant le tutoriel fourni sur le <a href="http://elinux.org/RPi_Advanced_Setup#Formatting_the_SD_card_via_fdisk_.22Expert_mode.22">wiki de raspberry pi</a>. Il suffit simplement de suivre le tutoriel à une petite modification près. Au lieu de formater la partition linux au format Ext3, nous allons la formater au format Ext4.<br />
<br />
ensuite, décompressez les deux archives <i><b>boot.tar.gz</b></i> et <i><b>rootfs.tar.gz</b></i> trouvées dans le dossier de buildroot <i>output/images</i>, dans respectivement, les partitions boot (FAT32 LBA) et rootfs (EXT4) créées précédemment.<br />
A noter que l'extraction de l'archive rootfs doit se faire avec les droits super utilisateurs. <br />
<pre class="brush: shell"># tar xzf output/images/boot.tar.gz -C /media/FAT32_PARTITION
# sudo tar xzf output/images/rootfs.tar.gz -C /media/EXT4_PARTITION
</pre><br />
ensuite démonter la carte SD et insérer la sur la carte raspberry pi.<br />
<pre class="brush: shell"># sudo umount /media/FAT32_PARTITION
# sudo umount /media/EXT4_PARTITION</pre><br />
Finalement après avoir ouvert une console série, et branché la raspberry pi, voici les traces de démarrage : <br />
<pre class="brush: shell">Linux version 3.1.9 (sinseman44@BENSERV) (gcc version 4.6.3 (crosstool-NG 1.15.2 - buildroot 2012.05) ) #1 PREEMPT Sun Jul 1 00:50:23 CEST 2012
CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: BCM2708
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512
Kernel command line: dma.dmachans=0x3c bcm2708_fb.fbwidth=720 bcm2708_fb.fbheight=480 bcm2708.boardrev=0x2 bcm2708.serial=0xd5a6dc6e
smsc95xx.macaddr=B8:27:EB:A6:DC:6E dwc_otg.lpm_enable=0 console=ttyAMA0,115200
kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 128MB = 128MB total
Memory: 125572k/125572k available, 5500k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xffc00000 - 0xffe00000 ( 2 MB)
vmalloc : 0xc8800000 - 0xd8000000 ( 248 MB)
lowmem : 0xc0000000 - 0xc8000000 ( 128 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc03b0000 (3744 kB)
.init : 0xc03b0000 - 0xc03cd000 ( 116 kB)
.data : 0xc03ce000 - 0xc03ec8c0 ( 123 kB)
.bss : 0xc03ec8e4 - 0xc04391d8 ( 307 kB)
NR_IRQS:85
timer_set_mode: unhandled mode:1
timer_set_mode: unhandled mode:3
Console: colour dummy device 80x30
console [tty1] enabled
Calibrating delay loop... 795.44 BogoMIPS (lpj=3977216)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
devtmpfs: initialized
NET: Registered protocol family 16
vc-mem: mm_vc_mem_phys_addr = 0x00000000
vc-mem: mm_vc_mem_size = 0x10000000 (256 MiB)
mailbox: Broadcom VideoCore Mailbox driver
bcm2708_vcio: mailbox at f200b880
bcm_power: Broadcom power driver
bcm_power_open() -> 0
bcm_power_request(0, 8)
bcm_mailbox_read -> 00000080, 0
bcm_power_request -> 0
Serial: AMBA PL011 UART driver
dev:f1: ttyAMA0 at MMIO 0x20201000 (irq = 83) is a PL011 rev3
console [ttyAMA0] enabled
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource stc
FS-Cache: Loaded
CacheFiles: Loaded
Switched to NOHz mode on CPU #0
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
bcm2708_dma: DMA manager at c8808000
bcm2708_gpio: bcm2708_gpio_probe c03d3d68
vc-mem: Videocore memory driver
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
FS-Cache: Netfs 'nfs' registered for caching
msgmni has been set to 245
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
BCM2708FB: registering framebuffer (720x480@16)
bcm2708_fb_set_par info(c7868000) 720x480 (720x480), 0, 16
BCM2708FB: start = c8900000,49385000 width=720, height=480, bpp=16, pitch=1440 size=691200 success=0
Console: switching to colour frame buffer device 90x30
BCM2708FB: register framebuffer (0)
brd: module loaded
loop: module loaded
vcos: [1]: vchiq_init_state: slot_zero = 0xffd80000, is_master = 0
vcos: [1]: vchiq_init_state: called
vcos: [1]: vchiq: initialised - version 2 (min 2), device 253.0
usbcore: registered new interface driver smsc95xx
cdc_ncm: 04-Aug-2011
usbcore: registered new interface driver cdc_ncm
dwc_otg: version 2.90b 6-MAY-2010 (platform bus)
Core Release: 2.80a
Setting default values for core params
Finished setting default values for core params
c8840008 -> 1
Using Buffer DMA mode
Periodic Transfer Interrupt Enhancement - disabled
Multiprocessor Interrupt Enhancement - disabled
Dedicated Tx FIFOs mode
dwc_otg bcm2708_usb: DWC OTG Controller
dwc_otg bcm2708_usb: new USB bus registered, assigned bus number 1
dwc_otg bcm2708_usb: irq 75, io mem 0x00000000
Init: Port Power? op_state=1
Init: Power Port (0)
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: DWC OTG Controller
usb usb1: Manufacturer: Linux 3.1.9 dwc_otg_hcd
usb usb1: SerialNumber: bcm2708_usb
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
usbcore: registered new interface driver uas
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
usbcore: registered new interface driver libusual
mousedev: PS/2 mouse device common for all mice
usbcore: registered new interface driver xpad
cpuidle: using governor ladder
cpuidle: using governor menu
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
bcm_power_open() -> 1
mmc0: SDHCI controller on BCM2708_Arasan [platform] using platform's DMA
mmc0: BCM2708 SDHC host at 0x20300000 DMA 2 IRQ 77
sdhci-pltfm: SDHCI platform and OF driver helper
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
Registering the dns_resolver key type
VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 5
Waiting for root device /dev/mmcblk0p2...
mmc0: new high speed SDHC card at address b368
mmcblk0: mmc0:b368 7.45 GiB
mmcblk0: p1 p2
EXT4-fs (mmcblk0p2): warning: maximal mount count reached, running e2fsck is recommended
EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) on device 179:2.
devtmpfs: mounted
Freeing init memory: 116K
usb 1-1: new high speed USB device number 2 using dwc_otg
EXT4-fs (mmcblk0p2): re-mounted. Opts: user_xattr,acl,barrier=1,data=ordered
usb 1-1: New USB device found, idVendor=0424, idProduct=9512
usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
hub 1-1:1.0: USB hub found
hub 1-1:1.0: 3 ports detected
usb 1-1.1: new high speed USB device number 3 using dwc_otg
usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
smsc95xx v1.0.4
smsc95xx 1-1.1:1.0: eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:a6:dc:6e
smsc95xx 1-1.1:1.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
øø
Welcome to RaspberryPi
(none) login: root
Password:
[root@(none) ~]# uname -a
Linux (none) 3.1.9 #1 PREEMPT Sun Jul 1 00:50:23 CEST 2012 armv6l </bio-0>
ARMv6-compatible processor rev 7 (v6l) BCM2708 GNU/Linux
</pre><br />
Amusez-vous bien ...</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-63463686216902085492012-07-01T11:08:00.000+02:002012-10-19T15:47:38.441+02:00Comment gagner du temps<div dir="ltr" style="text-align: left;" trbidi="on">Une fois que l'on a une chaine de compilation fonctionnelle, il ne sert à rien d'en reconstruire une à chaque fois, c'est pourquoi je propose <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFQUtwanY0OC1MeGM">ma chaîne de compilation croisée</a> (~ 228 Mo) pour la carte raspberry pi, compilée sur une machine X86, donc fonctionnelle sur les machines X86 ou 64bits.<br />
<br />
Si tout de fois, une chaîne de compilation croisée a déjà été compilée, il est préférable de nettoyer l'environnement avec d'utiliser la nouvelle chaîne.<br />
<pre class="brush: shell"># make clean</pre><br />
Pour l'utiliser, il faut tout d'abord la décompresser puis configurer buildroot, pour cela, on reprend la commande :<br />
<pre class="brush: shell"># tar xvzf arm-unknown-linux-gnueabi.tar.gz -C CHEMIN_INSTALLATION
# make menuconfig</pre><br />
Dans le menu, on entre dans le sous menu <i>toolchain </i>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFWQSUkZveeqS6g4iN8rNySl14IHJi4lZZjtslWDrfi4BISRhk8chql_VgSyNiD7EN96pRXqQTKYUmwsjlx22URkPOYS877VhcPT5AVZQ6OM3CLSpnnPhxJkvQQXPnBfxb9DynmanH2FE/s1600/external_toolchain_buildroot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFWQSUkZveeqS6g4iN8rNySl14IHJi4lZZjtslWDrfi4BISRhk8chql_VgSyNiD7EN96pRXqQTKYUmwsjlx22URkPOYS877VhcPT5AVZQ6OM3CLSpnnPhxJkvQQXPnBfxb9DynmanH2FE/s640/external_toolchain_buildroot.png" width="580" /></a></div><br />
Dans ce sous-menu, on choisi<i> external toolchain type</i> et <i>custom toolchain,</i> dans les deux premiers champs. Le suivant sert à entrer le chemin de la chaîne de compilation croisée, la libc est une glibc et elle a le support c++.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLL_qM26aiLlUx0xKaZk9rwf5BsKJ0xqS2MMFuXYZkCN_wQjNB41DfhLKUlECUFj_NEuqQciiC5MWM88qeZwlzZssTk44yo84HqEgN2FNt8CGKmCHnidAXXnL8gXUL6x9MEa2QHehMS3k/s1600/external_toolchain_buildroot_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLL_qM26aiLlUx0xKaZk9rwf5BsKJ0xqS2MMFuXYZkCN_wQjNB41DfhLKUlECUFj_NEuqQciiC5MWM88qeZwlzZssTk44yo84HqEgN2FNt8CGKmCHnidAXXnL8gXUL6x9MEa2QHehMS3k/s640/external_toolchain_buildroot_1.png" width="580" /></a></div><br />
Il ne reste plus qu'à compiler l'environnement avec cette nouvelle chaine et le tour est joué ...<br />
<pre class="brush: shell"># make</pre></div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-73914586951115038982012-06-26T10:49:00.000+02:002012-10-19T15:52:40.273+02:00On va faire du custom (partie 1)<div dir="ltr" style="text-align: left;" trbidi="on"><h3 style="text-align: left;">Introduction </h3><h3 style="text-align: left;"></h3>La plupart des utilisateurs utiliseront leur carte avec une distribution Linux adaptée, telle que <a href="http://downloads.raspberrypi.org/images/debian/6/debian6-19-04-2012/debian6-19-04-2012.zip">Debian squeeze</a> ou<a href="http://downloads.raspberrypi.org/images/archlinuxarm/archlinuxarm-13-06-2012/archlinuxarm-13-06-2012.zip"> Arch Linux</a> pour ne citer qu'eux (disponible en téléchargement sur le site de raspberry pi). Elles offrent la possibilité d'avoir une suite complète de logiciel pour l'administration du système, la programmation, le multimédia et autres.<br />
Ces distributions nécessitent d'avoir une carte SD avec une taille adaptée, environ 2 Go minimum.<br />
<br />
Je vais partir du postulat que je n'ai ni le besoin, ni l'envie, d'utiliser ce genre de distribution. Pour cela, je vais me construire un environnement minimaliste pour ma carte. <br />
<br />
Cet environnement sera constitué d' :<br />
<ul style="text-align: left;"><li>Une chaine de compilation croisée </li>
<li>Un bootloader</li>
<li>Un Noyau Linux</li>
<li>Un système de fichiers (avec tout ce qui va bien dedans, ex : busybox, etc ...)</li>
</ul>Dans cette première partie, On va s’intéresser à la construction de notre système et la deuxième partie abordera la mise en route de notre système sur la carte.<br />
<h3 style="text-align: left;"> <a name='more'></a></h3><h3 style="text-align: left;">Buildroot </h3><h3 style="text-align: left;"></h3><ul style="text-align: left;"></ul><div class="separator" style="clear: both; text-align: center;"><a href="http://buildroot.uclibc.org/images/logo_small.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://buildroot.uclibc.org/images/logo_small.png" /></a></div>Je vais utiliser un outil, <a href="http://buildroot.uclibc.org/">Buildroot</a>, qui me permettra de construire mon environnement. Buildroot est la réunion de plusieurs outils permettant de construire un système embarqué complet. Il a la capacité de pouvoir constuire, séparément ou pas, les différents éléments essentiels (cité plus haut) d'un système embarqué.<br />
<div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">La version de buildroot utilisée est elle aussi custom et y inclut les caractéristiques de la raspberry pi.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Récupération de Buildroot :</div><div class="separator" style="clear: both; text-align: left;"></div><pre class="brush: shell"># git clone git://github.com/nezticle/RaspberryPi-BuildRoot.git Buildroot</pre><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Une fois les différents objets récupérés, voila à quoi ressemble notre dossier :</div><pre class="brush: shell"># ls -al
drwxr-xr-x 7 sinseman44 sinseman44 4096 2012-06-06 18:57 board
drwxr-xr-x 10 sinseman44 sinseman44 4096 2012-06-06 18:57 boot
-rw-r--r-- 1 sinseman44 sinseman44 60374 2012-06-06 18:57 CHANGES
-rw-r--r-- 1 sinseman44 sinseman44 11980 2012-06-06 18:57 Config.in
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-06 18:57 configs
-rw-r--r-- 1 sinseman44 sinseman44 17987 2012-06-06 18:57 COPYING
drwxr-xr-x 2 sinseman44 sinseman44 28672 2012-06-13 16:52 dl
drwxr-xr-x 4 sinseman44 sinseman44 4096 2012-06-06 18:57 docs
drwxr-xr-x 14 sinseman44 sinseman44 4096 2012-06-06 18:57 fs
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-06 18:57 linux
-rw-r--r-- 1 sinseman44 sinseman44 24050 2012-06-06 18:57 Makefile
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-07 22:15 output
drwxr-xr-x 497 sinseman44 sinseman44 65536 2012-06-06 18:57 package
-rw-r--r-- 1 sinseman44 sinseman44 2128 2012-06-06 18:57 README.md
drwxr-xr-x 7 sinseman44 sinseman44 4096 2012-06-06 18:57 support
drwxr-xr-x 5 sinseman44 sinseman44 4096 2012-06-06 18:57 target
drwxr-xr-x 10 sinseman44 sinseman44 4096 2012-06-06 18:57 toolchain</pre><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Petite explication des différents fichiers/dossiers principaux de buildroot :</div><ul style="text-align: left;"><li><i>board</i> : Scripts et fichiers de configuration spécifiques pour chaque carte (un dossier pour chaque système embarqué).</li>
<li><i>boot</i> : Fichiers de configuration et de compilation des bootloaders sélectionnables.</li>
<li><i>dl</i> : Dossier de téléchargement des packages sélectionnés.</li>
<li><i>configs</i> : Fichiers de configuration de buildroot pour différents systèmes.</li>
<li><i>fs</i> : Fichiers de configuration et de création du système de fichiers.</li>
<li><i>linux</i> : Fichiers de configuration et de configuration du noyau linux.</li>
<li><i>output</i> : Dossier de sortie de l'environnement (images systèmes).</li>
<li><i>package</i> : Fichiers de configuration et de compilation des différents packages sélectionnables. </li>
<li><i>toolchain</i> : Fichiers de configuration et de compilation des chaines de compilation croisée.</li>
</ul><div class="separator" style="clear: both; text-align: left;">Certains fichiers de configuration de mon environnement diffèrent de la version originale pour le bon fonctionnement de la carte. Je vous propose<a href="https://docs.google.com/open?id=0B6WDjVnTAZgFQ0E1UXQ5eGZTeFE"> mon fichier de configuration buildroot</a> à placer dans le dossier <i>configs</i> et <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFeFhiaFhaZUs4cEU">mon fichier de configuration crosstool-ng</a> et <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFUFFTQTFuSkpfeFU">l'inittab</a> à placer dans le dossier <i>board/raspberrypi.</i></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">On va commencer par configurer l'environnement pour la carte raspberry pi (cette commande est à taper que la première fois que vous installez buildroot), tapez la commande :</div><pre class="brush: shell"># make raspberrypi_sinseman44_defconfig</pre><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Il est possible de configurer et compiler notre environnement dans un dossier autre que celui de buildroot, pour cela, taper la commande :</div><pre class="brush: shell"># mkdir -p /home/sinseman44/raspberrypi_output
# make raspberrypi_sinseman44_defconfig O=/home/sinseman44/raspberrypi_output
</pre><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Si vous décidez d'utiliser cette commande, la compilation et le choix des paquets se fera à partir de ce dossier créé et non plus à partir du dossier de buildroot. Ex:</div><pre class="brush: shell"># cd /home/sinseman44/raspberrypi_output
# make menuconfig ou make
</pre><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Maintenant, on va choisir les outils à installer sur le système (Le fichier defconfig utilisé précédemment configure l'environnement et les paquets à installer sur le système, normalement, cette commande est à utiliser que si vous souhaitez modifier la configuration) , tapez la commande :</div><pre class="brush: shell"># make menuconfig</pre><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj12P8iDvzP7oE-3GVly_JjgWfDGnLP_3zN_ErR5a6sghtjGMloFj4nGzPF_r0rVDeEr52wWXQu3EoUFCKqzekvpX-1e0A2E_GieAiLtcdKmoECcFEW-17X85CNIxEUOAw_0TgHAEmwLB4/s1600/raspberry_pi_buildroot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj12P8iDvzP7oE-3GVly_JjgWfDGnLP_3zN_ErR5a6sghtjGMloFj4nGzPF_r0rVDeEr52wWXQu3EoUFCKqzekvpX-1e0A2E_GieAiLtcdKmoECcFEW-17X85CNIxEUOAw_0TgHAEmwLB4/s400/raspberry_pi_buildroot.png" width="383" /></a></div><br />
Ce menu principal offre la possibilité de configurer indépendamment, chaque élément pour notre système (chaîne de compilation croisée, Noyau Linux, bootloader, type de système de fichiers et packages).<br />
<br />
Les différents paquets, classés en catégories, sont accessibles dans le sous-menu <i>Package Selection for the target</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdZ4x-l2Q9ZOgFoWDwEjdLLREHlywuH74DXZYwE5jBZ_9NhWR5rlwF_98RECoGG_yakLz03X2pw_0QjwISliJb7Am8Fw0pUcALKumguDjPwOuCGLVbRRfGw_I-jYvAK56QhYZ72I363_8/s1600/raspberry_pi_buildroot_package.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdZ4x-l2Q9ZOgFoWDwEjdLLREHlywuH74DXZYwE5jBZ_9NhWR5rlwF_98RECoGG_yakLz03X2pw_0QjwISliJb7Am8Fw0pUcALKumguDjPwOuCGLVbRRfGw_I-jYvAK56QhYZ72I363_8/s400/raspberry_pi_buildroot_package.png" width="388" /></a></div><br />
Après la configuration, on va compiler .... <br />
La commande magique est :<br />
<pre class="brush: shell"># make
[ ... BLABLABLA ... ]
[INFO ] Performing some trivial sanity checks
[INFO ] Build started 20120626.091634
[INFO ] Building environment variables
[INFO ] =================================================================
[INFO ] Retrieving needed toolchain components' tarballs
[00:16] /
[ ... BLABLABLA ... ]
</pre><br />
A cet instant là, on peut se détendre, ça peut prendre un moment (quelques minutes, voir quelques dizaines de minutes en fonction de la machine hôte, ex: sur un Core 2 duo, je met entre 45 minutes et 1 heure de compilation).<br />
<br />
On devrait finir sur cette dernière action sans erreur.<br />
<pre class="brush: shell">>>> Generating root filesystem image rootfs.tar
rm -f /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
echo "chown -R 0:0 /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/target" >> /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
cat target/generic/device_table.txt > /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_device_table.txt
echo -e '\n \n \n \n \n \n \n /bin/busybox f 4755 0 0 - - - - -\n/usr/share/udhcpc/default.script f 755 0 0 - - - - -\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n' >> /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_device_table.txt
echo "/home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/host/usr/bin/makedevs -d /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_device_table.txt /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/target" >> /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
echo " tar -c""f /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/images/rootfs.tar -C /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/target ." >> /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
chmod a+x /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
/home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/host/usr/bin/fakeroot -- /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_fakeroot.fs
rootdir=/home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/target
table='/home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/build/_device_table.txt'
gzip -9 -c /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/images/rootfs.tar > /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/images/rootfs.tar.gz
</pre>#<br />
<br />
Pour finir, toutes les éléments de notre système vont se trouver dans le dossier output :<br />
<pre class="brush: shell"># ls -al output
drwxr-xr-x 104 sinseman44 sinseman44 20480 2012-06-25 20:50 build/
drwxr-xr-x 4 sinseman44 sinseman44 4096 2012-06-22 13:05 host/
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-22 22:08 images/
lrwxrwxrwx 1 sinseman44 sinseman44 102 2012-06-25 21:44 staging -> /home/sinseman44/WORK/raspberry_pi/buildroot-2012.05/output/host/usr/arm-unknown-linux-gnueabi/sysroot/
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-22 11:43 stamps/
drwxr-xr-x 18 sinseman44 sinseman44 4096 2012-06-25 20:08 target/
drwxr-xr-x 2 sinseman44 sinseman44 4096 2012-06-22 09:45 toolchain/ </pre><br />
Les dossiers importants sont :<br />
<ul style="text-align: left;"><li><i>build</i> : dossier de compilation de tous nos paquets sélectionnés</li>
<li><i>host</i> : chaîne de compilation croisée (<i>arm-unknown-linux-gnueabi-gcc, ...</i>)</li>
<li><i>images</i> : les images compressées à transférer sur la carte SD (<i>boot.tar.gz</i>, <i>rootfs.tar.gz</i>)</li>
<li><i>target</i> : l'image de notre système de fichiers (permet de construire l'archive) </li>
<li><i>staging</i> : dossier d'installation de toutes les librairies et des headers de développement (utile lors de dépendances entre paquets)</li>
</ul><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Pour aller plus loin ...</h3><h4 style="text-align: left;"> </h4><h4 style="text-align: left;">Crosstool-NG</h4><h4 style="text-align: left;"></h4>Buildroot utilise plusieurs outils pour générer les différents éléments de notre de système, notamment pour la chaine de compilation croisée. Il offre le choix d'utiliser une chaine de compilation croisée externe, une chaine construite par buildroot (itself) ou l'utilisation de l'outil <a href="http://crosstool-ng.org/">Crosstool-NG</a>.<br />
<br />
Il est possible de configurer la chaine de compilation croisée, et je vous propose <a href="https://docs.google.com/open?id=0B6WDjVnTAZgFeFhiaFhaZUs4cEU">mon fichier de configuration</a> pour crosstool-NG. à placer dans le dossier <i>board/raspberrypi</i>.<br />
<pre class="brush: shell"># make ctng-menuconfig
# make</pre><br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIN7pGZoOymIy7g2NPZlrsTcp3rpSEOv_ukexkN7eCKlZ0KjtijJzWcWbpobZh_eClAXqhQQOcbNiLoX3SnvqmPqKSyxlcdne74VJ22zRnZQDIDZXt8S0w8tb0ytOKKn4JlE7NT97X9Q/s1600/raspberry_pi_crosstool_ng.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBIN7pGZoOymIy7g2NPZlrsTcp3rpSEOv_ukexkN7eCKlZ0KjtijJzWcWbpobZh_eClAXqhQQOcbNiLoX3SnvqmPqKSyxlcdne74VJ22zRnZQDIDZXt8S0w8tb0ytOKKn4JlE7NT97X9Q/s400/raspberry_pi_crosstool_ng.png" width="388" /></a></div><br />
Cette chaine, une fois construite, sera présente dans le dossier <i>output/host</i>.<br />
<h4 style="text-align: left;"> </h4><h4 style="text-align: left;">Busybox </h4><h4 style="text-align: left;"> </h4><div style="text-align: left;">Busybox est considéré comme le couteau suisse du système embarqué, il embarque dans un seul programme (gain de mémoire non négligeable), toutes les commandes de bases de linux (ls, mount, ps, ect ...). Il est, évidement, possible de configurer les commandes présentes sur notre système.</div><div style="text-align: left;"><br />
</div><div style="text-align: left;">Entrer la commande pour avoir l'interface de configuration de busybox :</div><pre class="brush: shell"># make busybox-menuconfig</pre><br />
puis la commande de compilation :<br />
<pre class="brush: shell"># make</pre><br />
Le binaire se trouvera dans le système de fichier, sous le nom <i>busybox </i>et de nombreux liens symboliques pointeront vers ce binaire pour accéder aux commandes. Vous pouvez le constater dans le dossier <i>output/target/bin</i>.<br />
<br />
<pre class="brush: shell"># ls -al output/target/bin
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 addgroup -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 adduser -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 ash -> busybox
-rwxr-xr-x 1 sinseman44 sinseman44 781092 2012-06-25 20:49 bash
-rwsr-xr-x 1 sinseman44 sinseman44 634136 2012-06-25 20:49 busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 cat -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 catv -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 chattr -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 chgrp -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 chmod -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 chown -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 cp -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 cpio -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 date -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 dd -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 delgroup -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 deluser -> busybox
lrwxrwxrwx 1 sinseman44 sinseman44 7 2012-06-25 20:08 df -> busybox
[ ... ]</pre>On peut maintenant aborder la seconde partie du tutoriel ...<br />
<br />
<br />
<h3 style="text-align: left;">Nota Bene :</h3><br />
Suite à un retour d'un lecteur de ce blog, il s'avère que l'<b><i>inittab</i></b> modifié, ne se copie pas dans le système de fichiers, suite à une ligne commentée dans le script <b>post-build.sh.</b> Ce script est appelé à chaque construction du système de fichiers.<br />
Cette modification sert à avoir la console série.<b><br />
</b><br />
<br />
<pre class="brush: shell">[...]
# add a corrected, and lightweight inittab
#cp board/raspberrypi/inittab $TARGETDIR/etc/inittab
[...]
</pre><br />
et à remplacer par :<br />
<br />
<pre class="brush: shell">[...]
# add a corrected, and lightweight inittab
cp board/raspberrypi/inittab $TARGETDIR/etc/inittab
[...]
</pre><br />
ou copier directement l'inittab modifié directement dans BUILDROOT_PATH/output/target/etc et refaire un make<br />
<br />
<pre class="brush: shell"># cp board/raspberrypi/inittab output/target/etc
# make
</pre><br />
</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-40319588093867932672012-06-20T16:05:00.001+02:002012-10-19T15:55:17.311+02:00Création d'une carte SD virtuelle<div dir="ltr" style="text-align: left;" trbidi="on">Une carte SD type pour la raspberry pi doit avoir au minimum deux partitions :<br />
<ul style="text-align: left;"><li>Partition de boot de type Fat32 amorçable, ou se trouveront les fichiers nécessaires pour initialiser le système.</li>
<li>Partition de système de fichiers de type Ext4, ou se trouvera le système de fichiers (Logique ;)).</li>
</ul>Les utilitaires nécessaires pour la création, la configuration et le montage de notre carte SD virtuelle sont :<br />
<ul style="text-align: left;"><li><i>dd</i> : Convertir un fichier en le copiant.</li>
<li><i>losetup</i> : activer et contrôler les périphériques de boucles.</li>
<li><i>fdisk</i> ou <i>cfdisk</i> : manipulateur de tables de partitions pour Linux. </li>
<li><i>kpartx</i> : <span class="goog-text-highlight">créer un mapping des périphériques à partir des tables de partitions.</span></li>
<li><i>mkfs.vfat</i> et <i>mkfs.ext4</i> : créer un système de fichiers linux.</li>
<li><i>mount</i> et <i>umount</i> : <span class="">monter/démonter un système de fichiers linux. </span></li>
</ul>C'est différents paquets doivent être préalablement installés sur votre distribution linux avant de commencer. <br />
<br />
<br />
<a name='more'></a><br />
<br />
<br />
On va commencer par créer un fichier vierge (rempli de caractères NULL) de type bloc, de taille 2Go, avec la commande linux <a href="http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man1/dd.1.html">dd</a>.<br />
<br />
<pre class="brush: shell"># dd if=/dev/zero of=fake_sd_card.img bs=1024 count=2000000
2000000+0 enregistrements lus
2000000+0 enregistrements écrits
2048000000 octets (2,0 GB) copiés, 86,1476 s, 23,8 MB/s
Paramètres:
-> if : fichier d'entrée.
-> of : fichier de sortie.
-> bs : nombre d'octets écrits en une fois.
-> count : nombres de blocs à écrire.</pre><br />
Maintenant, Il faut associer un périphérique de boucle avec notre image précédemment créé, grâce à la commande <a href="http://man.cx/losetup%288%29">losetup</a>.<br />
<br />
<pre class="brush: shell"># sudo losetup -f
/dev/loopX
-> -f : pour connaître le premier périphérique de boucle disponible.
-> X : le numéro du périphérique de boucle disponible.
<b># sudo losetup /dev/loop0 fake_sd_card.img</b>
Périphérique boucle : /dev/loop0
</pre><br />
Nous voila avec une association entre notre périphérique et notre fichier, on va créer une table de partitions et les partitions pour notre fichier image, pour cela, nous allons utiliser la commande <a href="http://pwet.fr/man/linux/administration_systeme/fdisk">fdisk</a>.<br />
<br />
<pre class="brush: shell"># sudo fdisk /dev/loop0
Commande (m pour l'aide): n (ajouter une nouvelle partition)
Commande d'action
e étendue
p partition primaire (1-4)
p
Numéro de partition (1-4, par défaut 1): (Touche ENTRER)
Utilisation de la valeur par défaut 1
Premier secteur (2048-3999999, par défaut 2048): (Touche ENTRER)
Utilisation de la valeur par défaut 2048
Dernier secteur, +secteurs or +taille{K,M,G} (2048-3999999, par défaut 3999999): +75M
Commande (m pour l'aide): t (modifier l'identifiant de système de fichier d'une partition)
Partition sélectionnée 1
Code Hexa (taper L pour lister les codes): c
Type système de partition modifié de 1 à c (W95 FAT32 (LBA))
Commande (m pour l'aide): a (bascule le drapeau d'amorce)
Numéro de partition (1-4): 1
</pre><br />
Et pour la partition du système de fichiers :<br />
<br />
<pre class="brush: shell">Commande (m pour l'aide): n (ajouter une nouvelle partition)
Commande d'action
e étendue
p partition primaire (1-4)
p
Numéro de partition (1-4, par défaut 2): (Touche ENTRER)
Utilisation de la valeur par défaut 2
Premier secteur (155648-3999999, par défaut 155648): (Touche ENTRER)
Utilisation de la valeur par défaut 155648
Dernier secteur, +secteurs or +taille{K,M,G} (155648-3999999, par défaut 3999999): (Touche ENTRER)
Utilisation de la valeur par défaut 3999999
</pre><br />
Pour afficher le résultat de nos actions :<br />
<br />
<pre class="brush: shell">Commande (m pour l'aide): p (affiche la table de partition)
Disque /dev/loop0 : 2048 Mo, 2048000000 octets
255 têtes, 63 secteurs/piste, 248 cylindres, total 4000000 secteurs
Unités = secteurs de 1 * 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Identifiant de disque : 0x29d14150
Périphérique Amorce Début Fin Blocs Id Système
/dev/loop0p1 * 2048 155647 76800 c W95 FAT32 (LBA)
/dev/loop0p2 155648 3999999 1922176 83 Linux
</pre><br />
Nous avons 2 partitions vierges, typées (une en W95 FAT32 et une autre en linux), il nous reste plus qu'à sauvegarder puis quitter l'utilitaire fdisk.<br />
<br />
<pre class="brush: shell">Commande (m pour l'aide): w (écrire la table sur le disque et quitter)
</pre><br />
Puisque nous sommes sur un fichier typé disque et non pas sur une vraie carte SD, une erreur apparaît lors de l'enregistrement, mais à ne pas prendre en compte dans notre cas.<br />
<br />
A ce moment là, les partitions ne sont pas explicitement présentes sur notre distribution, ce qui veut dire que si on exécute la commande : <br />
<br />
<pre class="brush: shell"># ls -al /dev</pre><br />
On ne verra pas nos deux partitions : /dev/loop0p1 et /dev/loop0p.<br />
<br />
L'utilitaire <a href="http://linux.die.net/man/8/kpartx">kpartx</a> va créer un mapping des périphériques en fonction de la table de partition donnée :<br />
<br />
<pre class="brush: shell"># sudo kpartx -a -v /dev/loop0
add map loop0p1 (253:0): 0 153600 linear /dev/loop0 2048
add map loop0p2 (253:1): 0 3844352 linear /dev/loop0 155648 </pre><br />
Maintenant si on ré-itère la commande :<br />
<br />
<pre class="brush: shell"># ls -al /dev/mapper
drwxr-xr-x 2 root root 100 2012-06-20 15:05 ./
drwxr-xr-x 16 root root 4420 2012-06-20 15:05 ../
crw------- 1 root root 10, 236 2012-06-18 16:47 control
lrwxrwxrwx 1 root root 7 2012-06-20 15:05 loop0p1 -> ../dm-0
lrwxrwxrwx 1 root root 7 2012-06-20 15:05 loop0p2 -> ../dm-1
</pre><br />
Nous visualisons bien que nos deux partitions sont présentes sur le système.<br />
<br />
Il va falloir les formater, pour cela nous allons utiliser les utilitaires <a href="http://pwet.fr/man/linux/administration_systeme/mkdosfs">mkfs.vfat</a> et <a href="http://www.unix.com/man-page/All/8/mkfs.ext4/">mkfs.ext4</a>.<br />
<br />
Pour formater la partition Fat32, la commande va être la suivante :<br />
<pre class="brush: shell"># sudo mkfs.vfat -F 32 /dev/mapper/loop0p1
</pre><br />
Pour formater la partition Linux en Ext4, la commande va être la suivante :<br />
<br />
<pre class="brush: shell"># sudo mkfs.ext4 /dev/mapper/loop0p2
mke2fs 1.41.14 (22-Dec-2010)
Étiquette de système de fichiers=
Type de système d'exploitation : Linux
Taille de bloc=4096 (log=2)
Taille de fragment=4096 (log=2)
« Stride » = 0 blocs, « Stripe width » = 0 blocs
120240 i-noeuds, 480544 blocs
24027 blocs (5.00%) réservés pour le super utilisateur
Premier bloc de données=0
Nombre maximum de blocs du système de fichiers=494927872
15 groupes de blocs
32768 blocs par groupe, 32768 fragments par groupe
8016 i-noeuds par groupe
Superblocs de secours stockés sur les blocs :
32768, 98304, 163840, 229376, 294912
Écriture des tables d'i-noeuds : complété
Création du journal (8192 blocs) : complété
Écriture des superblocs et de l'information de comptabilité du système de
fichiers : complété
</pre><br />
Pour accéder à ces deux partitions, on va finalement les monter avec l'utilitaire <a href="http://linux.die.net/man/8/mount">mount</a>. <br />
<br />
<pre class="brush: shell"># sudo mkdir -p /media/boot
# sudo mkdir -p /media/rootfs
# sudo mount /dev/mapper/loop0p1 /media/boot
# sudo mount /dev/mapper/loop0p2 /media/rootfs
</pre><br />
Pour utiliser le fichier, il va falloir démonter le périphérique de boucle associé à celui-ci, dans l'ordre, cela va nous donner :<br />
<br />
<pre class="brush: shell"># sudo umount /media/boot
# sudo umount /media/rootfs
# sudo kpartx -d -v /dev/loop0
del devmap : loop0p2
del devmap : loop0p1
# sudo losetup -d /dev/loop0
</pre><br />
Notre carte SD virtuelle est maintenant prête ....<br />
Dans un prochain billet, nous verrons son utilisation.</div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com1Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-15447756409993160362012-06-19T09:07:00.001+02:002012-06-19T11:12:01.898+02:00Do It Yourself - Protection Raspberry PI<div dir="ltr" style="text-align: left;" trbidi="on">
Il y a pas mal de projets de boiter de protections pour le raspberry pi. Certains déjà abouti, d'autres pas encore. Je vous propose ma solution "Do It Yourself".<br />
<br />
Je me suis procuré un boîtier plastique standard (transparent pour le fun) chez <a href="http://www.electronique-diffusion.fr/product_info.php?products_id=16306">électronique-diffusion</a> (quelques boutiques en France, dont une sur Toulouse, mais on peut aussi commander online), pour 6- 7 euros, correspondant au mieux aux dimensions de la carte.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd6acehognsgJHZGifBK7h1YxFm_igYy2OFceaHDpb9hQ2VLj50CHLFw2IOXVYfTSVWHqW2Yj4EaCbRUJxJdrARDkR6qXK2xeOilv9GllcTYPcWf2jin-Ob0CRmftOpukpGXHSYaWcfD0/s1600/DIY_case_raspberrypi_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd6acehognsgJHZGifBK7h1YxFm_igYy2OFceaHDpb9hQ2VLj50CHLFw2IOXVYfTSVWHqW2Yj4EaCbRUJxJdrARDkR6qXK2xeOilv9GllcTYPcWf2jin-Ob0CRmftOpukpGXHSYaWcfD0/s320/DIY_case_raspberrypi_1.jpg" width="320" /></a></div>
<br />
A première vue, la carte est trop large de quelques millimètres pour rentrer dans le boîtier, et il va falloir le raboter et le découper pour un accès aux différents connecteurs (les cotes ont été prises "à l’œil").<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ7iMsBIxqhtgZyj1MGeB9O0j0M-kYY7H2qXm3TYy2UC8KeoTuKTGzTfL6R3d01JLTkZSK51bEbpKEni4wrDjk9T7RXNKQ99hWtQUdvFHaBhRPRRwGMsYCV996_z-RgleSsC9ryBEmHMA/s1600/DIY_case_raspberrypi_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ7iMsBIxqhtgZyj1MGeB9O0j0M-kYY7H2qXm3TYy2UC8KeoTuKTGzTfL6R3d01JLTkZSK51bEbpKEni4wrDjk9T7RXNKQ99hWtQUdvFHaBhRPRRwGMsYCV996_z-RgleSsC9ryBEmHMA/s320/DIY_case_raspberrypi_2.jpg" width="320" /></a></div>
<br />
Une fois les modifications faites, voici ce que ça donne :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMKYLV8KO9vZoexSLWVj9KcLz-WrzwNhoANzL5MoFxSU-bB-qK4wADozIVw1IEQ38dHZTXcJ76lJPc1Jhb184FzVcIB22uc5_yxc3Hp0zAhRDyQK2HtOD3Jmetj4p28cPocNmSKi0eW-E/s1600/DIY_case_raspberrypi_11.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMKYLV8KO9vZoexSLWVj9KcLz-WrzwNhoANzL5MoFxSU-bB-qK4wADozIVw1IEQ38dHZTXcJ76lJPc1Jhb184FzVcIB22uc5_yxc3Hp0zAhRDyQK2HtOD3Jmetj4p28cPocNmSKi0eW-E/s320/DIY_case_raspberrypi_11.jpg" width="320" /></a></div>
<br />
Le boîtier fermé :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7K7Jyz6_WgJv8aqYWOAUj71yMtD2fv9rMK903AbUzmUyZCs4yeCRIeu_MZogkeDKuOqcCNKOq9QvGpwYNTwhcpw0e8QU7DlSBKGJMng1BGT9B7pklQsg7KlZf-n2u1s20JRqQKkt0D6w/s1600/DIY_case_raspberrypi_12.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7K7Jyz6_WgJv8aqYWOAUj71yMtD2fv9rMK903AbUzmUyZCs4yeCRIeu_MZogkeDKuOqcCNKOq9QvGpwYNTwhcpw0e8QU7DlSBKGJMng1BGT9B7pklQsg7KlZf-n2u1s20JRqQKkt0D6w/s320/DIY_case_raspberrypi_12.jpg" width="320" /></a></div>
<br />
Une protection à faire soi-même pour quelques euros et de l'huile de coude. ;) <br />
<br />
<br /></div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com0Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375tag:blogger.com,1999:blog-3014712466464327072.post-83358510052965094862012-06-14T23:01:00.000+02:002012-07-01T13:23:10.851+02:00La console UART c'est quand même plus pratique<div dir="ltr" style="text-align: left;" trbidi="on">
Ça y est j'ai craqué, La console sur la télévision (seule entrée HDMI disponible) ce n'était pas génial pour déboguer les éventuels problèmes sur le chargement de mon firmware. J'ai décidé de me construire un module grâce aux PINs UART sortantes.<br />
<br />
Une console série permet de contrôler un système à partir d'un terminal branché sur le port série d'un ordinateur. Il existe du matériel permettant de convertir des signaux série en signaux USB, donc d'utiliser une console série avec une connexion USB, c'est ce que je vais utiliser.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.ftdichip.com/Images/ftdi_1.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.ftdichip.com/Images/ftdi_1.gif" /></a></div>
Je me suis acheté un module <a href="http://www.ftdichip.com/Products/ICs/FT232R.htm">FTDI</a> (UART vers USB) sur Ebay (environ une quinzaine d'euros avec frais de port).<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt1-D0JR_LRhiX27XZfd-agwwv36P92hnvxlpBw27wgSbG_NDTKDtoGtvZ4hqtET0iHqoo9cI7x5dGBrr44LN-lkGIzomYfTZ8YL2UA1MWPhYP6rAqun_OUtgG9rQOVUg7ufqqUK0Ontw/s1600/20120614_201652.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt1-D0JR_LRhiX27XZfd-agwwv36P92hnvxlpBw27wgSbG_NDTKDtoGtvZ4hqtET0iHqoo9cI7x5dGBrr44LN-lkGIzomYfTZ8YL2UA1MWPhYP6rAqun_OUtgG9rQOVUg7ufqqUK0Ontw/s320/20120614_201652.jpg" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Seuls les PINs Rx, Tx et GND seront soudés sur le module FTDI et les signaux Rx et Tx seront inversés entre les cartes, comme indiqué sur le schéma suivant.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLoPFQiUYx1_udF-u0NpvzI0c8Q0x5pgasaQrSMV8BXlsn8UJvmYP-B0SAeRSbEz97yeIlvSNaR-W4_pAdR0Z9B08JMlDBNk2JfEyH3uRtzZhyRw5FccF1YgYwJM5Bi4K5u8hhsBUcU3s/s1600/ftdi_scheme.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLoPFQiUYx1_udF-u0NpvzI0c8Q0x5pgasaQrSMV8BXlsn8UJvmYP-B0SAeRSbEz97yeIlvSNaR-W4_pAdR0Z9B08JMlDBNk2JfEyH3uRtzZhyRw5FccF1YgYwJM5Bi4K5u8hhsBUcU3s/s320/ftdi_scheme.jpg" width="320" /></a></div>
<br />
Sur la raspberry pi, le schéma des Entrées Sorties est le suivant :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOipt3LkyfSMWO6vRKh8vFhrjpoliI-tiHGg4KP5pi__4OtEXGiIrC-MqGalPsib-K_xoPgYnF6gGs6zExifQR-MbT-K0oSKuppkCP4d-rFG7wc43X58Vg_jZhg6garQMdF-S-1C0hASM/s1600/254px-GPIOs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOipt3LkyfSMWO6vRKh8vFhrjpoliI-tiHGg4KP5pi__4OtEXGiIrC-MqGalPsib-K_xoPgYnF6gGs6zExifQR-MbT-K0oSKuppkCP4d-rFG7wc43X58Vg_jZhg6garQMdF-S-1C0hASM/s400/254px-GPIOs.png" width="173" /></a></div>
<br />
<a href="http://elinux.org/RPi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29">Le wiki de raspberry pi</a> explique le rôle de chaque Entrée/Sortie.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Le câblage, après deux, trois coups de fer à souder et de gaine thermodurcissable, ressemble à ça :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFhnnXcutWSM1SWV3OvN8xLCO1kM_I4ZNBW5H4JswkgnXneZVAai49V81-pzHQXWEmYhNjgEYuatp4ThJPuXmsux-flzkKrEHOoENmlImUHkwbLgVJvl2CUq63Q6Bs5_5hBPkhZyJIW4Q/s1600/20120614_210946.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFhnnXcutWSM1SWV3OvN8xLCO1kM_I4ZNBW5H4JswkgnXneZVAai49V81-pzHQXWEmYhNjgEYuatp4ThJPuXmsux-flzkKrEHOoENmlImUHkwbLgVJvl2CUq63Q6Bs5_5hBPkhZyJIW4Q/s320/20120614_210946.jpg" width="320" /></a></div>
Finalement le montage complet est le suivant :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgetflsqkfXmI0dO7F-eNFPOL8JAdmWkde9KU_4G8urmHa1fcr3MKO-K-TspUd1yFu9EmfkVAgPW63kkKWkqa5GXbizVzuW6WqWpC1rozmXyMAT5_e28iW7W-SUZyAoxDC7LkfxYzC2pXo/s1600/20120614_211113.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgetflsqkfXmI0dO7F-eNFPOL8JAdmWkde9KU_4G8urmHa1fcr3MKO-K-TspUd1yFu9EmfkVAgPW63kkKWkqa5GXbizVzuW6WqWpC1rozmXyMAT5_e28iW7W-SUZyAoxDC7LkfxYzC2pXo/s400/20120614_211113.jpg" width="400" /></a></div>
Au niveau de la configuration du port COM sur le PC, on est en 115200 bauds 8 N 1 sans flux de contrôle.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9aql40j_hSWLjlq2ucWyOGNUUyn75m5r6uIjEq5UYXxwJXdb5eLI_pF5SkNKY3cRgEUWJqrn-pDHaxZQM3OPHJ_JZTVP5jG_dtiE8Y1MRP-NBTI3Ux5G51jy5DAPuTVeB204eanA3DAI/s1600/serial_configuration_putty.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9aql40j_hSWLjlq2ucWyOGNUUyn75m5r6uIjEq5UYXxwJXdb5eLI_pF5SkNKY3cRgEUWJqrn-pDHaxZQM3OPHJ_JZTVP5jG_dtiE8Y1MRP-NBTI3Ux5G51jy5DAPuTVeB204eanA3DAI/s320/serial_configuration_putty.png" width="320" /></a></div>
Et ca fonctionne !!! La preuve en image :<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDDkkY-EHSWqXnMr5Oq9PCmLeq6180CPu8tDNBwzH9l96KKGGv6Oci3_RPj1VsHCohtH35Mc8I9Huvvq-d2jefY-azFi9ZCqdqvqo-m9wF0mnbwXdFEe76HXiE6HFThSCn-hFiDFfXMU0/s1600/puttty_console.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDDkkY-EHSWqXnMr5Oq9PCmLeq6180CPu8tDNBwzH9l96KKGGv6Oci3_RPj1VsHCohtH35Mc8I9Huvvq-d2jefY-azFi9ZCqdqvqo-m9wF0mnbwXdFEe76HXiE6HFThSCn-hFiDFfXMU0/s640/puttty_console.png" width="640" /></a></div>
<br />
Je suis prêt pour continuer le développement sur la carte Rapsberry pi.<br />
<br /></div>Coloc's Barhttp://www.blogger.com/profile/17307278592082437114noreply@blogger.com2Toulouse, France43.604652 1.44420943.512668000000005 1.2862805000000002 43.696636 1.6021375