Retrouvez cet article dans : Linux Magazine 92
Voici des mots qui pourraient faire sourire pas mal de développeurs ayant déjà essayé ces petits systèmes disponibles sur le marché depuis quelque temps.
Prix trop élevés, manque d’informations ou de support pour les particuliers, attentes interminables d’extensions pour votre carte si vous n’êtes pas expert en électronique ou tout simplement marre de recycler des cartes mères PC pour réaliser vos projets...
Ces quelques points noirs rendent malheureusement l’accès au monde de Linux embarqué encore trop difficile et contraignant.
Pourtant Linux est le candidat idéal pour ce type de développement : libre, performant, stable et disposant de nombreuses extensions intéressantes, comme Xenomai (système temps réel), il a tout pour plaire !
C’est fort de ce constat que nous avons décidé de créer le " Projet Armadeus ".
1. Présentation de l’Association
Le " Projet Armadeus " est une association à but non lucratif (loi 1907, car basée en Alsace), créée dans le but de faciliter l’accès à Linux embarqué aux personnes porteuses de projets qui n’ont jusqu’alors pas abouti, faute de temps ou de moyens.
Notre objectif est aussi de favoriser la collaboration entre personnes issues d’horizons différents, afin de permettre le développement d’applications souvent irréalisables seul.
Les moyens mis en œuvre par l’association pour arriver à ces fins sont :
- mise à disposition des adhérents d’une carte de développement avec l’ensemble Logiciel libre le plus complet possible (l’achat de la carte représente les droits d’adhésion) ;
- mise en place et gestion d’une communauté de développeurs ;
- aide au développement de nouveaux projets.
Voyons en détail ces points...
1.1 Matériel
La carte APF9328 utilisée par l’association est basée sur un processeur i.MXl de la société Freescale (ex Motorola) [1].
Ce processeur contient un cœur ARM9 cadencé à 192Mhz et une multitude de contrôleurs de périphériques : I2C, SPI, MMC, LCD, RS232, USB device, GPIO.
L’i.MXl est associé sur cette carte à une mémoire vive de type SDRAM de 16 Mo et une mémoire Flash NOR de 8 Mo, fonctionnant toutes deux sur un bus système à 96MHz. La connectivité Ethernet est assurée par un contrôleur 10/100 Mbits Davicom (DM9000).
En option, la carte peut aussi recevoir :
- un FPGA Xilinx de type Spartan 3 (200 k portes), permettant l’ajout facile de nouveaux contrôleurs de périphériques (par exemple un port PS/2, des ports PWM pour la commande de moteur, etc.). Il est même possible d’y placer un deuxième processeur (type Microblaze) !
- un CAN (Convertisseur Analogique Numérique) 8 canaux sur bus SPI et un CNA (Convertisseur Numérique Analogique) 2 canaux sur bus I2C.
L’utilisation du FPGA ne nécessite pas de connaissance particulière, car les IP (blocs fonctionnels) sont développés par plusieurs personnes du groupe spécialisées dans ce domaine.
Pour les utiliser, vous avez juste à sélectionner le ou les blocs dont vous avez besoin et les charger dynamiquement dans le FPGA. Évidemment, un driver côté Linux doit être aussi disponible pour piloter vos blocs ; son développement est en général fait conjointement avec celui de l’IP.
Pour ceux qui souhaiteraient écrire eux-mêmes le firmware pour ce FPGA, le kit de développement (webpack) est disponible gratuitement sur le site de Xilinx [2].
La carte se présente sous la forme d’un petit module de 4x7cm (APF9328) qui peut venir s’enficher sur une carte de votre conception (suivant l’application) ou sur la carte de développement proposée par l’association (DevLight), permettant de tester rapidement les fonctionnalités de bases et d’en intégrer facilement de nouvelles. Cette carte dispose de connecteurs RS232, Ethernet, USB et d’alimentation et d’une zone de prototypage permettant d’accéder aux principaux signaux du module.

Figure 1 : Le module APF9328

Figure 2 : La carte de développement (DevLight) avec ces connecteurs accueillant le module

Figure 3 : La zone de prototypage sur la carte de développement avec le nom des signaux
1.2 Logiciel
1.2.1 U-Boot
Le bootloader (chargeur de démarrage) du système est U-Boot [3]. C’est lui qui :
- initialise les fonctions vitales du système (horloge, SDRAM) après un reset ;
- fournit une interface permettant de reprogrammer la Flash du système (après chargement série ou Ethernet/TFTP) ;
- charge le code du FPGA au démarrage (si besoin) ;
- lance le système Linux (ou vos programmes maison ne nécessitant pas d’OS), à partir de la Flash ou bien d’une connexion réseau (TFTP).
1.2.2 Linux
L’OS du système est une version 2.6.18 de Linux, adaptée au processeur i.MXl. Cette version contient les pilotes pour les périphériques suivants : SPI, I2C, Ethernet, chargement FPGA, PWM, carte mémoire SD/MMC, clavier PS/2, écrans LCD graphiques sans contrôleurs (320x240 TFT & STN), port parallèle compatible ppdev (permettant de contrôler des LCD textes compatibles LCD4Linux) et USB device (Mode Mass Storage et Série).
1.2.3 uClibc/Buildroot
Le système de fichier (rootfs) est généré par Buildroot [4] et toutes les commandes Unix standards sont supportées grâce au " couteau suisse " de l’embarqué : Busybox [5].
Vous pouvez créer des programmes C/C++ Unix standard grâce à la présence de la bibliothèque C pour l’embarqué : uClibc [6]. L’i.MXl disposant d’une MMU (Memory Management Unit), vous avez la même interface de programmation que sur un système Linux x86 classique ; les espaces mémoire noyau et processus utilisateurs sont distincts, a contrario des systèmes uCLinux à base de processeurs ARM7.
1.2.4 Applicatif
L’utilisateur a la possibilité d’utiliser Qtopia Core [7] ou SDL [8] pour développer ses applications (graphiques ou non) de manière portable.
L’avantage de telles API réside dans le fait que l’application peut être entièrement écrite et simulée sur le PC de développement (Linux ou autre).
Si tant est qu’une bibliothèque ne soit pas supportée par Buildroot, il est assez facile d’intégrer celle-ci dans le processus de construction du système à partir du moment où cette bibliothèque supporte le classique configure, make, make install et la compilation croisée.
1.3 Support utilisateur
Le support utilisateur du projet s’articule autour de 4 points :
- un wiki [9] basé sur le moteur MediaWiki (aussi utilisé par Wikipédia) qui fournit un support complet aux utilisateurs sur toutes les fonctionnalités du système. Il leur permet aussi de participer à l’amélioration du contenu, soit en modifiant les pages existantes, soit en ajoutant leurs propres pages.
- un gestionnaire de bug : eh oui, tout projet contenant du logiciel se doit d’en posséder un ;-)
- une mailing list qui permet de faciliter la communication entre les différents développeurs. Les points techniques et organisationnels sont discutés ici.
- l’accès aux sources : nous utilisons SVN comme gestionnaire de version. L’accès en écriture à la base est réservé aux " intégrateurs ", mais n’importe qui peut charger les sources sur SourceForge [10] et nous faire part de ses modifications sous forme de patches (principe similaire à U-Boot et Linux).
1.4 Limitations
Étant une association à but non lucratif, nous avons limité l’utilisation des cartes obtenues dans le cadre de l’association à un usage particulier ou éducatif (autre association ou établissement d’enseignement). De même, les applications réalisées au sein du projet doivent être placées sous licence libre de manière à ce que tous les membres puissent en profiter et de manière à garantir leur pérennité. Nous n’avons pas non plus pour but la promotion de telle ou telle entreprise, mais bel et bien celle des Logiciels libres dans l’embarqué, vis à vis du plus grand nombre.
2. Exemple d’application
Voilà, après cette présentation, qui, je l’espère, ne vous a pas semblé trop rébarbative, voyons concrètement quel type d’application nous pouvons construire à partir des briques de base fournies par le projet. Vous vous êtes toujours dit que développer une console de jeu portable, c’était compliqué. Eh bien, détrompez vous, nous allons réaliser un prototype qui n’aura pas grand-chose à envier à ses concurrentes commerciales (hormis la logithèque ;-)).
Pour construire cette console, nous aurons besoin :
- d’un keypad : nous utiliserons un clavier PS/2 (pour notre première maquette) ;
- d’un écran LCD : nous utiliserons un écran TFT de récupération (Sharp LQ057 avec une résolution de 320x240 et des couleurs sur 18bits) ;
- d’un lecteur de carte mémoire pour stocker les jeux ; nous utiliserons une MMC comme " cartouche de jeu " ;
- d’une sortie son, rudimentaire dans notre exemple, obtenue avec la sortie PWM de l’i.MXl.

Figure 4 : Diagramme fonctionnel du système
2.1 Installation des outils de développement
Nous avons, dans un premier temps, besoin d’installer tous les outils nécessaires au développement. La génération du compilateur croisé, du débogueur, des images noyau et du système de fichier est entièrement automatisée, grâce à Buildroot. L’utilisateur doit juste disposer d’une connexion réseau haut-débit, car le script d’installation va aller charger tous les fichiers requis sur Internet. L’installation fonctionne sur Linux et Window$/Cygwin, mais, dans notre cas, nous utiliserons notre système préféré.
La première chose à faire est de récupérer l’archive de la dernière version du logiciel Armadeus sur SourceForge : http://sourceforge.net/projects/armadeus/.
Supposons que vous ayez chargé l’archive dans votre répertoire $HOME. Il faut ensuite la décompresser :
$ cd $HOME $ tar jxf armadeus-2.0.tar.bz2
Note:
Assurez-vous d’avoir au moins 2 Go d’espace libre à l’endroit où vous décompressez l’archive, car la compilation des outils de développement est assez gourmande en ressources !!
Un répertoire armadeus-2.0 est créé à l’endroit de la décompression. Il contient tous les fichiers nécessaires à la construction de votre environnement de développement.
Ensuite, il faut vérifier que les utilitaires nécessaires au processus sont bien présents sur votre système (par exemple sous Debian) :
$ sudo apt-get install autoconf automake bison ckermit \ flex g++ gettext libncurses5-dev subversion texinfo \ tftpd wget zlib1g-dev
Une fois ces vérifications effectuées, lancez la compilation :
$ cd armadeus-2.0 [armadeus-2.0]$ make menuconfig
Un système de configuration pseudo-graphique semblable au menuconfig du noyau Linux apparaît. Laissez les paramètres par défaut pour l’instant et enregistrez la configuration ([Escape], puis Yes). Enfin, lancez :
[armadeus-2.0]$ make
Quelques heures plus tard (suivant votre système ;-)), votre environnement est prêt. Dans le répertoire buildroot/, vous devriez voir les fichiers suivants :
u-boot.bin, l’image U-Boot ;linux-kernel-2.6.18.1-arm.bin, le noyau Linux ;rootfs.arm_nofpu.jffs2, l’image du système de fichier.
Il nous faut maintenant ajouter, dans la variable d’environnement PATH, le chemin vers les outils de compilation, afin par exemple de pouvoir lancer le compilateur croisé en appelant juste arm-linux-gcc. Rajoutez donc dans votre ~/.bashrc la ligne suivante :
export PATH=$PATH:/emplacement_archive/armadeus-2.0/buildroot/build_arm_nofpu/staging_dir/bin
2.2 Programmation de la carte
Une fois les outils de compilation et les images système générées, il vous faut les " flasher " sur la carte. Pour cela, nous allons utiliser U-Boot et la connexion réseau entre la carte et votre PC.

Figure 5 : Schéma montrant comment la cible et l’hôte doivent être interconnectés lors du développement
U-Boot utilise le protocole TFTP [11] pour transférer les données sur Ethernet, donc nous allons nous assurer que votre hôte est capable de le gérer correctement. Créez un répertoire /tftpboot en tant que root et donnez lui les droits en lecture écriture pour tout le monde :
$ sudo /bin/bash # mkdir /tftpboot # chmod 777 /tftpboot # exit
Configurez ensuite le démon tftpd pour qu’il utilise ce répertoire (référez-vous à la doc de votre distribution ou au wiki de l’association (généralement cela passe par l’édition du fichier /etc/xinetd.d/tftp) et copiez les images générées par la compilation dans /tftpboot/.
[armadeus-2.0]$ cp buildroot/u-boot.bin /tftpboot [armadeus-2.0]$ cp buildroot/linux-kernel-2.6.18.1-arm.bin /tftpboot [armadeus-2.0]$ cp buildroot/rootfs.arm_nofpu.jffs2 /tftpboot
Connectez ensuite votre carte sur un port série de votre PC (avec un câble croisé/Null Modem) et sur votre réseau Ethernet local. Le port série vous permet de communiquer avec les consoles U-Boot et Linux. Pour cela, vous devez avoir auparavant installé et configuré un émulateur de terminal série (nous recommandons C-Kermit [12] ; référez-vous au wiki si jamais vous avez besoin de plus d’infos pour l’installer).
Lancez Kermit afin de voir ce que la carte va vous envoyer sur la console série :
$ kermit -c Connecting to /dev/ttyUSB0, speed 115200 Escape character: Ctrl-\ (ASCII 28, FS): enabled Type the escape character followed by C to get back, or followed by ? to see other options. ----------------------------------------------------
Note : Dans mon cas, kermit est configuré pour utiliser mon adaptateur USB<->Série, associé au device /dev/ttyUSB0.
2.3 Démarrage de la carte
Mettez la carte sous tension : comme tout système embarqué, c’est le bootloader (ici U-Boot) qui démarre en premier. Celui-ci configure le processeur afin qu’il soit capable d’utiliser sa mémoire et d’accéder au périphérique de boot. U-boot a aussi la particularité d’offrir une console série à l’utilisateur afin que celui-ci puisse effectuer certaines actions manuellement.
Une fois le système initialisé, le bootloader charge le noyau Linux en mémoire. Il peut aller chercher l’image du noyau soit sur la mémoire Flash de la carte, soit sur le réseau. Le bootloader passe ensuite la main au noyau qui s’auto-décompresse.
Linux démarre, initialise ses périphériques, essaie de monter son système de fichier et ensuite exécute le programme /sbin/init. Ensuite, l’initialisation est dépendante du contenu du fichier /etc/inittab. À la fin de l’initialisation, vous avez en général une console Linux sur le port série, certains services réseau démarrés et si vous avez branché un LCD, des terminaux virtuels sur l’écran. Un peu comme sur les systèmes Linux des grands ;-).
Pour reflasher vos images, interrompez le démarrage de U-Boot en appuyant sur une touche de votre clavier lorsque celui-ci vous le propose.
U-Boot 1.1.3 (Oct 26 2006 - 20:27:59) ap9328 patch 2.4 U-Boot code: 0BF80000 -> 0BFA2524 BSS: -> 0BFA72D4 RAM Configuration: Bank #0: 08000000 16 MB Flash: 8 MB In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 BIOS>
A supposer que votre serveur tftp soit bien installé et vos images présentes sur celui-ci, vous pouvez lancer les commandes suivantes pour mettre à jour le noyau Linux et le rootfs :
BIOS > tftp 8000000 linux-kernel-2.6.18.1-arm.bin BIOS > run flash_kernel BIOS > tftp 8000000 rootfs.arm_nofpu.jffs2 BIOS > run flash_rootfs
Note :
tftp est la commande U-Boot qui permet de télécharger sur la cible, par le protocole TFTP, des données depuis votre hôte. Ces données sont placées dans la RAM de la cible, ici à l’adresse 0x08000000. flash_kernel et flash_rootfs sont deux scripts U-Boot permettant de flasher une image chargée en mémoire ; ils sont exécutés grâce à la commande run de U-Boot.
Votre système étant à jour, redémarrez la carte (bouton reset) et laissez Linux démarrer. Vous devriez voir apparaître le login système sur la console série :
Welcome to the Armadeus project. armadeus login:
2.4 Configuration matérielle
Maintenant que vous savez générer un système fonctionnel pour votre carte, nous allons ajouter le logiciel pour la transformer en console de jeu.
Le processeur i.MXl utilisé sur la carte Armadeus étant très souple au niveau de la configuration des périphériques, vous avez la possibilité de choisir d’activer certains modules hardware ou pas et ainsi d’avoir une configuration personnalisée. En désactivant des périphériques, vous récupérez ainsi des entrées/sorties généralisées (GPIO) que vous pouvez utiliser pour votre application. Par exemple, imaginons que vous n’ayez pas besoin du contrôleur LCD et que d’un seul port série. Vous pouvez les désactiver et ainsi avoir à votre disposition un vingtaine de pattes du processeur en tant qu’entrée/sortie.
Nous sommes en train de réfléchir à un outil graphique permettant de configurer le processeur de manière fine en quelques clics, mais pour l’instant la configuration matérielle se fait plus classiquement en activant ou non les drivers lors de la compilation du noyau Linux :
[armadeus]$ make linux-menuconfig
Dans la section " Device Drivers ", activez :
- le LCD Sharp LQ057 dans Graphic support->Motorola i.MX LCD support ;
- la PWM (pour le son) et le PS/2 dans Armadeus Specific drivers -> ;
(le driver MMC est activé par défaut dans la configuration standard)
Sauvez votre configuration.

Figure 6 : Sélectionnez les drivers nécessaires
La connexion physique entre ces périphériques et la carte est détaillée sur le wiki du projet [13]. Je vais essayer de la résumer simplement. Le LCD est branché directement sur les signaux venant du contrôleur intégré à l’i.MXl. Généralement un écran TFT sans contrôleur se pilote avec des signaux de contrôle/horloge (clock, hsync, vsync, enable) et des signaux de données représentant les valeurs de chaque composante de couleur pour un pixel donné. Dans le cas du LCD Sharp, chaque composante (Rouge, Verte, Bleue) peut être codée sur 6 bits, d’où la dénomination LCD 18 bits (3x6). L’i.MX ne pouvant piloter que des LCD au maximum 16 bits, il faut relier deux des lignes de poids faible de deux composantes à la masse (dans notre exemple Rouge et Bleu). On perd ainsi quelques couleurs par rapport aux possibilités de l’écran, mais il nous en reste encore plus de 65000 !
La logique du LCD est alimentée directement par le 3,3 V de la carte. Par contre, pour le rétro-éclairage une tension de 12 V est nécessaire : j’utilise ma bonne vieille alimentation stabilisée pour cela.
Note:
Notez qu’au moment où vous lirez ces lignes, l’association proposera à ses membres un LCD TFT Microtips 320x240 bon marché, avec sa carte d’adaptation ne nécessitant pas de tension externe pour le rétro-éclairage.
L’i.MXl ne disposant pas de contrôleur PS/2 en standard, nous implanterons celui-ci dans le FPGA. Ce dernier est relié à l’i.MXl par l’intermédiaire d’un bus 16 bits. Ainsi, on peut accéder aux IP programmées dans le FPGA comme s’il s’agissait d’un coprocesseur. Il est aussi possible de programmer le FPGA directement depuis l’i.MX, sans avoir recours à une sonde JTAG ou une mémoire externe. Les données sont stockées sur la Flash du système, lues par l’i.MX et envoyées au FPGA en série sur une GPIO, par U-Boot ou bien sous Linux. Pour notre IP PS/2, le FPGA nous fournit les 2 signaux CLOCK et DATA qui peuvent être directement reliés au connecteur du clavier si celui-ci accepte d’être alimenté en 3,3 V. Dans mon cas (clavier PS/2 + USB), il m’a fallu alimenter le clavier en 5 V et donc ajouter un régulateur de tension supplémentaire et un pont diviseur entre ce dernier et les signaux du FPGA.

Figure 7 : Adaptation des signaux PS/2 (5 v) vers ceux du FPGA (3,3 v)
La carte ne disposant pas d’un contrôleur sonore, nous utiliserons dans un premier temps la sortie PWM [14] de l’i.MXl qui est largement suffisante pour générer des petits bruitages (une carte d’extension avec chip sonore est actuellement en cours de développement). La PWM sera reliée directement à un petit buzzer piézoélectrique.
Note
Il est possible d’améliorer la qualité du son en plaçant un filtre passe-bas en sortie de la PWM, transformant ainsi le signal carré en sinusoïde, qui est de meilleur rendu sur un buzzer.
Pour la MMC, l’i.MXl disposant d’un contrôleur intégré, il suffit de connecter les signaux nom pour nom. Pour le connecteur, vous avez le choix entre bricoler le vôtre ou bien utiliser celui proposé aux membres de l’association. Celui-ci vient avec un petit PCB sur lequel on vient simplement connecter les signaux de la carte de développement.

Figure 8 : Voici à quoi ressemble le prototype une fois tous les éléments hardware connectés
2.5 Configuration logicielle spécifique
Maintenant que le hardware est connecté et que les drivers Linux sont activés, ajoutons les couches de " haut niveau ". Dans notre exemple, seule SDL sera nécessaire en plus de la configuration par défaut, donc lancez le configurateur de Buildroot et ajoutez cette bibliothèque :
[armadeus-2.0]$ make menuconfig

Figure 9 : Ajouter des packages dans buildroot
elancez la génération du système :
[armadeus-2.0]$ make
Quelques minutes plus tard, nos nouvelles images système sont prêtes. Nous pouvons les reflasher comme expliqué précédemment (2.2).
Reste encore à faire en sorte que le FPGA soit chargé avec l’IP PS/2 à chaque démarrage, par U-Boot. Pour cela, copier le fichier de configuration du FPGA dans /tftpboot :
[armadeus-2.0]$ cp firmware/PS2/ps2_top.bit /tftpboot/
Passez en mode console sous U-Boot et chargez le fichier en mémoire :
BIOS> tftp 8000000 ps2_top.bit
Puis flashez-le et activez le chargement automatique au démarrage :
BIOS> run flash_firmware .. done Erased 2 sectors Copy to Flash... done Flashing Firmware succeed BIOS> setenv firmware_autoload 1 BIOS> saveenv
2.6 Le jeu
Pour notre premier jeu, nous ferons simple : nous allons faire un clone d’Arkanoid/Breakout en C. Les sources du jeu sont incluses dans le projet, dans le répertoire target/demos/armanoid/.
Pour compiler la version PC, faites :
[armadeus-2.0]$ make -C target/demos/armanoid/
Et pour la version pour la cible :
[armadeus-2.0]$ make -C target/demos/armanoid/ clean [armadeus-2.0]$ make -C target/demos/armanoid/ TARGET=arm
Le but de cet article n’étant pas d’apprendre à utiliser SDL, nous partons du principe que vous avez déjà suivi les précédents articles à ce sujet dans GLMF.
Le code du jeu en lui-même n’étant pas une référence en matière de programmation de jeu, pour ceux qui connaissent déjà SDL, voire en matière de programmation tout court ;-), nous nous attarderons juste sur le module buzzer.c qui permet de jouer des sons depuis notre jeu afin de le rendre un peu plus sympa.
2.6.1 Production du son
Ce module est en fait une mini-bibliothèque avec 3 fonctions principales :
initBuzzer(), qui permet d’initialiser le système ;playSound( freq, temps ), qui permet de jouer un son d’une fréquence donnée pendant un certain temps ;releaseBuzzer(), qui permet de libérer toutes les ressources utilisées.
...
#define FREQ_SYS_FILE "/sys/class/pwm/pwm0/frequency"
#define ACTIVE_SYS_FILE "/sys/class/pwm/pwm0/active"
...
int initBuzzer()
{
int result = -1;
if( !initialized )
{
playing = 0;
fd = fopen( FREQ_SYS_FILE, "w" );
fda = fopen( ACTIVE_SYS_FILE, "w" );
if( (fd != NULL) && (fda != NULL) ) {
result = 0;
initialized = 1;
} else
printf(“Buzzer: pb pour ouvrir /sys/...\n”);
}
return( result );
}
Pour jouer un son, nous utilisons donc le driver PWM. Celui-ci se commande très simplement depuis l’interface fichier /sys :
/sys/class/pwm/pwm0/active, lorsque l’on écrit 1 dans ce fichier la PWM se met en marche. (0 pour l’arrêter) ;/sys/class/pwm/pwm0/frequency, une fois démarrée, on peut mettre dans ce fichier la fréquence désirée.
Par exemple, pour jouer un son depuis un shell, nous ferions :
# echo 1 > /sys/class/pwm/pwm0/active # echo 500 > /sys/class/pwm/pwm0/frequency ... on attend un petit peu ... # echo 0 > /sys/class/pwm/pwm0/active
Dans le cas de notre bibliothèque, cela revient à ouvrir les fichiers avec fopen(), puis à faire des fwrite() dessus.
void releaseBuzzer()
{
if( initialized )
{
playing = 0;
SDL_RemoveTimer( myTimerID );
timerExpired(0, 0);
fclose( fd );
fclose( fda );
initialized = 0;
}
}
void playSound( int aFreq, int aTime )
{
if( (!playing) && (initialized) )
{
char freq[16]; int nchar;
// Limite la frequence entre [50,15k] Herz
if( aFreq < 50 ) aFreq = 50;
if( aFreq > 15000 ) aFreq = 15000;
// Démarre la PWM
fwrite( "1", 1, 1, fda );
fflush( fda );
// Configure la PWM avec la fréquence requise
nchar = sprintf( freq, "%d", aFreq);
fwrite( freq, nchar, nchar, fd );
fflush( fd );
// Lance un timer qui stoppera le son
// une fois le délai expiré
myTimerID = SDL_AddTimer( (Uint32) aTime, \
timerExpired , 0);
playing = 1;
}
}
La fonction playSound() utilise les timers SDL afin de planifier la durée pendant laquelle le son doit être joué. À noter qu’après chaque fwrite() dans l’interface fichier de la PWM, il faut faire un fflush(), afin de signaler au système d’effectuer l’écriture immédiatement, sinon celle-ci est mise dans un tampon.
2.6.2 Préparation de la SD/MMC
La plupart des SD/MMC commercialisées ne sont pas formatées correctement ou ne disposent pas de table de partition standard. Pour pouvoir utiliser correctement une MMC sur la carte Armadeus, nous vous recommandons :
- d’effacer toute partition pouvant être présente sur la carte et de créer un partition primaire unique (type Linux ou Window$), en utilisant fdisk et un lecteur de carte sur votre PC de développement ;
- de formater ensuite la partition en EXT2 ou VFAT, selon vos besoins.
Nous ne détaillerons pas les étapes (rébarbatives) de cette " mise à neuf " de la MMC. Pour ceux qui auraient besoin de plus de renseignements, tout est expliqué sur le wiki de l’association [15].
À supposer que la carte est désormais prête à être utilisée (dans mon cas, associée à /dev/sdd1) et qu’il existe un point de montage /mnt/mmc sur votre hôte, copions maintenant Armanoid du PC sur la MMC :
# mount /dev/sdd1 /mnt/mmc/ $ cp target/demos/armanoid/armanoid /mnt/mmc/ $ cp target/demos/armanoid/*.bmp /mnt/mmc/ # umount /mnt/mmc
2.6.3 Lancement du jeu sur la cible
Nous allons maintenant écrire un petit script qui va mettre en place tout le système à chaque démarrage.
Pour cela, nous allons rajouter un élément dans le répertoire /etc/init.d/ de la carte. Ce répertoire contient les scripts lancés automatiquement à chaque démarrage de la carte (scripts commençant par " S "). Ajoutons donc, dans le rootfs, le nôtre qui sera lancé en dernier :
# vi /etc/init.d/S99game #!/bin/sh # Chargement des modules nécessaires: modprobe pwm modprobe apf9328ps2
N’oublions pas de rendre le script exécutable :
# chmod a+x /etc/init.d/S99game
Redémarrez la carte Armadeus :
# reboot
et attendez l’invite de login sur l’écran. Insérez votre MMC, celle-ci est reconnue automatiquement :
imx-mmc imx-mmc.0: card inserted mmcblk0: mmc0:0001 MMC 250880KiB mmcblk0: p1
Montons la MMC dans /media/mmc :
# mkdir -p /media/mmc # mount /dev/mmcblk0p1 /media/mmc/
Depuis la console Linux, lancez le jeu :
# /media/mmc/armanoid &
…et voilà, admirez le résultat :

Figure 10 : Le jeu sur PC

Figure 11 : ...et le jeu sur la cible
Évidemment, sur une véritable console, il faudrait que, lors de l’insertion de la carte mémoire, un menu listant les jeux disponibles vous soit proposé et vous permette de les démarrer. Bien sûr, rien ne vous empêche de développer cette partie-là maintenant que vous possédez les bases ! Une autre évolution peut aussi consister à remplacer le clavier PS/2 par un keypad classique en utilisant le driver keypad du projet et à recompiler des jeux un peu plus funs, type Doom. Je vous invite à suivre dans les mois qui viennent ces évolutions dans la partie Multimédia du wiki.
3. Domaines privilégiés d’utilisation du projet
Même si l’exemple donné est orienté " ludique ", de nombreux développements peuvent être envisagés autour du projet. Nous proposons un certain nombre de domaines dans lesquels nous souhaitons nous investir tout particulièrement :
- la domotique (gestion d’énergie, simulation de présence...) ;
- l’instrumentation (analyseur logique, oscilloscope, acquisition de données...) ;
- le multimédia : petites consoles de jeux, player MP3 réseau ;
- la robotique : commande et contrôle de robot.
Les nouvelles cartes d’extensions seront développées en priorité pour ces différents domaines.
Conclusion
Comme nous l’avons vu, le projet permet de développer relativement facilement et rapidement des systèmes complexes au premier abord. Son orientation open source permet aussi à chacun de participer en apportant ses idées et de se voir proposer de l’aide quant à leur réalisation. N’hésitez donc pas à venir nous rejoindre si vous avez envie d’approfondir vos connaissances en embarqué et êtes, comme nous, passionnés de Logiciels libres !
Rérérences
[1] La page de présentation de l’i.MXl chez Freescale : http://www.freescale.com/webapp/sps/site/prod_summary.jsp?nodeId=0162468rH311432973ZrDR&code=i.MXL
[2] Le WebPACK Xilinx pour le développement FPGA : http://www.xilinx.com/ise/logic_design_prod/webpack.htm
[3] U-Boot, l’un des bootloaders les plus utilisés dans l’embarqué : http://u-boot.sourceforge.net
[4] Le système de compilation de rootfs embarqué Buildroot : http://buildroot.uclibc.org
[5] BusyBox, le couteau suisse de l’embarqué : http://www.busybox.net
[6] Le site de la bibliothèque C embarquée uClibc : http://uclibc.org
[7] Le toolkit pour l’embarqué Qtopia (ex Qt/Embedded) : http://www.trolltech.com/products/qtopia
[8] La bibliothèque graphique SDL : http://www.libsdl.org
[9] Le wiki de l’association : http://www.armadeus.org
[10] Le projet sur SourceForge.net : http://sourceforge.net/projects/armadeus
[11] Trivial File Transfer Protocol :http://fr.wikipedia.org/wiki/TFTP
[12] C-Kermit :http://www.columbia.edu/kermit/ck80.html
[13] La section " Matériel " du wiki où sont expliquées toutes les connexions physiques avec les matériels supportés par la carte : http://www.armadeus.com/wiki/index.php?title=Hardware
[14] Pulse Width Modulation (Modulation de Largeur d’Impulsion) : http://fr.wikipedia.org/wiki/Modulation_de_largeur_d’impulsion
[15] Formater correctement une MMC : http://www.armadeus.com/wiki/index.php?title=Fr:MultiMediaCard
Retrouvez cet article dans : Linux Magazine 92

