MSP430 TP1 : prise en main et programmation assembleur

publicité
Département IF / Architecture Matérielle
MSP430 TP1 : prise en main et programmation assembleur
Introduction
Dans cette série de TP «msp430», on va étudier le fonctionnement d’un (petit) ordinateur pour mieux
comprendre l’interface entre le logiciel et le matériel. Vous devrez donc faire les diverses manipulations
demandées, et par moment écrire des bouts de programme.
Nous ne ramasserons pas de compte-rendu ; par contre, vous avez intérêt à prendre des notes tout au long
du déroulement du TP pour pouvoir les relire par la suite : dans les TP d’après, mais aussi avant les QCM,
et aussi avant l’examen ! Pour chaque exercice, mettez donc par écrit (sur papier ou sur ordinateur) les
manips que vous faites, les questions que vous vous posez, et les nouvelles notions que vous comprenez.
1
Découverte de la carte
Exercice 1 Pour chaque binôme, allez prendre le matériel nécessaire au TP : une carte d’expérimentation,
une sonde JTAG (le boîtier gris avec une nappe d’un côté), et un câble USB.
1.1
La carte mère
La carte que nous allons utiliser en TP est illustrée dans le schéma ci-dessous. La puce principale est celle
repérée FG4618
: c’est un microcontrôleur, on y reviendra par la suite. Mais d’abord, faisons le tour de la
4. Functional
Overview
carte.
The MSP430FG4618/F2013 experimenter’s board supports various applications
the use of the
on-chip peripherals connecting
Extrait de la through
documentation
: motherboard.pdf
page 6 to a number of on-board
components and interfaces as shown in Figure 2.
Wireless
CC1100/
2420/2500
EMK
Interface
Analog
Out
LCD
RS-232
Buzzer
JTAG1
FG4618
JTAG2
Microphone
F2013
Capacitive
Touch
Pad
Buttons
Figure 2: Experimenter’s board block diagram
Wireless communication is possible through the expansion header which is
compatible with all Chipcon Wireless Evaluation Modules from Texas Instruments.
1 microphone, audio output jack,
Interface to a 4-mux LCD, UART connection,
buzzer, and capacitive touch pad enable the development of a variety of
Sur cette carte mère, en plus du msp430, il y a tout un tas de périphériques :
1. un écran à cristaux liquides (pour afficher des chiffres et des icônes)
2. un microphone
3. un buzzer (pour jouer du son)
4. une prise casque (pour jouer du son aussi, mais plus joli)
5. un quartz (pour générer le signal d’horloge)
6. deux boutons poussoirs
7. des voyants lumineux (LED)
8. une roue tactile capacitive (touchpad) en forme de chiffre 4
9. un port série (RS-232)
etc. ...
Exercice 2 Pour chacun de ces éléments, indiquez sur le schéma page précédente son emplacement
approximatif. Certains éléments (LEDs, quartz) ne sont pas sur le schéma, vous devrez les chercher
directement sur la carte. Le quartz est repéré X2, et les diodes sont repérées LED1, LED2, LED3 et LED4.
Commentaire Vous aurez peut-être remarqué que la carte comporte deux microcontrôleurs. L’un est un
MSP430F2013 (c’est le petit), et l’autre un MSP430FG4618 (c’est le gros). C’est avec ce second msp430
qu’on va travailler dans ces TP. Les diodes LED1, LED2, et LED4 y sont connectées par des pistes de la
carte mère. La diode LED3, par contre, est connectée au F2013, qu’on ne va pas utiliser du tout. Vous
pouvez dès maintenant oublier son existence, ainsi que celle de la LED3.
Exercice 3 L’encadré page suivante montre le schéma électrique de la carte mère. Retrouvez les différents
composants vus jusqu’ici, et indiquez leur emplacement sur le schéma.
2
Extrait de la documentation : motherboard.pdf page 19
1
3
5
7
1
3
5
7
H2
H3
H5
H6
H7
10
P5.7
P5.5
UCA0SIMO
UCA0CLK
P7.5
P7.7
2
4
2
4
6
8
UCB0SDA
UCB0CLK
P3.5
P3.7
13
12
11
2
4
6
8
11
12
13
2
1
3
P6.0
P6.2
P6.4
P6.6
VEREFP5.0
P10.6
2
1
3
1
3
5
7
1
3
5
H8
H9
2
4
6
8
2
4
6
P6.1
P6.3
P6.5
P6.7
VEREF+
P5.1
P10.7
VCC
2
1
2
FET_PWR1 1
LCL_PWR1 3
2
LCL_PWR2 3
FET_PWR2 1
VCC_1
VCC_2
LCL_PWR1
FET_PWR1
14
12
10
8
6
4
2
13
11
9
7
5
3
1
GND
GND
VREG_EN
RESETCC
JTAG1
AVCC_4618
C8
10uF 0.1uF
C7
GND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
3
5
7
9
11
13
15
17
19
2
4
6
8
10
12
14
16
18
20
FIFO
FIFOP
GDO0
GDO2
P4.2
UCLK1
SIMO1
SOMI1
VCC
C1
0.1uF
GND
1
3
5
7
9
11
13
15
17
19
RF Daughter Card Connect
RF1
DVCC_4618
C2
0.1uF
RF2
2
4
6
8
10
12
14
16
18
20
75
74
73
72
71
70
69
68
67
66
65
64
63
62
61
60
59
58
57
56
55
54
53
52
51
1k
R5
3
2
SW1
8
7
6
DVCC_4618
GND
SW2
R21
0-DNP
0-DNP
R22
1A_1B_1C_1D
1F_1G_1E_DP1
2A_2B_2C_2D
2F_2G_2E_DP2
3A_3B_3C_3D
3F_3G_3E_COL3
4A_4B_4C_4D
4F_4G_4E_DP4
5A_5B_5C_5D
5F_5G_5E_COL5
6A_6B_6C_6D
6F_6G_6E_DP6
7A_7B_7C_7D
7F_7G_7E_DP7
C3
10uF
P3.5
1 JP1
2
SBWTDIO
SBWTCK
DOL_ERR_MINUS_MEM
ENV_TX_RX_8BC
ANT_A2_A1_A0
BT_B1_B0_BB
AU_AR_AD_AL
PL_P0_P1_P2
F1_F2_F3_F4
F5_PR_P4_P3
COM0
COM1
COM2
COM3
SoftBaugh SBLCDA4
(For opt. F2013 programming)
DVCC_4618
P$14
P$13
P$12
P$11
P$10
P$9
P$8
P$7
P$6
P$5
P$4
P$3
P$2
P$1
1N4148
D2
GND
8
7
6
5
2
5
DVCC_4618
PS8802
3
U2
PS8802
U1
Isolated RS232 Communication
100
Q1
MMBT5088
VCC
R9
2k2
GND
S0
S1
S2
S3
S4
S5
S6
S7
S8
S9
S10
S11
S12
S13
MSP-EXP430FG4618 PCB Ver 0-00
Document Number:
5
4
3
2
1
RS232
10uF
C4
G1
G2
9
8
7
6
VER:
0-00
S21
S20
S19
S18
S17
S16
S15
S14
COM0
COM1
COM2
COM3
PC_GND
Buzzer
Mute
P$26
P$25
P$24
P$23
P$22
P$21
P$20
P$19
P$18
P$17
P$16
P$15
Sheet: 1/1
MSP430FG4618/F2013 Experimenter's Board
UCA0TXD
UCA0RXD
P2.6
P2.7
P3.0
UCB0SDA
UCB0SCL
UCB0CLK
P3.4
P3.5
P3.6
P3.7
UTXD1
C13
URXD1
GND
0.1uF
DVCC_4618
LCDCAP
P5.7
C15
P5.6
P5.5
10uF
COM3
COM2
COM1
GND
COM0
P4.2
UCA0RXD
UCA0TXD
GND GND
Audio output jack
A1
R2
Power Supply Configuration
BATT
GND
C6
VCC_1: FG4618 Supply Config
VCC_2: F2013 Supply Config
C5
DVCC_4618
AVCC_4618
Pos 1-2: FET Powered
Pos 2-3: Battery Powered
VCC
R8
10
R10
10
10uF 0.1uF
DVCC_4618
P6.3
P6.4
C10
P6.5
P6.6
10uF
P6.7
VREF
X2
VEREF+
VEREFP5.1
P5.0
P10.7
P10.6
S0
S1
S2
S3
S4
S5
S6
S7
S8
S9
P6.5
(A5/OA2O)
2
JP4 1
2k2
MSP430FG4618 Pin Access
1
3
1
3
5
7
LCDCAP
P5.6
P7.0
UCA0SOMI
P7.4
P7.6
SW2
GDO2
VREG_EN
FIFOP
URXD1
SIMO1
UCLK1
P4.7
1
3
5
7
2
4
6
8
2
4
6
8
P3.0
UCB0SCL
P3.4
P3.6
9
14
15
16
VREF
C9
0.1uF
GND
GND
JP3 1
2
GND
P6.4
(A4/OA1I0)
(Output
Attn.)
R17
SW1
GDO0
RESETCC
FIFO
UTXD1
P4.2
SOMI1
P4.6
H4
P2.1
P2.3
UCA0RXD
P2.7
10
8
14
15
16
UCB0SDA
UCB0SCL
P3.0
UCB0CLK
R25
15.4k
Sallen-Key 2nd Order OA1 Active LPF
R24
1.4k
C17
3.3nF
D3
1N4148
+
SP1
9
470
R20
2
4
6
8
P6.0
(A0/OA0I0)
P6.7
(A7/DAC1)
C16
22nF
+
R12
2
4
6
8
8
INNER_GND
2 FET_PWR2
4 LCL_PWR2
6
8
10
12
14
LED3
150k
P6.1
(A1/OA0O)
R7
+
B1
-
R1
D1
1N4148
Date: 26-Oct-2006
3
2AL60P1
470
INNER_GND
JTAG2
1k
R29
R30
C14
P6.2
(A2/OA0I1)
R11
R6
470
R4
100k
2
1
GND
SBWTDIO 1
3
5
SBWTCK 7
9
11
13
VSS
VCC
U4
GND
1
14
2
2013_P1.0
3
2013_P1.1
4
2013_P1.2
5
2013_P1.3
6
2013_P1.4
7
2013_P1.5
8 SCL
H1
9 SDA
1
3
5
7
R16
Mic Input Circuitry and
1st Order OA0 Active HPF
P2.3
(Mic Supply)
P1.0/TACLK/ACLK/A0+
P1.1/TA0/A0-/A4+
P1.2/TA1/A1+/A4P1.3/VREF/A1P1.4/SMCLK/A2+/TCK
P1.5/TA0/A2-/SCLK/TMS
P1.6/TA1/A3+/SDO/SCL/TDI/TCLK
P1.7/A3-/SDI/SDA/TDO/TDI
10uF
C19
0
S1
470
LED2
1
3
5
7
C12
0.1uF
17
15
13
11
9
7
5
3
1
2
1
DNP
P2.0
P2.2
UCA0TXD
P2.6
VCC
2
PWR2 1
C11
GND
10
11
13
12
NMI/RST/SBWTDIO
TEST/SBWTCK
XIN/P2.6/TA1
XOUT/P2.7
18
16
14
12
10
8
6
4
2
MSP430F2013PW
17
15
13
11
9
7
5
3
1
5M1
R32
PWR1
GND
2k2
S2
100k
2
1
5
5
LED1
BAND
P$4
RING
P$2
TIP
P$1
C20
1uF
18
16
14
12
10
8
6
4
2
BB1
470n
Breadboard
17
15
13
11
9
7
5
3
1
BB2
GND
22k
+
P6.3
(A3/OA1O)
GND
R31
47k
2013_P2.6
2013_P2.7
BB3
GND
GND
R33
7
7
R3
R28
R23
6
6
GND
47k
100
99
98
97 P6.2
96 P6.1
95 P6.0
94
93
92
91
90
89
88
87
SW1
86
SW2
X1
85
GDO0
84
GDO2
83
RESETCC
82
VREG_EN
81
FIFO
80
FIFOP
79
P2.0
78
P2.1
77
P2.2
76
P2.3
470k
470
LED4
R14
470n
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
S10
S11
S12
S13
S14
S15
S16
S17
S18
S19
S20
S21
P7.7
P7.6
P7.5
P7.4
UCA0CLK
UCA0SOMI
UCA0SIMO
P7.0
P4.7
P4.6
UCLK1
SOMI1
SIMO1
10k
470
5M1
15p
5M1
C18
R15
C21
R13
1 JP2
2
R26
1k
3k3
R27
1
2
R34
VCC
18
16
14
12
10
8
6
4
2
R19
4
4
+
R18
10
5M1
M1
VCC_2013
1.2
Documentations techniques
Comme tout objet technologique, notre plate-forme de TP s’accompagne d’une documentation technique
abondante. Pour ne pas vous noyer sous la doc, nous vous en avons copié les extraits essentiels directement
dans le sujet, sous forme d’encadrés. Pour les plus curieux, nous vous avons aussi mis à disposition les
documents sur Moodle :
Motherboard.pdf décrit notre carte d’expérimentation et les différents composants présents sur la carte.
MSP430.pdf est le manuel générique de la puce MSP430. Le processeur est documenté au chapitre 3.
datasheet.pdf donne les détails techniques de notre modèle précis de msp430.
LCD.pdf décrit l’écran à crystaux liquides (qu’on utilisera à partir du TP2).
1.3
Vous avez dit microcontrôleur ?
Le MSP430FG4618 est un microcontrôleur, c’est à dire un System-on-Chip : une même puce qui contient à
la fois un processeur, de la mémoire, et des blocs périphériques. Si on zoome sur l’intérieur de la puce, on
a donc affaire à l’architecture illustrée ci-dessous.
Extrait de la documentation : msp430x4xx.pdf page 21
Quartz
Clock
System
ACLK
SMCLK
SMCLK
Flash/
ROM
RAM
Peripheral
Peripheral
Peripheral
ACLK
RISC CPU
16-Bit
JTAG interface
MCLK
MAB 16-Bit
MDB 16-Bit
MAB 16-Bit
MDB 8-Bit
Bus
Conv.
JTAG
ACLK
SMCLK
Peripheral
Peripheral
Peripheral
Peripheral
Peripheral
Commentaires Les flèches repérées MAB et MDB sont respectivement le Memory Address Bus et
le Memory Data Bus (les mêmes que dans la micro-machine). Ce sont eux qui relient le processeur
au reste-du-monde, comme dans toute machine de von Neumann qui se respecte. Le bloc repéré
JTAG interface permet justement de venir intercepter tout ce qui passe sur le bus, et donc de
contrôler finement le comportement de la machine. C’est ce qu’on va faire dans ces TP.
Exercice 4 Branchez maintenant la sonde JTAG sur la carte. Vous devriez pouvoir choisir sans difficulté
entre les deux connecteurs JTAG.
1.4
Zoom sur le processeur
Si on se rapproche encore, on tombe sur l’architecture suivante :
4
Extrait de la documentation : msp430x4xx.pdf page 43
MDB
MAB
15
0
R0/PC Program Counter
0
R1/SP Stack Pointer
0
R2/SR/CG1 Status
R3/CG2 Constant Generator
R4
General Purpose
R5
General Purpose
R6
General Purpose
R7
General Purpose
R8
General Purpose
R9
General Purpose
R10
General Purpose
R11
General Purpose
R12
General Purpose
R13
General Purpose
R14
General Purpose
R15
General Purpose
16
16
Zero, Z
Carry, C
Overflow, V
Negative, N
dst
src
16−bit ALU
Commentaire Attention, ce schéma ne montre que la vue «externe», c’est à dire du point de vue
de l’utilisateur. Une «vue interne» a comporterait d’autres éléments nécessaires à l’implémentation
(automate de contrôle, registre d’instruction, etc).
Les seuls éléments représentés sur le schéma sont ceux qui sont accessibles au programmeur : les
16 registres architecturaux, ainsi que l’unité arithmétique et logique. Remarquez au passage que
les 4 premiers registres sont spécialisés pour un usage particulier (R0 est le compteur ordinal, etc).
À l’inverse les 12 autres registres sont généraux, on peut y mettre ce qu’on veut.
Nous vous avons reproduit en annexe (page 13 et suivantes) les passages correspondants de la
documentation. Vous n’en avez pas besoin pour l’instant, mais pensez à y revenir lorsque vous
voudrez des détails sur l’usage des registres.
a. voir par exemple les figures 9.2 et 9.3 du poly de cours (page 80)
Exercice 5 Allez lire la page https://fr.wikipedia.org/wiki/Registre_de_processeur et résumez, en
une phrase, la différence entre un registre spécialisé et un registre général.
5
Exercice 6
contrôle.
2
Sur le schéma de la page 4, indiquez où se trouvent nos 16 registres, ainsi que l’automate de
Prise en main des outils : mspdebug
Pour communiquer avec la carte au travers de la sonde JTAG, on va utiliser un programme appelé
mspdebug. Cet outil va nous permettre de charger des programmes dans la mémoire, d’observer et de
contrôler l’exécution du programme, d’inspecter le contenu du CPU et de la mémoire, etc.
Exercice 7
Démarrez mspdebug en tapant la ligne commande suivante :
mspdebug -j -d /dev/ttyUSB0 uif
Vous devez obtenir une série d’informations techniques compliquées, puis une liste des commandes
disponibles, et enfin un prompt de la forme (mspdebug) en début de ligne. Commencez par effacer
complètement la puce en tapant dans mspdebug la commande erase .
On va maintenant se servir de mspdebug pour allumer et éteindre la diode LED4 sans passer par le CPU.
Pour initialiser la diode, il faut écrire la valeur 2 à l’adresse 49. Ensuite, on l’allumera en écrivant la valeur 2
à l’adresse 50, et on l’éteindra en écrivant 0 à l’adresse 50. 1
Exercice 8
Toujours dans mspdebug, tapez help mw et lisez l’aide de la commande memory write.
Remarquez au passage que vous pouvez aussi taper help tout court pour obtenir la liste des commandes
disponibles, et help bidule pour obtenir de l’aide sur la commande bidule.
Exercice 9
3
Faites s’allumer et s’éteindre la diode quelques fois.
Exécution d’un programme en mode pas-à-pas
Exercice 10
Créez un nouveau répertoire TP1, et retapez 2 dans un fichier tp1.s le programme suivant :
.section .init9
main:
/* initialisation de la diode rouge */
mov.b #2, &49
/* eteindre */
mov.b #0, &50
/* allumer */
mov.b #2, &50
loop:
jmp loop
Exercice 11
Traduisez ce programme en langage machine avec la commande suivante :
msp430-as -mmcu=msp430fg4618 -o tp1.o tp1.s
1. En effet, dans la vie, pour communiquer avec les périphériques depuis le processeur, on s’y prend de la même façon que
pour communiquer avec la RAM. Ce sera d’ailleurs le sujet du TP2.
2. Vous pouvez aussi essayer de copier-coller depuis le PDF, mais il faudra pas venir vous plaindre que ça marche pas (ce qui
sera le cas). Et puis c’est réellement formateur de retaper les exemples (si, si).
6
À savoir : assemblage VS éditions de liens
Pour passer d’un programme en langage assembleur à un programme exécutable, il faut réaliser
deux opérations :
1) l’assemblage consiste à convertir un fichier texte contenant des instructions vers un fichier
binaire contenant les même instructions, mais en langage machine. L’outil qui fait ça, l’assembleur, est typiquement nommé as , et permet de passer d’un fichier bidule.s à un fichier
bidule.o. C’est ce qu’on vient de faire dans l’exercice précédent. Mais ce n’est pas fini : le
programme consiste peut-être en plusieurs morceaux, qu’il faut maintenant coller ensemble.
2) l’édition de liens consiste à coller ensemble plusieurs fichiers machin.o, et à placer chacun
d’entre eux aux bonnes adresses, par exemple pour s’assurer qu’ils ne se marchent pas les
uns sur les autres. L’outil qui fait ça, l’éditeur de liens, est typiquement nommé ld , et produit
un fichier truc.elf
Invoquer ces différents outils comme il faut avec les bonnes options est compliqué et souvent source
d’erreur. Heureusement, il existe aussi une commande générique gcc qui est beaucoup plus simple
d’usage, et qui se charge d’appeler as et ld dans le bon ordre et avec les bons arguments. Ainsi,
vous pouvez obtenir directement un exécutable avec la commande suivante :
msp430-gcc -mmcu=msp430fg4618 -mdisable-watchdog -o truc.elf truc.s
Exercice 12
Depuis mspdebug, transférez votre programme sur la carte en utilisant la commande
prog tp1.elf , puis lancez-le avec la commande run . Constatez que la diode reste toujours allumée
(c’est normal, on ne l’éteint jamais). Interrompez l’exécution en appuyant sur Ctrl+C.
Exercice 13 Dans tp1.s, déplacez les instructions d’allumage et d’extinction à l’intérieur de la boucle
infinie, et exécutez de nouveau votre programme. Constatez que la diode reste encore toujours allumée.
En réalité, elle clignote bien, mais trop rapidement pour notre œil. C’est parce que la boucle tourne trop
vite ! La fréquence du CPU est de 1MHz, et chaque instruction prend une poignée de cycles d’horloge,
donc notre boucle tout entière tourne à plus de 100kHz. Interrompez de nouveau l’exécution, et au lieu de
la relancer avec run , utilisez cette fois la commande step qui exécute une seule instruction machine.
(faites donc help run et help step au passage). Constatez qu’en exécutant ainsi le programme en mode
pas-à-pas, on arrive maintenant à voir ce qui se passe.
4
Programmation en assembleur
Vous allez maintenant devoir modifier votre programme. Pour la syntaxe ASM, aidez-vous des explications
qui sont données dans les deux encadrés page suivante et page 9. Pour la mise au point, utilisez mspdebug.
En plus des commande qu’on a vues jusqu’ici, vous aurez peut-être besoin de la commande md pour
lire la mémoire, et de setbreak pour mettre des points d’arrêt. Commencez donc par taper help md et
help setbreak.
Exercice 14 Modifiez votre programme afin de ralentir suffisamment la boucle infinie pour pouvoir observer le clignotement à l’oeil nu. Pour cela, vous allez rajouter une boucle (ou plusieurs) qui incrémente une
variable jusqu’à atteindre une certaine valeur, par exemple 20000. Faites valider par un enseignant.
7
Utile pour le TP : La syntaxe ASM du msp430
Vous avez déjà rencontré ce jeu d’instructions en TD, mais avec une syntaxe un peu simplifiée. On
vous présente ici la syntaxe que vous allez devoir utiliser en TP.
Opérations La plupart des instructions est de la forme OPCODE SRC, DST . OPCODE est l’opération souhaitée, par exemple ADD, XOR, MOV, etc. La liste complète est donnée page suivante. SRC
et DST indiquent les opérandes sur lesquels travailler. Chaque opérande est de l’une des formes
suivantes :
— un nom de registre : R7, R15... (utilisez les numéros, pas de «SP» ni «PC» etc.)
— une constante immédiate : #42, #0xB600...
— une case mémoire désignée par son addresse : &1234, &0x3100...
Par exemple, l’instruction ADD &1000, R5 calcule la somme de R5 et de la valeur contenue dans
la case d’adresse 1000, et range le résultat dans R5. Attention, certaines combinaisons n’ont pas
de sens, et seront rejetées par l’assembleur avec un message d’erreur. Par exemple l’instruction
MOV R8, #36 ne veut rien dire.
Certaines instructions travaillent sur un seul opérande, et ont donc une syntaxe légèrement différente.
Par exemple INV DST inverse chacun des bits de DST, ou CLR DST met DST à zéro. Reportezvous à la liste page suivante pour plus de détails, et/ou à la doc : msp430x4xx.pdf page 61 et
suivantes.
Drapeaux Certaines instructions, notamment les opérations arithmétiques et logiques, modifient
le registre d’état (R2, cf encadré page 15), en particulier les drapeaux Z, N, C, V :
— Z est le Zero bit. Il passe à 1 lorsque le résultat d’une opération est nul, et il passe à 0 lorsqu’un
résultat est non-nul.
— N est le Negative bit. Il passe à 1 lorsque le résultat d’une opération est négatif (en complément
à deux) et il passe à 0 lorsqu’un résultat est non-négatif.
— C est le Carry bit. Il passe à 1 lorsqu’un calcul produit une retenue sortante, et il passe à 0
lorsqu’un calcul ne produit pas de retenue sortante.
— V est le Overflow bit. Il est mis à 1 lorsque le résultat d’une opération arithmétique déborde de
la fourchette des valeurs signées (en complément à deux), et à 0 sinon.
La liste page suivante détaille l’effet de chaque instruction sur les quatre drapeaux : un tiret lorsque
le drapeau n’est pas affecté, un 1 ou un 0 lorsque le drapeau passe toujours à une certaine valeur,
et une étoile lorsque l’effet sur le drapeau dépend du résultat.
Sauts conditionnels Les instructions de branchement sont de la forme JUMP label . Regardez
par exemple le programme page 6. Le saut peut être soit inconditionnel (instruction JMP), soit soumis
à une condition sur les drapeaux. Par exemple, l’instruction JNZ label est un Jump if Non-Zero :
elle sautera vers label si et seulement si le bit Z est faux.
Opérandes «word» ou «byte» Chaque instruction peut travailler sur des mots de 16 bits, ou sur
des octets. Il faut pour cela on préciser OPCODE.B. Par exemple, l’instruction MOV.B R10, &42
copie les 8 bits de poids faible de R10 vers l’octet situé à l’adresse 42, alors que l’instruction
MOV R10, &42 copie tout le contenu de R10 vers les deux octets situés aux adresses 42 et 43 a .
Reportez-vous à l’encadré page 17 pour plus de détails.
a. Précision : les 8 bits de poids faible vont en 42, et les 8 bits de poids fort vont en 43. On dit que le msp430 est de
type little-endian. Allez lire https://fr.wikipedia.org/wiki/Endianness si c’est la première fois que vous voyez ce
mot.
8
Extrait de la documentation : msp430x4xx.pdf page 115
Description
Operation
V
N
Z
ADC(.B)
dst
Add C to destination
dst + C → dst
*
*
*
*
ADD(.B)
src,dst
Add source to destination
src + dst → dst
*
*
*
*
ADDC(.B)
src,dst
Add source and C to destination
src + dst + C → dst
*
*
*
*
AND(.B)
src,dst
AND source and destination
src .and. dst → dst
0
*
*
*
Mnemonic
C
BIC(.B)
src,dst
Clear bits in destination
.not.src .and. dst → dst
−
−
−
−
BIS(.B)
src,dst
Set bits in destination
src .or. dst → dst
−
−
−
−
BIT(.B)
src,dst
Test bits in destination
src .and. dst
0
*
*
*
BR
dst
Branch to destination
dst → PC
−
−
−
−
CALL
dst
Call destination
PC+2 → stack, dst → PC
−
−
−
−
CLR(.B)
dst
Clear destination
0 → dst
−
−
−
−
0
CLRC
Clear C
0→C
−
−
−
CLRN
Clear N
0→N
−
0
−
−
CLRZ
Clear Z
0→Z
−
−
0
−
*
CMP(.B)
src,dst
Compare source and destination
dst − src
*
*
*
DADC(.B)
dst
Add C decimally to destination
dst + C → dst (decimally)
*
*
*
*
DADD(.B)
src,dst
Add source and C decimally to dst.
src + dst + C → dst (decimally)
*
*
*
*
*
DEC(.B)
dst
Decrement destination
dst − 1 → dst
*
*
*
DECD(.B)
dst
Double-decrement destination
dst − 2 → dst
*
*
*
*
Disable interrupts
0 → GIE
−
−
−
−
−
DINT
Enable interrupts
1 → GIE
−
−
−
INC(.B)
dst
Increment destination
dst +1 → dst
*
*
*
*
INCD(.B)
dst
Double-increment destination
dst+2 → dst
*
*
*
*
.not.dst → dst
EINT
INV(.B)
dst
Invert destination
JC/JHS
label
Jump if C set/Jump if higher or same
JEQ/JZ
label
Jump if equal/Jump if Z set
−
−
−
−
JGE
label
Jump if greater or equal
−
−
−
−
−
JL
label
Jump if less
JMP
label
Jump
JN
label
Jump if N set
PC + 2 x offset → PC
*
*
*
*
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
JNC/JLO
label
Jump if C not set/Jump if lower
−
−
−
−
JNE/JNZ
label
Jump if not equal/Jump if Z not set
−
−
−
−
MOV(.B)
src,dst
Move source to destination
−
−
−
−
−
−
−
−
−
src → dst
No operation
NOP
POP(.B)
dst
Pop item from stack to destination
@SP → dst, SP+2 → SP
−
−
−
PUSH(.B)
src
Push source onto stack
SP − 2 → SP, src → @SP
−
−
−
−
Return from subroutine
@SP → PC, SP + 2 → SP
−
−
−
−
*
RET
Return from interrupt
*
*
*
RLA(.B)
dst
Rotate left arithmetically
*
*
*
*
RLC(.B)
dst
Rotate left through C
*
*
*
*
RRA(.B)
dst
Rotate right arithmetically
0
*
*
*
RRC(.B)
dst
Rotate right through C
*
*
*
*
SBC(.B)
dst
RETI
Subtract not(C) from destination
dst + 0FFFFh + C → dst
*
*
*
*
SETC
Set C
1→C
−
−
−
1
SETN
Set N
1→N
−
1
−
−
SETZ
Set Z
1→C
−
−
1
−
*
SUB(.B)
src,dst
Subtract source from destination
dst + .not.src + 1 → dst
*
*
*
SUBC(.B)
src,dst
Subtract source and not(C) from dst.
dst + .not.src + C → dst
*
*
*
*
SWPB
dst
Swap bytes
−
−
−
−
SXT
dst
Extend sign
0
*
*
*
TST(.B)
dst
Test destination
dst + 0FFFFh + 1
0
*
*
1
XOR(.B)
src,dst
Exclusive OR source and destination
src .xor. dst → dst
*
*
*
*
Remarque chacune de ces instructions est documentée en détail dans la doc (msp430x4xx.pdf
page 61 et suivantes). N’hésitez pas à vous y reporter si vous avex besoin de précisions.
9
5
Programmation en C
Contrairement au langage d’assemblage qui est différent pour chaque jeu d’instructions, le langage C
permet de programmer en s’abstrayant largement des détails de l’architecture cible. Les opérations de
calcul et les structures de contrôle (boucles, fonctions, etc) ont une syntaxe unique, qui sera traduite par le
compilateur vers un programme ASM avec les bonnes instructions. Cependant, même s’il est découplé de
l’architecture concrète de la machine, le langage C offre au programmeur une vue abstraite calquée sur
l’architecture de von Neumann : un processeur d’un côté, et une mémoire de l’autre côté. La syntaxe des
pointeurs fait le lien entre les deux, permettant de désigner une case mémoire par son adresse, d’obtenir
l’adresse d’une variable, etc.
Dans cette partie du TP, on va s’intéresser à la manière dont un programme C est traduit en assembleur.
5.1
Compilation et exécution
Exercice 15
Retapez dans un fichier blink.c le programme suivant :
unsigned char* p5dir;
unsigned char* p5out;
unsigned int i;
int main(void)
{
// initialisation de la diode
p5dir = (unsigned char*) 50;
*p5dir = 2;
p5out = (unsigned char*) 49;
while(1)
{
// software delay
for(i=0;i<20000;i++)
{}//do nothing
// allumer
*p5out=2;
// software delay
for(i=0;i<20000;i++)
{}//do nothing
// eteindre
*p5out=0;
}
}
Exercice 16 En vous aidant des explications de l’encadré page suivante, compilez ce programme et
transférez-le sur le msp430. Constatez que la diode rouge clignote.
10
À savoir : la chaîne de compilation
La chaîne de compilation complète est illustrée ci-dessous :
C files
(.c)
cc (compiler)
Linker
script
(.ld)
execution
loader
as (assembler)
Assembly
files
(.s)
Object
files
(.o)
ld (linker)
Executable
program
(.elf)
objdump
(disassembler)
Disassembled
Code (.lst)
Library
object
files
(.o, .a)
Vous connaissez déjà certains outils : as, ld. Le chargement du programme, sous Linux, serait
effectué par le noyau. Dans ce TP, on utilise mspdebug pour transférer notre exécutable sur le
msp430.
Les nouveaux éléments sont cc le compilateur C, et objdump le désassembleur.
Compilation Plutôt que d’invoquer cc individuellement, on va encore une fois passer par la
commande gcc qui est plus confortable :
— pour faire seulement la compilation C vers assembleur, utilisez cette commande :
msp430-gcc -mmcu=msp430fg4618 -Wall -Werror -O1 -S -o truc.s truc.c
— pour faire la compilation et l’assemblage (C vers code machine), utilisez cette commande :
msp430-gcc -mmcu=msp430fg4618 -Wall -Werror -O1 -c -o truc.o truc.c
— pour faire aussi l’édition de liens dans la foulée, utilisez cette commande :
msp430-gcc -mmcu=msp430fg4618 -mdisable-watchdog -o truc.elf truc.c
Désassemblage Pour comprendre précisément ce qui se passe lors de l’exécution, il est souvent
utile d’examiner précisément le code machine. L’outil qui permet de faire ça s’appelle un désassembleur. Il prend en entrée un programme en langage machine (.o ou .elf) et produit en sortie
un fichier texte lisible à l’oeil nu (c’est presque de l’ASM). La ligne de commande à utiliser est la
suivante :
msp430-objdump -d truc.elf > truc.lst
Exercice 17 Désassemblez l’exécutable, et ouvrez le listing. Repérez les différents morceaux : en plus
de votre fonction main(), le linker a aussi inclus du code avant et après le programme. On ne va pas
chercher à comprendre ce code ajouté, mais par contre dans la suite on va étudier d’un peu plus près
le code assembleur de la fonction main(). Repérez respectivement l’initialisation des diodes, les deux
boucles de temporisation, la boucle infinie, et les instructions qui allument et éteignent la diode.
5.2
Compilation optimisante
Jusqu’ici, la traduction C vers assembleur restait assez directe. Mais dans le cas général, le compilateur n’a
aucune obligation de traduire ligne-par-ligne, ni de respecter l’ordre des instructions, etc. Sa seule garantie
est de respecter la sémantique de notre programme, c’est à dire intuitivement de ne pas changer «ce que
calcule» le programme. 3 Cette distinction est importante, car il existe évidemment plusieurs programmes
3. Pour avoir des idées plus précises sur les «règles du jeu» quand on utilise un compilateur, suivez un cours de compilation !
11
ASM qui «calculent la même chose» qu’un unique programme C. Le compilateur va donc essayer de
construire la meilleure traduction possible, c’est à dire celle qui calcule la même chose mais le plus vite
possible. On appelle cela l’optimisation.
Par exemple, dans notre cas, la boucle sur i n’a pas d’intérêt apparent pour la logique du programme, et
donc le compilateur peut être tenté de la supprimer complètement.
Exercice 18 Refaites l’exercice précédent en essayant les différents niveaux d’optimisation offerts par
gcc : -O0, -O1, -O2, et -O3. (Attention : la syntaxe correcte est «tiret», suivi de la lettre O majuscule, puis
d’un chiffre). Quelles sont les principales différences entre les programmes assembleur que vous obtenez ?
Exercice 19 Ajoutez à la déclaration de la variable i le mot-clé volatile, dont l’effet est d’interdire au
compilateur d’optimiser les accès à i. Une fois de plus, compilez votre programme avec les différents
niveaux d’optimisation et observez le code assembleur obtenu.
5.3
Représentation en machine des variables du programme
Pour faire cette partie, gardez le mot-clé volatile sur i et revenez au niveau d’optimisation -O1.
Exercice 20 Dans notre programme, la variable i est déclarée avec le type unsigned int. En observant
le code assembleur, indiquez quelle est la taille (en octets) de cette variable.
Modifiez votre programme en donnant à i les types int, unsigned long et également
unsigned long long. Quelle est la taille de i dans chacun de ces cas ?
Exercice 21
Exercice 22 Exécutez les quatre versions différentes du programme et comparez les fréquences de
clignotement dans chacun des cas. Comment expliquez-vous ces différences ?
Exercice 23 En observant de près le code des différentes versions, et/ou en les exécutant pas-à-pas,
expliquez comment est incrémentée la variable i dans chaque version.
12
Annexe : documentation des registres du CPU
Extrait de la documentation : msp430x4xx.pdf page 44
CPU Registers
3.2 CPU Registers
The CPU incorporates sixteen 16-bit registers. R0, R1, R2 and R3 have
dedicated functions. R4 to R15 are working registers for general use.
3.2.1
Program Counter (PC)
The 16-bit program counter (PC/R0) points to the next instruction to be
executed. Each instruction uses an even number of bytes (two, four, or six),
and the PC is incremented accordingly. Instruction accesses in the 64-KB
address space are performed on word boundaries, and the PC is aligned to
even addresses. Figure 3−2 shows the program counter.
Figure 3−2. Program Counter
15
1
Program Counter Bits 15 to 1
0
0
The PC can be addressed with all instructions and addressing modes. A few
examples:
MOV
MOV
MOV
3-4
#LABEL,PC ; Branch to address LABEL
LABEL,PC ; Branch to address contained in LABEL
@R14,PC ; Branch indirect to address in R14
RISC 16-Bit CPU
13
Extrait de la documentation : msp430x4xx.pdf page 45
CPU Registers
3.2.2
Stack Pointer (SP)
The stack pointer (SP/R1) is used by the CPU to store the return addresses
of subroutine calls and interrupts. It uses a predecrement, postincrement
scheme. In addition, the SP can be used by software with all instructions and
addressing modes. Figure 3−3 shows the SP. The SP is initialized into RAM
by the user, and is aligned to even addresses.
Figure 3−4 shows stack usage.
Figure 3−3. Stack Pointer
15
1
0
Stack Pointer Bits 15 to 1
MOV
MOV
PUSH
POP
2(SP),R6
R7,0(SP)
#0123h
R8
;
;
;
;
0
Item I2 −> R6
Overwrite TOS with R7
Put 0123h onto TOS
R8 = 0123h
Figure 3−4. Stack Usage
Address
PUSH #0123h
POP R8
0xxxh
I1
I1
I1
0xxxh − 2
I2
I2
I2
0xxxh − 4
I3
I3
I3
SP
SP
0123h
0xxxh − 6
SP
0123h
0xxxh − 8
The special cases of using the SP as an argument to the PUSH and POP
instructions are described and shown in Figure 3−5.
Figure 3−5. PUSH SP - POP SP Sequence
PUSH SP
POP SP
SPold
SP1
SP1
The stack pointer is changed after
a PUSH SP instruction.
SP2
SP1
The stack pointer is not changed after a POP SP
instruction. The POP SP instruction places SP1 into the
stack pointer SP (SP2=SP1)
RISC 16-Bit CPU
14
3-5
Extrait de la documentation : msp430x4xx.pdf page 46
CPU Registers
3.2.3
Status Register (SR)
The status register (SR/R2), used as a source or destination register, can be
used in the register mode only addressed with word instructions. The
remaining combinations of addressing modes are used to support the
constant generator. Figure 3−6 shows the SR bits.
Figure 3−6. Status Register Bits
15
9
8
V
Reserved
7
SCG1
0
OSC CPU
SCG0
GIE
OFF OFF
N
Z C
rw-0
Table 3−1 describes the status register bits.
Table 3−1.Description of Status Register Bits
3-6
Bit
Description
V
Overflow bit. This bit is set when the result of an arithmetic operation
overflows the signed-variable range.
ADD(.B),ADDC(.B)
Set when:
Positive + Positive = Negative
Negative + Negative = Positive,
otherwise reset
SUB(.B),SUBC(.B),CMP(.B)
Set when:
Positive − Negative = Negative
Negative − Positive = Positive,
otherwise reset
SCG1
System clock generator 1. This bit, when set, turns off the DCO dc
generator, if DCOCLK is not used for MCLK or SMCLK.
SCG0
System clock generator 0. This bit, when set, turns off the FLL+ loop
control
OSCOFF
Oscillator Off. This bit, when set, turns off the LFXT1 crystal oscillator,
when LFXT1CLK is not use for MCLK or SMCLK
CPUOFF
CPU off. This bit, when set, turns off the CPU.
GIE
General interrupt enable. This bit, when set, enables maskable
interrupts. When reset, all maskable interrupts are disabled.
N
Negative bit. This bit is set when the result of a byte or word operation
is negative and cleared when the result is not negative.
Word operation:
N is set to the value of bit 15 of the
result
Byte operation:
N is set to the value of bit 7 of the
result
Z
Zero bit. This bit is set when the result of a byte or word operation is 0
and cleared when the result is not 0.
C
Carry bit. This bit is set when the result of a byte or word operation
produced a carry and cleared when no carry occurred.
RISC 16-Bit CPU
15
Extrait de la documentation : msp430x4xx.pdf page 47
CPU Registers
3.2.4
Constant Generator Registers CG1 and CG2
Six commonly-used constants are generated with the constant generator
registers R2 and R3, without requiring an additional 16-bit word of program
code. The constants are selected with the source-register addressing modes
(As), as described in Table 3−2.
Table 3−2.Values of Constant Generators CG1, CG2
Register
As
Constant
Remarks
R2
00
−−−−−
Register mode
R2
01
(0)
Absolute address mode
R2
10
00004h
+4, bit processing
R2
11
00008h
+8, bit processing
R3
00
00000h
0, word processing
R3
01
00001h
+1
R3
10
00002h
+2, bit processing
R3
11
0FFFFh
−1, word processing
The constant generator advantages are:
! No special instructions required
! No additional code word for the six constants
! No code memory access required to retrieve the constant
The assembler uses the constant generator automatically if one of the six
constants is used as an immediate source operand. Registers R2 and R3,
used in the constant mode, cannot be addressed explicitly; they act as
source-only registers.
Constant Generator − Expanded Instruction Set
The RISC instruction set of the MSP430 has only 27 instructions. However, the
constant generator allows the MSP430 assembler to support 24 additional,
emulated instructions. For example, the single-operand instruction:
CLR
dst
is emulated by the double-operand instruction with the same length:
MOV
R3,dst
where the #0 is replaced by the assembler, and R3 is used with As = 00.
INC
dst
is replaced by:
ADD
0(R3),dst
RISC 16-Bit CPU
16
3-7
Extrait de la documentation : msp430x4xx.pdf page 48
CPU Registers
3.2.5
General-Purpose Registers R4 to R15
Twelve registers, R4 to R15, are general-purpose registers. All of these
registers can be used as data registers, address pointers, or index values, and
they can be accessed with byte or word instructions as shown in Figure 3−7.
Figure 3−7. Register-Byte/Byte-Register Operations
Register-Byte Operation
High Byte
Byte-Register Operation
Low Byte
High Byte
Unused
Byte
Register
Memory
Byte
Example Byte-Register Operation
R5 = 0A28Fh
R5 = 01202h
R6 = 0203h
R6 = 0223h
Mem(0203h) = 012h
Mem(0223h) = 05Fh
ADD.B
ADD.B
R5,0(R6)
Memory
Register
0h
Example Register-Byte Operation
08Fh
@R6,R5
05Fh
+ 012h
+ 002h
0A1h
00061h
Mem (0203h) = 0A1h
R5 = 00061h
C = 0, Z = 0, N = 1
C = 0, Z = 0, N = 0
(Low byte of register)
3-8
Low Byte
(Addressed byte)
+ (Addressed byte)
+ (Low byte of register)
−>(Addressed byte)
−>(Low byte of register, zero to High byte)
RISC 16-Bit CPU
17
Téléchargement