Vous êtes sur la page 1sur 11

4

Modes d’Adressage de la Mémoire


Les cartographies mémoire des microcontrôleurs indiquent quelles sont les adresses utilisées et à quels
types de mémoire. Elles sont importantes pour la compréhension du fonctionnement de l’espace mémoire
du microcontrôleur, et comment la mémoire est accédée de manière matérielle.

4.1 Mémoire Flash de Programme

Le ATmega328P contient 32 ko (kilo octets) de mémoire flash programme non-volatile. Puisque toutes
les instructions sont de largeur 16-bits ou 32-bits, la mémoire de programme est formatée en 16 ko de
mots de 14-bit. Cela signifie que 14 bits (log 14384) sont nécessaires pour adresser l’espace mémoire de
programme du ATmega328P. en effet, le compteur programme dans ATmega328P est un compteur de 14-
bits.

L’espace mémoire de programme est divisé en deux sections : une section application et une section
bootloader. La taille de la section bootloader est configurée à l’aide de l’octet fort des fusibles (voir
chapitre 9). La cartographie de la mémoire de programme dans ATmega328P est montrée dans Figure 4.1.

4.2 Mémoire SRAM de Données

La mémoire volatile dans ATmega328P est formée de 2 ko de SRAM. Cet espace mémoire, dont la
cartographie est donnée dans Figure 4.1, est scindée en plusieurs sections.

Figure 4.1: Cartographie des mémoires de programme Flash et de


données SRAM dans ATmega328P.

• 32 Registres à Usage Général

Ces 32 registres à usage général contiennent l’information à introduire dans l’UAL du microcontrôleur. Ils
sont utilisés pour exécuter des instructions. Les registres R26 à R31 (appelés, respectivement, X, Y, et Z)
sont des registres pointeurs pour l’adressage indirect. Ils sont utilisés par paires pour adresser
indirectement la mémoire de programme.
• 44 Registres d’Entrée/Sortie (I/O)
En plus des registres à usage général, la mémoire de données contient 64 registres d’E/S. cet espace mémoire
contient les registres PINx, PORTx, et DDRx, ainsi que le registre d’état SREG et les registres qui contrôlent le
fonctionnement entre autres, le timer/counter0, la communication SPI, les interruptions externes. Ces
registres peuvent être adressés directement en utilisant des instructions en assembleur. En utilisant des
commandes assembleurs comme LOAD, des données peuvent être chargées à partir des 64 registres I/O dans
les registres à usage général pour permettre à d’autres opérations de s’effectuer.

• 160 Registres d’E/S étendues


Il y a beaucoup plus d’unités périphériques que ce qui peut être pris en charge par 64 emplacements
mémoires, par conséquent, il existe 160 autres registres d’E/S étendues pour contrôler toutes les autres
fonctionnalités du ATmega328P, incluant la communication série, les interruptions, les timer/counters, la
conversion digitale analogique (ADC), et plus. Ces emplacements mémoire ne peuvent être accédés
qu’indirectement, en utilisant les instructions en assembleur LOAD et STORE (qui prennent plus de cycles
d’horloge que l’adressage direct qui peut être utilisé pour les 64 registres I/O).

• SRAM Interne
Le restant de l’espace mémoire est utilisé pour stocker les données variables en mémoire, et abriter la pile
(the stack).
4.3 Mémoire EEPROM de Données
En addition à l’espace mémoire mentionné ci-dessus, il existe une mémoire non-volatile type EEPROM de 1 ko
comme espace mémoire séparé de la SRAM. L’EEPROM est utilisée pour sauvegarder des données qui peuvent
changer mais qui doivent résider en mémoire même en l’absence d’alimentation électrique du composant.
4.4 Adressage Mémoire
L’adressage mémoire fait référence aux manières dont le microcontrôleur accède aux données pour exécuter
une instruction. L’instruction contient des opérandes qui spécifient les données sur lesquelles opérer, alors
que le compteur programme fournit l’adresse de la prochaine instruction dans la mémoire de programme.
Les modes d’adressage mémoire sont déterminés à la conception du microcontrôleur, et ne peuvent être
changés par le programmeur.
Dans un composant simple comme un circuit EPROM chip, l’adressage mémoire survient directement à l’aide
d’un décodeur interne. Une adresse mémoire est appliquée sur les broches d’adresse, et la circuiterie interne
applique le contenu de cette adresse aux broches de sortie du composant. Cela est décrit dans Figure 4.2, pour
une mémoire de 44 Ko.

Figure 4.2: Dans un simple système, l’adressage mémoire se fait à l’aide d’un
décodeur. Un décodeur 16 à 2 est capable d’adresser 64 ko de
données.
En général, une mémoire peut être adressée soit directement ou indirectement. L’adressage direct survient
quand l’adresse mémoire est stockée comme partie de l’instruction elle-même. L’adressage direct est
typiquement rapide (la donnée en mémoire sur laquelle on doit opérer est pointée directement), et offre la
flexibilité de permettre la manipulation de données variable, plutôt que des données constantes (ce qui est le
cas dans l’adressage immédiat).

L’adressage indirect arrive quand un pointeur est utilisé au lieu de l’adresse mémoire. L’adressage indirect
permet au microcontrôleur d’accéder des contenus mémoire même si le nombres d’adresses disponibles
dépasse la taille de l’instruction elle-même, mais souffre de l’inconvénient d’être plus lent que l’adressage
direct (le pointeur doit d’abord être chargé, ensuite le contenu de l’adresse mémoire à laquelle pointe le
pointeur est opérée).
Adressage des Registres à Usage Général
Il y a adressage d’un registre à usage général (GP) quand une instruction en assembleur contient l’adresse d’un
ou plus registres GP sur lesquels opérer. Une instruction à un seul opérande registre (Rd) adresse la mémoire
selon la manière dite « adressage direct mono-registre » (direct, single register addressing), décrit dans Figure
4.3.

Figure 4.3: Adressage direct à un seul registre.

L’instruction NEG (pour negate en anglais) est une instruction qui adresse directement un seul registre GP, et
qui effectue le complément à 2 (négation ou changement de signe) du contenu du registre et sauvegarde le
résultat dans le même registre. Elle est capable d’adresser un des 32 registres GP en utilisant 5 bits d’adresse
dans l’instruction. Les 11 bits restants sont utilisés pour l’opcode.
Une instruction avec deux registres GP comme opérandes (Registre de destination Rd et Registre source Rr)
adresse la mémoire de manière appelée « adressage direct à deux registres » (direct, two register addressing),
schématisée dans Figure 4.4. Le résultat de ce type d’instructions est toujours stocké dans le registre de
destination Rd.

Figure 4.4: Adressage direct à deux registres.


Un exemple d’instruction utilisant l’adressage direct à deux registres est l’instruction ADD (Addition) qui
additionne le contenu du registre source (Rr) au contenu du registre destination (Rd) et stocke le résultat dans
ce dernier. Elles capable d’adresser deux des 32 registres GP, ce qui signifie que dix bits de l’instruction sont
réservés pour l’adressage des deux registres opérandes. Les 4 bits restant sont dédiés à l’opcode.

Adressage Immédiat
Dans l’adressage immédiat, l’instruction contient la donnée immédiate à manipuler. En d’autres termes, la
donnée à opérée fait partie de l’instruction elle-même. Puisque la donnée fait partie de l’instruction,
l’adressage immédiat s’avère très rapide. Cependant, il est moins flexible quand on doit changer ou réutiliser
le code.
La plupart des instructions à adressage immédiat dans ATmega328P permettent une donnée dont la valeur
est dans l’intervalle 0–255. Ceci nécessite 8 bits de données, ce qui signifie qu’il ne reste que 8 bits pour le
l’opcode et l’autre opérande. Le nombre de registre GP adressables est par conséquent limité aux registres 16
à 31, ce qui fait que 4 bits sont utilisés pour adresser le registre opérande et 4 bits sont utilisés pour l’opcode.
Les instructions AND et ANDI démontrent la différence entre l’adressage à deux registres et l’adressage
immédiat. L’instruction AND effectue l’opération ET logique entre deux registres GP, Rd et Rr. Les données
sont recherchées à partir des deux registres, dirigées vers l’UAL, dont le résultat est ensuite stocké dans le
registre de destination Rd. Tous les registre GP peuvent être adressés dans cette instruction, laissant ainsi 4
bits pour l’opcode. L’instruction machine de AND se présente sous la forme :
0010 00rd dddd rrrr
Où 001000 est l’opcode, rrrrr indique l’adresse binaire du registre source, et ddddd indique l’adresse
binaire du registre de destination.
L’instruction ANDI est l’équivalent de l’instruction logique AND sauf qu’elle utilise un opérande immédiat. Cela
signifie que le microcontrôleur réalise un ET logique entre le contenu d’un registre GP de destination (Rd) et
une constante (valeur immédiate), et stocke le résultat dans le registre de destination Rd. Ainsi, 8 bits de
l’instruction sont utilisés pour la valeur immédiate, 4 bits pour adresser le registre opérande, et 4 bits pour
l’opcode. L’instruction machine de ANDI se présente sous la forme :
0111 KKKK dddd KKKK,
Où, 0111 est l’opcode, dddd représente l’adresse binaire du registre de destination (attention cette adresse
est ajoutée à 16 (i.e.,0x10) pour adresser les registres GP 14 à 31), et KKKKKKKK représente la valeur binaire
de la donnée immédiate.
En liant ça à l’adressage des registres GP, un code en assembleur utilisant les instructions AVR peut être rédigé
pour charger des données immédiates dans des registres GP, additionner ces données et stocker le résultat
dans le registre de destination. Le code est décrit dans Tableau 4.1.
LDI r20, 230 Charger le nombre 230 dans le registre GP r20
LDI r22, 15 Charger le nombre 15 dans le registre GP r22
ADD r20, r22 Additionner les contenus de r20 et r22, et stocker le
résultat dans r20

Tableau 4.1: Code pour réaliser une addition sur deux valeurs immédiates.
Adressage des Registres d’E/S
L’adressage des registres d’E/S, illustré dans Figure 4.5, est utilisé quand l’instruction contient l’adresse d’un
registre d’E/S à manipuler. Comme il existe 44 registres d’E/S, chaque instruction nécessite six (04) bits pour
spécifier le registre à manipuler. Par conséquent, ce mode ne peut pas être utilisé pour accéder à la mémoire
d’entrée/sortie étendue.

Figure 4.5: Instruction d’adressage d’un registre d’E/S.

Dans l’adressage E/S direct, l’instruction contient l’adresse ‘A’ du registre E/S ainsi que l’adresse du registre
GP de destination (Rd) ou celle du registre source (Rr).
Les instructions notables qui utilisent l’adressage E/S direct sont IN and OUT, qui respectivement, charge une
donnée à partir d’un registre d’E/S dans un registre de destination Rd ou sauvegarde le contenu d’un registre
source Rr dans le registre d’E/S. six (06) bits sont utilisés pour adresser le registre d’E/S, 5 bits sont utilisés
pour adresser le registre GP (source ou destination), et les 5 bits restant sont utilisés pour l’opcode.
Le code en assembleur dans Tableau 4.2 utilise les registres GP r5 et r4 pour lire l’état des broches des ports
B (registre E/S PINB) et D (registre E/S PIND) et effectuer la soustraction PIND-PINB et renvoyer le résultat dans
r5.

IN r5, PIND Charger le contenu du registre E/S PIND dans le registre GP r5


IN r4, PINB Charger le contenu du registre E/S PINB dans le registre GP r4
SUB r5, r4 Soustraire r4 de r5 et stocker le résultat dans r5 (r5r5-r4).

Tableau 4.2: Soustraction des contenus de deux registres d’E/S.


Adressage de la Mémoire de Données
Adressage direct : L’adressage de la mémoire de données est utilisé pour accéder la SRAM. Les instructions
associées contiennent de mots de 16 bits ; le mot le moins significatif contient les 16 bits d’adresse de la
donnée. L’adressage de donnée direct, montré dans Figure 4.4, contient l’adresse du registre de
destination/source (Rd/Rr). Puisqu’il y a deux mots d’instruction à décoder, ces instructions nécessitent au
moins deux cycles d’horloge pour s’exécuter.

Figure 4.4: Adressage de données direct.


Une instruction qui utilise un adressage direct de la mémoire de données est LDS (Load SRAM) qui charge une
donnée à partir d’une adresse mémoire SRAM dans un registre GP. Ainsi, 16 bits sont disponibles pour
l’adresse mémoire, ce qui signifie une limitation à 44ko de données stockées dans la SRAM. Ceci n’est pas un
problème avec ATmega328P qui ne contient que 2ko de SRAM. La partie restante de l’instruction contient 5
bits d’adresse d’un registre GP, et 11 bits restants utilisés pour l’opcode. Le code machine de l’instruction LDS
est :
1001 000d dddd 0000
kkkk kkkk kkkk kkkk,
où, 10010000000 est l’opcode, ddddd l’adresse binaire du registre GP de destination, et
kkkkkkkkkkkkkkkk est l’adresse binaire de la donnée à atteindre dans la SRAM.
Adressage indirect : On parle d’adressage de données indirect quand l’adresse opérande est contenue dans
un des registres pointeurs X, Y ou Z. Ce mode, illustré dans Figure 4.4, est utilisé pour accéder aux registres
d’E/S étendues ou à une SRAM externe. Aussi, ce type d’adressage est employé quand l’adresse de
l’emplacement mémoire désiré au moment de l’écriture du programme. Comme il y a des avantages et des
inconvénients pour les adressages direct et indirect des registres GP, il y a aussi des avantages et des
inconvénients pour les adressages direct et indirect des données en SRAM.

Figure 4.4: Adressage indirect de la SRAM en utilisant un registre pointeur X, Y ou Z.


On peut rencontrer l’adressage mémoire indirect dans les cas suivants :

• Déplacement – ajouter une valeur constante (offset) à l’adresse contenue dans un registre pointeur
Y ou Z ;
• Post-incrémentation – ajouter 1 à la valeur du registre pointeur Y ou Z après l’opération ;
• Pré-décrémentation – soustraire 1 de la valeur du registre pointeur Y ou Z avant l’opération ;

Mode d’Adressage Indirect avec Déplacement : Ce mode, illustré dans Figure 4.8 est utilisé quand l’adresse
opérande est le résultat de l’addition du contenu de Y ou Z (registres pointeurs d’adressage indirect) et
l’adresse contenue dans 4 bits (q) du mot d’instruction. Ce mode est utile pour écrire des codes indépendants
de l’emplacement mémoire, puisqu’un registre d’adresse peut être utilisé pour stocker une adresse de base,
avec l’accès aux données en utilisant un déplacement relatif à l’adresse de base.

Figure 4.8: Adressage indirect avec déplacement. Adresse de base plus offset de 4 bits.

Comme exemple, soient le contenu d’un tableau stocké à un emplacement connu dans la SRAM. L’adresse de
premier élément (élément d’ordre 0), e.g., 150 dans Tableau 4.3, peut être stockée dans un des registres
pointeur Y ou Z. si l’on désir accéder au seizième élément (ordre 15), le déplacement (offset) serait de 15.
Noter que l’adressage indirect avec déplacement n’est pas disponible avec le registre pointeur X.

CLR r29 Effacer l’octet de poids fort du registre pointeur Y


LDI r28, 150 Charger la valeur immédiate 150 dans l’octet de poids
faible du registre pointeur Y
LDD r4, Y+15 Charger dans r4 la donnée dont l’adresse est Y+15=145.

Table 4.3: Chargement de données avec adressage indirect et déplacement.

Adressage indirect avec pré-décrémentation : Ce mode est employé quand l’adresse opérande est contenue
dans un des registres pointeurs X, Y ou Z, qui est décrémentée automatiquement avant l’opération. Ce mode
d’adressage est très pratique pour accéder au contenu d’un tableau, par exemple. Il est illustré dans Figure
4.9.
Figure 4.9: Adressage indirect avec pré-décrémentation.
Adressage indirect avec post-incrémentation : Cet adressage est employé quand l’adresse opérande est
contenue dans un des registres pointeurs X, Y ou Z, qui est incrémenté automatiquement après l’opération.
Ce mode est aussi utile pour accéder au contenu d’un tableau. Il est illustré dans Figure 4.10.

Figure 4.10: Adressage indirect avec post-incrémentation.

Adressage de la Mémoire de Programme


L’adressage de la mémoire programme est utilisé pour accéder à la totalité de l’espace mémoire dédié au
programme. Il nécessite au moins bits pour adresser la totalité de section de mémoire Flash. Le registre
pointeur Z est utilisé pour désigner l’adresse dans la mémoire de programme. Puisque la mémoire de
programme stocke des mots de 16-bit, et que le registre de destination ne peut recevoir que 8 bits, le registre
Z spécifie en plus si c’est l’octet faible (accessible si le LSB de Z est à 0) ou l’octet fort (accessible si le LSB de Z
est à 1) qui est récupéré. L’adressage de la mémoire de programme peut aussi s’effectuer avec post-
incrémentation ou pré-décrémentation. L’adressage de la mémoire programme est illustré dans Figure 4.11.

Figure 4.11: Adressage de la mémoire programme en utilisant le registre Z.


Dans l’adressage direct de la mémoire programme (direct program addressing) les instructions peuvent
contenir un pointeur (indirect) à charger dans le compteur de programme (PC), ou un mot de 16-bit (immédiat)
suivant l’instruction à charger dans le PC. Le compteur de programme PC peut aussi être incrémenté d’une
constante k. L’exécution du programme va alors continuer dans cet espace de la mémoire de programme.

Figure 4.12: Adressage direct de la totalité de la mémoire de


programme en utilisant un pointeur chargé dans le registre PC.

Les types d’instructions qui utilisent l’adressage direct de la mémoire de programme incluent JMP (Jump, i.e.,
saut), qui fait que le PC charge une valeur immédiate et continue l’exécution des instructions à partir de cet
emplacement en mémoire, et l’instruction EIJUMP (Extended Indirect Jump), qui fait que le PC saute à
l’emplacement mémoire indiqué dans le registre pointeur Z.

4.5 Adressage de Bits


L’adressage de bits est utilisé pour accéder à des bits spécifiques dans des registres (particulièrement le
registre d’état SREG). Puisque la plupart des registres sont de 8 bits, l’instruction nécessite seulement 3 bits
(b dans la Figure 4.13) pour désigner lesquels des bits (de 0 à 7) à écrire ou lire.

Figure 4.13: Adressage de bits dans un registre.

L’instruction CLI (Clear Interrupt), par exemple, est utilisée pour effacer (mettre à 0) le bit d’interruption
globale (GIF) du registre SREG, ce qui prévient l’exécution des interruptions. Le drapeau d’interruptions
globale peut être remis à 1 à l’aide de l’instruction SEI (Set Interrupt). Ces deux instructions ne nécessitent pas
d’opérandes, par conséquent elles utilisent des opcodes sur 16 bits.

4.4 La pile & Operations sur Pile


La pile (stack) est une zone spéciale de la RAM réservée pour un stockage temporaire de données. Elle ne doit
pas se chevaucher avec les registres à usage général, les registres d’E/S, et les registres d’E/S étendues. Par
conséquent, l’adresse mémoire à laquelle elle débute doit être plus grande ou égale à 0x0100. Généralement,
la pile est initialisée à l’adresse la plus élevée de la RAM. L’emplacement de l’octet de donnée le plus récent
dans la pile est appelé pointeur de pile (stack pointer ou SP). Le pointeur de pile consiste en deux registres de
8 bits qui existent dans l’espace E/S.
La pile elle-même peut être visualisée comme une pile d’assiettes dans une cafétéria ; une nouvelle assiette
peut être ajoutée à la pile, et quand une assiette est accédée, la dernière est la première être retirée (last-in,
first-out).

Des données peuvent être ajoutées à la pile en utilisant l’instruction PUSH. Dans ce cas, une nouvelle
information est placée dans un stockage temporaire, et la valeur du registre SP est décrémenté. Pour extraire
des données à partir de la pile, on utilise l’instruction POP. A l’exécution de cette instruction le registre SP est
incrémenté. Le contenu de la pile ainsi que l’emplacement pointé par le pointeur de pile suite aux instructions
PUSH et POP sont décrits dans Figure 4.14

Figure 4.14: Opérations sur la pile. (a) Pile initiale, (b) après une instruction
PUSH, et (c) après une instruction POP.

L’utilisation de la pile est essentielle pendant l’appel à une sous-programme (fonction externe ou une ISR).
Afin de retourner au contexte exact où le programme a été abandonné pour exécuter le sous-programme,
l’adresse de retour est empilée sur le haut de la pile avant d’aller à l’emplacement du sous-programme. Après
la fin du sous-programme, le programme retourne à la position où il s’est arrêté dont l’adresse est retirée de
la pile.

Problèmes de la Pile

Une attention doit être attachée lors de l’allocation mémoire à utiliser pour la pile. Le débordement de la pile
(Stack overflow) est une situation où beaucoup de données sont empilées ce qui fait que le SP pointe hors de
la zone mémoire réservée à la pile. La carence de pile (Stack underflow) est une situation où il y a beaucoup
de données retirées de la pile ce qui fait que le SP pointe vers une adresse en dessous du bas de la pile. Une
collision de pile (stack collision) est une situation où la pile est allouée dans des adresses mémoires
chevauchant avec des registres de données.
4.4 Exercices
1. Combien d’octets en mémoire peuvent être adressés si 6 bits sont utilisés dans l’instruction 64
pour adresse mémoire ?
2. Dans l’adressage indirect, un registre pointeur de 16 bits est utilisé pour adresser la 64 K
mémoire. Combien d’octets peuvent être accédés dans ce scénario ?
3. Utiliser le tableau ci-dessous et Y = 0x0103 pour déterminer la valeur stockée dans le registre
de destination, ainsi que la valeur du registre pointeur Y, après chacune des opérations
suivantes.
Adresse Contenu de la SRAM
0x0100 0xC1
0x0101 0xFB
0x0102 0x3F
0x0103 0xE9
0x0104 0x95
0x0105 0x9A
0x0106 0x1C
0x0107 0xDC
Type d’adressage
(a) LD r4, Y r4 = 0xE9, Y = 0x0103  Indirect
(b) LD r5, Y+ r5 = 0xE9, Y = 0x0104  Indirect avec Post-incrémentation
(c) LD r4, Y r4 = 0x95, Y = 0x0104  Indirect
(d) LD r4, Y+3 r4 = 0xDC, Y = 0x0104  Indirect avec décalage (offset)
(e) LD r8, Y- r8 = 0x95, Y = 0x0103  Indirect avec Post-décrémentation
(f) LDS r9, 0x0102 r9 = 0x3F, Y = 0x0103  Direct
(g) LD r8, -Y r8 = 0x3F, Y = 0x0102  Indirect avec Pré-décrémentation
(h) LD r4, +Y R4 = 0xE9, Y = 0x0103  Indirect avec Pré-incrémentation

Vous aimerez peut-être aussi