Les ordinateurs embarqués sous le système d’exploitation Linux sont massivement présents dans les technologies modernes (transports, multimédia, téléphonie mobile, appareils photos …).
L’ordinateur Raspberry PI constitue un support d’apprentissage performant, très bon marché et disposant d’une forte communauté sur le net. Il possède des entrées/sorties puissantes permettant une connexion avec le monde physique par l’intermédiaire de capteurs et d’actionneurs.
L’objectif de ce TP est de réaliser une rapide prise en main d’un système embarqué au travers d’un ordinateur Raspberry PI qui sera largement utilisée en projet et d’effectuer un tour d’horizon des pratiques de mise en œuvre et de développement.

rasp1
Figure 1. Ecosystème Raspberry Pi

Présentation de l’activité

Objectifs

Se remémorer :

  • les bases de la programmation en C/C++ :

  • les principes de la compilation

Apprendre :

  • la gestion un système embarqué

  • la gestion des fichiers sur un système déporté (ssh, scp, Dolphin, …​)

  • les principes et les avantages de la cross-compilation

Mettre en oeuvre :

  • les méthodes de développement sur/pour un système déporté

Durée

  • Entre 4h et 6h

Ressources

Matériel(s) :

  • 1 PC avec système d’exploitation Linux

  • 1 Raspberry Pi avec OS Débian

Logiciel(s) :

  • cross-compilateur arm-linux-gnueabihf-g++

Documentation :

  • Cours de Mr Antoine sur la programmation objet de 1ière année (disponible sur Chamilo).

  • Sites de référence sur C/C++ :

    • cplusplus.com

    • cppreference.com

Pré-requis

  • Maîtrise du langage C (séquences, tests, boucles, variables, fonctions, paramètres, compilation multi-fichiers)

Compte rendu

Il sera constitué :

  • des réponses aux questions en veillant à soigner la rédaction

  • des programmes source commentés

1. Le Raspberry Pi

1.1 Présentation

Raspberry Pi est un petit ordinateur sous le système d’exploitation Linux sur carte SD destiné à des applications d’informatique embarquée. Le cœur de l’ordinateur est un FPGA intégrant un processeur, de la RAM et de nombreux périphériques.

Exercice 1

  • Quel est la référence du processeur qui équipe votre carte Raspberry Pi 2 ?

  • Quel est son type d’architecture ?

  • Combien de cœurs possède-t-il ?

  • Quel est la quantité de RAM disponible ?

  • Quels sont les bus de communication disponibles ?

  • Quelle version de VFP (Vector Foating Point) supporte-il ?

Raspberry Pi peut être directement connecté à une IHM classique, souris/clavier/ecran HDMI ou vidéo composite, cependant comme tout ordinateur Linux, Raspberry Pi peut intégrer ses propres outils de développement et une IHM reposant sur SSH contrôlable depuis un autre ordinateur par Ethernet ou WIFI.

Le connecteur d’extension supporte les entrées/sorties parallèles ainsi que la plupart des bus de communication. C’est un support particulièrement économique et puissant qui peut être facilement mis en œuvre dans de petits systèmes nécessitant un accès au monde physique par des capteurs/actionneurs disposants d’interfaces numériques.

rasp2
Figure 2. Description matérielle du Raspberry Pi

1.2 Les connecteurs d’extensions

Le connecteur d’extension de la carte Raspberry PI est utilisé pour raccorder des périphériques de communication (UART, I2C, SPI, …​) ou TOR (Tout Ou Rien).

Les broches peuvent avoir des fonctions différentes suivant qu’elles sont activées en tant que GPIO (Global Purpose Input Output), périphérique de communication ou sorties PWM (Pulse Width Modulation).

rasp3
Figure 3. Connecteur J8
rasp4
Figure 4. Détail du brochage

Exercice 2

  • Identifiez les broches à utiliser pour la communication UART

  • Donnez la signification des noms de broches suivant : RXD0, TXD0, SDA1, SCL1

2. Raspbian

2.1 Présentation

Raspbian est un système d’exploitation libre basé sur la distribution GNU/Linux Debian, et optimisé pour le plus petit ordinateur du monde, le Raspberry Pi.

Raspbian ne fournit pas simplement un système d’exploitation basique, il est aussi livré avec plus de 35 000 paquets, c’est-à-dire des logiciels pré-compilés livrés dans un format optimisé, pour une installation facile sur votre Raspberry Pi via les gestionnaires de paquets.

Le Raspberry Pi est une framboise merveilleuse, mais elle reste néanmoins dotée d’une puissance inférieure à celle d’un ordinateur moderne. Par conséquent, il est préférable d’installer un système optimisé pour lui.

Raspbian a été créé dans cette optique, et il est donc tout particulièrement adapté au Raspberry Pi.

Par ailleurs, en tant que distribution dérivée de Debian, il répond à la majeure partie de la très vaste documentation de Debian.

rasp5

2.2 Téléchargement et installation

Exercice 3

  • Téléchargez la dernière image de Raspbian et déployez la sur la carte microSD à votre disposition :

$ sudo dd if=dateRev-raspbian-dist.img | pv | sudo dd of=/dev/sdx bs=4096
Remplacez x dans sdx par la lettre de média appropriée !
dateRev-raspbian-dist.img est le nom de l’image de Rapbian téléchargée

3. Prise en main directe

rasp6
Avant de brancher quoi que ce soit
  1. Assurez-vous de disposer de l’ensemble des éléments listés. Puis, suivez ces instructions :

  2. Commencez par insérer votre carte microSD dans le logement prévu sur le Raspberry Pi.

  3. Ensuite, connectez votre souris et votre clavier USB aux ports USB du Raspberry Pi.

  4. Assurez-vous que votre moniteur est sous tension et que vous avez sélectionné l’entrée appropriée (p. ex. HDMI 1, DVI, etc.).

  5. Ensuite, reliez votre Raspberry Pi à votre moniteur à l’aide du câble HDMI.

  6. Connectez votre Raspberry Pi au réseau à l’aide d’un câble Ethernet.

  7. Lorsque vous avez branché tous les câbles et inséré la carte microSD requise, branchez l’alimentation électrique micro USB. Cette action met sous tension et démarre votre Raspberry Pi.

3.1 Démarrage

Au premier démarrage, l’écran suivant apparait, sinon utilisez la commande :

$ sudo raspi-config
raspi config
Le mot de passe par défaut de l’utilisateur pi est raspberry

Exercice 4

  • Indiquez votre emplacement géographique et heure, (locale et timezone).

  • Étendez le système de fichier à l’ensemble de la carte SD en sélectionnant l’option Expand filesystem dans le menu Advanced Options

  • Configurez le clavier et activez le serveur SSH.

3.2 Connexion au réseau

Pour se connecter à un réseau, il faut renseigner le fichier interfaces :

$ vi /etc/network/interfaces

Exercice 5

  • Configurez la connexion filaire pour recevoir automatiquement les paramètres - - Identifiez votre adresse IP.

  • Vérifiez dans le navigateur l’accès à internet.

Que faire si la résolution de nom d’hôte échoue ?

Si la résolution de nom échoue, il faut renseigner le fichier le DNS dans fichier /etc/resolv.conf :

nameserver 192.168.1.1

Pour trouver l’adresse du DNS, utilisez la commande :

    $ nslookup
    Serveur :  box
    Address:	192.168.1.1

    Nom :	  raspberrypi
    Address: 192.168.1.68

Ce fichier peut être écrasé au prochain démarrage de la Raspberry Pi et donc empêcher l’accès à internet pour installer par exemple des paquets logiciels.

Pour corriger ce problème :

  • après avoir renseigné le fichier /etc/resolv.conf, installer le paquet resolvconf avec la commande

$ sudo apt-get update
$ sudo apt-get install resolvconf
  • renseigner ensuite le fichier /etc/dhcpcd.conf avec une directive static domain_name_servers à laquelle on fournit l’adresse IP du serveur DNS :

static domain_name_servers=192.168.1.1

3.3 Mise à jour

  • Mise à jour de la liste des paquets

$ sudo apt-get update
  • Mise à jour des paquets installés (NE PAS FAIRE ICI !)

$ sudo apt-get upgrade
  • Mise à jour de la distribution Raspbian (NE PAS FAIRE ICI !)

$ sudo apt-get dist-upgrade

4. Compilation sur cible

4.1 Définition

C’est le mode de compilation le plus simple : on procède comme sur un PC fonctionnant sous une distribution classique le linux.

4.2 Mise en oeuvre

Exercice 6

  • Saisissez le programme suivant en enregistrez dans le dossier personnel de l’utilisateur pi sous le nom hello1.cpp :

hello1.cpp
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string prenom;
	cout << "Test d'ecriture et de compilation d'un programme C++ sur Raspbery PI " << endl ;
	cout << "- Ecriture sur cible  " << endl ;
	cout << "- Enregistrement local  " << endl ;
	cout << "- Compilation sur cible  " << endl ;
	cout << "Quel est ton prenom ? " ;
	cin >> prenom;
	cout << "Bonjour " << prenom << endl;
}
  • Compilez et exécutez le programme. Sauvegardez le rapport de compilation.

$ g++  -ftime-report hello1.cpp  –o  hello1

5. Prise en main à distance

5.1 ssh / scp

En général, les systèmes embarqués n’ont pas de moniteur, de clavier et de souris, ils sont conçus pour fonctionner à l’intérieur d’un système matériel et donc inaccessible. Leur gestion se fait alors à distance, par l’intermédiaire de liaisons de communications séries (souvent RS232) ou par réseau filaire ou wifi.

On accède alors au système en mode console grâce au protocole SSH (Secure Shell) et on gère les fichiers grâce à l’utilisation de protocoles d’échange comme FTP, SFTP ou encore SCP.

On peut également gérer l’interface graphique en mode distant (« terminal distant ») mais l’utilisation d’une interface graphique dans la plupart des systèmes embarqués est une hérésie. Elle consomme des ressources inutilement.

5.2 Hôte linux

Sur un hôte linux standard, les protocoles SSH et SCP sont généralement déjà installé.

Depuis un hôte linux connecté au réseau, ouvrez une session SSH avec la Raspberry PI dans un terminal. Explicitez les différentes étapes.

Exercice 7

  • Depuis un hôte linux connecté au réseau, ouvrez une session SSH avec la Raspberry PI dans un terminal. Explicitez les différentes étapes lors de la première connexion.

$ ssh <ip_raspberry>

La commande scp permet de copier un fichier ou un répertoire (option -r) d’un client vers un serveur ou d’un serveur vers un client.

$ scp  <Fichier_local>  <login@IP_client_distant:Chemin>
$ scp  <login @IP_serveur_distant:Chemin/Fichier>
  • Depuis votre hôte linux, copiez le fichier hello1.cpp présent sur la Raspberry PI dans votre dossier personnel.

  • Explicitez les différentes étapes et donnez la syntaxe précise utilisée.

  • Le gestionnaire de fichiers de l’hôte local Linux openSuse est Dolphin. Ce gestionnaire de fichiers permet de se connecter à un serveur distant et de monter le dossier indiqué dans le système de fichiers local, ce qui permet d’y naviguer graphiquement. Cliquez sur l’icone réseau et ajoutez un dossier réseau qui pointe vers le dossier racine de votre Raspberry.

  • Explicitez les différentes étapes et les illustrer avec des copies d’écran.

  • Ouvrez l’éditeur de texte de votre hôte linux (Kate par exemple), saisissez et enregistrez localement le programme suivant sous le nom hello2.cpp :

hello2.cpp
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string prenom;
	cout << "Test d'ecriture et de compilation d'un programme C++ sur Raspbery PI " << endl ;
	cout << "- Ecriture sur hote distant linux  " << endl ;
	cout << "- Enregistrement sur hote distant puis transfert sur cible  " << endl ;
	cout << "- Compilation sur cible depuis hote distant  " << endl ;
	cout << "Quel est ton prenom ? " ;
	cin >> prenom;
	cout << "Bonjour " << prenom << endl;
}
  • Transférez le fichier sur la carte Raspberry PI dans le dossier personnel de l’utilisateur pi.

  • Depuis l’hôte linux openSuse, compilez et exécutez le programme sur la cible. Sauvegardez le rapport de compilation.

$ g++  -ftime-report hello2.cpp  –o  hello2

5.3 Hôte Windows

Sous Windows, on utilisera le logiciel (PC) WinSCP et/ou le client SSH (Secure Shell) Putty.

Exercice 8

hello3.cpp
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string prenom;
	cout << "Test d'ecriture et de compilation d'un programme C++ sur Raspbery PI " << endl ;
	cout << "- Ecriture sur hote distant Windows  " << endl ;
	cout << "- Enregistrement sur hote distant puis transfert sur cible  " << endl ;
	cout << "- Compilation sur cible depuis hote distant  " << endl ;
	cout << "Quel est ton prenom ? " ;
	cin >> prenom;
	cout << "Bonjour " << prenom << endl;
}
  • Transférez le fichier sur la carte Raspberry PI dans le dossier personnel de l’utilisateur pi.

  • Depuis l’hôte Windows, compilez et exécutez le programme sur la cible. Sauvegardez le rapport de compilation.

g++  -ftime-report hello3.cpp  –o  hello3

5.4 Cross-compilation

Le processus de compilation mobilise les ressources du système (temps processeur et mémoire). Il nécessite également un espace de stockage suffisant pour l’enregistrement des données temporaires de compilation.

Sur un système embarqué, ces caractéristiques matérielles sont naturellement limitées et il est souvent préférable de procéder à la compilation des sources sur un système plus performant puis de transférer les exécutables obtenus sur la cible.

Ce type de compilation s’appelle cross-compilation ou compilation croisé en français. Il s’agit de compiler sur une machine (PC) pour une autre (Raspberry PI).

Le cross-compilateur doit être construit sur mesure, pour une cible donnée et sur un système hôte donné. Il faut donc le compiler en utilisant le compilateur de l’hôte, des outils pour la cible (binutils) et des bibliothèques C adaptées (libC).

Cette préparation peut être très complexe. Il faut faire les bons choix et résoudre les problèmes de dépendances. Heureusement, il existe des solutions « pré-faites » pour une plateforme et un OS spécifique, par exemple, pour le Raspberry Pi sous Rasbian : https://www.raspberrypi.org/documentation/linux/kernel/building.md

Exrecice 8

  • Sur votre hôte linux openSuse, clonez le dépôt de la chaine de compilation croisée (cross-compilation toolchain) officielle de la fondation Raspberry Pi :

git clone https://github.com/raspberrypi/tools ~/tools
Si l’utilitaire de gestion des dépots git n’est pas installé, procéder à son installation depuis yast
  • Renseignez le système sur l’emplacement des fichiers nécessaires à la compilation croisée en mettant à jour la variable d’environnement $PATH :

$ echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin >> ~/.bashrc
$ source ~/.bashrc
  • Ouvrez l’éditeur de texte de votre hôte linux (Kate par exemple) et saisissez et enregistrez localement le programme suivant sous le nom hello4.cpp :

hello4.cpp
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string prenom;
	cout << "Test d'ecriture et de crosscompilation d'un programme C++ pour Raspbery PI" << endl ;
	cout << "- Ecriture sur hote distant Ubuntu  " << endl ;
	cout << "- Transfert par ssh / serveur monte dans FS Ubuntu  " << endl ;
	cout << "- Compilation sur hote  " << endl ;
	cout << "Quel est ton prenom ? " ;
	cin >> prenom;
	cout << "Bonjour " << prenom << endl;
}
  • Depuis l’hôte linux openSuse, compilez, transférez l’exécutable généré et exécutez le sur la cible. Sauvegardez le rapport de compilation.

arm-unknown-linux-gnueabihf-g++ -ftime-report hello4.cpp -o hello4 -static-libstdc++
  • Explicitez les différentes étapes.

6. Conclusion

  • Dressez un tableau des différentes méthodes pour obtenir un exécutable pour le Raspberry Pi.

Développement
(Local ou Distant)

Durée de compilation
(secondes)

Transfert exécutable
(Méthode)

  • Conclure sur l’intéret d’utiliser la compilation croisée