Un pointeur est un groupe de cases mémoires (2 ou 4 octets
suivants les implémentations) pouvant contenir une adresse,
exemple:
char C;
char *PtC;
C est une variable de type char et PtC est un
pointeur
pouvant pointer des objets de type char.
L'opérateur & donne l'adresse d'un objet; pour faire
pointer PtC vers C il faut donc utiliser l'instruction:
PtC = &C; /* l'adresse de C est rangée dans PtC. */
L'opérateur étoile (*) représente
l'opérateur
d'indirection. Si on l'applique a un pointeur, il donne accès a
l'objet pointe par ce
pointeur. Les 2 exemples suivants montrent comment utiliser les
opérateurs
& et *:
exemple1:
char c;
char *p;
p = &c; /*
l'adresse de c est rangée dans p */
*p = 'd'; /* c vaut
maintenant
le caractère 'd' */
int tab[10];
int *pt;
exemple2:
pt = &tab[5]; /* l'adresse de
la case 5 du tableau tab est rangée dans pt */
*pt =
12;
/* la case 5 de tab vaut maintenant 12 */
pt = pt + 1; /* pt pointe
maintenant la case 6 de tab */
*pt =
34;
/* la case 6 de tab vaut maintenant 34 */
#define PIA 0xF00043A1 /* adresse de base du PIA sur le kit 68040 */
/* deplacement a ajouter a l'adresse PIA pour
atteindre
* les registres du PIA:
*/
#define CRA
2
/* reg de contrôle du port A */
#define DDRA 0 /* reg de
contrôle
du port A */
#define ORA 0
/* reg de lecture/écriture du port A */
#define CRB 6 /*
reg de contrôle du port B */
#define DDRB 4 /* reg de direction
du port B */
#define ORB 4 /*
reg de lecture/écriture du port B */
Vous devez commencer par déclarer un pointeur capable de pointer les registres du PIA.
Une simple question: qu'elle est le type de donnée des registres d'un circuit PIA 6821 ?
Les registres du PIA sont sur 8 bits soit 1 octet.
Quel est le type dans du langage C qui code des données sur 1 octet ?
Et bien la réponse n'est pas trivial car elle
dépend
de du compilateur C que vous utilisez. Un petit truc pour
résoudre
cette question: l'opérateur sizeof applique a une
variable
ou bien directement a un type vous retourne la taille en octets de
cette
variable ou de ce type. Le programme suivant vous montre l'utilisation
de l'opérateur sizeof:
#include <stdio.h>
main() {
char TabChar[10];
int TabInt[10];
printf("taille
d'un
char = %d octet\n",sizeof( char ));
printf("taille d'un unsigned char = %d
octet\n",sizeof(
unsignedchar ));
printf("taille
d'un
int = %d octets\n",sizeof( int ));
printf("taille d'un unsigned int = %d
octets\n",sizeof(
unsigned int ));
printf("taille d'un short int
= %d octets\n",sizeof( short int ));
printf("taille d'un float = %d
octets\n",sizeof(
float ));
printf("taille d'un double = %d octets\n",sizeof(
double ));
printf("taille du tableau char TabChar[10] =
%d
octets\n",sizeof( TabChar ));
printf("taille du tableau int
TabInt[10]
= %d octets\n",sizeof( TabInt ));
}
Remarque: sur le kit 68040 la fonction printf n'est pas disponible, vous pouvez utiliser les fonctions suivantes:
puts( uitoa( sizeof( short int ) ) );
L'exécution de ce programme donne:
taille d'un
char = 1 octet
taille d'un unsigned char = 1 octet
taille
d'un
int = 4 octets
taille d'un unsigned int = 4 octets
taille d'un short int = 2 octets
taille d'un float = 4 octets
taille d'un double = 8 octets
taille du tableau char TabChar[10] = 10 octets
taille du tableau int TabInt[10] = 40 octets
On prendra le type char pour coder les registres 8 bits
du PIA. La déclaration du pointeur peut être la
suivante:
char *PtRegPIA;
On peut initialiser (faire pointer) PtRegPIA soit dans
le code principal avec l'instruction:
PtRegPIA = (char *) PIA;
Soit directement dans la déclaration:
char *PtRegPIA = (char *) PIA;
Remarque au sujet du "cast" (char *): Ce cast est nécessaire pour signifier au compilateur que PIA est une adresse d'un objet de type char (char = 1 octets ou 8 bits pour les registres de notre PIA).
Si l'on veut affecter la valeur 00 dans le registre CRB
il suffit d'utiliser l'instruction suivante:
*(PtRegPIA + CRB) = 0x00;
PtRegPia pointe sur le premier registre du PIA, on ajoute le déplacement CRB pour pointer sur CRB. L'opérateur * permet de modifier le contenu pointer c'est a dire mettre la valeur 0x00 dans le registre CRB. Cette instruction est relativement lourde, mais en utilisant la notation tableau l'instruction devient limpide:
PtRegPIA[ CRB ] = 0x00; /* qui est équivalent a *(PtRegPIA + CRB) = 0x00; */
On peut encore simplifier la notation *(PtRegPIA + CRB) en
masquant
sa complexité a l'aide d'un define:
#define PtRegPIA
0x05CEF1
/* adresse de base du PIA */
#define CRB *(char *) (PtRegPIA + 6) /* reg de controle du port B */
et voici son utilisation:
CRB = 0x00;
Après l'action du pré-processeur (qui est automatiquement lance avant la compilation) l'instruction précédente devient:
*(char *) (0x05CEF1 + 6) = 0x00;
| |
|
|
|
| |
|
|
- déplacement pour attendre le registre CRB.
| |
|
- l'adresse de base du PIA.
| | -
déclaration
du pointeur.
| - pointeur sur char.
|- opérateur d'indirection: pour avoir accès au
contenu pointé.
Trouver la déclaration du define n'est pas facile
mais
l'utilisation devient est extrêmement simple. Maintenant vous
devez
pouvoir aisément manipuler les pointeurs pour atteindre tous les
adresses du kit 68040.
Lors de la reconnaissance d'interruption, une copie interne du SR est effectuée, le processeur passe en mode superviseur le masque d'interruption est mis au niveau de l'interruption prise en compte (le processeur ne pourra alors être interrompu que par une interruption de niveau supérieur). Le processeur attend le numéro de vecteur du circuit qui vient de l'interrompre en effectuant une lecture:
- Place les lignes FC2,FC1 et FC0 a 1 1 1
- Place le niveau de l'interruption sur les lignes A3, A2, A1 et les lignes A19, A18, A17, A16 à 1 1 1 1 ($f)
- Active les lignes SIZ0, SIZ1 et R/W\ pour
commencer un cyle de lecture du numero de vecteur d'interruption (sur 1
octet) emit par le peripherique.
- Le peripherique doit placer son numero de vecteur et terminer le cycle en activant le DSACKx\.
Si le peripherique ne peut pas fournir de numéro de vecteur, une logique externe doit activer le signal AVEC\ processeur pour que celui-ci génère en interne un numéro de vecteur: c'est l'auto vectorisation. Sur kit 68332 l'interruption provenant du PTM genere un auto vecteur de niveau 4:
Désignation | Niveau | adresse | Provenance de l'interruption |
auto vecteur de niveau 4 | 4 | VBR + $70 | IRQ PTM 6840 |
Numéro de vecteur | [VBR] + offset | Utilisation | |
Déc. | Hexa. | ||
0 | 0 | 000 | Initialisation du SSP après un RESET |
- | 4 | 004 | Initialisation du PC après un RESET |
2 | 8 | 008 | Erreur bus |
3 | 12 | 00C | Erreur d'adresse |
4 | 16 | 010 | Instruction illégale |
5 | 20 | 014 | Division par zéro |
6 | 24 | 018 | Instruction CHK |
7 | 28 | 01C | Instruction TRAPV |
8 | 32 | 020 | Violation de privilège |
9 | 36 | 024 | Trace |
10 | 40 | 028 | Émulateur ligne 1010 |
11 | 44 | 02C | Émulateur ligne 1111 |
12-14 | 48 | 030 | réserve |
15 | 60 | 03C | Interruption non initialisée |
16-23 | 64-95 | 04C-05F | réservé |
24 | 96 | 060 | Interruption parasite |
26 | 100 | 064 | Auto-Vecteur d'interruption Niveau 1 |
26 | 104 | 068 | Auto-Vecteur d'interruption Niveau 2 |
27 | 108 | 06C | Auto-Vecteur d'interruption Niveau 3 |
28 | 112 | 070 | Auto-Vecteur d'interruption Niveau 4 |
29 | 116 | 074 | Auto-Vecteur d'interruption Niveau 5 |
30 | 120 | 078 | Auto-Vecteur d'interruption Niveau 6 |
31 | 124 | 07C | Auto-Vecteur d'interruption Niveau 7 |
32-47 | 128-191 | 080-0BF | Vecteurs d'instruction TRAP |
48-63 | 192-255 | 0C0-0FF | Réservé |
64-255 | 256-1023 | 100-3FF | Vecteurs d'interruption utilisateur |
main()
{
/* Initialisation de la table des vecteurs d'it
*/
static void (**TabVect)() = (void (**)())
AdrTabVect;
/* Mise en place du vecteurs d'it IRQ du PTM */
TabVect[ VECT_PTM ] = InterruptionPTM;
.
.
.
}
TabVect est un pointeur qui pointe vers un tableau qui contient des adresses de fonctions.