De plus en plus de cartes électroniques à bas coût sont disponibles sur le marché de l’embarqué. Dans quasiment tous les cas elles sont équipées d’un coeur ARM [1]. Par exemple, le RaspberryPi [2] (ARM11 : architecture armv6) ou les cartes Olinuxino [3] (ARM9 (armv5) pour la iMX233 et Cortex A8 (armv7) pour la carte A13) utilisent des processeurs ayant un coeur ARM. Suivant le processeur utilisé, celui-ci peut posséder une unité de calcul en virgule flottante. Nous aurons donc à installer une chaîne de cross-compilation qui supporte ou pas l’unité de calcul en virgule flottante. Sur Debian, le projet emdebian [4] propose des cross-compilateurs pour les architectures précédemment cités.
Qu’est-ce que la cross-compilation ?
Je reprend ici la définition de developpez.com [5] :
Il peut arriver, souvent ou rarement selon votre domaine, que vous ayez besoin de compiler un programme pour une plateforme différente de celle qui est utilisée pour le développement. Par exemple, pour créer une application pour un téléphone portable, vous n’allez certainement pas programmer avec votre téléphone. Vous développerez plutôt votre application toujours sur ordinateur mais la compilerez pour le téléphone et non pour votre système. C’est la cross-compilation.
Dans notre cas la machine de développement est un PC sous GNU/Linux Debian 6 ou 7 et la cible est un système embarqué à base de SoC [6] ARM (RaspberryPi ou Olinuxino).
Installer la chaîne de cross-compilation sur votre Debian
Lancez un interpréteur de commandes avec les droits « root » sur votre Debian (généralement « Terminal administrateur »). Il faut tout d’abord rajouter la clé public GnuPG [7] du dépôt emdebian (cela permet de vérifier la signature des paquets que vous téléchargez). Puis éditer le fichier des sources de paquetages pour ajouter le dépôt de la emdebian enfin il faut installer le cross-compilateur à proprement parler. Vous pouvez donc taper les commandes suivantes :
1 2 |
root@portable-od:~# apt-get install emdebian-archive-keyring root@portable-od:~# nano /etc/apt/sources.list |
Rajoutez alors la première ligne pour une debian 7 Wheezy OU la deuxième ligne pour une debian 6 Squeeze:
1 2 |
deb http://www.emdebian.org/debian/ sid main deb http://www.emdebian.org/debian/ squeeze main |
Mettez à jour la liste des paquetages disponibles :
1 |
root@portable-od:~# aptitude update |
On cherche maintenant les différentes versions du cross-compilateur gcc pour arm:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
root@portable-od:~# aptitude search gnueabi root@debian7:~# aptitude search gnueabi p binutils-arm-linux-gnueabi - GNU binary utilities, for arm-linux-gnueab p binutils-arm-linux-gnueabihf - GNU binary utilities, for arm-linux-gnueab v c++-compiler-arm-linux-gnueabi - v c++-compiler-arm-linux-gnueabih - v c-compiler-arm-linux-gnueabi - v c-compiler-arm-linux-gnueabihf - p cpp-4.3-arm-linux-gnueabi - The GNU C preprocessor p cpp-4.4-arm-linux-gnueabi - GNU C preprocessor p cpp-4.4-arm-linux-gnueabihf - The GNU C preprocessor p cpp-4.5-arm-linux-gnueabi - The GNU C preprocessor p cpp-4.5-arm-linux-gnueabihf - The GNU C preprocessor p cpp-4.6-arm-linux-gnueabi - GNU C preprocessor p cpp-4.6-arm-linux-gnueabihf - GNU C preprocessor p cpp-4.7-arm-linux-gnueabi - GNU C preprocessor p cpp-4.7-arm-linux-gnueabihf - GNU C preprocessor p g++-4.3-arm-linux-gnueabi - The GNU C++ compiler p g++-4.4-arm-linux-gnueabi - GNU C++ compiler p g++-4.4-arm-linux-gnueabihf - The GNU C++ compiler p g++-4.5-arm-linux-gnueabi - The GNU C++ compiler p g++-4.5-arm-linux-gnueabihf - The GNU C++ compiler p g++-4.6-arm-linux-gnueabi - GNU C++ compiler p g++-4.6-arm-linux-gnueabihf - GNU C++ compiler p g++-4.7-arm-linux-gnueabi - GNU C++ compiler p g++-4.7-arm-linux-gnueabihf - GNU C++ compiler p gcc-4.3-arm-linux-gnueabi - The GNU C compiler p gcc-4.3-arm-linux-gnueabi-base - The GNU Compiler Collection (base package) p gcc-4.4-arm-linux-gnueabi - GNU C compiler p gcc-4.4-arm-linux-gnueabi-base - GCC, the GNU Compiler Collection (base pac p gcc-4.4-arm-linux-gnueabihf - The GNU C compiler p gcc-4.4-arm-linux-gnueabihf-bas - The GNU Compiler Collection (base package) p gcc-4.5-arm-linux-gnueabi - The GNU C compiler p gcc-4.5-arm-linux-gnueabi-base - The GNU Compiler Collection (base package) p gcc-4.5-arm-linux-gnueabihf - The GNU C compiler p gcc-4.5-arm-linux-gnueabihf-bas - The GNU Compiler Collection (base package) p gcc-4.5-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gcc-4.5-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gcc-4.6-arm-linux-gnueabi - GNU C compiler p gcc-4.6-arm-linux-gnueabi-base - GCC, the GNU Compiler Collection (base pac p gcc-4.6-arm-linux-gnueabihf - GNU C compiler p gcc-4.6-arm-linux-gnueabihf-bas - GCC, the GNU Compiler Collection (base pac p gcc-4.6-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gcc-4.6-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gcc-4.7-arm-linux-gnueabi - GNU C compiler p gcc-4.7-arm-linux-gnueabi-base - GCC, the GNU Compiler Collection (base pac p gcc-4.7-arm-linux-gnueabihf - GNU C compiler p gcc-4.7-arm-linux-gnueabihf-bas - GCC, the GNU Compiler Collection (base pac p gcc-4.7-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gcc-4.7-plugin-dev-arm-linux-gn - Files for GNU GCC plugin development. p gccgo-4.7-arm-linux-gnueabi - GNU Go compiler p gccgo-4.7-arm-linux-gnueabihf - GNU Go compiler p gdb-arm-linux-gnueabi - The GNU Debugger |
Si vous désirez installer la chaîne de cross-compilation « classique » (sans support pour l’unité de calculs flottants) tapez par exemple :
1 |
root@portable-od:~# aptitude install g++-4.7-arm-linux-gnueabi |
Si vous désirez une chaîne qui supporte « l’unité de calculs flottants » (hf : hard float en anglais, actuellement seulement si vous êtes sous debian 7 Wheezy), tapez:
1 |
root@portable-od:~# aptitude install g++-4.7-arm-linux-gnueabihf |
Vérifiez votre installation en tapant le début du compilateur puis la touche TAB deux fois (exemple ci-dessous pour le compilateur g++ classique) :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
root@portable-od:~# arm-linux- arm-linux-gnueabi-addr2line arm-linux-gnueabi-gprof arm-linux-gnueabi-ar arm-linux-gnueabi-ld arm-linux-gnueabi-as arm-linux-gnueabi-ld.bfd arm-linux-gnueabi-c++filt arm-linux-gnueabi-ld.gold arm-linux-gnueabi-cpp-4.7 arm-linux-gnueabi-nm arm-linux-gnueabi-elfedit arm-linux-gnueabi-objcopy arm-linux-gnueabi-g++-4.7 arm-linux-gnueabi-objdump arm-linux-gnueabi-gcc-4.7 arm-linux-gnueabi-ranlib arm-linux-gnueabi-gcc-ar-4.7 arm-linux-gnueabi-readelf arm-linux-gnueabi-gcc-nm-4.7 arm-linux-gnueabi-size arm-linux-gnueabi-gcc-ranlib-4.7 arm-linux-gnueabi-strings arm-linux-gnueabi-gcov-4.7 arm-linux-gnueabi-strip |
Il faut ensuite établir les liens symboliques vers le nom du cross-compilateur (ci dessous pour la version classique, pour la version avec support des calculs flottants rajouter ‘hf’ coller à ‘gnueabi’ => ‘gnueabihf’) :
1 2 |
root@portable-od:~# ln -s /usr/bin/arm-linux-gnueabi-gcc-4.7 /usr/bin/arm-linux-gnueabi-gcc root@portable-od:~# ln -s /usr/bin/arm-linux-gnueabi-g++-4.7 /usr/bin/arm-linux-gnueabi-g++ |
Premier test de la chaîne de cross-compilation
Vous allez compiler le programme suivant:
1 2 3 4 5 6 7 8 |
#include <iostream> using namespace std; int main() { cout << "Cross compilation ARM OK" << endl; return 0; } |
Vous taperez donc les commandes suivantes:
1 2 3 4 |
root@portable-od:~# nano arm-hello.cpp root@portable-od:~# arm-linux-gnueabi-g++ arm-hello.cpp -o arm-hello root@portable-od:~# ./arm-hello -bash: ./arm-hello : fichier binaire impossible à lancer |
La dernière commande est intéressante. On a essayé de lancer le binaire « arm-hello » sur une architecture i386 alors que l’on a compilé pour une architecture de type ARM : résultat le binaire ne peut être exécuté !
Pour savoir pour quel architecture un binaire est compilé, vous utilisez la commande ‘file’ (qu’il faut installer si elle n’est pas disponible) :
1 2 3 4 |
root@portable-od:~# aptitude install file root@portable-od:~# file arm-hello arm-hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x72fa9b146a359e4f866133ed06be736488ea71fa, not stripped |
Il y a deux choses intéressantes à signaler :
- le binaire « arm-hello » est bien compilé pour une architecture ARM,
- le binaire est « not stripped », ce qui signifie qu’il a encore les symboles dans son code pour le débogage. Or si l’on ne désire pas déboger cet exécutable, il faut retirer ce qui n’est pas utile. Le binaire final sera alors plus « léger ».
Ci-dessous, on regarde la taille du binaire avant et après avoir retiré les informations de debogage avec la commande ‘strip’ :
1 2 3 4 5 |
root@portable-od:~# ls -l arm-hello -rwxr-xr-x 1 root root 7377 janv. 30 16:55 arm-hello root@portable-od:~# arm-linux-gnueabi-strip arm-hello root@portable-od:~# ls -l arm-hello -rwxr-xr-x 1 root root 4244 janv. 30 17:07 arm-hello |
On passe de 7377 octets à 4244 octets !
Transférer et exécuter le binaire sur la plateforme ARM
Une fois que vous disposez du binaire, il faut le tester sur la plateforme concernée : RaspberryPi ou Olinuxino. Dans les deux cas, il faut connecter la carte à un réseau ethernet : soit en filaire, soit en Wifi. Il est conseillé pour cette partie d’utiliser une des bornes wifi disponible dans la section et de la configurer pour qu’elle distribue des adresses ip par le serveur dhcp intégré. Votre station de développement sera configuré en dhcp, la carte ARM sera configuré en dhcp soit en filaire, soit en wifi : ainsi les deux machines seront sur le même réseau.
Vérifiez la config réseau sur chacune des machines avec la commande ‘ifconfig’. Testez la commande ping entre les deux machines. Enfin pour envoyer un fichier vers la carte ARM depuis votre station de développement:
1 |
root@portable_od:~# scp arm-hello root@adresse_ip_machine_arm |
Dans un autre terminal vous pouvez vous connecter sur la carte ARM par ssh:
1 |
root@portable_od:~# ssh root@adresse_ip_machine_arm |
Sur la machine ARM, vous pouvez alors lancer l’exécutable :
1 2 |
root@olinuxino:~# ./arm-hello Cross compilation ARM OK |