Obligement - L'Amiga au maximum

Vendredi 24 mai 2019 - 05:03  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Assembleur - Utilisation et programmation des interruptions
(Article écrit par Philippe Rivaillon et extrait d'Amiga News Tech - mars 1992)


Oui, vous avez bien lu : interruptions. Je sais, ça fait le troisième article sur ce sujet dans l'ANT, et vous vous attendez sûrement à du rabâchage...

Eh bien non, car les interruptions ont été traitées seulement sous Exec. Moi, je vous propose d'aborder les interruptions sans passer par la moindre bibliothèque : on va faire ça à la main comme des grands. De plus, nous allons voir en détail les sources d'interruptions et leur utilisation. Enfin, nous jetterons un coup d'oeil sur les exceptions et les instructions TRAP. Allez, entrons dans le vif du sujet...

Les interruptions matérielles

Ces interruptions permettent soit de se synchroniser avec le matériel, soit d'effectuer des actions à des moments bien précis (ni avant, ni après). De plus, l'utilisation d'interruptions permet un gain de temps non négligeable : pendant que l'on attend un événement, on peut effectuer d'autres tâches (qui ne dépendent pas du résultat de cet événement, bien entendu).

Étudions donc les registres de contrôle d'interruptions afin d'en mieux connaître la provenance et l'utilisation.

INTENA  $DFF09A Interruptions autorisées (écriture)
INTENAR $DFF01C Interruptions autorisées (lecture)

Registres modifiés par l'utilisateur pour spécifier ses choix.

INTREQ  $DFF09C Interruptions demandées (écriture)
INTREQR $DFF01E Interruptions demandées (lecture)

Registres utilisés par le système pour lancer le processus d'interruption. Également modifiés par l'utilisateur une fois l'interruption effectuée (effaçage du bit de déclenchement de l'interruption).

Le format de ces quatre registres (en fait, seulement deux, mais ayant chacun une adresse en lecture et une en écriture) est identique. La description qui suit est donc générale.

Bit 15 : SET/CLR

Lors d'une écriture dans INTENA ou INTREQ, si le bit 15 est mis, tous les autres bits à 1 du mot transféré sont également mis à 1 dans la destination et ceux qui étaient à 0 dans la source resteront inchangés. Si le bit 15 est à 0, tous les bits à 1 de la source seront effacés dans la destination et ceux qui étaient à 0 dans la source resteront inchangés.

Exemples :

Pour effacer les bits 0 à 7 d'INTREQ : move.w #$00ff,$DFF09C.
Pour placer les bit 0 à 7 d'INTENA : move.w #$80ff,$DFF09A.

Bit 14 : INTEN (Master Interrupt Enable)

Les interruptions ne peuvent avoir lieu que si ce bit est mis à un dans INTENA. En le mettant à 0, vous supprimez toutes les tentatives d'interruption.

Bit 13 : EXTER (IRQ niveau 6)

Ce bit concerne l'interruption externe à travers le CIA B (voir la note ci-dessous).

Bit 12 : DSKSYN (IRQ niveau 5)

Ce bit concerne l'interruption ayant lieu lorsque la lecture des données d'un lecteur de disquette est synchronisée avec le contenu du registre DSKSYNC ($DFF07E). Pour que cette interruption soit déclenchée, il faut que la demande de synchronisation ait été faîte (bit 9 de ADKCON mis à 1).

Bit 11 : RBF (Receive Buffer Full, IRQ niveau 5)

Ce bit concerne l'interruption pour le port série 1. Elle sera exécutée si le tampon mémoire d'entrée (SERDATR, $DFF018) est plein et peut être lu par l'utilisateur (voir aussi le bit 0).

Bits 10-7 : AUD3-0 (IRQ niveau 4)

Ces quatre bits concernent les interruptions pour les canaux audio 3 à 0. En mode automatique, elles ont lieu dès que Paula a pris en compte le contenu des registres audio (que l'on peut alors changer). En mode manuel, elles ont lieu à la fin de chaque transmission d'un mot de donnée sonore (on charge alors le prochain mot). Pour plus de renseignements sur ces interruptions, reportez-vous à cet article.

Bit 6 : BLIT (Blitter Finished, IRQ niveau 3)

Ce bit concerne l'interruption ayant lieu dès que le Blitter a fini sa tâche. Notez que le bit 14 de DMACONR ($DFF002) permet aussi de savoir si le Blitter a fini son travail. L'utilisation de l'une ou l'autre méthode dépend du contexte. Mais, en règle générale, la seconde est plus souvent utilisée, surtout quand le Blitter est beaucoup sollicité (sinon, on perd trop de temps lors des interruptions). La première peut rendre de grands services quand deux transferts importants se suivent : le second transfert sera déclenché par interruption dès la fin du premier. Ceci permettra d'effectuer de nombreuses tâches dès l'envoi du premier transfert, sans se soucier du deuxième.

Bit 5 : VERTB (Vertical Blank, IRQ niveau 3)

Ce bit concerne l'interruption de retour du spot de balayage vidéo. Elle a lieu dès que celui-ci est arrivé en bas du moniteur et qu'il s'apprête à remonter.

Bit 4 : COPPER (IRQ niveau 3)

Ce bit concerne l'interruption... Copper (gagné !). C'est l'utilisateur qui décide de la déclencher, à l'aide d'une liste Copper appropriée.

Bit 3 : PORTS (IRQ niveau 2)

Ce bit concerne l'interruption externe à travers le CIA A (voir la note ci-dessous).

Bit 2 : SOFT (IRQ niveau 1)

Ce bit concerne les interruptions logicielles (voir article sur les interruptions sous Exec).

Bit 1 : DSKBLK (IRQ niveau 1)

Ce bit concerne l'interruption ayant lieu lorsque la transmission des données à travers le canal DMA disque est achevée (fin d'une lecture ou d'une écriture). Cette interruption est le seul moyen de savoir quand le lecteur a fini son travail.

Bit 0 : TBE (Transmit Buffer Empty, IRQ niveau 1)

Ce bit concerne l'interruption pour le port série 1. Elle est déclenchée lorsque le tampon mémoire de sortie (SERDAT, $DFF030) est près à recevoir de nouvelles données (voir aussi le bit 11).

Note concernant les interruptions CIA : tout d'abord, notons que les CIA ont été traités dans ces articles : 1, 2 et 3. Vous savez sans doute qu'il existe plusieurs sources d'interruptions pour chaque CIA (A et B) : timers, clavier, etc. Donc, lorsqu'une interruption de niveau 2 ou 6 survient, il faut être capable de différencier la source de cette interruption au sein du CIA concerné. De plus, il faut pouvoir contrôler les interruptions (autorisation, interdiction) des CIA. Pour cela, et aussi bizarre que cela puisse paraître, nous ne disposons que d'un registre de contrôle par CIA !

Le fonctionnement est en fait très simple : lors de l'écriture, on fixe les interruptions autorisées et interdites à l'aide d'un masque (même fonctionnement que pour INTENA) et lors de la lecture, on se renseigne sur les interruptions survenues. En gros, c'est comme si nous avions une sorte d'INTENA (écriture) et d'INTREQR (lecture) dans le même registre.

A chaque lecture de ces registres le contenu en est effacé : c'était le seul moyen d'indiquer qu'une interruption avait été traitée puisqu'une écriture n'agit que sur les autorisations d'IT. C'est bien pratique, mais attention à bien traiter toutes les interruptions survenues : il ne peut y avoir qu'une lecture, donc chargez le contenu du registre voulu dans un registre de donnée et effectuez ensuite vos tests, sinon, certaines interruptions risqueraient de ne jamais être traitées.

Un autre problème se pose du fait de la structure de ces registres : comment savoir quelles interruptions sont autorisées avant de les traiter ? A la lecture, le bit 7 permet de savoir si au moins l'une des interruptions survenues est autorisée. Il faudra se contenter de cela, mais dans la plupart des cas ce sera suffisant (il est rare que deux interruptions aient lieu simultanément).

ICR-A $BFED01 (Interrupt Control Register CIA A)
ICR-B $BFED00 (Interrupt Control Register CIA B)

Attention, seul l'octet de poids faible est utilisé.

Bit 7 : SET/CLR (écriture) - IR (lecture)

En écriture, ce bit a les mêmes fonctions que le bit 15 d'INTENA (voir plus haut). En lecture, il permet de déterminer quelle interruption est survenue, d'après la table suivante :
  • Si les bits 0 à 6 sont à 0, IR l'est aussi.
  • Si un et un seul des bits 0 à 6 est mis, IR l'est aussi si l'interruption correspondante (pour le CIA s'entend) est autorisée. Sinon, IR est à 0.
  • Si plusieurs des bits 0 à 6 sont mis, IR l'est aussi si au moins une des interruptions correspondantes est autorisée (laquelle ? ben, heu...). Sinon, IR est à 0.
Bit 6 et 5

Inutilisés.

Bit 4 : FLG

Interruption par drapeau (flag).

Bit 3 : SP

Interruption due au port série plein ou vide. Dans le cas du CIA A, cela signifie qu'une donnée émanant du clavier est arrivée.

Bit 2 : ALRM

Interruption de TOD alarme.

Bit 1 : TB

TIMER B arrivé en dessous de 0.

Bit 0 : TA

TIMER A arrivé en dessous de 0.

Interruption, me voici !

Je ne reprendrai pas l'explication parfaite accomplie dans cet article. Je prends le relais juste au moment où le 68000, une fois passé en mode superviseur, saute au vecteur correspondant au niveau de l'interruption. Rappelons tout de même que ces vecteurs sont situés de $64 à $7C pour les interruptions de niveau 1 à 7.

Voyons donc comment se déroule une routine de traitement d'interruption typique.
  1. Sauvegarde des registres du processeur utilisés dans le programme d'interruption.
  2. Vérification d'INTEN afin de déterminer si on doit traiter ou non les interruptions.
  3. Vérification de la provenance de l'interruption.
  4. Traitement le cas échéant et effacement du drapeau correspondant dans INTREQ (sinon, cette même interruption sera traitée une infinité de fois).
  5. Restauration des registres sauvegardés en 1.
  6. Retour au mode utilisateur par RTE.
Le processus est donc très simple : vous initialisez correctement INTENA pour autoriser votre interruption et vous précisez l'adresse de votre routine dans le tableau de vecteurs en ayant bien soin de sauvegarder l'ancienne adresse afin de la replacer une fois le travail accompli. Comme vous le voyez sûrement, cette méthode n'est pas vraiment compatible avec le multitâche (NDLR : quel doux euphémisme...), puisque vous n'effectuez que votre propre interruption...

Voici maintenant une méthode permettant, dans certains cas, d'éviter la perte de temps causée par l'exécution d'une interruption et de simplifier les choses : primo, ne pas autoriser les interruptions ; secundo, faire une boucle d'attente testant INTREQR ; tertio, vider INTREQ. Cela est intéressant dans des cas d'attente du lecteur de disquette, d'un chronomètre, etc.

Exemples d'application

Les routines suivantes ne sont bien sûr pas directement exécutables, mais vous donneront un ordre d'idée de ce qu'il faut faire : c'est à mon avis le principal (un long source est moins intéressant). Bref, il s'agit d'une synchronisation toute bête avec l'écran.

Première méthode : interruption simple

interruptions

Deuxième méthode : interruption avec retranchement sur l'ancienne

interruptions

Troisième méthode : interruption ???

interruptions

Les exceptions

Les interruptions n'étant finalement rien d'autre qu'un type particulier d'exception, il était normal de terminer cet article par leur étude. Pour définir simplement les exceptions, on pourrait dire qu'il s'agit d'interruptions système servant à la détection des erreurs et, dans le cas de l'Amiga, débouchant parfois sur les terribles Guru Mediations. Vous comprenez aisément l'intérêt de tout ceci : orienter les erreurs du système vers ses propres routines de traitement. C'est notamment ainsi que les débogueurs procèdent pour que vos programmes ne plantent pas l'ordinateur à la moindre erreur de votre part.

Il existe deux types d'exceptions : celles causées volontairement par le programmeur (diverses instructions du 68000 sont spécialement prévues à cet effet), et celles causées involontairement, suite à un bogue du programme. Nous commencerons cette étude par la deuxième catégorie.

La chasse aux bogues

N'oublions pas que l'exception n'est qu'une interruption : il se passe exactement la même chose pour les deux et la programmation est aussi la même (RTE à la fin de la routine). La seule chose qu'il reste à savoir est : où mettre l'adresse de sa routine ? Cadeau, voici la liste des vecteurs d'exceptions, classés par adresses.
  • Erreur Bus ($00000008) : déclenchée par la machine ou par un coprocesseur, par exemple lors d'accès à une zone de mémoire réservée ou inexistante.
  • Erreur d'adresse ($0000000C) : se produit lors d'un accès à une adresse mémoire impaire avec un mot ou un mot long.
  • Instruction illégale ($00000010) : déclenchée si une instruction n'est pas reconnue. Le jeu d'instruction du 68000 étant codé sur deux octets, cela donne 65 536 possibilités différentes. Le 68000 est loin d'en connaître autant.
  • Division par zéro ($00000014) : no comment !
  • Instruction CHK ($00000018) : déclenchée par l'instruction CHK (voir plus loin).
  • Instruction TRAPV ($0055001C) : déclenchée si le bit V (bit 1) du mot d'état (SR) est mis lors de l'exécution de l'instruction TRAPV (voir plus loin).
  • Violation de privilège ($00000020) : déclenchée si une instruction ou une zone mémoire réservée au mode superviseur est utilisée en mode utilisateur (sur Amiga, toute la mémoire disponible est accessible aussi bien en mode utilisateur qu'en mode superviseur).
  • Trace ($00000024) : exécutée après chaque instruction en mode Trace (bit 15 du registre SR). Facilite la conception d'un débogueur.
  • Lignes "A" ($00000028) et "F" ($0000002C) : déclenchée dès qu'une instruction du type $Axxx ou $Fxxx est lue par le 68000 (par exemple, $A020 ou $F001). Cela permet de se fabriquer de nouvelles instructions que le 68000 ne possède pas. L'interprétation se fera lors de l'exception.
  • Interruption non initialisée ($0000003C) : déclenchée si une interruption est provoquée par un périphérique non initialisé.
  • Interruption parasite ($00000060) : déclenchée si une erreur Bus survient pendant la confirmation de l'interruption par le circuit l'ayant provoquée : l'interruption était un parasite.
Le reste ne constitue plus réellement des exceptions, mais jetons tout de même un rapide coup d'oeil dessus.
  • Interruptions niveau 1-7 ($00000064 - $0000007C).
  • Instructions TRAP ($00000080 - $000000BC).
  • Interruptions utilisateur ($00000100 - $000003FF).
Attention a la Trap...

Comme vous l'avez deviné, nous allons maintenant étudier les instructions TRAP. Il en existe deux sortes :

TRAP #vecteur

Le vecteur est exprimé sur 4 bits ; il désigne donc un chiffre entre 0 et 15. Cette instruction a pour effet d'exécuter l'exception de numéro de vecteur indiqué (vecteur 0=$80->vecteur 15=$BC) après suivi du processus habituel d'interruption (passage en mode superviseur, etc.). La routine sur laquelle se branche le 68000 est programmée de la même manière qu'une interruption quelconque (sauvegarde des registres utilisés, fin par un RTE).

L'intérêt d'une telle instruction est que l'on n'a pas besoin de connaître l'adresse de la routine pour l'exécuter ; on peut réaliser un système à morphologie variable assez facilement. Par exemple, le système d'exploitation complet de l'Atari ST (TOS et GemDOS) est entièrement basé sur les TRAP.

interruptions

C'est aussi simple que ça !

TRAPV

Si le bit V (bit 1) du mot d'état SR est mis lors de l'exécution de cette instruction, il se produit une exception, sinon rien ne se passe.

Rappelons la signification de ce bit : il est utilisé pour indiquer à l'utilisateur que l'intervalle numérique ouvert a été dépassé lors d'une opération arithmétique. Par exemple :

interruptions

L'instruction TRAPV peut donc permettre à l'utilisateur de contrôler si des résultats d'opérations arithmétiques ne sont pas erronés et dénués de sens, du fait qu'ils dépassent l'intervalle fixé. C'est donc très important dans les applications mathématiques ou demandant des calculs précis.

Instruction CHK

CHK <adresse effective>,Dn

Cette instruction vérifie que le mot de poids faible du registre spécifié Dn est compris entre 0 et une limite supérieure donnée. Si ce n'est pas le cas, c'est-à-dire si Dn.W<0 ou Dn.W><adresse effective>, alors l'exception CHK est déclenchée.


[Retour en haut] / [Retour aux articles]