Debian logo [embedded-µC.LINUX]

5. Un premier programme : «Hello, World!»

Pour illustrer les contextes et le cycle de développement présentés ci-avant, on prend un premier exemple de programme très connu : afficher «Hello, World!» à l'écran.

La «mise au point» de ce programme simpliste sert aussi à prendre en main les outils de la chaîne de développement.

5.1. Codes source

Voici le code source du premier programme hello.c sous sa forme «usuelle».

Exemple 1. Affichage de la chaîne «Hello, World!» sur GNU/Linux avec GCC

#include <stdio.h> 1

int main() { 2

        printf ("Hello, World!\n"); 3
        return 0; 4
}

1

#include <stdio.h> : inclusion des prototypes de sous-programmes de la bibliothèque standard d'entrée-sortie (stdio ou standard input output).

D'une manière générale, pour que l'on puisse utiliser les fonctions d'une bibliothèque, il faut que les prototypes (ou en-têtes) de ces fonctions soient parcourus par le pré-processeur (voir Section 4, « Cycle de développement »). Si cette condition est satisfaite, le pré-processeur «connaît» la liste des paramètres possibles d'une fonction et leurs types. Il peut ensuite contrôler que les appels à ces fonctions sont conformes.

Cet exemple de programme utilise la fonction printf qui appartient à la bibliothèque stdio.

2

int main() { : début du programme principal.

En C, le programme principal peut être assimilé à une «fonction comme les autres» à qui on peut passer des paramètres (entre les parenthèses) depuis le Shell et qui renvoie à ce même Shell une indication sur ses conditions d'exécution (un nombre entier).

L'accolade '{' est le délimiteur de début des instructions du programme principal.

3

printf ("Hello, World!\n"); : appel de la fonction printf de la bibliothèque standard d'entrée-sortie.

Une chaîne de caractères est délimitée par des guillemets et les caractères spécifiques sont précédés par '\'. On parle de caractères d'échappement. Dans cet exemple, '\n' correspond au saut de ligne.

Les instructions sont séparées par le caractère ';'.

4

return 0; : valeur renvoyée au système d'exploitation (via le Shell) en fin de programme.

La valeur 0 correspond à une sortie «sans erreur» du programme.

Cette instruction n'a de sens que lorsque le programme est exécuté via un système d'exploitation avec lequel il est possible d'échanger des informations.

Voici le code source du même premier programme ser_hello.c sous sa forme «embarquée». Le code n'est pas aussi simple que dans le cas précédent. Comme indiqué dans la Section 3.2, « Ordinateur cible sans système d'exploitation » on ne dispose pas de noyau dans ce contexte. Le programme doit donc intégrer le pilotage du périphérique d'affichage. Ici, il s'agit de la liaison série qui est utilisée pour «l'affichage» de la chaîne «Hello, World!».

Avec le synoptique ci-dessus, on développe (voir Section 4, « Cycle de développement ») le programme sur le PC. Une fois que l'on a obtenu le fichier contenant le code exécutable du programme, on le transfère via la liaison série à l'aide du moniteur. Enfin, après avoir réinitialisé le microcontrôleur en mode exécution, le programme utilisateur est lancé.

En mode exécution, le programme utilisateur peut piloter la liaison série de façon complètement autonome si on lui fournit les sous-programmes nécessaires. C'est le cas de l'exemple de code source ci-dessous.

Exemple 2. Affichage de la chaîne «Hello, World!» avec un microcontrôleur MSC1210 & SDCC

#include <stdio.h> 1
#include <msc1210.h>
#include "ser_msc1210.h"

// (sur)définition du sous-programme putchar utilisé par printf
void putchar(char c) { 2
  ser_putc(c);
  }

void main(void) { 3

	// Appuyer sur <Entrée> pour ajuster automatiquement
	// le débit de la liaison 
        autobaud(); 4

        // Initialisations pour SDCC
	EA=1;

	// Affichage sur le terminal
        printf("Hello, World!"); 5
        putcr();

        while(1); 6
}

1

Comme indiqué dans le premier cas, les directives #include servent à inclure des définitions pour le pré-processeur. Dans le cas présent, 3 fichiers de définitions sont utilisés.

  • stdio.h : fichier d'en-tête contenant les prototypes des fonctions d'entrées-sorties standard. Si ce fichier porte le même nom que celui donné dans le premier fichier source, le catalogue des sous-programmes mis à disposition sur un microcontrôleur est nettement réduit relativement au cas général d'une machine avec système d'exploitation.

    Dans le cas présent, ce fichier fournit le prototype de la fonction printf utilisée pour émettre la chaîne de caractères depuis le microcontrôleur sur la liaison série.

  • msc1210.h : fichier d'en-tête contenant les définitions des registres des microcontrôleurs de la famille MSC12xx.

  • ser_msc1210.h : fichier d'en-tête contenant les prototypes des sous-programmes intégrés dans la mémoire ROM du composant microcontrôleur. Dans cet exemple, ce sont les fonctions de pilotage de la liaison série qui sont utiles : autobaud et ser_putc.

    Le fait que ce fichier soit noté «entre guillemets» indique qu'il s'agit d'un fichier local qui n'est pas fourni avec la chaîne de développement. Voir le fichier ser_msc1210.h et la documentation MSC1210 ROM Routines sur ces fonctions intégrées.

2

void putchar(char c); : surdéfinition de la fonction d'affichage d'un caractère.

Cette fonction fait «normalement» partie de la bibliothèque standard et son rôle est d'envoyer un caractère à l'écran. Dans le cas présent, on utilise une nouvelle définition de cette fonction. Son rôle est maintenant d'envoyer le caractère sur la liaison série. La fonction tx_byte fait partie de la bibliothèque intégrée du microcontrôleur. Sa définition est donnée dans le fichier d'en-tête rom1210.h. Voir MSC1210 ROM Routines.

Le mot clé void signifie que la fonction ne renvoie aucun paramètre. Le paramètre d'entrée c est défini comme étant de type caractère (représenté sur un octet) par le mot clé char. Voir Section 7.3, « Types de représentation des données »

3

void main(void) { : début du programme principal.

Par différence avec le premier programme, on constate avec l'emploi des mots clé void qu'aucun paramètre n'est passé en entrée et qu'aucun paramètre n'est renvoyé en sortie. Ce codage est tout à fait normal dans un contexte sans système d'exploitation. Ce programme sera le seul exécuté sur le microcontrôleur. Il n'aura donc pas à échanger avec un autre logiciel.

4

autobaud(); : appel de la fonction de détection automatique du débit sur la liaison série.

Cette fonction est très pratique. Le programme reste en attente d'un appui sur la touche <Entrée> du système de développement (le PC) pour déterminer le débit de transmission en bauds. Sans cette «attente», le programme se lancerait directement après le reset du microcontrôleur ce qui est trop rapide si des manipulation sont à effectuer manuellement sur le système embarqué.

5

printf("Hello World !"); : appel de la fonction printf.

Cet appel de fonction se présente comme dans le cas du premier programme excepté pour le traitement du saut de ligne en fin de chaîne de caractères. Avec la liaison série, on est obligé d'envoyer deux caractères spécifiques : '\r' (retour chariot ou Carriage Return ou CR) pour renvoyer le curseur en début de ligne et '\n' (saut de ligne ou Line Feed ou LF) pour descendre le curseur d'une ligne. Cette opération est réalisée par l'appel à la fonction putcr().

6

while(1); : boucle «d'attente» infinie.

Comme le programme est la seule application en cours d'exécution sur le microcontrôleur, et qu'il n'y a plus d'opération à effectuer, on place le processeur dans un état d'attente infinie grâce à cette instruction de bouclage. C'est une technique usuelle qui permet de s'assurer que le processeur ne cherche pas à interpréter le contenu de la mémoire située après l'application utilisateur comme un programme.

5.2. Compilation & exécution sur Windows XP

Ce contexte est décrit dans la Section 3.1, « Ordinateur cible avec système d'exploitation ».

On distingue deux familles de systèmes d'exploitation : Windows et GNU/Linux.

Pour que le résultat de l'exécution du programme soit «visible», on a ajouté l'instruction system("pause"); qui demande à l'utilisateur d'appuyer sur une touche. Sans cette instruction, le Shell serait refermé dès la fin de l'exécution du programme et le message ne serait pas visible.

5.3. Compilation & exécution sur GNU/Linux

Les outils de la chaîne de développement sont installés par défaut avec le système d'exploitation. On peut donc appeler directement le compilateur gcc (voir Section 13.2, « C/C++ sur GNU/linux ».

phil@b0x:~/src$ cat hello.c
#include <stdio.h>

int main() {

        printf ("Hello, World!\n");
        return 0;
}

phil@b0x:~/src$ gcc hello.c
phil@b0x:~/src$ ./a.out
Hello, World!
phil@b0x:~/src$

Dans ce contexte, on commence par ouvrir un nouveau Shell dans lequel on effectue toutes les opérations individuelles : édition du code source, compilation et exécution.

5.4. Compilation sur Windows & exécution sur cible MSC1210

Ici, les programmes sont développés sur un PC et exécutés sur la machine cible. C'est le contexte décrit dans la Section 3.2, « Ordinateur cible sans système d'exploitation ».

Pour l'exemple de programme retenu, on choisit d'afficher la chaîne de caractères sur le terminal du système de développement (ie. le PC) via une liaison série.

Outils de développement

Pour que la chaîne de développement SDCC soit plus facile à utiliser sur un système d'exploitation Microsoft™, il est vivement conseillé de reconstituer un environnement de travail GNU/Linux-like à l'aide des outils Cygwin.

Une fois les outils Cygwin installés, on dispose d'un shell Bash et surtout de l'application de contrôle du compilateur make qui permet de gérer les dépendances entre les différents fichiers sources et en-têtes.

Après avoir travaillé avec ces outils pendant «un certain temps», il ne restera plus qu'une dernière étape à franchir : abandonner le système MicrosoftGNU/Linux-like au profit d'un véritable système GNU/Linux.

Compilation avec Windows XP

On appelle le compilateur SDCC à partir d'une console.

Le fichier ser_hello.ihx contient le code exécutable du programme au format Intel Hex. Il s'agit d'un format texte ASCII de représentation du code machine du microcontrôleur utilisé pour le transfert du système de développement vers le système cible.

Le fichier ser_hello.asm contient le code source du programme en langage assembleur. Une lecture rapide de ce fichier montre que les fonctions d'optimisation du compilateur ont été efficaces.

Utilisation d'un Makefile

Pour faciliter les développements de programmes «plus complets» que cet exemple, un patron de Makefile est fourni avec les fichiers sources distribués avec ce document : Makefile.

Pour démarrer un nouveau développement, il suffit de copier ce patron dans un nouveau répertoire et d'affecter à la variable BASENAME le nom du nouveau fichier source en langage C.

Ce patron de Makefile suppose que l'on utilise systématiquement la liaison série comme interface utilisateur. Il fait donc référence au fichiers sources et en-têtes qui permettent d'utiliser cette liaison série. Ces fichiers sont aussi présentés dans ce document à la Section 14.2, « Sources MSC1210 ».

Transfert du programme avec Windows XP

Texas Instruments™ fournit un logiciel appelé TIDownloader qui pilote la liaison série entre le PC et le système embarqué. Ce logiciel sert à la fois au transfert du code du programme et aux tests d'exécution avec son terminal. Il est téléchargeable à l'adresse : Software for Programming the Flash Memory Using the Serial Port v1.3.4 (Rev. C) (sbac018c.zip, 2381 KB ).

Il faut positionner l'interrupteur «vers le haut» pour accéder au moniteur intégré du microcontrôleur. Après un appui sur le bouton Reset, les opérations de transfert peuvent débuter.

Exécution du programme depuis Windows XP

Une fois le transfert achevé, on positionne l'interrupteur «vers le bas» et on appuie sur le bouton Reset pour lancer le programme.

5.5. Compilation sur GNU/Linux & exécution sur cible MSC1210

Ce contexte est identique au précédent. Les programmes sont développés sur une machine avec un système GNU/Linux et exécutés sur le microcontrôleur du système cible. Ces conditions sont décrites dans la Section 3.2, « Ordinateur cible sans système d'exploitation ».

Relativement à la section précédente, il est inutile d'installer des outils supplémentaires pour mettre en oeuvre la chaîne de développement SDCC puisque les applications telles que le shell bash et make sont systématiquement fournies avec les distributions GNU/Linux.

Pour l'exemple de programme retenu, on choisit d'afficher la chaîne de caractères sur le terminal du système de développement (ie. le PC) via une liaison série.

Compilation avec GNU/Linux

L'appel du compilateur est identique entre les deux systèmes. Les formats de fichiers sont aussi identiques. Le code exécutable du programme est contenu dans le fichier ser_hello.ihx.

$ sdcc ser_hello.c

$ ll
total 144K
-rw-r--r-- 1 phil phil 8.4K Apr 19 22:19 ser_hello.asm
-rw-r--r-- 1 phil phil  466 Apr 18 21:38 ser_hello.c
-rw-r--r-- 1 phil phil  12K Apr 19 22:19 ser_hello.ihx
-rw-r--r-- 1 phil phil  193 Apr 19 22:19 ser_hello.lnk
-rw-r--r-- 1 phil phil  22K Apr 19 22:19 ser_hello.lst
-rw-r--r-- 1 phil phil  14K Apr 19 22:19 ser_hello.map
-rw-r--r-- 1 phil phil 1.1K Apr 19 22:19 ser_hello.mem
-rw-r--r-- 1 phil phil 3.7K Apr 19 22:19 ser_hello.rel
-rw-r--r-- 1 phil phil  22K Apr 19 22:19 ser_hello.rst
-rw-r--r-- 1 phil phil  37K Apr 19 22:19 ser_hello.sym
Utilisation d'un Makefile

Pour faciliter les développements de programmes «plus complets» que cet exemple, un patron de Makefile est fourni avec les fichiers sources distribués avec ce document : Makefile.

Pour démarrer un nouveau développement, il suffit de copier ce patron dans un nouveau répertoire et d'affecter à la variable BASENAME le nom du nouveau fichier source en langage C.

Ce patron de Makefile suppose que l'on utilise systématiquement la liaison série comme interface utilisateur. Il fait donc référence au fichiers sources et en-têtes qui permettent d'utiliser cette liaison série. Ces fichiers sont aussi présentés dans ce document à la Section 14.2, « Sources MSC1210 ».

Transfert du programme avec GNU/Linux

Pour effectuer le transfert de fichier en mode ASCII entre le PC de développement et le microcontrôleur, on utilise une application appelée minicom sur les systèmes GNU/Linux.

À partir d'un Shell, on appelle minicom avec les options :

  • -o pour désactiver le dialogue Hayes entre les équipements connectés sur la liaison série.

  • -8 pour pouvoir utiliser les codes ASCII sur 8 bits.

$ minicom -o -m -8

Le paramétrage de la liaison se fait avec les options suivantes :

A - Serial Device         : /dev/ttyS0
B - Lockfile Location     : /var/lock
C - Callin Program        :
D - Callout Program       :
E - Bps/Par/Bits          : 19200 8N1
F - Hardware Flow Control : No
G - Software Flow Control : No

Il est important de désactiver le contrôle matériel de flux pour que la fonction de détection automatique du débit puisse s'exécuter normalement.

Il faut positionner l'interrupteur «vers le haut» pour accéder au moniteur intégré du microcontrôleur. Après un appui sur le bouton Reset, on doit obtenir l'invite de commande suivante :

MSC1210 Ver:000305F10
>

Il faut effacer le contenu de la mémoire du microcontrôleur avant de procéder au transfert. La séquence à saisir est la suivante :

>M0000 ok
>M8000 ok
>E
>L

On peut ensuite lancer le transfert de fichier en mode ASCII après avoir sélectionné le fichier ser_hello.ihx :

+---------[ascii upload - Press CTRL-C to quit]---------+
|.......................................................|
|7.8 Kbytes transferred at 1991 CPS.....................|
|.......................................................|
|.......................................................|
|11.5 Kbytes transferred at 1962 CPS... Done.           |
|                                                       |
| READY: press any key to continue...   
Exécution du programme depuis GNU/Linux

Une fois le transfert achevé, on positionne l'interrupteur «vers le bas» et on appuie sur le bouton Reset pour lancer le programme.

On obtient alors un affichage de la chaîne de caractères «tant attendue» sur le terminal du PC de développement.

MSC1210 Ver:000305F10
>M0000 ok
>M8000 ok
>E
>T
>
>Hello World !