18
Cours 11, Partage du temps de microprocesseur et RTOS Q11.1 Qu'est-ce qu’un système d’exploitation? Un programme permettant à l’usager et au programmeur de gérer efficacement les ressources du système microprocesseur. Q11.2 Quelle est la différence entre un système d’exploitation préemptif et un système d’exploitation non-préemptif? Le système d’exploitation préemptif interrompt la tâche en cours, puis il décide quelle tâche sera exécutée entre l’interruption présente et la prochaine interruption du système d’exploitation. Un système d’exploitation non-préemptif charge un programme en mémoire. Puis, il l’exécute au complet avant de s’attaquer à la tâche suivante. Q11.3 Comparez ensemble une super-boucle, un système d’exploitation non-préemptif et un système d’exploitation préemptif. Quels sont les avantages et les désavantages de chacune de ces approches pour attribuer le temps de CPU aux tâches? La super-boucle est simple, les tâches sont exécutées en série (la séquence d’exécution des tâches est connue) et tout le temps de microprocesseur est alloué aux tâches. Cependant, il n’y a pas de contrôle ou supervision des tâches : si une tâche prend trop de temps de microp rocesseur ou gèle, les autres tâches sont pénalisées. Il est aussi plus difficile d’insérer des nouvelles tâches dans une super-boucle, même s’il est tout-à-fait possible de le faire. Le système d’exploitation non-préemptif a essentiellement les mêmes avantages et désavantages que la super-boucle. Cependant, il permet d’exécuter de nouvelles tâches (qui n’étaient pas dans le programme au moment de la compilation) et offre des ressources aux nouvelles tâches. Le système d’exploitation préemptif est possiblement le plus efficace par rapport aux performances du système : les pertes de temps de microprocesseur causés par les délais ou les attentes après les périphériques sont minimes. En contrepartie, le système est plus complexe, les tâches sont exécutées selon une séquence qui varie (cela peut créer des erreurs d’exécution) et le système d’exploitation utilise toujours un peu de temps de microprocesseur pour gérer les tâches. Enfin, le système d’exploitation préemptif requiert plus de RAM pour sauvegarder l’information reliées à l’exécution de chaque tâche et pour le pile de chaque tâche. Q11.4 Dans un système microprocesseur, quelles sont les responsabilités du système d’exploitation? - Gérer le temps de microprocesseur - Gérer les accès aux périphériques et fournir des routines pour y accéder - Gérer la mémoire pour les processus - Gérer les exceptions et les programmes en faute - Gérer les communications réseaux - Fournir une interface usager Q11.5 Un RTOS n’a pas les mêmes critères de performance qu’un système d’exploitation qui n’est pas temps réel. Cela a plusieurs impacts sur le design du système d’exploitation. Quelle est la principale différence entre un RTOS et un OS lorsque le système d’exploitation détermine la prochaine tâche à exécuter? Lorsque le système d’exploitation alloue de la mémoire?

Cours 11, Partage du temps de microprocesseur et RTOS

  • Upload
    others

  • View
    1

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 11, Partage du temps de microprocesseur et RTOS

Q11.1 Qu'est-ce qu’un système d’exploitation?

Un programme permettant à l’usager et au programmeur de gérer efficacement les ressources

du système microprocesseur.

Q11.2 Quelle est la différence entre un système d’exploitation préemptif et un système

d’exploitation non-préemptif?

Le système d’exploitation préemptif interrompt la tâche en cours, puis il décide quelle tâche

sera exécutée entre l’interruption présente et la prochaine interruption du système

d’exploitation. Un système d’exploitation non-préemptif charge un programme en mémoire.

Puis, il l’exécute au complet avant de s’attaquer à la tâche suivante.

Q11.3 Comparez ensemble une super-boucle, un système d’exploitation non-préemptif et

un système d’exploitation préemptif. Quels sont les avantages et les désavantages de

chacune de ces approches pour attribuer le temps de CPU aux tâches?

La super-boucle est simple, les tâches sont exécutées en série (la séquence d’exécution des

tâches est connue) et tout le temps de microprocesseur est alloué aux tâches. Cependant, il n’y

a pas de contrôle ou supervision des tâches : si une tâche prend trop de temps de microp

rocesseur ou gèle, les autres tâches sont pénalisées. Il est aussi plus difficile d’insérer des

nouvelles tâches dans une super-boucle, même s’il est tout-à-fait possible de le faire.

Le système d’exploitation non-préemptif a essentiellement les mêmes avantages et

désavantages que la super-boucle. Cependant, il permet d’exécuter de nouvelles tâches (qui

n’étaient pas dans le programme au moment de la compilation) et offre des ressources aux

nouvelles tâches.

Le système d’exploitation préemptif est possiblement le plus efficace par rapport aux

performances du système : les pertes de temps de microprocesseur causés par les délais ou les

attentes après les périphériques sont minimes. En contrepartie, le système est plus complexe,

les tâches sont exécutées selon une séquence qui varie (cela peut créer des erreurs

d’exécution) et le système d’exploitation utilise toujours un peu de temps de microprocesseur

pour gérer les tâches. Enfin, le système d’exploitation préemptif requiert plus de RAM pour

sauvegarder l’information reliées à l’exécution de chaque tâche et pour le pile de chaque

tâche.

Q11.4 Dans un système microprocesseur, quelles sont les responsabilités du système

d’exploitation?

- Gérer le temps de microprocesseur

- Gérer les accès aux périphériques et fournir des routines pour y accéder

- Gérer la mémoire pour les processus

- Gérer les exceptions et les programmes en faute

- Gérer les communications réseaux

- Fournir une interface usager

Q11.5 Un RTOS n’a pas les mêmes critères de performance qu’un système d’exploitation

qui n’est pas temps réel. Cela a plusieurs impacts sur le design du système d’exploitation.

Quelle est la principale différence entre un RTOS et un OS lorsque le système

d’exploitation détermine la prochaine tâche à exécuter? Lorsque le système d’exploitation

alloue de la mémoire?

Page 2: Cours 11, Partage du temps de microprocesseur et RTOS

L’algorithme d’ordonnancement/planification des tâches doit tenir compte des contraintes

temps-réel pour un RTOS. Les tâches exécutées en premier seront les tâches temps-réel, c’est-

à-dire celles que l’on doit exécuter à l’intérieur d’un temps limité afin d’éviter un échec du

système.

L’algorithme d’allocation de mémoire dans un RTOS doit être plus rapide et plus simple que

celui d’un OS afin d’éviter de retarder l’exécution des tâches temps-réel. Le OS aura un

algorithme plus lent qui fera un meilleur usage de la mémoire.

Q11.6 Que fait-on dans une application utilisant une super-boucle pour réduire la

consommation de puissance du microprocesseur?

Il arrive régulièrement que la super-boucle, c’est-à-dire le programme principal, ne soit

exécutée qu’à tous les intervalles de temps prédéfinis lorsque le système est inactif. On met

une function sleep exécute à chaque boucle de main qui réduit ou coupe l’horloge du

processeur.

Q11.7 Comment fait un système d’exploitation préemptif pour s’assurer de ne pas allouer

de temps à une tâche qui attend ou à une tâche bloquée, c’est-à-dire en attente d’une

réponse d’un périphérique?

Le système d’exploitation garde en mémoire l’état de chaque tâche. Quand une tâche appelle

une fonction du système d’exploitation pour attendre ou pour accéder à un périphérique, l’état

de la tâche change. Ainsi, le système d’exploitation sait qu’il ne doit pas exécuter la tâche tant

que le délai n’est pas expiré ou que le périphérique n’a pas répondu.

Q11.8 Lorsqu’un processus ou une tâche accède à un périphérique lent, l’état de la tâche

devrait devenir bloqué. Comment le programmeur doit-il indiquer au système d’exploitation

que la tâche qu’il a programmée est maintenant en attente d’un périphérique?

Dans la mesure du possible, le programmeur n’a pas à indiquer au système d’exploitation que

sa tâche est bloquée : le programmeur appelle une fonction du système d’exploitation pour

accéder au périphérique et cette fonction met la tâche dans l’état bloqué.

Q11.9 Lorsqu’une tâche appelle une fonction du système d’exploitation pour attendre

(exemple : void OS_Wait(int Xms)), le système d’exploitation met la tâche dans l’état “en

attente”. Habituellement, quel évènement permet de sortir de cet état?

Le système d’exploitation gère le temps dans l’interruption du système d’exploitation. À

toutes les interruptions du système d.exploitation, il regarde si une tâche a fini d’attendre et

ajuste l’état de la tâche en conséquence.

Q11.10 Qu'est-ce qu'une section critique dans un programme?

Une section critique est une portion de code qui doit s’exécuter de façon atomique parce

qu’elle accède à une section de mémoire ou à un périphérique partagée entre plusieurs

threads. Il ne doit absolument pas y avoir plus d'un thread simultanément. Dans le cas d'un

SMI, lagestion des sections critiques est particulièrement importante entre le main et les

interruptions.

Q11.11 Un programmeur crée une fonction F() traitant une variable globale MaVar. La

fonction F() est appelée à chaque exécution de la boucle du main. De plus, la fonction F()

est appelée lors de l'interruption du timer0. Est-ce que ces opérations sont valides? Si elles

sont valides, pourquoi? Si elles ne sont pas valides, comment régler le problème?

Page 3: Cours 11, Partage du temps de microprocesseur et RTOS

La fonction F() n'étant pas réentrante, il risque d'y avoir des conflits sur MaVar. La solution

dans ce cas serait d'utiliser un processus de sémaphores pour l'exécution la fonction F() ou

pour tout changement sur MaVar, permettant ainsi d'éviter le conflit.

Q11.12 Un programmeur doit coder une machine à états appelant différentes fonctions

possédant le même type de retour et les mêmes paramètres pour chaque état. Exemple :

switch(FunctionAExecuter)

{

case ExecuteFunction1 :

Function1();

Break;

case ExecuteFunction2 :

Function2();

Break;

case ExecuteFunction2 :

Function3();

Break;

}

Cependant, dans le but d'alléger le code, il souhaite éviter d'utiliser un switch-case ou une

série de if imbriqués pour déterminer la fonction à appeler dans son main par rapport à

l'état actuel. Quelle autre solution peut-il employer? Décrivez brièvement cette solution.

Il peut utiliser un pointeur de fonction global. Ce pointeur de fonction pourra être modifié par

chaque fonction pouvant s'exécuter pour déterminer l'état suivant. Ainsi, il n'y a qu'à appeler,

dans le main, ce pointeur de fonction, qui exécutera la fonction nécessaire à l'état en cours.

Q11.13 Décrivez le principe d'utilisation des sémaphores et mutex.

Ce principe comporte d'abord une opération de test qui permet de vérifier si une ressource est

disponible et par la suite, l'obtenir si tel est le cas. La vérification et l’obtention de la

ressource ne peuvent être interrompues par d’autres tâches. Lorsque la ressource est obtenue,

la ressource est utilisée, et, ensuite, une opération propre aux sémaphores et mutex permet de

libérer la ressource.

Q11.14 Un système d’exploitation préemptif exécute à tour de rôle les tâches 1 et 2 telles

qu’implémentées ci-dessous. Les deux tâches appellent une fonction pour lire une mémoire

EEPROM SPI:

Tâche 1 Tâche 2 Fonction d’accès à la mémoire void Tache1(void)

{

short a;

InitT1();

while(1)

{

...

if(evenement1())

{

a= LireEEPROMSPI(20);

}

}

}

void Tache2(void)

{

short d;

InitT1();

while(1)

{

...

if(evenement2())

{

d= LireEEPROMSPI(40);

}

}

}

short LireEEPROMSPI(short adresse)

{

short ValeurLue;

EnvoieOctetSPI(CMD_LECTURE);

EnvoieOctetSPI(adresse >> 8);

EnvoieOctetSPI(adresse & 0xFF);

//Gènère l’horloge SPI pour lire mem.

EnvoieOctetSPI(0);

ValeurLue = REG_SPI_RX*256;

EnvoieOctetSPI(0);

ValeurLue += REG_SPI_RX;

return ValeurLue;

}

Page 4: Cours 11, Partage du temps de microprocesseur et RTOS

Pourquoi l’exécution de ces tâches par le système d’exploitation ne fonctionnera pas?

Supposons que le système d’exploitation interrompt la tâche 1 au milieu de la fonction

LireEEPROMSPI. Si le système d’exploitation exécute ensuite la tâche 2 et que la tâche 2

appelle aussi LireEEPROMSPI, les signaux envoyés à la mémoire seront incorrects.

Q11.15 Lisez et répondez aux questions de SMI_C11_Wait_Avec_OS_Preemptif.pdf (voir

les notes de cours).

Voir SMI_C11_Wait_Avec_OS_Préemptif.pdf.

Q11.16 Expliquez les fonctions GetMutex et ReleaseMutex retrouvée à la fin de

SMI_C11_Notes sur les Mutex.pdf (voir les notes de cours).

Get Mutex :

Si la tâche active a déjà le mutex, on sort de la fonction.

Sinon, la tâche active attend après le mutex :

- Elle vérifie si le Mutex est disponible après avoir désactivé les interruptions

o Si le Mutex est disponible, on le prend et on sort

o Si le Mutex n’est pas disponible, on indique au OS que la tâche attend après le

Mutex (pour que la tâche ne soit pas exécutée inutilement pendant l’attente) et

on attend le Mutex.

Release Mutex :

- On libère le Mutex.

- On remet dans l’état prêt-à-être-exécuté toutes les tâches qui attendaient après le

mutex.

Page 5: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 12 : Compilation, Édition de liens et IDE

Q12.1 Quel est le rôle d'un compilateur?

Le compilateur interprète le texte d’un fichier texte afin de générer le code machine et la liste

de toutes variables/fonctions correspondant au texte. Le compilateur génère un fichier objet

pour chaque fichiercompilé.

Q12.2 Quel est le rôle de l'éditeur de liens?

L’éditeur de lien fait le lien entre les divers fichiers d’un programme afin de créer

l’exécutable. Il vérifie que toutes les variables et fonctions du programme sont définies à

travers tous les fichiers du programme, il place toutes les variables et fonctions en mémoire,

puis il crée l’exécutable.

Q12.3 Que contient un fichier objet? À quoi sert ce type de fichier?

Un fichier objet contient toute l’information nécessaire pour que l’éditeur de lien puisse

insérer la partie de programme contenue dans le fichier à l’intérieur del’exécutable. Le fichier

objet contient donc du code compilé et des symboles indiquant les variableséfonctions

définies dans les fichiers et les variables/fonctions utilisées dans le fichier, mais qui n’y sont

pas définies.

Q12.4 Que contient un fichier exécutable?

Un fichier exécutable contient des informations sur le fichier, le code compilé et toute

l’information nécessaire pour que code puisse être placé en mémoire, puis exécuté. Cela

comprend les besoins en mémoire RAM, l’information sur les librairies à joindre

dynamiquement au code (dll), l’information sur la virtualisation du programme et plus.

Q12.5 Associez chaque opération d'optimisation à un type d'optimisation (haut niveau,

locale, globale, architecturale/dépendante de l'architecture).

Opération Type

Retirer d'une boucle du code qui est calculé inutilement à chaque itération Globale

Remplacer les instances d'une variable constante directement apr la constante Locale

Réarranger les instructions pour améliorer la performance du pipeline Architecturale

Remplacer des procédures par leur contenu (inlining) Haut niveau

Q12.6 Pourquoi est-il recommandé de vérifier le fonctionnement d'un programme de

nouveau après l'application d'optimisations?

L'optimisation du code apporte des modifications au code écrit par le programmeur. Ces

modifications peuvent découvrir des problèmes latents ou même créer de nouveaux problèmes

pour plusieurs raisons (manque d'information de la part du programmeur, opérations non-

désirées par le programmeur, erreur dans le compilateur, etc).

À noter : la plupart des compilateurs accélèrent le traitement sur les nombres à virgule

flottante en approximant certaines opérations. Généralement, cela amène un gain en

performance sans affecter la qualité du résultat. Or, les librairies de calcul scientifique sont

très sensibles aux erreurs numériques. Dans certains cas, il est très important de spécifier au

compilateur de ne pas optimiser ces opérations pour ne pas fausser les résultats.

Page 6: Cours 11, Partage du temps de microprocesseur et RTOS

Ce type d'erreur peut être détecté par l'application d'une série de tests unitaires. Les bancs

d'essai sont vraiment utiles, même pour le logiciel!

Q12.7 Supposons que le fichier A utilise la variable VarB déclarée dans le fichier B. Vous

retrouverez, dans le fichier A, “extern int VarB;”. Pour l’éditeur de lien, cette phrase

permet de relier le symbole déclaré dans le fichier au symbole défini dans le fichier B. Cette

déclaration sert-elle au compilateur? Si oui, à quoi? Si non, pourquoi?

La déclaration de VarB permet au compilateur de connaître la taille et la nature de VarB. Il

pourra ainsi indiquer des erreurs de compilation, optimiser le code et générer les instructions

nécessaires à la manipulation de VarB. Par exemple, certaines instructions permettent de

manipuler des int alors que d’autres n’opèrent que sur des shorts ou des chars. Pour savoir

quelles instructions du microprocesseur utiliser, le compilateur doitsavoir que VarB est un

int...

Q12.8 L’énoncé suivant est faux, dites pourquoi : “Le JTAG est une norme définissant un

protocole permettant d’écrire les instructions dans la mémoire du microprocesseur et de

déverminer les instructions exécutées par celui-ci.

Depuis les tout premiers microprocesseurs, des circuits logiques à l’intérieur même du

microprocesseur permettent de déverminer les applications. Ces circuits, des circuits de

debug, permettent d’arrêter l’exécution d’instruction (break point) et, par la suite, de lire

(voire d’écrire), les valeurs des registres du microprocesseur tout comme la mémoire du

système.

Le circuit de debug permet aussi de tester le microprocesseur, il a des interruptions (trap) qui

lui sont propres, parfois des broches dédiées et il fait partie intégrante du microprocesseur.

Pour accéder au circuit de debug, plusieurs interfaces peuvent être utilisées : le port série

(RS232), le port parallèle, ..., et le JTAG. Donc, la norme JTAG ne définit pas de protocole

pour écrire les instructions de la mémoire du microcontrôleur (le terme microprocesseur était

également faux...), ni pour déverminer les instructions. Le JTAG est une interface de contrôle

pour communiquer avec le circuit de debug du microprocesseur.

Q12.9 Un programme est constitué de fichiers en assembleur et de fichiers en écrits en

langage C. Décrivez comment seront traités ces fichiers pour générer l’exécutable?

L’assembleur « compilera » les fichiers écrits en assembleur et génèrera les fichiers objets

correspondants. Le compilateur compilera les fichiers écrits en langage C et génèrera les

fichiers objet correspondants. L’éditeur de lien reliera tous les fichiers objets entre eux, peu

importe leur provenance.

Page 7: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 13, Mémoires-Logiciel

Q13.1 Que se produirait-il si les variables locales étaient compilées de la même manière

que des variables globales?

Il risquerait d'y avoir de nombreux conflits, cela empêcherait que les fonctions soient

réentrantes, il y aurait une plus grande utilisation de la mémoire, impossible de faire de la

récursivité.

Q13.2 Quels sont les données nécessaires à mettre sur la pile lors de l'appel d'une fonction?

Dans quel ordre? Pourquoi faut-il les mettre dans cet ordre?

Il faut d'abord mettre les paramètres de la fonction, puis l'adresse de retour, et ensuite l'espace

alloué pour les variables locales.

Les paramètres d’entrée de la fonction sont mis sur la pile en premier parce qu’ils sont établis

avant le saut vers le code de la fonction (avant le CALL). Ensuite, l’appel de la fonction

requiert la sauvegarde de l’adresse de retour. Enfin, Seule la fonction utilise les variables

locales, elle alloue elle-même de l’espace memoire pour la pile pour celles-ci.

Les variables locales doivent donc être enlevées de la pile à la fin de la fonction. L'adresse de

retour ne doit pas non plus rester sur la pile à la fin de la fonction, elle a été mise lors de

l'instruction d'appel de la function et elle sera donc enlevée de la pile elle aussi lors de

l'instruction de retour de la fonction.

Ainsi, la fonction est dite “propre” puisque tout ce qu'elle a mis sur la pile a été enlevé. Enfin,

les paramètres de la fonction doivent être à cet endroit étant donné qu'il est possible qu'ils

soient modifiés, la fonction faisant souvent un traitement sur ces données, et il faut donc

qu'après la fonction, il soit possible de les dépiler afin de récupérer le résultat.

Q13.3 Définissez les termes suivants dans un contexte d’allocation dynamique de mémoire:

Mot ou expression Définition

Allocation dynamique Réserver de la mémoire pour des variables crées pendant que le

programme roule.

Tas (Heap) Réserver de la mémoire pour des variables crées pendant que le

programme roule.

Fragmentation Mesure du nombre d’espace libres dans la mémoire allouée.

Q13.4 Quelles sont les paramètres d’entrée des fonctions New/Malloc et Free/Delete? Que

retournent ces fonctions?

La fonction New reçoit en argument la taille de la variable à créer. Elle retourne l’adresse de

la mémoire alloué à la nouvelle variable : (void*) new (int TailleDeLaVariableACreer).

La fonction Free ne retourne rien. Elle libère la mémoire allouée à la variable dont l’adresse

est passée en argument : void Free(void* AdresseDeMemoireALiberer).

Q13.5 Nommez et expliquez les principaux avantages et désavantages d'utiliser un memory

pool.

Avantages :

- Simple

- Rapide

Page 8: Cours 11, Partage du temps de microprocesseur et RTOS

Il ne suffit que de prendre un bloc dans la liste des blocs libres et de retourner une référence à

celui-ci pour allouer de l'espace mémoire, et pour le libérer, il faut seulement remettre ce bloc

dans la liste des blocs libres.

Désavantages :

- Fragmentation intern: chaque bloc étant fixe, il est fort possible que pour un objet

donné alloué dynamiquement, plus d'espace mémoire que necessaire sera alloué.

- Doit connaître les applications d'avance : pour qu'un memory pool soit adéquat, il faut

idéalement savoir à l'avance la taille moyenne, la taille maximale et la quantité

maximale des objets alloués.

Q13.6 Il y a deux stratégies principales utilisées afin de passer les paramètres d’une

fonction. Nommez ces stratégies et comparez-les entre elles.

Utilisation de registres et utilisation d'une pile.

L’utilisation des registres permet de faire un appel de fonction simple et rapide, en évitant des

accès à la mémoire pour y mettre des paramètres. Cependant, l'utilisation de la pile est

privilégiée puisque le nombre d'arguments d'une fonction n'est pas limité au nombre de

registres disponibles sur un microprocesseur donné.

Q13.7 Quels critères sont utilisés pour évaluer les performances d’un algorithme

d’allocation dynamique de mémoire?

L’algorithme doit :

- Maximiser l’utilisation du tas: il doit éviter la fragmentation le plus possible et utiliser

le moins de mémoire possible pour maintenir l’information sur les segments de

mémoire libres et utilisés.

- Allouer et libérer de la mémoire rapidement.

- Être ajustable en fonction du programme exécuté et de ses besoins en mémoire allouée

dynamiquement.

- Maximer la portabilité et la compatibilité avec différents systems

- Maximiser la localité : si des caches de données sont utilisées, les variables allouées

dans la même fonction ou des fonctions proches devraient être dans des régions de

mémoire adjacente.

- Détecter les erreurs efficacement.

- Éviter les anomalies ou les exceptions

Page 9: Cours 11, Partage du temps de microprocesseur et RTOS

Q13.8 Expliquez dans vos mots comment fonctionne un Memory Pool? Écrivez un exemple

d’implémentation des fonctions New et Delete pour cet algorithme d’allocation dynamique

de mémoire.

Le tas est divisé en blocs de taille fixe et un champs de bit du chaque bloc est libre ou occupé.

La fonction new réserve le premier bloc de taille suffisante et change le bit pour indiquer qu’il

est occupé. La fonction Free change le bit du bloc libérer pour indiquer qu’il est libre.

(void*) new(unsigned int TailleAllouer)

{

unsigned int i;

if(TailleAllouer > TAILLE_DES_BLOCS)

return null; //Les blocs, tous de même taille, sont trop petits!!!

for(i = 0; i < NOMBRE_DE_BLOCS; i++)

{

if(EtatDesBlocs[i] = BLOC_LIBRE)

return &BlocDeTas[i];

}

return null; //Pas de bloc libre!!!

}

void free(void* AdrBlocALiberer)

{

unsigned int BlocALiberer;

if((AdrBlocALiberer < DEBUT_DU_TAS) || (AdrBlocALiberer > FIN_DU_TAS))

return;

BlocALiberer = (AdrBlocALiberer - DEBUT_DU_TAS)/ TAILLE_DES_BLOCS;

EtatDesBlocs[BlocALiberer] = BLOC_LIBRE;

}

Q13.9 Expliquez dans vos mots comment l’algorithme de monsieur Doug Lea présenté dans

les notes de cours?

Voir http://g.oswego.edu/dl/html/malloc.html

Q13.10 Pourquoi doit-on indiquer au compilateur de ne pas initialiser une plage d'adresses

assignée à une mémoire externe?

L'initialisation de la plage de mémoire se fera au démarrage du programme. À ce moment, il

n'y a pas de lien de communication établi entre le microprocesseur et la mémoire externe.

Selon le type de microprocesseur utilisé, cela peut soulever une exception matérielle, bloquer

l'exécution ou amener un comportement indéterminé. Quoi qu'il en soit, la mémoire ne sera

pas initialisée à la valeur désirée.

Q13.11 La déclaration d'une variable à point flottante peut augmenter la taille de code de

plusieurs kilooctets selon le type de microprocesseur utilisé. Pourquoi?

Certains microprocesseurs ne comportent pas de FPU (floating point unit). Par contre, il est

toujours possible d'émuler les opérations à virgule flottante à l'aide d'opérations sur les

entiers. En absence d'un FPU, un bon compilateur va automatiquement inclure dans votre

Page 10: Cours 11, Partage du temps de microprocesseur et RTOS

code, une librairie de fonctions émuler ces opérations. Ces opérations sont complexes (par

rapport aux mêmes opérations sur des entiers), ce qui amène l'augmentation de la taille du

code.

Astuce : il n'est pas recommandé d'utiliser des variables à virgule flottante sur un

microprocesseur dépourvu d'un FPU. En plus d'augmenter la taille du code, l'émulation des

opérations peuvent prendre des milliers de cycles d'horloge, même pour des opérations

élémentaires... Il est recommandé d’éviter les fractions ou de représenter les fractions en

binaire avec des nombres décimaux à point fixe (fixed-point decimal; chaque unité d’un entier

vaut 0.01 par exemple) lorsque le microprocesseur n’a pas de FPU.

Q13.12 L'utilisation de certaines librairies standards peut augmenter la taille de code de

plusieurs kilooctets. Pourquoi?

Bien que l'implantation d'une librairie standard puisse varier, son comportement doit se

conformer à une interface fixe. Elles contiennent donc un lot de fonctionnalités qui mène à

l'augmentation de la taille du code. Même s’il s’agit d’une pratique à éviter, il parfois est

préférable de « réinventer la roue » en implantant des fonctions existantes, tout en éliminant

les fonctionnalités superflues, afin de respecter les contraintes d'utilisation de mémoire.

Q13.13 Quelle stratégie devrait être utilisée par le programmeur afin de déterminer la taille

de la pile requise?

Pour déterminer la taille de la pile, le programmeur peut faire une inspection du code.

Cependant, la méthode est peu précise. Habituellement, le code est exécuté dans des

conditions d’opération typiques, avec une pile très grande, et on observe la quantité de

mémoire utilisée pour la pile afin d’optimiser. Dans tous les cas, il est recommandé de

toujours déclarer une pile plus grande que ce qui semble nécessaire…

Page 11: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 14: Alimentations et horloges

Q14.1 Décrivez le rôle de chaque composante dans le convertisseur AC-DC simple illustré

ci-dessous:

120VAC

60Hz

Transformateur

Pont de diodes

C Charge

Transformateur: abaisser la tension AC à un niveau près de la tension DC désirée (l’amplitude

maximum du signal AC à la sortie du transformateur détermine le niveau DC de sortie du

système.

Pont de diodes: Redresser la tension AC. Le condensateur se charge quand le signal AC est

plus grand que la tension aux bornes du condensateur, mais ne se décharge pas par la source

AC dans le cas contraire grâce au pont de diodes.

Condensateur: Emmagasiné l’énergie provenant de lasource AC lorsque la tension AC est

supérieure à la tension au bornes du condensateur, puis redonner cette énergie à la charge.

Q14.2 Nommez les deux types de régulateurs faisant une conversion DC-DC et décrivez

chacun brièvement.

Régulateur linéaire: Convertit une tension DC en une autre tension stable en sortie. Un

régulateur linéaire est simple, peu dispendieux. Cependant, ils sont relativement peu efficaces,

dissipant beaucoup d'énergie, et la tension d'entrée doit toujours être plus grande que la

tension de sortie.

Régulateur à découpage Accumulation d'énergie dans une inductance ou un condensateur,

puis commute un interrupteur pour redistribuer l'énergie ainsi accumulée à un autre circuit. Ils

sont plus efficaces, avec peu de dissipation d'énergie. Ils sont cependant plus complexes et

plus coûteux. Leur tension de sortie est aussi en général plus bruitée.

Q14.3 Comment mesure-t-on l’efficacité d’un régulateur DC-DC?

Efficacité = Puissance de sortie / Puissance d’entrée.

Puissance = Voltage * Courant…

Q14.4 Le circuit suivant illustre un régulateur linéaire. Expliquez son principe de

fonctionnement et montrez que la perte d’énergie dans le régulateur est proportionnelle à

la différence entre la tension d’entrée et la tension de sortie.

Vdc_Entrée Charge Vdc_SortieDiode

Zener

R

C

NPN

Page 12: Cours 11, Partage du temps de microprocesseur et RTOS

La résistance R limite le courant dans la diode Zener qui impose la tension à la base du

transistor NPN : La tension de sortie apparaissant sur la charge sera la tension d’avalanche de

la Zener, moins la tension Vbe (base-émetteur) du transistor.

Le courant utilisé par charge (Icharge) transitera par le transistor NPN et chargera le

condensateur, nécessaire pour stabiliser la tension de sortie. En régime permanent, courant

circulant dans le transistor NPN sera celui de la charge.

La tension aux bornes du NPN sera celles de l’entrée moins celle de la sortie (Vdc_Entrée –

Vdc_Sortie). Puisque P=VI, le transistor dissipera Icharge * (Vdc_Entrée – Vdc_Sortie)…

Q14.5 Expliquez le principe des watchdogs.

Un watchdog est un circuit intégré permettant de détecter un problème à l'exécution, soit un

problème matériel ou un blocage dans le logiciel (comme une boucle infinie dans lequel il est

impossible de sortir) et qui effectue dans ce cas un reset du système. Un watchdog interne doit

être activé par le logiciel puis, par la suite, nourri régulièrement afin qu'il n'y ait pas de

timeout et donc de reset.

Q14.6 Donnez l'utilité d'un Phase-lock loop (PLL) et décrivez brièvement sa structure.

Un PLL permet de multiplier la fréquence d'une horloge. Il est généralement composé d'un

détecteur de phase, d'un filtre passe-bas, d'un oscillateur électronique à fréquence variable et

d'une boucle de rétroaction comportant un diviseur de fréquence.

Q14.7 Mettre plusieurs microprocesseurs sur le même circuit d’horloge n’est

habituellement pas une bonne idée. Pourquoi?

D’abord, les circuits d’horloge sont souvent des circuits sensibles aux charges capacitives:

connecter deux circuits intégrés à la même horloge augmente et modifie la charge vue par

l’horloge, pouvant conduire à l’arrêt de l’horloge ou, plus probablement, à un changement de

la fréquence d’opération. Ensuite, les signaux d’horloge sont des signaux haute-fréquence.

Ces signaux devront parcourir des traces plus longues s’il y a deux circuits intégrés connectés

sur l’horloge. Cela génèrera plus de bruit et plus de charge sur le circuit d’horloge…

Q14.8 À quoi servent les condensateurs de découplage?

Les condensateurs de découplage servent à absorber les variations de courant dans le circuit

intégré. Cela permet d'isoler le circuit intégré du bruit à l'extérieur du circuit intégré tout en

réduisant l'impact des variations du courant du circuit imprimé sur l'alimentation extérieure.

Q14.9 Nommez trois événements causant la réinitialisation (reset) d'un microcontrôleur.

- Lors de la mise sous tension du circuit (power on reset)

- Lorsque la broche RESET du microcontrôleur est activée

- Lorsque commandé par le watchdog interne (watchdog reset)

- Lors d'une chute de tension sous un certain seuil (brownout reset)

- Lorsque le système se trouve dans un état instable ou indésirable (dans ce cas, le reset

peut être commandé par une instruction du microcontrôleur).

Q14.10 Quelle est la différence entre la puissance dynamique et la puissance statique?

La puissance statique est causée par le courant de fuite des transistors tandis que la puissance

dynamique est causée par la commutation des transistors.

Q14.11 Pourquoi veut-on séparer l'alimentation d'un CAN/CNA (ADC/DAC) du reste d'un

SMI?

Page 13: Cours 11, Partage du temps de microprocesseur et RTOS

Les variations de courant provenant des circuits intégrés du système peuvent se transmettre

aux niveaux de conversion internes d'un CAN/CNA, ce qui injecte du bruit dans le signal et

affecte ainsi la performance de ces modules

Q14.12 Le circuit suivant représente un régulateur SMPS de type Boost. Dans ce circuit,

Vdc_Entrée est une source d’alimentation DC, Reg est un circuit intégré de type régulateur

et la Charge est résistive. Expliquez, à partir de la figure, comment fonctionne le circuit et

dites quel voltage devrait-on retrouver aux bornes de la charge par rapport à la tension de

la source d’alimentation.

Vdc_Entrée Reg Charge

Voir http://en.wikipedia.org/wiki/Boost_converter pour la réponse!

Q14.13 Pour faire un circuit oscillant (une horloge), il faut obligatoirement un inverseur

(ou équivalent) et un délai. Le circuit suivant, un « relaxation oscillator », utilise un

comparateur pour générer un signal d’horloge. Expliquez comment ce circuit fonctionne.

Le comparateur agit comme un inverseur et le RC sur la broche V– du comparateur cause le délai.

Si on suppose que Vdd = 5V, que Vss vaut -5V, que Vout = 5V et que V- vaut 0 initialement :

- V+ sera à 2.5V

- Comme Vout est à 5V, le condensateur C se chargera jusqu’à 2.5V

- Lorsque C dépassera 2.5V, V- sera > à V+ et le comparateur sortira Vss ou -5V

- V+ deviendra -2.5V

- Comme Vout est à -5V, le condensateur C se déchargera de 2.5V à -2.5V

- Lorsque C dépassera -2.5V, V- sera < à V+ et le comparateur sortira Vdd ou 5V

- On retourne à la première étape…

Voir « Relaxation Oscillator » sur Wikipedia pour plus de détails…

Q14.14 (Pour experts) Comment pourrait-on modifier le « relaxation oscillator » de la

question précédente pour que le circuit ne donne pas une onde carrée en sortie, mais

génère des impulsions de largeur fixe (un PWM avec un duty cycle différent de 50%)? Il y a plusieurs solutions possibles. Cependant, la solution la plus simple, généralement utilisée en industrie, est

d’utiliser une ou deux diodes pour que le temps de charge du condensateur ne soit pas le même que son temps de

décharge :

Page 14: Cours 11, Partage du temps de microprocesseur et RTOS

Dans le circuit ci-dessus, le condensateur se décharge environ deux fois plus vite qu’il ne se charge et le duty

cycle de la sortie devrait être autour de 66%, si on avait une diode parfaite.

Q14.15 Un microprocesseur tombe en mode sommeil à toutes les secondes. Il dort pendant

900 millisecondes, puis il est réveillé par une interruption de timer pendant 100

millisecondes. Pendant son réveil, le microprocesseur traite intensivement des données

provenant de ces ADCs, transférées par DMA. Le microprocesseur exécute des instructions

à 256MHz quand il est réveillé, mais n’a pas d’horloge lorsqu’il dort. Un ingénieur novice

a décidé de filtrer l’alimentation du microprocesseur comme suit, afin de réduire le bruit vu

sur les ADCs :

3.3V 3.3V_f

Micro

contrôleur

Vcoeur

VadcC1

L1

C3

C2

Dites-pourquoi l’idée n’est pas bonne et expliquez comment on pourrait corriger.

Lorsque le microprocesseur se réveille, sa consommation de courant augmente énormément. Habituellement, un

microprocesseur consomme quelques uA en mode sommeil et quelques dizaines de mA lorsque actif. Or,

l’inductance L1 s’opposera à cette brusque augmentation de courant. Elle créera une tension qui s’opposera à la

variation de courant et fera diminuer, très temporairement Vcoeur et Vadc : 3.3V_f deviendra peut-être 3V à tous

les réveils du cœur pour peut-être quelques us… Cette brève chute de tension faussera la lecture des ADCs à tous

les réveils du cœur! On corrige comme suit :

3.3V 3.3V_f

Micro

contrôleur

Vcoeur

VadcC1

L1

C3

C2

Page 15: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 15: SMI versus architecture du microprocesseur Q15.1 Quels critères permettent d’évaluer l’architecture d’un microprocesseur?

- La vitesse d’exécution des programmes

- Le coût

- La consommation de puissance en fonction de la fréquence d’opération

- La taille du code requise pour exécuter une tâche

- Le support disponible pour l’environnement immédiat du microprocesseur : debug,

caches, système d’exploitation, et plus.

Q15.2 Le ARM Cortex M4 a-t-il une architecture Load/Store ou une architecture

Mémoire/Registre pour accéder à la mémoire? Pourquoi?

Load/Store parce que c’est plus simple et permet une exécution efficace des instructions en

pipeline.

Q15.3 Le ARM Cortex M4 a-t-il une architecture RISC ou une architecture CISC?

Pourquoi?

Une architecture essentiellement RISC (avec des instructions 16 ou 32 bits) parce que c’est

plus simple et permet une exécution efficace des instructions en pipeline. L’architecture n’est

pas tout-à-fait risc pour permettre une réduction de la taille des programmes (il faut plus

d’instructions avec une architecture RISC pour exécuter une tâche qu’avec une architecture

CISC).

Q15.4 Le ARM Cortex M4 a un pipeline d’instruction d’une profondeur de 3. Pour quelle

raison les concepteurs du ARM Cortex M4 n’ont-ils pas choisi une profondeur de 2 ou de

4?

La profondeur de pipeline est déterminée par la fréquence d’horloge que l’on veut supporter :

plus on veut exécuter les instructions rapidement, plus les instructions doivent être découpées

en petites parties. On veut cependant avoir la plus petite profondeur de pipeline possible parce

qu’un pipeline profond est un pipeline complexe...

Une profondeur de pipeline de 3 permet d’exécuter des instructions Thumbs2 à quelques

centaines de MHz, ce qui est adéquat pour la quasi-totalité des systèmes microprocesseurs

actuels.

Q15.5 Quels sont les impacts de l’utilisation d’un pipeline d’instruction sur l’exécution de

vos programmes?

Le principal impact est la vitesse : le pipeline accélère énormément l’exécution d’instructions.

Les problèmes reliés à l’exécution des instructions en pipeline (aléas de contrôle, de données

et de structure) rendront aussi plus complexe le calcul de temps d’exécution d’une fonction,

même en assembleur. Par exemple, si le code est exécuté à partir de la mémoire RAM qui

contient les données, cela produira des stalls de pipeline. Si on programme en assembleur, les

références au PCdoivent tenir compte du pipeline, sinon le compilateur s’en occupe...

Q15.6 Énumérez et décrivez trois fonctionnalités du ARM Cortex M4 afin de supporter un

éventuel système d’exploitation.

- Protection de la mémoire

- Instruction SVC

- Latence très courte pour entrer dans les interruptions

Page 16: Cours 11, Partage du temps de microprocesseur et RTOS

- Banque de registres de pointeur de pile

- Systick timer

Q15.7 La protection de la mémoire et la translation d’adresse (adresse virtuel traduite en

adresse physique) sont des tâches qui doivent être effectuées par le matériel (habituellement

par le MMU du microcontrôleur). Pourquoi?

Ces deux opérations doivent se faire pendant l’exécution des instructions. Par exemple, si on

veut vérifier que l’instruction LOAD R2,[adresse] accède à une « adresse » valide, on ne peut

pas exécuter d’autres instructions par le faire…

Page 17: Cours 11, Partage du temps de microprocesseur et RTOS

Cours 16: Interfaces et Système d’Exploitation

Q16.1 Pour répondre aux questions suivantes, choisissez parmi Programme Usager,

Système d’Exploitation, Bootloader et Microcontrôleur.

Qui implémente les fonctions d’accès aux périphériques?

Qui implémente le code de traitement des interruptions?

Qui gère l’état des processus afin de ne pas exécuter une tâche qui attend après un

périphérique?

Qui accède aux registres des périphériques afin de le contrôler?

Le système d’exploitation, le système d’exploitation, le système d’exploitation et encore

système d’exploitation.

Q16.2 Lorsque vous appelez une procédure d’entrée/sortie comme WriteFile pour accéder à

un périphérique, que fait la procédure d’entrée/sortie?

La procédure vérifie d’abord si l’accès est légal et si les ressources sont disponibles.

Ensuite, la procédure d’entrée/sortie débute l’accès au périphérique en appelant les fonctions

du pilote de périphérique adéquates.

Finalement, la procédure change l’état du processus et met le processus en attente jusqu’à ce

que l’accès soit terminé.

La toute dernière étape consiste à retourner le résultat de l’accès à la fonction appelante.

Q16.3 Il est dit dans les notes de cours que la fonction d’accès au périphérique devrait être

appelée avec une interruption logicielle (SVC). Avec un exemple de code, illustrez comment

se ferait l’appel de la fonction “FileWrite(UART_Handle, Chaine, 8)” avec une

interruption logicielle. Inventez les données qui manquent afin de répondre à la question.

Les paramètres de l’appel de la fonction sont mis dans des registres prédéterminés.

LDR R0,=UART_Handle

LDR R1,=Chaine

MOV R2, #8

La fonction est appelée avec l’interruption logicielle ayant le numéro correspondant.

SVC #5 //On assume que SVC $5 correspond à FileWrite!

Le système d’exploitation appellera la fonction FileWrite (contrairement au processus usager,

le système d’exploitation connaît l’adresse de la fonction!) :

void SVC_Handler(void){

int NumeroDeSVC;

NumeroDeSVC = GetSVCNumber(); //Lire la pile ou un registre du microcontrôleur

switch( NumeroDeSVC){

case 0:

case 5:

FileWrite(“R0”, “R1”, “R2”);

Break;

}

Page 18: Cours 11, Partage du temps de microprocesseur et RTOS

}

Q16.4 En programmation, qu’est-ce qu’un “handle"?

Un numéro de référence vers un fichier ou un périphérique ou une autre structure de données.

Q16.5 Lorsque plusieurs processus ou tâches exécutés “simultanément” veulent utiliser le

même périphérique, comment devrait se faire l’arbitration de l’accès multiple au

périphérique? Qui gère l’accès multiple? Que se passe-t-il avec une tâche qui ne peut pas

accéder au périphérique parce que ce dernier est utilisé par une autre tâche?

Lorsqu’un processus veut utiliser une ressource (mémoire partagée ou périphérique ou autre)

qui peut être utilisée par un autre processus, ce processus doit utiliser un Mutex afin d’obtenir

l’usage exclusif de la ressource.

Le programmeur du processus est responsable de l’utilisation des Mutex.

Toutefois, c’est le système d’exploitation qui implémente les fonctions d’obtention et de

relâche des Mutex. Quand une tâche veut réserver une ressource avec un

“GetMutex(Ressource)”, le code de la fonction GetMutex:

- Si la ressource est disponible :

o Réserve la ressource pour la tâche

o Continue l’exécution de la tâche

- Si la ressource n’est pas disponible :

o Change l’état du processus pour que le processus ne soit plus exécuté

o Attend que la ressource devienne disponible pour entrer en compétition de

nouveau afin de l’obtenir.