OAL OEM Adaptation Layer B-203 CE 4.2 OAL OEM Adaptation Layer (Original Equipment Manufacturer) jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
B-203 CE 4.2 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 OAL_V1.0.ppt
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
Interruptions x86 2 entrées d’interruptions sur les CPU x86 B-203 CE 4.2 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 NMI : Non Maskable Interrupt Cette entrée est prévue pour recevoir un signal externe prioritaire qu’il est impératif de traiter immédiatement ; les exemples typiques sont les signaux de coupure d’alimentation, d’erreur mémoire irrécupérable… INT ou IT : Interrupt Cette entrée est prévue pour recevoir un signal externe émis par un organe qui nécessite un traitement de la part du CPU. De nombreux périphériques étant susceptibles de demander des services, un contrôleur d’interruption reçoit les différentes demandes, gère les priorités entre ces demandes. PIC : Programmable Interrupt controller La table des vecteurs permet d’associer à chacune des interruptions le point d’entrée d’un programme : le mécanisme hardware prend en charge la lecture du numéro de vecteur puis déclenche le logiciel qui lui est associé. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
PIC Gère 8 IT (cascadable jusqu’à 64 IT) Gère les priorités CE 4.2 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 PIC : contrôleur d’interruption utilisé depuis les débuts du PC ; ce contrôleur gère 8 entrées d’interruptions (IR0-IR7) et répercute l’interruption la plus prioritaire parmi les 8 vers le CPU (ou un autre PIC) par un signal INT. Le nombre des interruptions gérées est trop limité pour un PC. Aussi on utilise le fait que le 8259A est conçu pour être cascadable, c’est-à-dire qu’une entrée d’interruption sur un contrôleur « primaire » peut recevoir une interruption (INT) en provenance d’un contrôleur secondaire qui gère lui-même 8 entrées d’interruption. Traditionnellement, l’entrée IR2 du contrôleur reçoit un contrôleur secondaire, ce qui conduit à un total de 15 niveaux d’interruption sur un PC : 7 entrées sur le contrôleur primaire, la huitième entrée étant démultipliée en huit entrées par le contrôleur secondaire. La dénomination des interruptions est flottante IR ou IRQ pour Interrupt Request ou encore INT. En particulier on rencontre souvent INT2. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
Configuration de base PC CE 4.2 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 Il s’agit des circuits classiques utilisés dans la norme PC. On trouve la documentation associée sur les sites des fabricants de semi-conducteurs ou encore sur le site www.alldatasheet.com. Aujourd’hui, ces circuits ou leurs équivalents modernisés sont intégrés dans les chipsets pour PC ou dans les microcontrôleurs. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
OAL Architecture jc/md/lp-01/05 OAL x86
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
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
Initialisation du port de Debug CE 4.2 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 Le port de debug permet en connectant un simple terminal ASCII ou un hyperterminal de d’afficher des messages prévus pour suivre le déroulement des opérations. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
B-203 CE 4.2 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 OAL_V1.0.ppt
Mapping des interruptions (1) B-203 CE 4.2 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 L’utilisation par le système Windows CE d’interruptions renumérotées à travers des tables de correspondance permet d’adapter des organisations matérielles d’interruptions différentes d’un processeur à l’autre aux besoins de CE. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
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
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
Mapping des interruptions (5) B-203 CE 4.2 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; \ } Le premier appel de la macro DEBUGCHK vérifie que l’interruption CE SysIntr de l’entrée g_Sysintr2IntrMap[SysIntr] est bien non définie ; si ce n’est pas le cas, la macro provoque un appel à la fonction DebugBreak qui elle-même déclenche l’intervention du debugger. Le second appel fait le même travail pour l’interruption hardware Irql. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
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
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
Fonctions de gestion de consommation OEMIdle OEMPowerOff jc/md/lp-01/05 OAL x86
Fonctions de gestion du temps OEMGetRealTime OEMSetRealTime OEMSetAlarmTime SC_GetTickCount jc/md/lp-01/05 OAL x86
Fonctions de gestion port parallèle OEMParallelPortGetByte OEMParallelPortSendByte OEMParallelPortGetStatus jc/md/lp-01/05 OAL x86
Fonctions de gestion ethernet OEMEthInit OEMEthEnableInts OEMEthDisableInts OEMEthISR OEMEthGetFrame OEMEthSendFrame OEMEthQueryClientInfo OEMEthGetSecs jc/md/lp-01/05 OAL x86
Liaison série 16550 jc/md/lp-01/05 OAL x86 B-203 CE 4.2 À l’origine, le circuit de gestion de la liaison série fut le INS8250 conçu par National Semiconductor et utilisé dans les premiers PC. Il a été corrigé et amélioré dans une version NS16450 puis NS16550 suivie d’une version NS16550A utilisée systématiquement dans les PC. Depuis 1995, ce circuit à peine modifié est rebaptisé PC16550D ; il reste la référence dans le monde du PC car c’est le circuit compatible avec tous les BIOS classiques des PC. Il existe plusieurs variantes suivant les technologies ou le nombre des circuits intégrés dans un même composant, par exemple chez Texas Instruments le TL16C554A ; il existe aussi des variantes améliorées (par exemple des FIFO plus grandes) mais en général les améliorations ne sont pas prises en charge par les BIOS standards. Aujourd’hui, ce circuit est directement intégré dans les chipsets. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
16550 UART asynchrone jusqu’à 1,5 Mbauds Gestion des signaux MODEM CE 4.2 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 UART : Universal Asynchronous Receiver/Transmitter jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Registres du 16550 DLAB A2 A1 A0 R/W Register R CE 4.2 Registres du 16550 DLAB A2 A1 A0 R/W Register R RBR : Receiver Buffer Register W THR : Transmitter Holding Register 1 IER : Interrupt Enable Register x IIR : Interrupt Identification Register (status) FCR : FIFO Control Register LCR : Line Control Register MCR : MODEM Control Register LSR : Line Status Register MSR : MODEM Status Regster SCR : Scratch Register DLL : Divisor Latch least (Baud Rate low) DLM : Divisor Latch most (Baud Rate high) Dans l’architecture x86 les signaux Read et Write sont séparés. Dans la table ci-dessus, la colonne R/W indique que le registre concerné est accessible : - en lecture seule R - en écriture seule W - en lecture et en écriture R/W. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
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
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
Line Control Register Bit 0 : codage nombre de bits de data CE 4.2 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 DLAB : Divisor Latch Access Bit. Quand ce bit est positionné à 1, on a accès en lecture et en écriture aux registres qui contiennent le diviseur à utiliser pour programmer le Baud Rate Generator, aux adresses %000 (partie basse du diviseur) et %001 (partie haute du diviseur. Quand ce bit est à 0, le registre visible à l’adresse %000 est le Receiver Buffer Register tandis que celui qui est visible à l’adresse %001 est le Transmitter Holding Register. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
MODEM Control Register B-203 CE 4.2 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 Loopback correspond à un mode de fonctionnement prévu pour tester le bon fonctionnement de la liaison : la sortie est rebouclée par le hardware sur l’entrée. Dans les nouveaux chipsets qui intègrent la fonction 16550, le bit 3 sert aussi à autoriser ou à interdire les interruptions pour l’ensemble du composant 16550 (bit EI/DI). jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
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
Offset des registres du 16550 B-203 CE 4.2 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 IoPortBase sera utilisée par le logiciel comme un pointeur du type pointeur de caractère non signé PUCHAR, placé à l’adresse 0x03F8 qui est l’adresse prévue dans l’architecture PC pour le port série 1 ; le port série 2 est quant à lui en 0x02F8. Les autres symboles définissent les offsets des différents registres par rapport à l’adresse de base. Un registre supplémentaire est disponible à l’adresse 0x07. Les adresses identiques correspondent aux registres accessibles par le positionnement du bit DLAB et/ou accessibles en lecture seule ou en écriture seule. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Status du 16550 // Masque des bits du Line Status Register CE 4.2 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) Ces masques sont utilisés par les logiciels pour améliorer la lisibilité quand il faut consulter les différents bits du Line Status Register. Le dernier symbole regroupe les trois erreurs qui peuvent survenir en réception (la réception d’un BREAK n’est pas une erreur). jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
WRITE_PORT_UCHAR VOID WRITE_PORT_UCHAR( PUCHAR Port, UCHAR Value); Parameters Port [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 Values None. jc/md/lp-01/05 OAL x86
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
OEMInitDebugSerial // Access Baud Divisor, DLAB=1 WRITE_PORT_UCHAR(IoPortBase+comLineControl, 0x80); // 38400 Bauds WRITE_PORT_UCHAR(IoPortBase+comDivisorLow,0x3); WRITE_PORT_UCHAR(IoPortBase+comDivisorHigh, 0x00); // 8-bit, no parity, DLAB=0 WRITE_PORT_UCHAR(IoPortBase+comLineControl, 0x03); // Enable FIFO if present WRITE_PORT_UCHAR(IoPortBase+comFIFOControl, 0x01); // No interrupts, polled WRITE_PORT_UCHAR(IoPortBase+comIntEnable, 0x00); // Assert DTR, RTS WRITE_PORT_UCHAR(IoPortBase+comModemControl,0x03); Le mode de fonctionnement choisi est le mode par interrogation (polling) : il n’y a pas d’interruption déclenchée par le contrôleur de la ligne série ; le CPU viendra régulièrement visiter le status register pour examiner si un caractère est disponible ou si le sérialiseur est prêt à transmettre un nouveau caractère. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
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
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
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
Interrupt Request Register (1) B-203 CE 4.2 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 Comme indiqué dans un commentaire précédent, lorsqu’une interruption est prise en compte, le bit correspondant est transféré dans l’ISR et il est réinitialisé dans l’IRR. Ainsi, une nouvelle interruption sur le même niveau, peut être prise en compte mais ne sera pas exploitée tant que le bit correspondant de l’ISR ne sera pas acquitté, c’est-à-dire remis à 0, soit automatiquement, soit par un un mot de commande explicite. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Interrupt Request Register (2) jc/md/lp-01/05 OAL x86
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
Programmable Interrupt Controller CE 4.2 Programmable Interrupt Controller PIC 8259A jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Architecture du PIC jc/md/lp-01/05 OAL x86
Câblage des PICs jc/md/lp-01/05 OAL x86 B-203 CE 4.2 Le PIC esclave transmet les demandes d’interruption reçues sur les broches IR0 à IR7 au PIC maître par la liaison INT (esclave) vers IR2 (maître). Pendant les séquences de dialogue entre le CPU et les PIC, le PIC maître sélectionnera le bon esclave par le bus privé entre les PIC constitué par les lignes CAS0 à CAS2. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Principe de fonctionnement B-203 CE 4.2 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 IRQ : interrupt request IRR : Interrupt Request Register ISR : In-Service Register INTA : Interrupt Acknowledge. Le détail du fonctionnement diffère suivant l’initialisation des registres internes du PIC. Avec un CPU x86, deux échanges avec le signal INTA se succèdent. Pendant le premier échange le PIC concerné transfère le bit de l’IRR qui correspond à l’interruption la plus prioritaire dans le bit correspondant de l’ISR et supprime ce bit de l’IRR. Pendant le second cycle avec INTA le PIC concerné, maître ou esclave, émet le vecteur d’interruption ; ce vecteur est constitué de cinq bits fixés lors de l’initialisation du composant, complété par 3 bits qui correspondent au niveau d’interruption servi. Pendant ce cycle, on peut effacer automatiquement le bit de l’ISR préparant ainsi le traitement d’une nouvelle interruption. On peut aussi effacer à la demande le bit de l’ISR par une commande explicite. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
B-203 CE 4.2 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 Le mode avec acquittement automatique n’est pas à recommander s’il y a plusieurs sources d’interruption sur un même niveau, ce qui est souvent le cas dans les PC. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
B-203 CE 4.2 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 ICW : Initialization Command Word OCW : Operation Command Word jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
B-203 CE 4.2 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) En fait, ICW1 est reconnu par le bit A0 à 0 et le bit D4 du bus de données à 1. La séquence d’initialisation est supposée s’effectuer complètement et lorsqu’elle terminée, on ne peut plus envoyer de mots ICW2, ICW3 ou ICW4. Le bit A0 à 1 correspondra dorénavant au mot de commande OCW1. Le bit A0 à 0 et le bit D4 à 0 correspondront aux mots de commande OCW2 et OCW3. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
ICW2 pour X86 Bit 0 : 0 Bit 1 : 0 Bit 2 : 0 CE 4.2 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 Lors du cycle de lecture qui permet au CPU de connaître le vecteur d’interruption, les huit bits placés sur le bus de données sont constitués des bits V7 à V3 et de trois bits V2 à V0 générés automatiquement par le PIC pour spécifier quel est le niveau d’interruption traité. Quand il y a plusieurs PIC dans une architecture, les bits V3 à V7 permettent de repérer le PIC concerné par l’interruption indiquée par les trois bits poids faibles du vecteur reçu. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
ICW3 Maître Bit 0 : 1 → entrée connectée sur un autre PIC CE 4.2 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 Dans l’architecture PC, on utilise normalement deux PIC, l’esclave étant connecté sur IR2. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
ICW3 Esclave Bit 0 : codage du slave ID (ID0) CE 4.2 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 Les bits 0, 1 et 2 permettent à l’esclave de savoir sur quelle entrée du PIC maître il est connecté. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
B-203 CE 4.2 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 Le bit 1 à 1 introduit l’acquittement automatique de l’interruption. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
Operation Command Words B-203 CE 4.2 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 Une commande avec A0=0 et D0=1 provoque la réinitialisation du PIC. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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
OCW2 (1) Bit 0 : codage du niveau d’IR concerné 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
B-203 CE 4.2 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 La gestion des priorités peut devenir complexe, d’autant plus qu’il y a interférence avec un mode disponible de masquage dynamique des interruptions (ce mode est introduit par les D5 et D6 du mot de commande OCW3. Les priorités peuvent être circulaires ou même complètement gérées par les mots de commande OCW2 et OCW3. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
OCW3 Bit 0 : avec Bit 1, codage pour lire IRR (10) ou CE 4.2 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 Les bits 5 et 6 permettent d’introduire une gestion dynamique du masquage des interruptions qui vient compléter les possibilités offertes pour la gestion des priorités introduites dans le mot de commande OCW2. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Mapping des PICs PIC maître adresse 0x20 PIC esclave adresse 0xA0 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
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
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 jc/md/lp-01/05 OAL x86
Initialisation des PICs (2) B-203 CE 4.2 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 mov al, 00Bh ; OCW3: Select In Service Register out 020h, al mov al, 0FFh ; OCW1: Start with all interrupts disabled OCW3 : adresse 20, donc A0=1, la donnée est 00001011, D4=0 implique un OCW, D3=1, c’est un OCW3. Pour les autres bits : D7 est toujours à 0 D6=0 et D5=0, on n’utilise pas le mode spécial de masquage des interruptions D2=0, on utilise le mode de fonctionnement sans polling D1=1 et D0=1, on prépare la lecture de l’ISR sur la prochaine lecture OCW1 : adresse 21, donc A0=1, après la séquence d’initialisation, il s’agit des OCW1. Les bits de l’octet de données sont recopiés dans l’IMR. Tous les bits sont à 1, donc toutes les interruptions sont masquées. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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 mov al, 002h ; Init command 3, ICW3: slave on IRQ 2 out 0A1h, al jc/md/lp-01/05 OAL x86
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 ; end of initialization jc/md/lp-01/05 OAL x86
Initialisation des PICs (5) B-203 CE 4.2 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 out 0A0h, al ; PIC2 } OCW2 : 00100000, A0=0, D4=0, implique un OCW, D3=0, c’est un OCW2 Bits D7, D6 et D5=001 : non specific end of interruption Bits D2, D1 et D0=000, en fait indifférents pour le mode de fin d’interruption choisi jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
Récupération de l’IT par CE B-203 CE 4.2 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 La fonction HookInterrupt est appelée normalement pendant l’initialisation par la fonction OEMInit ; après l’initialisation, chaque interruption physique reçue sera transformée en l’interruption logique associée puis traitée par un programme ISR (Interruption Service Routine) approprié. jc/md/lp-01/05 OAL x86 OAL_V1.0.ppt
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 jc/md/lp-01/05 OAL x86