\section*{But du document}
Ce document essaye d'aider le programmeur C classique à trouver son chemin pour programmer
de systèmes embarqués. 

\subsection*{Contexte}
Ce document a été principalement rédigé par Jérôme Pouiller
 (\url{jerome.pouiller@gmail.com}), développeur système. 
\begin{quote}
  \emph{
    Il est surtout composé de retour d'expérience de mes divers projets au
    sein de la société Easter-Eggs\footnote{\url{http://www.easter-eggs.com}}, et en
    particulier d'un projet de système de reconnaissance de caractères.
    J'essaye de faire ici le point sur mes connaissances actuelles.
  }
\end{quote}

\subsection*{Remarque sur les anglicismes}
Nous nous excusons auprès des puristes francophones. Ils trouveront dans
ce document un certains nombre d'anglicismes. Ces anglicismes sont
signalés par leur emphasement. Très souvent, nous ne connaissons pas la
traduction française de ces mots et souvent le mot français est
tellement peu utilisé qu'il n'apporte rien. Si quelqu'un trouve des
anglicismes et connaît les traductions françaises, nous serions heureux de mettre
à jour ce document.
%cross compiler -> cross-compilateur
%patch ->
%target -> architecture cible
%host -> architecture hote
%toolchain -> chaine d'outils ? chaine de compilation?

%Dans le même registre, il arrive parfois que 'gcc' soit utilisé à la place de "compilateur"


\subsection*{Licence}
Vous êtes libres:
\begin{itemize}
\item de reproduire, distribuer et communiquer ce document  un tiers
\item de modifier ce document
\item d'utiliser ce document à des fins commerciales
\end{itemize}
Selon les conditions suivantes:
\begin{itemize}
  \item Paternité: Vous devez citer le nom de l'auteur original.
  \item Partage des Conditions Initiales à l'Identique: Si vous
    modifiez, transformez ou adaptez ce document, vous n'avez le droit de
    distribuer le document qui en résulte que sous un contrat identique à
    celui-ci.
\end{itemize}
A chaque réutilisation ou distribution, vous devez faire apparaître
clairement aux autres les conditions contractuelles de mise à
disposition de cette création.

Chacune de ces conditions peut être levée si vous obtenez l'autorisation
du titulaire des droits.

La version complète de la licence peut être trouvée sur
\url{http://creativecommons.org/licenses/by-sa/2.5/legalcode}

\subsection*{Configuration matérielle}
Ce document est fortement lié au retour d'expérience d'Easter-Eggs sur
un système de reconnaissance de caractères. Les principaux points techniques de ce système:
\begin{itemize}
  \item La compilation est gérée par \bold{Autotools}
  \item Le système est compilé à l'aide de \bold{gcc} cross compilé pour ARM (diverses
    versions, principalement 3.4 et 4.0).
  \item Le système fonctionne sur une carte PC104 \bold{Cogen CSB336}\cite{CSB336DS}
  \item La carte PC104 contient un processeur \bold{MC9328MXL}\cite{MCDS}
  \item \dots basé sur un cœur \bold{ARM920T}\cite{920TDS}
  \item Le tout est connecté à un PC par une sonde \bold{Abatron
    BDI2000}\cite{BDI2000man}
  \item La sonde contient un microcode\footnote{\emph{firmware}} BdiGdb pour ARM7/9
\end{itemize}

\section{La \emph{toolchain}}
Pour travailler sur une architecture distante, vous aurez sûrement
besoin d'une \emph{toolchain}. Une \emph{toolchain} est un ensemble d'outils
comprenant au moins un compilateur, un assembleur et un
éditeur de liens\footnote{plus connu sous le nom de \emph{linker}}
exécutable sur une architecture X produisant des binaires pour une
architecture Y.

Vous avez trois solutions:
\begin{itemize}
  \item Utiliser une \emph{toolchain} binaire précompilée
  \item Utiliser certains scripts facilitant la compilation d'une
  \emph{toolchain}
  \item Compiler vous-même votre \emph{toolchain}
\end{itemize}

\paragraph{Remarque au sujet des normes C:} On pense souvent que le C
est un langage immuable. C'est faux. A chaque changement de versions
majeures de gcc, la syntaxe du C change (je ne parle même pas des
options et encore moins du passage sur un autre compilateur). Si devez
compiler un code existant (tel que le noyau), renseignez-vous sur le
compilateur utilisé et essayez d'utiliser le même. Sinon, vous aurez des
problèmes de compilation à résoudre à la main (et parfois, ça n'est pas
une simple question de syntaxe).

\subsection{Utiliser une \emph{toolchain} binaire précompilée}
Si vous travaillez avec des compilateurs propriétaires, on vous fournira
sûrement une \emph{toolchain} précompilée. Vous pourrez aussi trouver
quelques \emph{toolchains} précompilées sur Internet. En particulier:
\begin{itemize}
\item CodeSourcery\footnote{\url{
http://www.codesourcery.com/gnu_toolchains/arm}} une
excellente \emph{toolchain} basé sur gcc.
\item Eldk ( Embedded Linux Development Kit)\footnote{\url{http://www.denx.de/wiki/DULG/ELDK}} pour ARM, Mips et PowerPC. La distribution contient aussi une série d'outils précompilés pour l'architecture cible.
\item Vous trouverez aussi un paquet Debian pour compiler pour palmOS.
\end{itemize}

L'installation d'une \emph{toolchain} est souvent très simple (Une simple
décompression d'archive suffit généralement). Néanmoins, il existe
tellement de combinaisons compilateur/hôte/cible, que vous ne pourrez
pas toujours trouver de \emph{toolchain} précompilée adaptée à vos besoin.

Même si vous trouvez une version hôte/cible correspondant à vos
besoins, vous aurez peut-être besoin d'avoir d'autre version de gcc pour
compiler votre  code\footnote{surtout si vous essayez de compiler du code
existant}. Typiquement, toutes les versions du noyau Linux ne compilent
pas avec toutes les versions de gcc

\subsection{Compiler vous-même votre \emph{toolchain}}
Pour un maximum de souplesse, vous pouvez compiler vous même votre
\emph{toolchain}. Sachez que c'est un processus long et difficile. Il vous
faudra parfois \emph{patcher} le code pour qu'il fonctionne correctement.

% Je rappelle les paramètres importants pour fabriquer un cross compiler : 
% \begin{itemize}
%   \item --build=l'architecture actuelle
%   \item --host=l'architecture qui va executer le compilateur
%   \item --target=l'architecture pour laquelle vous allez compiler au
% final
% \end{itemize}
Vous trouverez des informations plus détaillées sur
\url{http://www.mega-tokyo.com/osfaq2/index.php/GCC Cross-Compiler}

\subsection{Utilisation de scripts}
Heureusement, il existe un certains nombre de scripts vous permettant de
fabriquer plus facilement un cross-compilateur.

\subsubsection{CrossTool}
CrossTool\footnote{\url{http://www.kegel.com/crosstool/}} est ensemble
de scripts pour générer des toolchains basées sur Gcc. C'est le script
que je vous conseille d'utiliser. Il n'y pas de problème particulier à
l'utilisation de CrossTool. Néanmoins, toutes les configurations ne
fonctionnent pas. Vous aurez peut-être besoin de tester plusieurs
configuration avant d'obtenir quelque chose fonctionnel. Je vous
déconseille fortement d'essayer de \emph{patcher} le code. Cela vous
prendra souvent beaucoup de temps, et vous ne pourrez plus garantir le
bon fonctionnement de votre \emph{toolchain}. Vous pouvez visualiser les
résultats des compilation sur
\url{http://www.kegel.com/crosstool/crosstool-0.42/buildlogs/}.
Normalement, si votre \emph{toolchain} compile, il y a de très fortes
chances pour qu'elle fonctionne correctement.

\subsubsection{BuildRoot}
BuildRoot\footnote{\url{http://buildroot.uclibc.org/}} va  plus loin que
CrossTool en tentant  de compiler un système GNU/Linux complet. Il 
compile donc une \emph{toolchain}  gcc, puis  les différents  outils
indispensables  pour le  bon fonctionnement  d'un  GNU/Linux (le  tout 
basé  sur  la  $\mu$Libc)  enfin,  il installe le  tout dans un  répertoire
sous la forme  d'une arborescence complète. Vous n'avez plus qu'a
transférer ce répertoire sur votre architecture cible.

Néanmoins, BuildRoot semble ne plus être maintenu depuis Février 2005.
Je vous conseille donc de plutôt utiliser PtxDist.

\subsubsection{PtxDist}
PtxDist\footnote{\url{
http://www.pengutronix.de/software/ptxdist\_en.html}} est l'outil qui se
veut le  plus abouti. Comme BuildRoot, il est capable de  générer  une
arborescence  GNU/Linux  pour  une architecture  cible.  Il utilise
CrossTool afin de fabriquer sa \emph{toolchain}. Vous pouvez de plus le
configurer  pour  construire  automatiquement  un  noyau  ou  bien
simplement  une \emph{toolchain}. Enfin Il permet  de plus  de gérer 
facilement vos propres \emph{patchs}.

PtxDist  associé à un serveur Subversion bien fait et
quelques règles de \emph{quality assurance} peut devenir  un outil extrêmement
puissant pour la fiabilité et la mise à jour automatique de votre système

\section{Le système de dépendances}

% Remarquez pour notre carte (CSB336), il existe un patch pour le Kernel
% 2.6.7 : http://www.dave-tech.it/download/misc/sw

Pour compiler votre projet, vous aurez besoin d'un système de comilation possèdant la notion d'architecture hôte et d'architecture cible. Vous avez en gros le choix entre utiliser
Cmake, Automake et faire un système de compilation personnalisé. Si vous devez utiliser des Makefile lisez absolument ``Recursive Make Considered Harmful'' de
Peter Miller\cite{rmake}, une référence. 

\subsection{Autoconf}
Que vous utilisiez Automake ou votre propre système fait maison, rien ne
vous dispense d'utiliser Autoconf. Autoconf:
\begin{itemize}
 \item vous facilitera l'écriture de votre script configure (portabilité
   maximum)
 \item permettra de facilement gérer les options de compilation et
   principalement les options liées à la cross compilation
 \item vous permettra de gérer les VPATH de manière plus transparente.
\end{itemize}

\subsection{Système maison}
Si vous  avez une bonne  connaissance des systèmes de  compilation, vous
pouvez vous  lancer dans  un système  personnalisé. Vous  pouvez calquer
votre système  de compilation  sur Kconfig (système de compilation du
noyau  Linux) qui  est assez bien  fait.  Je lui  reproche 
principalement  d'être orienté  arbre  de compilation  et  non graphe 
de  compilation  à  cause de  sa  structure récursive. Ensuite, la
gestion des VPATH n'est pas aussi simple que dans Automake. Néanmoins,
il possède une bonne gestion des différente options de compilation  et
de la  cross compilation. En particulier, il offre une interface
graphique pour la configuration de votre système\footnote{Remarquez que
cette interface ne possède une utilité que si vous avez beaucoup
d'options et que votre système doit être utilisé par un nombre assez
important de développeurs}.   A partir de ces éléments, vous  devriez
pouvoir  créer un  système de  compilation ``from  scratch'' adaptés à 
vos besoins. Quoi  qu'il en  soit, préparez-vous à  écrire un Makefile
de plus de 2000 lignes!

\subsection{CMake}
Il y a encore quelques mois, CMake n'offrait pas de fonctionnalités suffisantes
pour être utilisé pour la cross-compilation. Les choses ont bien évoluées depuis. Il semblerait
CMake soit devenu le meilleur outils de compilation (en tous cas c'est ce que les caractéristiques technique montrent). A voir\dots

\subsection{Automake}
Vous pouvez aussi utiliser Automake. Automake est très
puissant mais malheureusement, il souffre de quelques défauts sur les
Makefile non-récursif (pas de variable indiquant le répertoire courant
du fragment de Makefile) et au niveau de la cross-compilation (pas de
gestion automatique de la variable \sys{HOSTCC} comme avec KConfig).

L'utilisation d'Automake ne remet pas en cause l'article de Peter
Miller\cite{rmake}. L'écriture d'un Makefile non-récursif peut paraître un peu plus
fastidieuse, mais elle vous évitera bien des soucis.

Si vous voulez un bel exemple d'utilisation de Autoconf/Automake, regardez les
sources de ImageMagick

\subsection{Compilation de binaire sur l'architecture hôte avec Automake}
Vous aurez sûrement des programmes à compiler sur votre architecture
hôte (génération de données, génération de programmes de tests, etc\dots).
Malheureusement, il n'existe pas de cible du type
\sys{BUILD\_noinst\_PROGRAMS}\footnote{qui indiquerait que la cible doit
être compilée pour la l'architecture locale} dans Automake. Il n'existe
pas non plus d'options du type \sys{ma\_binaire\_CC =
gcc}\footnote{D'ailleurs, si des développeurs Automake nous lisent, ces
fonctionnalités serait grandement appréciées}. La meilleure méthode
pour générer des données à l'aide de binaires compilées pour l'architecture
hôte est sûrement:
\begin{verbatim}
data.h: $(genData_SOURCES)
        $(MAKE) $(AM_MAKEFLAGS) CC=$(BUILDCC) CCLD=$(BUILDCCLD) \
          CFLAGS="$(BUILDCFLAGS)" genData
\end{verbatim}
Les variables \sys{\$(BUILDCC)} \sys{\$(BUILDCCLD)} et \sys{\$(BUILDCFLAGS)} doivent être
gérée par Autoconf (ou votre propre script de configuration):
\begin{verbatim}
AC_CANONICAL_HOST
[...]
if test x$cross_compiling = xyes; then
  BUILDCC=${BUILDCC:=${build_alias}-gcc}
else
  BUILDCC=${BUILDCC:=$CC}
fi
BUILDCCLD=${BUILDCCLD:=$BUILDCC}
\end{verbatim}
Vous pouvez ajouter:
\begin{verbatim}
AC_ARG_VAR(BUILDCC, 
  C compiler to build local tools (for cross compilation))
AC_ARG_VAR(BUILDCFLAGS, 
  C compiler flags to build local tools (for cross compilation))
AC_ARG_VAR(BUILDCCLD,
  linker to build local tools (for cross compilation))
\end{verbatim}
afin que d'officialiser l'utilisation des variables \sys{BUILDCC}, \sys{BUILDCFLAGS}
et \sys{BUILDCCLD} pour l'utilisateur.

Remarquez que nous n'avons ici que passé que les variables les plus
utilisé de la compilation. Vous aurez peut-être besoin d'utiliser les
variable \sys{BUILDAS}, \sys{BUILDASFLAGS}, etc\dots

\subsection{Les VPATH}
Utiliser VPATH consiste à compiler dans un répertoire différent des sources. Par
exemple:
\begin{verbatim}
  build\$ ../src/configure
\end{verbatim}
L'intérêt est d'avoir plusieurs configuration en même temps. Ainsi:
\begin{verbatim}
  myproject\$ mkdir final_arm debug_i386
  myproject\$ cd final_arm
  myproject/final_arm\$ ../configure CFLAGS="-O3 -DNDEBUG" \
    --host=arm-linux --build=i486-linux-gnu
  myproject/final_arm\$ cd ../debug_i386
  myproject/debug_i386\$ ../configure CFLAGS="-ggdb3"
\end{verbatim}

L'utilisation de VPATH est automatique dans Autoconf. Veillez simplement a
ce que votre code soit compilable de n'importe où. Utilisez pour cela
les macros générées par Autoconf: \sys{@abs\_top\_srcdir@}, \sys{@top\_builddir@},
etc\dots De même Automake gérera automatiquement le changement de
répertoire des sources. Il vous restera tout de même à faire attention à
la gestion des scripts.

Si vous utilisez VPATH avec un système de Makefile
non-récursifs\footnote{Ce que je préconise}, n'oubliez pas que, sauf
exception, toutes vos commandes sont exécutées à la racine de répertoire
de compilation.

\subsection{Make distcheck}
Voici, à mon avis, le plus gros avantage d'Automake: la cible distcheck. 
Distcheck:
\begin{itemize}
  \item récupère tous les fichiers déclarés dans Automake
  \item les compresse dans une archive
  \item décompresse les sources en lecture seule dans un nouveau répertoire
  \item compile dans un répertoire séparé des sources en utilisant VPATH
  \item installe le système dans une arborescence séparée des sources et
    de du répertoire de compilation
  \item exécute \sys{make check} si la cible existe
  \item effectue un \sys{make uninstall} puis, un \sys{make distclean}
  \item vérifie que le répertoire, après le \sys{make distclean} est dans le
    même état qu'à la décompression
\end{itemize}
Ainsi, en une seule commande, vous pouvez vérifier une grande partie de la
cohérence de votre projet. Même si elle ne permet pas de voir tous les
problèmes, le système est tout de même intéressant. 

Parmi les options importantes, \sys{DISTCHECK\_CONFIGURE\_FLAGS} permet
de passer des option à configure lors de la procédure. 

\section{Initialiser votre cible}
Cette section décrit comment exécuter du code sur une architecture ne
possédant pas d'OS\@.

\subsection{\sys{crt0.s}}
Au détour d'un forum ou de vos recherches, vous entendrez parler de
\sys{crt0.s}. Ce fichier contient les premières instructions exécutée
par un programme elf. Il initialise la pile, copie les données
pré-initialisées dans une zone accessible en lecture/écriture et
initialise le segment BSS (contenant les variables devant être
initialisée à zéro) à zéro. Si vous utilisez un OS, ce fichiers sera
automatiquement utilisé par votre compilateur. Si vous travaillez sur une
architecture sans OS, ce fichier n'est pas suffisant car il n'initialise
pas le matériel (en particulier, il n'initialise pas la mémoire avant de
l'utiliser et plantera certainement). Néanmoins, il pourra vous être
très utile comme fichier d'exemple. En particulier, il utilise souvent
des variables provenant de l'éditeur de liens.

\subsection{Les premières instructions}
Quelques conseils pour écrire la procédure de démarrage. Vous aurez
besoin d'être proche de votre votre éditeur de lien et de votre
processeur pour écrire cette procédure. Vous échapperez difficilement à
quelques lignes d'assembleur. 

Votre processeur démarre sûrement en plaçant PC à l'adresse \sys{0x0}.
Il est possible que le segment de mémoire \sys{0x0} soit \emph{mappé}
matériellement (c'est à dire câblé sur votre carte) à deux adresses. Ce
\emph{mappage} permet très souvent d'utiliser une mémoire (typiquement,
une mémoire flash) câblées plus haut dans la mémoire. Vous trouverez ces
informations dans la documentation de votre processeur ou de votre
carte\footnote{Et si vous câblez votre propre carte, n'oubliez pas de
mettre une mémoire sur l'adresse \sys{0x0}}. Vous devez donc écrire un
code (si possible relogeable en mémoire, pour éviter les problèmes liés au
\emph{mappage} de la mémoire) et le placer à l'adresse 0x0. Déclarez un
segment\footnote{En fait, vous pourriez utilisez le même segment que le
reste de votre code pour placer votre code d'initialisation, mais très
souvent, Vous aurez besoin que la procédure d'initialisation soit
séparée du reste du code}. Par compatibilité avec les outils externes,
tels que les binutils ou le débogueur,et les scripts ld appelez-le
\sys{.init}:
\begin{verbatim}
.section .init, "x" 
.code 32  /* Always ARM mode after reset */
\end{verbatim}
Nous verrons plus tard comment demander à l'éditeur de lien de placer un
segment à un endroit précis de la mémoire. Par compatibilité avec les
outils externes, nous devons exporter le symbole \sys{start},
\sys{\_start} ou \sys{\_\_program\_start} suivant les outils. Le plus simple
est de tout exporter:
\begin{verbatim}
.global __program_start
.global _start
.global start
\end{verbatim}
Sur la plupart des processeurs, les premier octets définissent la table
des interruptions\footnote{Vous pourrez trouvez cette information dans la documentation de votre processeur}. Par exemple, si l'interruption ``IRQ'' est déclenché,
votre processeur sautera à l'adresse \sys{0x18}. A vous de vous débrouiller
pour que l'interruption se déroule bien. Le premier élément du vecteur
est généralement utilisé pour démarrer (et souvent, le premier élément
se trouve à l'adresse \sys{0x0}, ce qui est bien pratique pour initialiser le
processeur). D'une manière générale, les premières lignes de votre code
ressemblerons à:
\begin{verbatim}
.org    0x00
  ldr   pc,[pc,#24]      
.org    0x04
  ldr   pc,[pc,#24]      /* Branch to undef_handler */
.org    0x08
  ldr   pc,[pc,#24]      /* Branch to swi_handler */
.org    0x0c
  ldr   pc,[pc,#24]      /* Branch to prefetch_handler */
.org    0x10
  ldr   pc,[pc,#24]      /* Branch to data_handler */
.org    0x14
  nop
.org    0x18
  ldr   pc,[pc,#24]      /* Branch to irq_handler */
.org    0x1c
  ldr   pc,[pc,#24]      /* Branch to irq_handler */
.org    0x20
.long   cstartup
.org    0x24
.long   undef_handler
.org    0x28
.long   swi_handler
.org    0x2c
.long   prefetch_handler
.org    0x30
.long   data_handler
.org    0x34
.long   undef_handler
.org    0x38
.long   irq_handler
.org    0x3c
.long   fiq_handler
\end{verbatim}
Les directive \sys{.org} permettent de placer le code suivant à une adresse
précise relativement au début du segment. Vous remarquerez que la plupart
de ses directive sont superflues, mais, elles permettent à l'assembleur
de retourner une erreur en cas de mauvaise configuration. Dons notre
exemple, le processeur commence à l'adresse \sys{0x0} et saute directement sur
\sys{cstartup} ou nous pourrons commencer à réellement initialiser le
processeur. En cas d'interruption telle que \sys{undef\_handler}, le processeur
sautera en \sys{0x4} qui l'emmènera dans la fonction \sys{undef\_handler} gérant
réellement l'interruption.

Il ne nous reste maintenant plus qu'à déclarer une étiquette \sys{cstartup:}
et commencer l'initialisation du processeur et des périphériques de base.
Vous devez maintenant vous reporter aux documentation des divers
composant de votre système pour (dans l'ordre pour les cas les plus
courants):
\begin{itemize}
  \item Configurer l'horloge de votre processeur
  \item Configurer la RAM (en particulier, l'horloge, le
    rafraîchissement, etc\dots)
  \item effectuer le rôle de \sys{crt0.s}:
    \begin{itemize}
      \item Initialiser LES piles\footnote{Il est effectivement possible
        que le processeur (en particulier si il possède une MMU\footnote{\emph{Memory
        Management Unit} ou Unité de Gestion de Mémoire pour les puristes}) gère
        une pile contextuelle: pile système, pile superviseur, pile utilisatrice, etc\dots}
      \item initialiser le segment BSS (c'est à dire les données
        initialisées avec 0).
      \item initialiser les données accessible en lecture/écriture
    \end{itemize}
    Pour toutes ces actions, vous aurez besoin de données issues de
    l'éditeur de lien. 
    % Pour les scripts standards de ld, il s'agit de
    % \sys{\_\_DATA\_START\_\_},  \sys{\_\_DATA\_END\_\_} (début et fin des données à
    % recopier), \sys{\_\_INIT\_DATA\_START\_\_} (endroit où recopier les données),
    %  \sys{\_\_STACK\_END\_\_} (fin de la pile\footnote{n'oubliez pas qu'une pile
    % part de la fin et remonte dans la mémoire}), \sys{\_\_bss\_start\_\_},
    % \sys{\_\_bss\_end\_\_} (début et fin des adresses mémoires à initialisé avec
    % 0). 
    Notez que vous ne pouvez pas appeler de fonctions C de manière
    traditionnelle tant que que vous n'avez pas initialisé les piles.
  \item Activer le MMU\footnote{L'initialisation du MMU n'est pas
    triviale. Même si le principe est toujours de créer un table
    associative de blocs de mémoire, les structures changent beaucoup entre
    les processeurs. Très souvent la documentation du processeur donne un
    exemple de code}
  \item Activer les divers cache de mémoire. Généralement, il s'agit du cache de
    données et cache d'instructions. Notez que très souvent, à cause des
    algorithmes de \emph{write-back} utilisés, le cache de données ne peut
    être activé que si le MMU est activé\footnote{remarquez que le cache de
    donnée et le MMU peuvent induire des bugs difficile à trouver si ils
    sont mal configurés. Faites particulièrement attention à l'emplacement
    du vecteurs d'interruptions, aux plage d'adresse d'entrées/sorties et
    aux accès concurent à la mémoire (cas courant: un DMA accédant à la
    mémoire par un processus asynchrone)}
  \item Configurer les différents périphériques: écran LCD, caméra,
    clavier, etc\dots
\end{itemize}

\section{L'éditeur de lien}
Si la cible sur laquelle vous compilez possède un OS et un système de
fichiers, vous n'avez pas à toucher aux options de l'éditeur de lien.
Sinon, vous aurez surement besoin de savoir comment fonctionne une
binaire afin de configurer l'éditeur de lien.

L'éditeur de lien permet de spécifier à quel endroit de la mémoire
chaque segment de programme doit être chargé. Il permet aussi de définir
des emplacements pour la mémoire de travail: la pile, le tas, et éventuellement les
entrées/sorties.

Je vous conseille de reprendre le script ld par défaut puis de le
modifier pour vos besoin. Cela vous permettra d'être le plus compatible
avec les outils extérieurs. 

Quelques règles (assez logiques en fait):
\begin{itemize}
  \item Les segments demandant d'être permanent en mémoire doivent se
    trouver sur les plage en ROM (Flash). Il s'agit au minimum la procédure
    de démarrage de votre processeur (\sys{.init}) et, à moins que vous ayez
    un périphérique de stockage, tout le code (\sys{.tex}, \sys{ctors},
    \sys{dtors}, etc\dots) et les données (\sys{.data}, \sys{.rodata}).
  \item Les segments de mémoire de travail (\sys{.bss}, \sys{.stack},
    \dots) doivent se trouver sur une plage de mémoire RAM
  \item Les segments de debug (\sys{.debug*}) ne doivent pas être chargé
    dans la mémoire de l'architecture cible. Elle sont simplement utilisée
    par le débogueur.
\end{itemize}

La structure des scripts ld est majoritairement composé de directives
\begin{verbatim}
  .nom : { *(.nom) }
\end{verbatim}
ou
\begin{verbatim}
  .nom adresse : { *(.nom) }
\end{verbatim}
ou
\begin{verbatim}
 __symbole__ = .;
\end{verbatim}
Dans le premier cas, on demande à l'éditeur de lien de placer le segment
suite au segment précédant automatiquement.

Dans le second cas, on demande à l'éditeur de lien de placer le segment à une adresse précise.

Enfin, la dernière syntaxe demande de définir un symbole qui aura pour
valeur l'adresse actuelle (symbolisée par ``\sys{.}''). C'est ainsi que
vous pouvez savoir ou l'éditeur de lien a placé votre pile par exemple. 

\section{Utilisation d'une sonde BDI2000}

La sonde BDI2000 de Abatron est une des sondes Jtags les plus populaires.
Elle est compatible avec gdb et avec un peu de configuration, on peut
l'utiliser dans les débogueur basé sur gdb tels qu'Emacs, kdbg,
kdevelop, etc\dots Elle permet donc une grande souplesse d'utilisation.
Néanmoins, sa conception commence à devenir obsolète et sa configuration
peu paraître difficile. 

Il existe bien d'autre sondes. Néanmoins, nous ne les avons pas testées et leur utilisation avec la \emph{toolchain} GNU est souvent difficile (voir impossible).

\subsection{Utilitaire de configuration}

La BDI2000 utilise principalement une interface TCP/IP pour communiquer.
La configuration de la sonde (et principalement de son interface
réseau) se fait par le port série, à la manière d'un routeur. La sonde
est livrée avec un utilitaire qui se compile sans problème. 

Néanmoins, il semblerait que cet utilitaire soit bogué. Nous n'avons pas
réussi à modifier correctement la sonde avec cet utilitaire. La sonde
est aussi vendue avec une version Windows du programme de configuration.
Ce programme fonctionne parfaitement sous wine. Grâce à la version
Windows, nous avons réussi à correctement configurer la sonde. 

Sur les version récent (9.4) de wine, il suffit de créer un lien
symbolique de \sys{/dev/ttyS?} et \sys{~/.wine/dosdevice/com1} puis de lancer
l'utilitaire par \sys{wine ../B20ARMGD.EXE}. La configuration réseau n'a
besoin d'être faite qu'une fois (sauf bien évidement en cas de
changement de réseau)

\subsection{Microcode de la sonde}
La sonde BDI est une sonde Jtags générique. Seul le programme contenu
sur la sonde permet de l'utiliser pour une architecture ou une interface
particulière.

Votre sonde doit donc tout d'abord recevoir un microcode. Typiquement, vous aurez une ligne du genre:
\begin{verbatim}
$ ./bdisetup.d/bdisetup -u -p/dev/ttyS0 -aGDB -tARM
\end{verbatim}
où
\begin{itemize}
  \item La sonde Jtags connectée sur le port
    /dev/ttyS0\footnote{Attention aux droit sur /dev/ttyS0}
  \item \sys{GDB} est le nom de l'interface
  \item \sys{ARM} est le type de processeur\footnote{les anglophones
    diraient que \sys{GDB} est le \emph{frontend} et \sys{ARM} le
    \emph{backend}.}
\end{itemize}

\subsection{Configuration de l'interface réseau}

Typiquement, la ligne suivante permet de configurer l'interface réseau
de la sonde.
\begin{verbatim}
$ ./bdisetup -c -p/dev/ttyS0 -i10.0.0.150 -m255.255.255.0
\end{verbatim}
L'adresse IP est \sys{10.0.0.150} et le masque de sous-réseau \sys{255.255.255.0}.

Remarquez que la sonde permet aussi d'être configurée par Bootp

\subsection{Téléchargement par tftp}
Il faut maintenant donner à la sonde un fichier de configuration. La
sonde est capable de récupérer ce fichier sur un serveur tftp. Je vous
conseille l'utilisation de atftpd comme serveur tftp. Il est inclus dans
la plupart des distributions et sa configuration est très
simple\footnote{triviale}. Cependant, n'oubliez pas que les serveurs
tftp ne font généralement pas de translation de chemin. Si vous indiquez
\sys{/tftpboot} comme racine du serveur et que vous voulez récupérer le
fichier \sys{/tftpboot/boot}, il faudra spécifier \sys{/tftpboot/boot}
(et non \sys{/boot} comme sur la plupart des serveurs http et ftp). Je
vous conseille d'installer atftp (le client lié à atftpd) pour tester
votre installation. Une fois votre serveur tftp en place, on spécifie
l'adresse du serveur tftp et d'un fichier de configuration toujours par
l'intermédiaire du port série:

\begin{verbatim}
$ ./bdisetup -c -p/dev/ttyS0 -h10.0.0.36 -f/tftpboot/config.cfg
\end{verbatim}

\subsection{Structure du fichier de configuration}

Reportez vous à la documentation de la sonde BDI\cite{BDI2000man} pour une référence
complète sur le fichier de configuration. Voici un exemple de
configuration: 
\begin{verbatim}
[INIT]
MMAP 0x00000000 0x000000FF
MMAP 0x00200000 0x00300000
MMAP 0x08000000 0x0C000000
MMAP 0x10000000 0x10800000

[TARGET]
; Cpu type
CPUTYPE   ARM920T
; JTAG clock (0=Adaptive, 1=8MHz, 2=4MHz,...)
CLOCK     1
RESET     HARD
; Memory model (LITTLE | BIG)
ENDIAN    LITTLE
STARTUP   RESET
;catch unhandled exceptions
;VECTOR    CATCH
;the BDI working mode (LOADONLY | AGENT)
BDIMODE   AGENT
;SOFT or HARD
BREAKMODE SOFT
;Workspace in target RAM for fast programming
WORKSPACE 0x08000000 

[HOST]
IP     10.0.0.36
FILE   /home/tftpboot/bin.elf
FORMAT ELF
;Load application MANUAL or AUTO after reset
LOAD   AUTO

[FLASH]
;workspace in target RAM for fast programming
WORKSPACE 0x08000000
;Flash type (AM29F | AM29BX8 | AM29BX16 | I28BX8 |
CHIPTYPE STRATAX16 
;The size of one flash chip in bytes (e.g. AM29F010
CHIPSIZE 0x00800000

;The width of the flash memory bus in bits (8 | 16 | 32)
BUSWIDTH 16 
ERASE  0x10000000 ;erase sector 0 of flash in U12 (AM29F010)
ERASE  0x10004000 ;erase sector 1 of flash
ERASE  0x10008000 ;erase sector 2 of flash
ERASE  0x1000C000 ;erase sector 3 of flash
ERASE  0x10010000 ;erase sector 4 of flash
ERASE  0x10014000 ;erase sector 5 of flash
ERASE  0x10018000 ;erase sector 6 of flash
ERASE  0x1001C000 ;erase sector 7 of flash
ERASE  0x10020000 ;erase sector 4 of flash
\end{verbatim}

Remarque: Le format de la binaire est fortement dépendante de l'éditeur de liens
utilisé. En particulier, si vous souhaiter porter un novaux linux, vous
devrez utiliser \sys{FORMAT BIN}

\section{Gdb}

Vous devrez utiliser une version de gdb compilée pour l'architecture cible. Très souvent, gdb à été avec le reste des outils de la \emph{toolchain}.

\subsection{Connexion par une sonde}
Votre sonde est maintenant connecté au réseau et vous lui avez spécifié
certain paramètres de base sur le type de système que vous souhaitez
déboguer par l'intermédiaire du fichier de configuration. Il vous reste
maintenant à vous connecter à votre sonde par gdb. 

Gdb à besoin de connaître la binaire que vous utilisez afin de connaître
les symboles de débogage et les sources de votre application. Il est
important que cette binaire soit parfaitement synchronisé avec le
contenu de la mémoire de votre système. 

Ensuite, gdb est capable de se connecter à un serveur Gdb par
l'intermédiaire de la commande \sys{target remote hote:port}. Gdb
utilisera ce serveur pour le débogage en lui même.

Pour bien comprendre le fonctionnement de Gdb, il est important de
rappeler que si vous avez correctement configuré votre éditeur de lien
les symboles de débogage ne sont pas chargé sur l'architecture cible.
Seul gdb les lit. Ensuite, gdb est capable de convertir les adresses
brutes de la sonde en nom de fonction/nom de fichier.

\subsection{Connexion par gdbserver}
Dans le cas où vous travailleriez sur un linux embarqué, vous pouvez utiliser la commande \sys{gdbserver} sur votre cible. Naturellement, gdbserver doit être compilé pour l'architecture cible.

Il vous faudra ensuite configurer un peu gdb pour qu'il retrouve les informations de debuggage.

Afin que gdb retrouve les bibliothèque chargée par votre programme. Ce prefixe sera ajouté à chaque demande de chargement d'une bibliotèque :
\begin{verbatim}
set solib-absolut-prefix {emplacement de votre arborescence cible}
\end{verbatim}
Indiquer à gdb où se trouve les information de debug de la binaire :
\begin{verbatim}
file {votre binaire}
\end{verbatim}
Se connecter :
\begin{verbatim}
target remote {hote}:{port}
\end{verbatim}

\subsection{Interfaces pour gdb}
Vous n'avez peut-être pas la patience d'apprendre à utiliser gdb en
ligne de commande. Il existe différentes interfaces:
\begin{itemize}
 \item DDD
 \item kdevelop
 \item Emacs
 \item vim
 \item kdbg
\end{itemize}
Dans tous les cas, il faudrat modifier l'initialisation de gdb de manière à la faire correspondre avec votre environnement.

\section*{Conclusion}
Nous avons passé en revue les difficultés que vous pourrez rencontrer
dans le développement d'un système embarqué mais, il en existe d'autres.
Si vous souhaitez faire des remarques ou des précisions sur le contenu
de ce tutoriel, mailez-moi.


