OAL OEM Adaptation Layer
description
Transcript of OAL OEM Adaptation Layer
jc/md/lp-01/05 OAL x86 1
OALOEM Adaptation Layer
(Original Equipment Manufacturer)
jc/md/lp-01/05 OAL x86 2
Objectif du chapitre
• Présentation de la couche OAL• Survol de l’initialisation de la plate-forme • Fonctionnement des interruptions dans une
architecture PC classique à base de x86• Interruptions dans Windows CE• Étude de l’exemple de la liaison série
– Contrôleur de ligne série 16550– Contrôleur d’interruption 8259 – Programmes d’initialisation du 16550 et du 8259
jc/md/lp-01/05 OAL x86 3
OAL (1)
• Couche logicielle d’adaptation entre le noyau Windows CE standard et le hardware spécifique utilisé dans une application
• L’OAL assure l’initialisation de la plate-forme lors du lancement du système à partir du boot loader ou à partir d’une réinitialisation physique « reset »
jc/md/lp-01/05 OAL x86 4
OAL (2)
• En particulier initialisation des mécanismes nécessaires immédiatement :
• Debugging (série, parallèle, Ethernet)• Interruptions• Real Time Clock• Timers• Outils de diagnostic
jc/md/lp-01/05 OAL x86 5
Interruptions x86
• 2 entrées d’interruptions sur les CPU x86– NMI non masquable– INT classique
• Nécessité d’un contrôleur externe pour disposer d’un plus grand nombre d’interruptions
• Contrôleur Intel 8259A (PIC) « norme » PC• Gestion par une table de vecteurs
jc/md/lp-01/05 OAL x86 6
PIC
• Gère 8 IT (cascadable jusqu’à 64 IT)• Gère les priorités • 2 PICs dans les CEPC (15 lignes d’IT)
– Un maître qui transmet la demande au CPU– Un esclave connecté sur l’IRQ2 du maître
jc/md/lp-01/05 OAL x86 7
OAL
• Cette couche étant spécifique au hardware réalisé, c’est au concepteur du hardware d’écrire les routines nécessaires
• Nous prendrons comme exemple les routines d’initialisation de la ligne série et du contrôleur d’interruption PIC
jc/md/lp-01/05 OAL x86 8
Configuration de base PC
• Dans l’architecture classique d’un PC, on trouve autour d’un CPU x86 au moins les éléments suivants :
• Contrôleur de ligne série : 16650• Contrôleur d’IT : 8259• Timer : 8254• Horloge temps réel RTC : 146818• Contrôleur de DMA : 8237
jc/md/lp-01/05 OAL x86 9
OAL Architecture
jc/md/lp-01/05 OAL x86 10
Démarrage de CE
• Point d’entrée : procédure _Startup • Startup appelle KernelInitialize• KernelInitialize appelle :
– OEMInitDebugSerial– OEMInit– OEMGetExtensionDRAM
• KernelInitialize lance le noyau
jc/md/lp-01/05 OAL x86 11
Startup
• Initialisation du CPU– Mode superviseur– Little endian– Disable interrupts– Inhibit du cache et du MMU– Configuration du contrôleur mémoire– Configuration des LEDs– …
• Saut à KernelInitialize
jc/md/lp-01/05 OAL x86 12
Initialisation du port de Debug
• OEMInitDebugSerial()– Configuration de la ligne série
• OEMReadDebugByte()– Lecture d’un byte
• OEMWriteDebugByte()– Écriture d’un byte
• OEMWriteDebugString()– Écriture d’une chaîne de caractères
jc/md/lp-01/05 OAL x86 13
OEMInit
• Initialisation du hardware non faite dans StartUp• Mapping des interruptions• Initialisation des PICs• Fonctions de gestion des interruptions• Initialisation des timers• Initialisation du port parallèle• Initialisation du debug Ethernet• Initialisation du bus PCI
jc/md/lp-01/05 OAL x86 14
OEMGetExtensionDRAM
• La fonction provoque le parcours de la mémoire en faisant des cycles écriture/lecture pour détecter la fin réelle de la zone mémoire.
• La valeur par défaut située dans Config.bib sera ajustée
• Un mécanisme plus complexe remplace cette fonction lorsqu’on veut gérer plus de deux sections de mémoire
jc/md/lp-01/05 OAL x86 15
Mapping des interruptions (1)
• Un système x86 dispose de 16 niveaux d’interruption (dont un sert au chaînage)
• Afin qu’un même niveau physique puisse être partagé par plusieurs périphériques, le système utilise un numéro logique SYSINTR_XXXXX
• Il faut donc créer des tables de correspondance– Numéro logique → numéro physique– Numéro physique → numéro logique
jc/md/lp-01/05 OAL x86 16
Mapping des interruptions (2)
• Il y a 40 numéros logiques possibles• Les numéros logiques 0 à15 sont réservés par
Microsoft• Le numéro logique 16 porte le nom de
SYSINTR_FIRMWARE • Un certain nombre de numéros logiques sont
affectés lors du mapping initial• Un utilisateur qui lance un driver sous IT, non
mappé au départ doit obtenir un numéro logique par la fonction KernelIoControl
jc/md/lp-01/05 OAL x86 17
Mapping des interruptions (3)
• Au départ les deux tables de correspondance sont initialisées à 0xFF
• Une macro assure le remplissage des deux tables SETUP_INTERRUPT_MAP(SysIntr,Irq)
• Une fonction de Debug est utilisée pour s’assurer qu’au départ la correspondance entre l’IT physique et l’IT logique est bien unique
jc/md/lp-01/05 OAL x86 18
Mapping des interruptions (4)
• Après lancement du système, d’autres utilisateurs pourront venir ajouter leur programme d’interruption– Sur un niveau physique libre– Sur un niveau physique déjà utilisé en
établissant un chaînage
jc/md/lp-01/05 OAL x86 19
Mapping des interruptions (5)
Void SetUpInterruptMap(){ // Initialisation des 2 tables de correspondance // Dans les fonctions prononcer le 2 à l’anglaise : « to » ! memset(g_Sysintr2IntrMap, 0xFF, sizeof(g_Sysintr2IntrMap)); memset(g_Intr2SysintrMap, 0xFF, sizeof(g_Intr2SysintrMap));
//MACRO #define SETUP_INTERRUPT_MAP(SysIntr, Irq) \ { \ DEBUGCHK(g_Sysintr2IntrMap[SysIntr] == INTR_UNDEFINED); \ DEBUGCHK(g_Intr2SysintrMap[Irq] == SYSINTR_UNDEFINED); \ g_Sysintr2IntrMap[SysIntr] = Irq; \ g_Intr2SysintrMap[Irq] = SysIntr; \ }
jc/md/lp-01/05 OAL x86 20
Mapping des interruptions (6)
// IRQ0 is timer0, the scheduler tick SETUP_INTERRUPT_MAP(SYSINTR_RESCHED,INTR_TIMER0); SETUP_INTERRUPT_MAP(SYSINTR_KEYBOARD, 1); // IRQ2 is the cascade interrupt for the second PIC
SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+3, 3); SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+4, 4); SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+5, 5);
// IRQ6 is normally the floppy controller. // IRQ7 is LPT1, It can be used for parallel port driver. SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+7, 7);
// IRQ8 is the real time clock.
jc/md/lp-01/05 OAL x86 21
Mapping des interruptions (7)
SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+9, 9); SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+10, 10); SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+11, 11); SETUP_INTERRUPT_MAP(SYSINTR_TOUCH, 12); // IRQ13 is normally the coprocessor
// IRQ14 is normally the hard disk controller. SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+14, 14); SETUP_INTERRUPT_MAP(SYSINTR_FIRMWARE+15, 15); #undef SETUP_INTERRUPT_MAP}
jc/md/lp-01/05 OAL x86 22
Fonctions de gestion des interruptions
• OEMInterruptEnable• OEMInterruptDisable• OEMInterruptDone
• Ces fonctions sont appelées par le noyau pour compléter l’action des fonctions système:
– InterruptInitialize– Interruptdisable– InterruptDone
jc/md/lp-01/05 OAL x86 23
Fonctions de gestion de consommation
• OEMIdle• OEMPowerOff
jc/md/lp-01/05 OAL x86 24
Fonctions de gestion du temps
• OEMGetRealTime• OEMSetRealTime• OEMSetAlarmTime• SC_GetTickCount
jc/md/lp-01/05 OAL x86 25
Fonctions de gestion port parallèle
• OEMParallelPortGetByte• OEMParallelPortSendByte• OEMParallelPortGetStatus
jc/md/lp-01/05 OAL x86 26
Fonctions de gestion ethernet
• OEMEthInit• OEMEthEnableInts• OEMEthDisableInts• OEMEthISR• OEMEthGetFrame• OEMEthSendFrame• OEMEthQueryClientInfo• OEMEthGetSecs
jc/md/lp-01/05 OAL x86 27
Liaison série
16550
jc/md/lp-01/05 OAL x86 28
16550
• UART asynchrone jusqu’à 1,5 Mbauds• Gestion des signaux MODEM• 12 registres internes sélectionnés par 3 signaux
d’adresse, les signaux Read et Write et le bit 7 (DLAB) du registre LCR (Line Control Register)
• Mode avec FIFO : 16 bytes en émission et en réception
• Mode sans FIFO : double buffer en émission et en réception
jc/md/lp-01/05 OAL x86 29
Registres du 16550
DLAB A2 A1 A0 R/W Register
0 0 0 0 R RBR : Receiver Buffer Register
0 0 0 0 W THR : Transmitter Holding Register
0 0 0 1 R/W IER : Interrupt Enable Register
x 0 1 0 R IIR : Interrupt Identification Register (status)
x 0 1 0 W FCR : FIFO Control Register
x 0 1 1 R/W LCR : Line Control Register
x 1 0 0 R/W MCR : MODEM Control Register
x 1 0 1 R/W LSR : Line Status Register
x 1 1 0 R/W MSR : MODEM Status Regster
x 1 1 1 R/W SCR : Scratch Register
1 0 0 0 R/W DLL : Divisor Latch least (Baud Rate low)
1 0 0 1 R/W DLM : Divisor Latch most (Baud Rate high)
jc/md/lp-01/05 OAL x86 30
Interrupt Enable Register
• Bit 0 : autorisation IT récepteur ready• Bit 1 : autorisation IT transmetteur vide• Bit 2 : autorisation IT erreur en réception • Bit 3 : autorisation IT MODEM status• Bit 4 : 0• Bit 5 : 0• Bit 6 : 0• Bit 7 : 0
jc/md/lp-01/05 OAL x86 31
Interrupt Identification Register
• Bit 0 : 0 si IT pending• Bit 1 : codage de la source de l’ IT (bit 0)• Bit 2 : codage de la source de l’ IT (bit 1)• Bit 3 : codage de la source de l’ IT (bit 2)• Bit 4 : 0• Bit 5 : 0• Bit 6 : 1 si FIFO en service• Bit 7 : 1 si FIFO en service Exemple : un codage de l’ IT = 4 correspond à une
interruption du Receiver pour « caractère disponible »
jc/md/lp-01/05 OAL x86 32
FIFO Control Register
• Bit 0 : 1 autorise la FIFO• Bit 1 : 1 reset de la Receive FIFO• Bit 2 : 1 reset de la Transmit FIFO• Bit 3 : DMA Mode• Bit 4 : réservé• Bit 5 : réservé• Bit 6 : seuil de déclenchement IT FIFO ( LSB)• Bit 7 : seuil de déclenchement IT FIFO ( MSB)
jc/md/lp-01/05 OAL x86 33
Line Control Register
• Bit 0 : codage nombre de bits de data• Bit 1 : codage nombre de bits de data• Bit 2 : 0 un bit de stop• Bit 3 : 0 pas de parité, 1 avec parité• Bit 4 : 0 parité impaire, 1 parité paire• Bit 5 : logique du bit de parité• Bit 6 : 1 génération d’un break• Bit 7 : DLAB (accès Baud Rate Registers) Ex : codage du nombre de bits : %11 → 8 bits data
jc/md/lp-01/05 OAL x86 34
MODEM Control Register
• Bit 0 : DTR, gère le signal DTR• Bit 1 : RTS, le signal RTS• Bit 2 : OUT1, gère une sortie auxiliaire• Bit 3 : OUT2, gère une sortie auxiliaire• Bit 4 : LOOP, gère le mode loopback• Bit 5 : 0• Bit 6 : 0• Bit 7 : 0
jc/md/lp-01/05 OAL x86 35
Line Status Register
• Bit 0 : 1 DR, Receiver Data Ready• Bit 1 : 1 OE, Overrun Error• Bit 2 : 1 PE, Parity Error• Bit 3 : 1 FE, Framing Error• Bit 4 : 1 BI, Break Interrupt• Bit 5 : 1 THRE, Transmitter Holding Reg. Empty• Bit 6 : 1 TEMT, Transmitter Empty (vide)• Bit 7 : 1 erreur dans la FIFO de réception
jc/md/lp-01/05 OAL x86 36
Baud Rate Generator
• Avec un oscillateur à 1,8432 MHz les nombres à placer dans les registres diviseurs du Baud Rate Generator pour obtenir les vitesses classiques sont :– 110 bauds 1047– 330 bauds 384– 1200 bauds 96– 9600 bauds 12– 38400 bauds 3
jc/md/lp-01/05 OAL x86 37
Offset des registres du 16550
#define IoPortBase ((PUCHAR) 0x03F8)#define comTxBuffer 0x00#define comRxBuffer 0x00#define comDivisorLow 0x00#define comDivisorHigh 0x01#define comIntEnable 0x01#define comIntId 0x02#define comFIFOControl 0x02#define comLineControl 0x03#define comModemControl 0x04#define comLineStatus 0x05#define comModemStatus 0x06
jc/md/lp-01/05 OAL x86 38
Status du 16550
// Masque des bits du Line Status Register #define LS_TSR_EMPTY 0x40#define LS_THR_EMPTY 0x20#define LS_RX_BREAK 0x10#define LS_RX_FRAMING_ERR 0x08#define LS_RX_PARITY_ERR 0x04#define LS_RX_OVERRUN 0x02#define LS_RX_DATA_READY 0x01
#define LS_RX_ERRORS (LS_RX_FRAMING_ERR | LS_RX_PARITY_ERR | LS_RX_OVERRUN)
jc/md/lp-01/05 OAL x86 39
Accès aux ports
• Windows CE utilise deux fonctions pour accéder aux registres de l’espace I/O utilisé par tous les périphériques
– WRITE_PORT_UCHAR– READ_PORT_UCHAR
jc/md/lp-01/05 OAL x86 40
WRITE_PORT_UCHAR
VOID WRITE_PORT_UCHAR( PUCHAR Port, UCHAR Value);
ParametersPort
[in] Pointer to the port that must be a mapped memory range in I/O space.
Value [in] Byte to be written to the port.
Return ValuesNone.
jc/md/lp-01/05 OAL x86 41
READ_PORT_UCHAR
UCHAR READ_PORT_UCHAR( PUCHAR Port );Parameters
Port [in] Pointer to the port that must be a mapped memory range in I/O space.
Return Values
This function returns the byte read from the specified port address.
jc/md/lp-01/05 OAL x86 42
OEMInitDebugSerial
// Access Baud Divisor, DLAB=1WRITE_PORT_UCHAR(IoPortBase+comLineControl, 0x80);// 38400 Bauds WRITE_PORT_UCHAR(IoPortBase+comDivisorLow,0x3); WRITE_PORT_UCHAR(IoPortBase+comDivisorHigh, 0x00);// 8-bit, no parity, DLAB=0WRITE_PORT_UCHAR(IoPortBase+comLineControl, 0x03);// Enable FIFO if presentWRITE_PORT_UCHAR(IoPortBase+comFIFOControl, 0x01);
// No interrupts, polledWRITE_PORT_UCHAR(IoPortBase+comIntEnable, 0x00); // Assert DTR, RTSWRITE_PORT_UCHAR(IoPortBase+comModemControl,0x03);
jc/md/lp-01/05 OAL x86 43
OEMReadDebugByte (1)
int OEMReadDebugByte(void){ unsigned char ucStatus; unsigned char ucChar; if ( IoPortBase ) {// le port existe, lecture du status ucStatus = READ_PORT_UCHAR
(IoPortBase+comLineStatus); if ( ucStatus & LS_RX_DATA_READY )
{// il y a un caractère dans le buffer de réception ucChar = READ_PORT_UCHAR (IoPortBase+comRxBuffer);
jc/md/lp-01/05 OAL x86 44
OEMReadDebugByte (2)
// caractère correct ?
if ( ucStatus & LS_RX_ERRORS )
return (OEM_DEBUG_COM_ERROR);
else
return (ucChar);
}// fin du if ( ucStatus & LS_RX_DATA_READY )
}// fin du if (IoPortBase)
return (OEM_DEBUG_READ_NODATA);
}// fin OEMReadDebugByte
jc/md/lp-01/05 OAL x86 45
OEMWriteDebugByte
void OEMWriteDebugByte(BYTE ucChar){ if ( IoPortBase ) { while ( !(READ_PORT_UCHAR(IoPortBase+comLineStatus)
& LS_THR_EMPTY) ) { ; // le port existe, attente de Tx RDY } WRITE_PORT_UCHAR(IoPortBase+comTxBuffer, ucChar); }}
jc/md/lp-01/05 OAL x86 46
OEMWriteDebugString
void OEMWriteDebugString(unsigned short *str){ if (IoPortBase) { while ( *str )
{ while ( !(READ_PORT_UCHAR(IoPortBase+comLineStatus) & LS_THR_EMPTY) )
{ ; // le port existe, attente de Tx RDY } WRITE_PORT_UCHAR(IoPortBase+comTxBuffer, (UCHAR)*str++); } }// fin du if (IoPortBase)}
jc/md/lp-01/05 OAL x86 47
Interrupt Request Register (1)
• Mémorise les demandes d’interruption des lignes IR0 à IR7
• Pour les architectures X86 la demande est mémorisée sur front montant
• Acquittement automatique de la demande lors de la prise en compte par le processeur
• Lorsqu’une demande est mémorisée, et si elle n’est pas masquée par l’Interrupt Mask Register, cela entraîne l’envoi du signal INT au CPU
jc/md/lp-01/05 OAL x86 48
Interrupt Request Register (2)
jc/md/lp-01/05 OAL x86 49
Interrupt Enable Register
• Bit 0: This bit enables the Received Data Available Interrupt
(and timeout INT in the FIFO mode) when set to logic 1• Bit 1: This bit enables the Transmitter Holding Register Empty Interrupt when set to logic 1.• Bit 2: This bit enables the Receiver Line Status Interrupt when set to logic 1.• Bit 3: This bit enables the MODEM Status Interrupt when set to logic 1.• Bits 4 through 7: These four bits are always logic 0.
jc/md/lp-01/05 OAL x86 50
Programmable Interrupt Controller
PIC 8259A
jc/md/lp-01/05 OAL x86 51
Architecture du PIC
jc/md/lp-01/05 OAL x86 52
Câblage des PICs
D a ta B u s (8 )
C o n tro l B u s
A d d re s s B u s (1 6 )
M A S T E RS L A V E A
S P /E N IR5 IR0IR1IR2IR3IR4IR6IR7
C A S2
C A S 0
C A S18 2 5 9
0AC S D 0 -7 IN T A IN T
G N D V c c
S P /E N IR5 IR0IR1IR2IR3IR4IR6IR7
C A S2
C A S 0
C A S1 8 2 5 9
0AC S D 0 -7 IN T A IN T
jc/md/lp-01/05 OAL x86 53
Principe de fonctionnement
• Les IRQ entrantes sont mémorisées dans le registre IRR (IRQ0 la plus prioritaire)
• Le priority resolver détermine le niveau demandeur autorisé le plus prioritaire et génère le signal INT
• Le CPU répond par INTA ce qui mémorise le bit du niveau le plus prioritaire dans ISR
• Le CPU envoie à nouveau INTA et récupère le vecteur d’interruption sur le bus de données
jc/md/lp-01/05 OAL x86 54
Interrupt Mask Register
• Registre de 8 bits• Chaque bit correspond à un masque pour le
niveau d’interruption correspondant• Un bit à 1 masque l’interruption• Une IT survenant sur un niveau masqué est
mémorisée dans le registre IRR mais ne provoque pas l’envoi du signal INT vers le CPU
• Ce registre (IMR) sera positionné par un mot de commande OCW1
jc/md/lp-01/05 OAL x86 55
In-Service Register
• Mémorise les niveaux d’interruption en cours de traitement (1 bit par niveau)
• En fin de traitement en mode X86, le programme de traitement de l’interruption doit générer une commande pour acquitter le bit correspondant, à moins de fonctionner avec acquittement automatique
jc/md/lp-01/05 OAL x86 56
Accès aux registres
• L’accès ne se fait pas par un adressage mais par l’envoi de mots de commande OCWx
– OCW1 permet d’écrire l’IMR– OCW3 sélectionne la lecture de l’IRR ou de l’ISR.
La lecture réelle de ces registres est faite par un
nouvel accès au boîtier
• L’accès aux registres par le logiciel n’a de sens qu’après le déroulement d’une séquence d’initialisation par l’envoi de mots ICWx
jc/md/lp-01/05 OAL x86 57
Programmation du PIC
• Après un reset hardware le PIC doit être configuré par 3 ou 4 mots de commandes appelés ICWs (Initialization Command Word)
• Un bit du mot de commande ICW1 précise s’il y a 3 ou 4 mots de commande
• ICW1 est envoyé avec le bit A0 à 0, les autres ICWs sont envoyés avec le bit A0 à 1
• Après la phase d’initialisation le PIC peut recevoir de nouvelles commandes par des OCWs (Operation Command Word)
jc/md/lp-01/05 OAL x86 58
ICW1 pour X86
• Bit 0 : 1 ICW4 nécessaire • Bit 1 : 0 mode cascadé, 1 PIC unique• Bit 2 : 0 en X86• Bit 3 : 0 interruption sur front, 1 sur niveau • Bit 4 : 1 spécifie avec A0 à 0 un ICW1 • Bit 5 : 0 en X86• Bit 6 : 0 en X86• Bit 7 : 0 en X86
jc/md/lp-01/05 OAL x86 59
ICW2 pour X86
• Bit 0 : 0• Bit 1 : 0• Bit 2 : 0• Bit 3 : bit V3 du vecteur d’interruption• Bit 4 : bit V4 du vecteur d’interruption • Bit 5 : bit V5 du vecteur d’interruption• Bit 6 : bit V6 du vecteur d’interruption• Bit 7 : bit V7 du vecteur d’interruption Les bits 0,1,2 sont positionnés automatiquement par le
PIC avec la valeur du niveau d’IT traitée
jc/md/lp-01/05 OAL x86 60
ICW3 Maître
• Bit 0 : 1 → entrée connectée sur un autre PIC• Bit 1 : 1 → entrée connectée sur un autre PIC• Bit 2 : 1 → entrée connectée sur un autre PIC• Bit 3 : 1 → entrée connectée sur un autre PIC• Bit 4 : 1 → entrée connectée sur un autre PIC• Bit 5 : 1 → entrée connectée sur un autre PIC• Bit 6 : 1 → entrée connectée sur un autre PIC• Bit 7 : 1 → entrée connectée sur un autre PIC Dans notre cas un esclave sur IR2 donc 0x04
jc/md/lp-01/05 OAL x86 61
ICW3 Esclave
• Bit 0 : codage du slave ID (ID0)• Bit 1 : codage du slave ID (ID1)• Bit 2 : codage du slave ID (ID2)• Bit 3 : 0• Bit 4 : 0• Bit 5 : 0• Bit 6 : 0• Bit 7 : 0 Dans notre cas l’esclave est sur IR2 d’où 010
jc/md/lp-01/05 OAL x86 62
ICW4 pour X86
• Bit 0 : 1 mode X86• Bit 1 : 0 acquitté par le programme d’IT• Bit 2 : 0 mode normal X86• Bit 3 : 0 mode normal X86• Bit 4 : 0 mode normal X86• Bit 5 : 0• Bit 6 : 0• Bit 7 : 0
jc/md/lp-01/05 OAL x86 63
Accès aux registres
Après la séquence d’initialisation• Écriture de l’Interrupt Mask Register par une
commande OCW1• Lecture de l’Interrupt Request Register ou de
l’In-Service Register en deux temps : écriture d’un OCW3 (bit 0 à 0 pour l’IRR et à 1 pour l’ISR) ; cette écriture positionne le boîtier pour que la lecture suivante fournisse le contenu de l’IRR ou de l’ISR sur le bus de données
jc/md/lp-01/05 OAL x86 64
Operation Command Words
• Les commandes OCW sont envoyées individuellement sans ordre à respecter et à tout moment
• OCW1 est défini par A0=1• OCW2 et OCW3 sont définis par A0=0 et D4=0• La différence entre OCW2 et OCW3 est faite par
le bit D3 de la commande : D3=0 pour un OCW2 et D3=1 pour un OCW3
jc/md/lp-01/05 OAL x86 65
OCW1
• Écriture de l’Interrupt Mask Register (IMR)• Défini par A0=1• Les bits D0 à D7 de l’OCW1 sont écrits dans
l’IMR• Chaque bit correspond à un niveau d’IT• Le registre est un masque :
– Un bit à 1 inhibe le niveau d’interruption– Un bit à 0 autorise le niveau d’interruption
jc/md/lp-01/05 OAL x86 66
OCW2 (1)
• Bit 0 : codage du niveau d’IR concerné• Bit 1 : codage du niveau d’IR concerné• Bit 2 : codage du niveau d’IR concerné• Bit 3 : 0• Bit 4 : 0• Bit 5 : les bits 5, 6 et 7 permettent de gérer • Bit 6 : des modes différents de traitement de• Bit 7 : l’interruption
jc/md/lp-01/05 OAL x86 67
OCW2 (2)
• Quand le PIC est programmé pour fonctionner avec un acquittement spécifique de l’interruption (dans ICW4, Bit D1=1), on peut disposer de plusieurs commandes pour gérer finement l’acquittement des interruptions
• On peut notamment introduire une gestion circulaire des priorités par les commandes envoyées par le logiciel qui traite l’interruption ;ces commandes concernent le niveau indiqué par les bits 0,1 et 2 du mot OCW2
jc/md/lp-01/05 OAL x86 68
OCW3
• Bit 0 : avec Bit 1, codage pour lire IRR (10) ou• Bit 1 : ISR (11) sur la prochaine lecture du PIC• Bit 2 : 0 fonctionnement normal• Bit 3 : 1 (OCW3)• Bit 4 : 0 (OCW)• Bit 5 : 0 fonctionnement normal• Bit 6 : 0 fonctionnement normal• Bit 7 : 0
jc/md/lp-01/05 OAL x86 69
Mapping des PICs
• PIC maître adresse 0x20– Le fil A0 du bus d’adresse étant connecté sur
l’entrée A0 du PIC, un échange à l’adresse 20 correspond à la sélection du PIC avec une entrée A0 à 0, alors qu’un échange à l’adresse 21 correspond à une sélection du PIC avec une entrée A0 à 1
• PIC esclave adresse 0xA0– De même, les deux adresses seront 0xA0 et 0xA1
jc/md/lp-01/05 OAL x86 70
Programmation des PICs
• Séquence d’initialisation en assembleur pour suivre au mieux toutes les commandes ICWs. On a successivement 4 ICWs pour le PIC maître et 3 ICWs pour le PIC esclave et deux OCWs
• Nous programmons les modes les plus simples • Ultérieurement, nous rencontrerons la séquence
de traitement des interruptions qui fera intervenir d’autres OCWs
jc/md/lp-01/05 OAL x86 71
Initialisation des PICs (1)
void InitPICs(void) { int i; __asm { ; ; First, do PIC 1 master mov al, 011h ; Init command 1, ICW1: cascade, 4 ICW out 020h, al ; 020h, address PIC1, A0=0 jmp short $+2
mov al, 040h ; Init command 2, ICW2: vector to 64 out 021h, al ; 021h, address PIC1, A0=1
jmp short $+2
jc/md/lp-01/05 OAL x86 72
Initialisation des PICs (2)
mov al, 004h ; Init command 3, ICW3: slave on IRQ 2 out 021h, al jmp short $+2 mov al, 001h ; Init command 4, ICW4: normal EOI out 021h, al jmp short $+2
mov al, 00Bh ; OCW3: Select In Service Register out 020h, al
mov al, 0FFh ; OCW1: Start with all interrupts disabled out 021h, al
jc/md/lp-01/05 OAL x86 73
Initialisation des PICs (3)
; Now do PIC 2 slave on IRQ2 of PIC 1
mov al, 011h ; Init command 1, ICW1: cascade, 4 ICW
out 0A0h, al ; 0A0h, address PIC2, A0=0
jmp short $+2
mov al, 048h ; Init command 2, ICW2: vector to 72
out 0A1h, al ; 0A1h, address PIC2, A0=1
jmp short $+2
mov al, 002h ; Init command 3, ICW3: slave on IRQ 2
out 0A1h, al
jmp short $+2
jc/md/lp-01/05 OAL x86 74
Initialisation des PICs (4)
mov al, 001h ; Init command 4, ICW4: normal EOI
out 0A1h, al
mov al, 00Bh ; OCW3: Select In Service Register
out 0A0h, al
mov al, 0FFh ; OCW1: Start with all interrupts disabled
out 0A1h, al
; end of initialization
jc/md/lp-01/05 OAL x86 75
Initialisation des PICs (5)
; Clear any interrupts that might be pending after a warm ; reboot
mov al, 020h ; OCW2: non specific End Of Interruption out 020h, al ; PIC1
mov al, 020h ; OCW2: non specific End Of Interruption out 0A0h, al ; PIC2 }
jc/md/lp-01/05 OAL x86 76
Récupération de l’IT par CE
• A chaque vecteur d’interruption est associé par la fonction HookInterrupt un même programme de traitement d’interruption (PeRPISR) qui fournit au système le numéro logique associé à l’interruption physique en cours de traitement
• Le système interroge alors sur ce niveau les éventuels programmes chaînés
• Si ce programme n’est pas concerné par cette interruption, il rend le contrôle au système
jc/md/lp-01/05 OAL x86 77
Conclusion
Nous avons :• Présenté quelques unes des fonctions utilisées
pour démarrer la plate-forme• Étudié le principe du traitement des interruptions
dans Windows CE• Préparé l’utilisation de ce mécanisme à travers
l’exemple d’une liaison série en nous limitant à la récupération de l’interruption par le système