Raspberry Pi (2/3)

Au moment d’écrire ces lignes, Raspbian est livré avec GCC 8.3.0, Binutils 2.31.1 et Glibc 2.28.
Cette information est importante, car la compilation croisée fera référence à ces versions.

Installation Raspian

Installation Raspbian Buster Lite from scratch avec BalenaEtcher

SSH

SSH est désactivé par défaut sur Raspberry. Il faut dans un premier temps se connecter avec un clavier sur le port USB et un écran sur le port HDMI.
Une fois loguer :

Login : pi
Pass: raspberry 
       (Attention clavier anglais par défaut avec la connexion console !)

il faut activer SSH à travers commande :

sudo raspi-config

Activation Wifi

L’activation du Wifi (s’il n’y a pas de connexion filaire) se fait également avec
la commande « sudo raspi-config », voir menu « Network Option »
Spécifier SSID et Mot de Passe Wifi.

Par la suite un redémarage du Raspberry Pi est nécesaire

Ensuite l’adresse IP du Raspberry PI s’obtient avec la commande

ip address

Accès Distance

Par la suite un simple ssh sur la machine hôte permet de se connecter au Raspberry

ssh pi@192.168.1.137

Première connexion

Mise à jour

Tout d’abord, assurez-vous que votre système est mis à jour.

 sudo apt update
 sudo apt upgrade 

Linux & Kernel

Version Linux (Système exploitation)

lsb_release -a
  No LSB modules are available.
  Distributor ID: Raspbian
  Description:    Raspbian GNU/Linux 10 (buster)
  Release:        10
  Codename:       buster

La version Linux (noyau) :

uname -a
  Linux raspberrypi 4.19.93-v7+ #1286 SMP Mon Jan 6 13:18:44 GMT 2020 
  armv7l GNU/Linux
    4.19.93-v7+ 
         - noyau Linux 4.19.93
   armv7l
          Architectures ARM type RISC 
           - 32 bits (ARMv1 à ARMv7) 
          -  64 bits (ARMv8).

Le noyau est le cœur du système, c’est lui qui s’occupe de fournir aux logiciels une interface de programmation pour utiliser le matériel.
Sa caractéristique principale est d’être multitâche et multi-utilisateur.

Add-ON
Si vous utilisez le processus de mise à jour : update/upgrade cela mettra automatiquement à jour le noyau vers la dernière version stable.
Il s’agit de la procédure recommandée par rapport à la Mise à jour manuelle à l’aide de
:

rpi-update 

Outils de Développement

Binutils

Les Binutils GNU sont une collection d’outils binaires. Les principaux sont:
ld – l’éditeur de liens GNU.
as – l’assembleur GNU…
La version installée s’obtient avec

ld -v
   GNU ld (GNU Binutils for Raspbian) 2.31.1

Outils de compilation

Introduction

GCC, Make, ..sont les outils essentiels permettant de compiler et développer en C.
Ces outils (en principe déjà installés) s’installent avec

sudo apt-get install build-essential

GCC

La version GNU Compiler Collection, abrégé en GCC, est un ensemble de compilateurs créés par le projet GNU.
GCC est un logiciel libre capable de compiler divers langages de programmation, dont C, C++, Objective-C, Java, Ada et Fortran

gcc --version
  gcc (Raspbian 8.3.0-6+rpi1) 8.3.0
  Copyright (C) 2018 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  
  There is NO warranty; not even for MERCHANTABILITY or FITNESS 
  FOR A PARTICULAR PURPOSE.

GNU C Lib

GNU C Library (glibc) est la bibliothèque standard C.

Les fichiers standards se trouvent sous ‘usr/lib’ et ‘/usr/include’

Outil de debug

gdb est installé, mais il est intéressant d’utiliser gdbserver pour un debug en remote

sudo apt-get install gdbserver

Quelques outils

LDD

ldd (de l’anglais List Dynamic Dependencies) est un utilitaire Unix qui affiche la liste des bibliothèques partagées nécessaires pour chaque programme ou bibliothèque passés sur la ligne de commande.
ldd risquent d’essayer d’obtenir les renseignements de dépendances en exécutant directement le programme. Par conséquent, vous ne devriez jamais utiliser ldd sur du code exécutable non sûr, car cela pourrait avoir
pour conséquence l’exécution de code arbitraire.

Un autre moyen de traiter les exécutables est objdump

objdump

« objdump » est un programme en ligne de commande pour afficher diverses informations sur les fichiers objets sur les systèmes d’exploitation de type Unix. Par exemple, il peut être utilisé comme un désassembleur pour afficher un exécutable sous forme d’assemblage

#Lecture de bibliothèque 
  objdump -x /chemin/vers/le/programme | grep NEEDED 

#Désassemblage  
  objdump -x /chemin/vers/le/programme

Librairies C

Compilation

Les premières étapes de la compilation, c’est-à-dire toutes celles qui se situent avant celle de l’édition de liens, consistent à transformer les fichiers dits sources(extension.c) en fichiers dits objet(extension.o).
Prenons par exemple

gcc -Wall -o fichier_objet -I{répertoire_Include} -c  fichier_source_C

Pour indiquer à gcc que l’on souhaite compiler un fichier source, il suffit de lui donner l’option -c et le nom de votre fichier source.
On peut également choisir le nom du fichier objet résultat de la compilation avec l’option -o.
L’option -Wall demande au compilateur d’afficher tous les messages de prévention (lorsque quelque chose est ambigue, par exemple).

Le résultat de la compilation est un fichier appelé module objet. Bien que formé d’instructions machine, il n’est pas exécutable. En effet, la précompilation a permis de donner par exemple la définition de la fonction printf. La compilation a préparé son usage mais n’a pas ajouté les séquences d’instructions machine qui la réalise. Il reste à les lier avec notre fichier objet pour pouvoir les utiliser.

Édition de liens

Cela consiste à produire un exécutable
Pour construire le programme éxécutable, il faut indiquer à gcc quels morceaux doivent être utilisés. Au minimum, le fichier objet généré par la compilation et éventuellement une librairie (ou plusieurs, selon le cas). L’option -o permet d’indiquer le nom du programme éxécutable à construire et l’option -l le nom d’une librairie. De manière générale la commande ressemblera à :  

gcc -Wall -o nom_exec -L{chemin/lib} -lnom_librairie fichiers_objet  

Emplacement par défaut des librairies

Les fichiers standards se trouvent sous ‘usr/lib’ et ‘/usr/include’, mais cela va beaucoup plus loin !

L’éditeur de liens dynamique habituel sous Linux utilise un cache pour trouver ses bibliothèques.
Le cache est stocké dans /etc/ld.so.cache, et est mis à jour par ldconfig qui recherche les chemins qui lui sont donnés dans /etc/ld.so.conf et les fichiers dans /etc/ld.so.conf.

Il n’y a donc pas de valeur par défaut pour LD_LIBRARY_PATH !
La recherche de bibliothèque par défaut n’en a pas du tout besoin.
Si LD_LIBRARY_PATH est défini, il est utilisé en premier, mais ne désactive pas les autres recherches (qui incluent également quelques répertoires par défaut).

Le fichier cache /etc/ld.so.cache, contient une liste compilée des objets partagés candidats précédemment trouvés dans le chemin de la bibliothèque augmentée. Le chemin par défaut sont /lib, puis /usr /lib.

Sur Raspberry l’emplacement par défaut des librairies

En prenant chaque fichier, nous arrivons au total à
 #Défault
 /lib
 /usr/lib
 #00-vmcs
  /opt/vc/lib
 #Multiarch support
 /usr/local/lib/arm-linux-gnueabihf
 /lib/arm-linux-gnueabihf
 /usr/lib/arm-linux-gnueabihf
 /usr/lib/arm-linux-gnueabihf/libfakeroot
 #libc default configuration
 /usr/local/lib

Librairies Statique et Dynamique

Les librairies contiennent la définition de fonctions susceptibles d’être utilisées par plusieurs programmes. Il existe deux types de librairies :

  • les librairies statiques et
  • les librairies dynamiques.

Static

Le nom des librairies statiques est typiquement de la forme : lib***.a
Par exemple en regardant dans le répertoire/usr/lib vous trouverez :
–libc.a est la librairie standard C (fonctions malloc,exit, etc.) ;
–libm.a est la librairie mathématique (fonctions sqrt,cos, etc.) ;

Dynamic

Le nom des librairies dynamiques est typiquement de la forme :lib***.so
Dans le répertoire/usr/lib vous trouverez également les versions dynamiques des librairies ci-dessus.

Différence

Utiliser des librairies statiques, revient à inclure la définition des fonctions de la librairie dans votre fichier exécutable
Utiliser des librairies dynamiques, revient à indiquer à votre programme l’emplacement d’où il pourra charger en mémoire
ces définitions après le lancement du programme.

Le choix se fait au niveau de la compilation avec le paramètre static

gcc -static -static-libstdc++ -static-libgcc

Nommage des librairies

Soit la librairie libXXX.a (ou libXXX.so) se trouvant dans un répertoire dont le chemin absolu est chemin.
Pour compiler un fichier source prog.c faisant appel à des fonctions de cette librairie, il faut taper la ligne de commande suivante :

gcc prog.c -Lchemin -lXXX -o prog
gcc prog.c -L/usr/lib -lm -o prog

Création d’une librairie statique

Pour créer une librairie statique à partir des fichiers objet, il faut utiliser la commande ar qui archive ces fichiers dans un seul fichier.
L’option -r permet d’insérer les nouveaux fichiers dans l’archive.
L’option -v (verbose) permet d’afficher à l’écran le nomdes fichiers insérés.

ar -rv libtoto.a prog1.o prog2.o prog3.o … progn.o

Création d’une librairie dynamique

Pour créer une librairie dynamique à partir des fichiers objet, on peut utiliser gcc avec l’option -shared.

 gcc -o libtoto.so -shared prog1.o prog2.o prog3.o … progn.o

Gestion GPio Raspberry

Introduction

Nous utilisons la librairie WirinPi pour gérer les entrées sorties du Raspberry

sudo apt-get install wiringpi

Librairies ajoutées

Avant Installation

Après installation

Exemple d’une Led qui clignotte

Un simple programme C qui va permettre de faire clignoter une LED

#include <stdio.h>
#include <wiringPi.h>

#define LED 0
int main (void)
{
  // Init 	
  printf("Raspberry Pi Init");
  wiringPiSetup ();
  pinMode (LED, OUTPUT);
  for (;;)
  {
    digitalWrite (LED, HIGH); 
    delay (500);
    digitalWrite (LED,  LOW); 
    delay (500);
  }
  return 0 ;
}

Compilation

# Compilation
gcc -Wall -c led.c -o led.o

#Edition de lien
gcc -Wall -o led  -L/usr/lib -lwiringPi led.o

Vérification locale

# Vérification des bibliothèques
ldd ./led
  linux-vdso.so.1 (0x7ede8000) 
       /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so =>
       /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0x76f6e000)   
  libwiringPi.so => /usr/lib/libwiringPi.so (0x76f50000) 
  libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76e02000)
  libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76d80000) 
  libpthread.so.0 => 
       /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76d56000) 
   librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76d3f000) 
   libcrypt.so.1 => 
       /lib/arm-linux-gnueabihf/libcrypt.so.1 (0x76cff000) 
   /lib/ld-linux-armhf.so.3 (0x76f83000)

# Ou méthode recommandée d'aprés la littérarure
  objdump -x led | grep NEEDED
   NEEDED               libwiringPi.so
   NEEDED               libc.so.6

Cette commande nous informe de la nécessité de la librairie
libwiringPi.so

Rsync

Un petit aparté sur un programme qu’il sera nécessaire d’utiliser pour la compilation croisée
sync (pour remote synchronization ou synchronisation à distance), est un logiciel de synchronisation de fichiers.
rsync travaille de manière unidirectionnelle c’est-à-dire qu’il synchronise, copie ou actualise les données d’une source (locale ou distante) vers une destination (locale ou distante) en ne transférant que les octets des fichiers qui ont été modifiés.
Utilisation

rsync -avz login@serveur.org:/source/ destination
a ou --archive   : pour dire que vous voulez la récursivité et préserver pratiquement tout. 
-z ou --compress : compresse les données lors du transfert. 
v                : verbose

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *