P. 1
Cours - Programmation C pour systèmes embarqués.pdf

Cours - Programmation C pour systèmes embarqués.pdf

|Views: 25|Likes:
Publié parHichem Taghouti

More info:

Published by: Hichem Taghouti on Sep 17, 2013
Droits d'auteur :Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

03/17/2014

pdf

text

original

Programmation C pour systèmes embarqués

Sylvain MONTAGNY sylvain.montagny@univ-savoie.fr Bâtiment chablais, bureau 13 04 79 75 86 86
Retrouver tous les documents de Cours/TD/TP sur le site www.master-electronique.com

Présentation des cours : Sommaire
z

Cours : 10.5 h en 7 séances
z z z

1ère partie : Rappel sur le langage C (exercices de base) 2ème partie : La programmation en langage C avancée 3ème partie : Implémentation de code sur cible embarquée (DSP TMS 320C5416) 4ème partie : Présentation du TP : Réalisation d’un algorithme de compression de données.

z

Université de Savoie

2

Présentation TP
z TD

: 20 h en 5 séances

Le but de ce projet est d'écrire un programme de compression de fichiers textes, sans perte d'information. On demande également d'écrire un décompresseur qui devra restaurer le fichier original. L’algorithme proposé ici est l'algorithme de Huffman.

Université de Savoie

3

Examen

z

Une note :
z

z

14 points : Le déroulement du TP/Projet jusqu’à la soutenance. 6 points sur la soutenance (présentation de votre projet et de l’intégration sur le DSP)

Université de Savoie

4

1ère partie : Rappel sur le langage C (exercices de base)
z

Donner l’exécution du code suivant :
#include <stdio.h> #include <stdlib.h> int main(void){ unsigned char i; unsigned char tab[5]={1,2,4,8,16}; for (i=0;i<5;i++) { printf("Le %d° elt est %d\n",i+1,tab[i]); } return EXIT_SUCCESS; }

Université de Savoie

5

for(i=0.i++){ for(j=5-i. } return EXIT_SUCCESS.1ère partie : Rappel sur le langage C (exercices de base) z Donner l’exécution du code suivant : #include <stdio.i<5. } Université de Savoie 6 .j<5.j++){ printf("++").j.h> int main() { int i. } printf("\n").

Le prototype de la fonction est le suivant : int longueur(char *s) Université de Savoie 7 .1ère partie : Rappel sur le langage C (exercices de base) z Écrire une fonction C calculant la longueur d'une chaîne de caractères. donnée en argument.

} Université de Savoie 8 . while (s[n] != '\0') { n++. #include <stdlib.h> int longueur(char *s) { int n = 0. } return n. donnée en argument.1ère partie : Rappel sur le langage C (exercices de base) z Écrire une fonction C calculant la longueur d'une chaîne de caractères.

pour compter les occurrences de chaque lettre de l’alphabet dont la taille est fixée par une constante (correspondant au nombre de lettre de l’alphabet).1ère partie : Rappel sur le langage C (exercices de base) Soit un texte donné par une chaîne de caractères. Un tableau d'entiers statique nommé « occ ». Université de Savoie 9 . Le but est de compter le nombre d'occurrences de chaque lettre minuscule. Vous afficherez la chaîne de caractère à l’écran. Question 1 : Réaliser les déclarations suivantes : z z z z Le texte (chaîne de caractère constante) sera déclaré dans un tableau nommé « ch ». Un pointeur nommé « p » pour parcourir le texte.

1ère partie : Rappel sur le langage C (exercices de base) Université de Savoie 10 .

ch). } Université de Savoie 11 .h> #define NB_LETTRE 26. */ char ch[]="ceci est une chaîne de test".1ère partie : Rappel sur le langage C (exercices de base) #include <stdio. void main(void) { /* déclaration d'une chaîne <=> tableau de caractères. */ char *p = ch. /* déclaration d'un tableau de 26 cases */ int occ[NB_LETTRE]. /* déclaration d'un pointeur sur une chaîne de caracteres. printf("Chaîne en mémoire : %s\n".

1ère partie : Rappel sur le langage C (exercices de base) z Question 2 : Initialiser le tableau d’occurrence à zéro : Université de Savoie 12 .

i<NB_LETTRE. for (i=0. Université de Savoie 13 .1ère partie : Rappel sur le langage C (exercices de base) z Question 2 : Initialiser le tableau d’occurrence à zéro : /* initialisation du tableau des occurrences à 0. */ int i=0.i++) occ[i]=0.

1ère partie : Rappel sur le langage C (exercices de base) z Question 3 : Compter les occurrences jusqu’à la fin de la chaîne de caractère : Université de Savoie 14 .

1ère partie : Rappel sur le langage C (exercices de base) z Question 3 : Compter les occurrences jusqu’à la fin de la chaîne de caractère : /* parcours de la chaîne jusqu’au ‘\0’ */ while (*p != '\0') { if ( (*p >= 'a‘) && (*p <= 'z‘) ) { occ[*p-'a'] = occ[*p-'a'] + 1. } p++. } Université de Savoie 15 .

1ère partie : Rappel sur le langage C (exercices de base) z Question 4 : Afficher le contenu du tableau occ Université de Savoie 16 .

i++) { printf("Nombre de %c : %d\n". i<nb_lettres. } Université de Savoie 17 .1ère partie : Rappel sur le langage C (exercices de base) z Question 4 : Afficher le contenu du tableau occ for (i=0.occ[i]). 'a'+i.

les erreurs classiques du C… 18 . les structures. type de fonction. les options d’optimisations à la compilation. les typedef. porté des variables. manipulation de registre. la pile.2ème partie : La programmation en langage C avancée z z z z z z z z z z z z z z z z Lisibilité du code. les pointeurs. les opérateurs. les types de variables. le main(). pointeurs. allocation dynamique. occupation mémoire.

Université de Savoie 19 .Lisibilité du code C z Exercice : Réaliser un code qui imprime les N premiers éléments d'un tableau d’entier A[] en insérant un espace entre les éléments et en commençant une nouvelle ligne après chaque dixième chiffre.

else printf(" ").i. i=i+1){ printf("%d". for (i=0.Lisibilité du code C void main(void){ int A[80].&N). i<N. scanf(’’%d’’.N. A[i]). if ((i%10) == 9) printf("\n"). } } Université de Savoie 20 .

i++) printf("%d%c". (i%10==9)?'\n':' '). } Université de Savoie 21 . void main(void){ int A[80]. très pratique mais beaucoup moins lisible. for (i=0. scanf(’’%d’’.N. i<n.&N).i. a[i].Lisibilité du code C z Voici une deuxième façon de coder.

Fonction += Addition et affectation -= Soustraction et affectation *= Multiplication et affection /= Division et affectation %= Modulo et affectation ++ Incrémentation équivalences… parfois à éviter Exemple Equivalence nombre=nombre+5 nombre += 5. nombre /= 2. nombre -= 6. nombre = nombre % 4 nombre = nombre + 1. nombre = nombre . nombre *= 3. nombre %= 4.Lisibilité du code C z Quelques Op. nombre++.1.Décrémentation nombre--. y x x y = = = = x x + 1 x + 1 x 22 -. y = x++ y = ++x Université de Savoie .

_.r'}{nlwb!/*de}'c . a )&&t == 2 ?_ <13 ?main ( 2.main(-61.#'/*{}w+/w#cdnr/+.a)char*a.dc i@bK'(q)-[w]*%n+r3#l.vpbks./+k#.Lisibilité du code C #include <stdio.d}rw' i. 27+t. 2 .m ."@n'+.a+1)+a)):1.0. :{nl]'/*{q#'ld.}{w+K w'K:'+}e#'._.{}r/*de}+. a ):3.1_.{}:\nuwloca-O.{return!0<t?t<3?main(-79./w{%+.#q#n'){)#}w'){){nl]'/ +#n'./n{n+. r{#w'r nc{nl]'/#{l.h> main(t./w#q#n+ ./*{*+.#q#n+./#{l.dq#'l q#'+d'K#!/+k#.}##'*}#nc.-13.*a. a + 1 ):0<t?main ( 2. t. _+1./'r :'d*'3.main( -94.fxntdCeghiry")..t<_?main( t+1.# ){nl]!/n{n#'.main(-86. "%s %d %d\n" ):9:16:t<0?t<-72?main( _.#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"):t<-50?_==*a ?putchar(31[a]):main(-65.a+main(-87.q#'r}eKK#}w'r}eKK{nl]'/#.*+./+#n+.#nw]'/+kd'+e}+.+.{nl'{}rw]'/+.'._.+'K {rw' iK{.[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i.a+1):main((*a == '/') + t. _./#.} Université de Savoie 23 . "!ek.a+1). "%s"):*a=='/'||main(0.

Lisibilité du code C z Règle z z z à respecter : z Mettre des commentaires explicites Ne pas trop compresser le code Respecter une homogénéité dans votre façon de coder. ou respecter celle déjà existante. Organiser la mise en page de votre code. Université de Savoie 24 .

double. long. z Afin de connaître la taille (en octet) d’une variable. float dépendent de la cible processeur utilisée.Les types de variables char = 1 octet (signed ou unsigned) z Int. on utilise la fonction sizeof() : z printf(’’ int=%d octets ’’. sizeof(int)). Note : Il n’existe pas de type Booléen en C Université de Savoie 25 .

Les types de variables z Cas d’une compilation pour processeur 32 bits z z Voir le cas d’un compilateur C pour PIC16F ou PIC18F (microchip) Voir le cas d’un compilateur C pour DSP TMS320 (Texas Instruments) (page suivante) Université de Savoie 26 .

Les types de variables Université de Savoie 27 .

Note : %d -> entier signed / %u -> entier unsigned Université de Savoie 28 . char c=128. c+a). a). c). unsigned char b=64. Note : Une déclaration est signed par défaut. ». a).Les types de variables z Donner la représentation binaire des nombres suivants : z z z z char a=64. z Quel est l’affichage des fonctions suivantes? z z z z printf(’’%d printf(’’%d printf(’’%u printf(’’%u ». ». unsigned char d=128. ».

Les types de variables z Conversion explicite : La conversion de type consiste à transformer un type de valeur en un autre. le compilateur prévoit une conversion implicite suivant l'ordre : { char -> int -> long -> float -> double } et { signed -> unsigned } Université de Savoie 29 . en respectant la syntaxe suivante (<type>) <expression> z Conversion implicite : Lorsque les deux opérandes sont de type différent.

Les types de variables Décrivez le conversion du type. d = 2.0 – m + 0xA2CL. return 0. ainsi que les affectations du code suivant : int main(void) { int n. } Université de Savoie 30 . d = n / m.4. double d. l = (int) (m / d). n = (int) 3. m = 5. d = 5. n = 1. d = 'A' * 6. m. l. d = n / ((double) m).

f(). j).Portée des variables z static : permet à une variable locale d’être persistante et donc de conserver sa valeur pendant les appels successifs de la fonction. i. j++.\n". f(). /* i ne sera initialisé qu’une fois*/ int j = 0. return 0. /* j sera initialisé à chaque fois */. printf("i vaut %d et j vaut %d. #include <stdio. } Université de Savoie 31 .h> void f(void) { static int i = 0. } int main(void) { f(). i++.

Une variable globale est déjà persistante. L’objectif de la nommer en « static » est simplement de la « privatiser » au fichier où elle est déclarée. C’est-à-dire qu’elle ne pourra pas être utilisée depuis un autre fichier. Université de Savoie 32 .Portée des variables z static : Cas des variables globales.

une nouvelle variable est créer avec une nouvelle allocation mémoire. printf("a1=%d\n". } // a1=2 33 . void next1(void). /* definition of external (non static)*/ void main(void){ a1=2. next1().a1).a1).c */ #include <stdio. /* File : ext. Si on omet ce terme.h> void next(void). printf("a1=%d\n.Portée des variables z extern : permet de spécifier que la variable a été déclarer dans un autre fichier. int a1=1. next().

void next(void) { char a1. b1=77.c */ int b1=0. void next1(void) { float b1.2. } 34 . a1='a'. a1=13. b1=19.Portée des variables /* File file1.c */ extern int a1. } /* File file2.

Une variable peut avoir plusieurs qualificateurs Université de Savoie 35 .Qualificateur de variables z Le C définit des qualificateurs pouvant influer sur une variable : z z const : pour définir une variable dont la valeur ne devrait jamais changer . volatile : désigne une variable pouvant être modifiée notamment par une source externe indépendante du programme.

i = 1. Université de Savoie 36 . sans quoi toute tentative de modification ultérieure entraînera une erreur de la part du compilateur : Étudier les codes suivants : const int i = 0.Qualificateur de variables Qualificateur 'const' La classe const indique au compilateur que la valeur de la variable ne doit pas changer. Il est donc impératif d'assigner une valeur à la déclaration de la variable.

pointeur[0] = 0. pointeur = "Hello world !". pointeur = "Hello world !". Université de Savoie 37 .Qualificateur de variables void fonction( const char * pointeur ) { pointeur[0] = 0. pointeur = "Nouvelle chaîne de caractères". const char * const pointeur = "Salut tout le monde !". } char * const pointeur = "Salut tout le monde !".

mais dont la valeur peut changer quand même. Par exemple : extern const volatile int horloge_temps_reel. qu'on ne peut modifier à partir du programme. Cela annule toute optimisation que le compilateur pourrait faire. >>déclare une variable entière.Qualificateur de variables Qualificateur 'volatile' Ce mot-clé sert à spécifier au compilateur que la variable peut être modifiée à son insu. Université de Savoie 38 . Elle pourrait désigner une valeur incrémentée régulièrement par une horloge interne. et l'oblige à procéder à chaque lecture ou écriture dans une telle variable tel que le programmeur l'a écrit dans le code. z On peut combiner const et volatile dans certaines situations.

. n'importe quelle valeur différente de zéro est considérée vraie. a = une_fonction(). réels. if (a = b) { /* Le code qui suit sera toujours exécuté . etc.. */ } z On préférera : int a.Évaluation des expressions booléennes (1) z Le C ne possède pas de type booléen dédié. zéro étant considéré comme faux. b = 2.. if (a != 0) { /* .). if (a) { /* . a = une_fonction(). */ } z Attention : int a = 0.. comme : int a. Dans ce langage. */ } Université de Savoie 39 . tableaux. pointeurs. Ce qui veut dire que n'importe quelle expression peut être utilisée à l'intérieur des tests (entier... Cela peut conduire à des expressions pas toujours très claires.

De la même manière si l'opérande gauche d'un OU logique (||) est évalué à vrai. z Dans le cas du ET logique (&&). } Université de Savoie 40 . si l'opérande gauche s'évalue à faux (valeur zéro). similaires sémantiquement à leur équivalent binaire & et |) ont une exécution totalement différente.Évaluation des expressions booléennes (2) Les opérateurs logiques de comparaisons (&& et ||. on sait déjà que le résultat du ET sera faux et donc ce n'est pas la peine d'évaluer l'opérande droite. z if (z != 0 && a / z < 10) { printf("Tout va bien\n"). le résultat sera aussi vrai (valeur !=0) et donc l'évaluation de l'opérande droite est inutile.

Mettre à 1 le bit 4 de a : unsigned a = 0x000F. on retrouve des registres de 8.Les manipulations de bits (1) z z Les manipulations de bits sont beaucoup utilisées dans l’embarqué. 16 ou 32 bits qu’il faut modifier. /* 0000 0000 0000 1111 */ Université de Savoie 41 . /* 0000 0000 0000 1111 */ z Mettre à zéro le bit 3 de a : unsigned a = 0x000F. Pour contrôler un périphérique matériel.

Mettre à 1 le bit 4 de a : unsigned a = 0x000F. /* 1111 1111 1111 0111 */ unsigned c = a & b. /* 0000 0000 0000 1111 */ unsigned b = 0x0010. /* 0000 0000 0000 1111 */ unsigned b = 0xFFF7. on retrouve des registres de 8. 16 ou 32 bits qu’il faut modifier. /* 0000 0000 0000 0111 soit 0x0007 */ Université de Savoie 42 . Pour contrôler un périphérique matériel. /* 0000 0000 0001 0000 */ unsigned c = a | b.Les manipulations de bits (1) z z Les manipulations de bits sont beaucoup utilisées dans l’embarqué. /* 0000 0000 0001 1111 soit 0x001F */ z Mettre à zéro le bit 3 de a : unsigned a = 0x000F.

/* 0000 0000 0000 1111 */ 43 . /* 0000 0000 0000 1111 */ z Tester si le bit 3 de a est à 1 et si le bit 15 est à 0 : unsigned a = 0x000F.Les manipulations de bits (2) z Tester si le bit 2 de a est à 1 : unsigned a = 0x000F.

} 44 .Les manipulations de bits (2) z Tester si le bit 2 de a est à 1 : unsigned a = 0x000F. /* 0000 0000 0000 1111 */ if (a & (1u << 2)) { printf("bit 2 = 1"). } else { printf("bit 2 = 1 et bit 15=0 n’est pas vérifié"). /* 0000 0000 0000 1111 */ if ( (a & (1u << 3)) && (a&(1u<<15))==0 ) { printf("bit 2 = 1 et bit 15=0"). } z Tester si le bit 3 de a est à 1 et si le bit 15 est à 0 : unsigned a = 0x000F. } else { printf("bit 2 = 0").

Université de Savoie 45 . le point d’entrée du programme sera précisé dans la phase d’édition de liens par l’initialisation du vecteur d’interruption nommé RESET. Dans un système embarquée sans système d’exploitation.Le main() z Le main() est le point d’entrée d’une application.

A quoi sert un pointeur ? Université de Savoie 46 .

jnt i.i++){ for(j=0.Les tableaux (1) z Un tableau est un regroupement consécutif de donnée de même type et de taille fixe. int i. } } } // Tableau à 1 dimension void main(void){ int tableau[4].j. // Tableau à 2 dimensions void main(void){ int tableau[4][3].i++){ tableau[i]=0. for(i=0i<4. for(i=0i<4. } } Université de Savoie 47 .j++){ tableau[i][j]=0.j<3.

Les tableaux (2) tableau[0] tableau[1] tableau[2] tableau[3] tableau[0][0] tableau[0][1] tableau[0][2] tableau[1][0] tableau[1][1] tableau[1][2] tableau[2][0] tableau[2][1] tableau[2][2] tableau[3][0] tableau[3][1] tableau[3][2] Université de Savoie 48 .

Université de Savoie 49 .Les tableaux (3) z Passage de paramètre des tableaux à des fonctions : z Un tableau n’est jamais passé en paramètre. c’est son adresse qui est fournie.

Organisation logicielle 0xFFFFFFFF stack SP (Stack Pointer) address space heap (dynamically allocated) data segment Data : (static and global) code segment (=program) PC (Program Counter) 0x00000000 Université de Savoie 50 .

Organisation logicielle z z Code segment : Emplacement ou se trouve le code compilé. Elle contient les adresses de retour des fonctions et les variables locales. z Stack : C’est une zone de stockage de type LIFO. C’est une zone de donnée qui grossi à la réservation de zone mémoire (malloc) et qui se réduit lors de la libération (free). Data segment : z z Data : contient toutes les variables « static » et « globales » (initialisées ou non) Heap : Le tas est géré dynamiquement. Cette zone mémoire est beaucoup plus rapide que l’utilisation du Heap. Université de Savoie 51 .

il est important de connaître les options de compilation d’optimisation.Optimisation du code z Dans le contexte de l’embarqué. Université de Savoie 52 . Il y a en effet un compromis à trouver entre la taille de l’exécutable produit et le temps d’exécution.

and: Removes unused assignments Eliminates local common expressions z Option -O2 (niveau 2) (default optimization level) z z Performs all -O1 optimizations. and: Performs loop optimizations Université de Savoie 53 .Optimisation du code z Option -O0 (niveau 0) z z z z Allocates variables to registers Performs loop rotation Eliminates unused code Simplifies expressions and statements z Option -O1 (niveau 1) z z z Performs all -O0 optimizations.

You're Reading a Free Preview

Télécharger
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->