Interfacciamento a periferiche Periferica controller o interfaccia CPU/RAM. In genere la periferica è elettromeccanica e l interfaccia digitale (scheda sul bus o integrata su motherboard). Ma l esatta demarcazione tra periferica e controller è dettata dagli standard con cui questi devono interagire. P.es.: PC con porta parallela standard CENTRONICS: 1. la porta appartiene al controller interno al sistema 2. ad essa va collegata una stampante opportuna (periferica) 3. l interazione controller-stampante obbedisce allo standard Un interfaccia può essere: custom, sviluppata con progetto ad hoc con componenti MSI con chip di supporto standard LSI per una periferica specifica; programmabile (adattabile via SW a più periferiche). In un PC anche l interazione sistema-interfaccia tende a seguire standard (tradizionalmente quelli del PC-AT IBM). Il SW pilota le interfacce modificandone i registri, detti anche port. Un interfaccia tipica possiede: registri di controllo registri di stato registro dati Ogni registro ha un indirizzo a 16 bit nello spazio di I/O; il registro è reso accessibile dall interfaccia quando questa ne riconosce l indirizzo I/O sul bus indirizzi/controllo. Interrupt X86 20/01/00 15.29 1/9
I/O a controllo di programma: polling Istruzioni x86 per l IO copiano tra registri di I/O e / (NB: la destinazione è sempre il 1 operando dell istruzione): ( contiene l indirizzo del registro di input) imm8 (imm8 è l indirizzo a 8 bit del registro di input) ( contiene l indirizzo del registro di output) imm8 (imm8 è l indirizzo a 8 bit del registro di output) L interazione via istruzioni non può essere atomica, cioè dar luogo appena l istruzione è completata a un azione significativa della periferica. Infatti tali istruzioni durerebbero troppo, richiederebbero l interazione con più registri e non se ne potrebbe dare per scontato il successo. (l I/O atomico è possibile via gli del DOS che richiamano però intere subroutine). Caratteristiche SW di I/O con polling (interrogazione): usa solo, ma non servizi DOS gli eventi esterni lo influenzano modificando i registri di stato, ma è il programma a decidere quando esaminare i registri il flusso di esecuzione non può essere alterato dall esterno Tipica struttura SW per singola operazione I/O (l interfaccia si presuppone inizializzata): 1. polling ripetuto interfaccia: sei disponibile per operazione I/O? 2. read o write registro dati interfaccia 3. polling ripetuto interfaccia: operazione di I/O ha avuto successo? Spesso (3) è impossibile (non corrisponde a un bit) o inutile; la sua funzione la farà in parte (1) nella seguente operazione di I/O (se l interfaccia torna disponibile per un altra operazione di I/O, quella precedente sarà stata completata, per lo più con successo). Interrupt X86 20/01/00 15.29 2/9
Polling: schema tipico Costanti registri periferica: STR EQU... ;Indirizzo Status Register Periferica DR EQU... ;Indirizzo Data Register periferica Input di un byte dalla periferica in : inbyte proc push dx mov dx,str ; polling registro teststr: in al,dx ; di stato STR sul test al,01 ; bit 0: periferica pronta per input jz teststr inbyte mov dx,dr ; indirizza registro dati periferica in al,dx ; input dato pronto pop ret endp dx Output del byte in sulla periferica: outbyte proc push dx push ax ; ax=dato per output: salvalo su stack mov dx,str ; polling registro teststr: in al,dx ; di stato STR sul test al,02 ; bit 1: periferica pronta per output jz teststr outbyte mov dx,dr ; indirizza registro dati periferica pop ax ; recupera dato per output da stack out dx,al ; output dato pop ret endp dx Interrupt X86 20/01/00 15.29 3/9
Routine di servizio di interrupt È una routine attivabile da cause diverse da chiamate o salti; queste cause si dicono interrupt. L architettura x86 prevede routine di servizio di interrupt contraddistinte da un numero n in (n senza segno a 8 bit) n si dice anche numero o tipo dell interrupt che attiva la routine. Un vettore di interrupt è una dword che specifica segmento (MSW) e offset (LSW) di una routine di servizio di interrupt. Nell x86, il vettore per l interrupt n è la nesima dword dall indirizzo 0, cioè la dword di indirizzo assoluto 4n. I vettori in si dicono Interrupt Service Routine address Table; IRST serve a reperire le routine di servizio interrupt (vedi (4,6) sotto). Al verificarsi di un interrupt di tipo n (qualunque ne sia l origine), la CPU compie queste azioni: 1. salva i flag sullo stack 2. disabilita (clear) i flag TF (Trap) e IF (Interrupt enable) 3. salva sullo stack 4. carica in la word alta del vettore di interrupt n 5. salva sullo stack 6. carica in la word bassa del vettore di interrupt n La routine di servizio dell interrupt dovrebbe terminare con che: 1. ripristina dallo stack 2. ripristina dallo stack 3. ripristina dallo stack i flag (in genere ciò riabilita gli interrupt). Interrupt X86 20/01/00 15.29 4/9
Interrupt software Una prima classe di interrupt sono quelli richiesti dal software: l esecuzione dell istruzione! " # n causa un interrupt di tipo n. Normalmente la routine di servizio corrispondente fa parte del SO. Accedere ai servizi del SO con! " # è vantaggioso: si pensi di cambiare l immagine in memoria del SO e con questa: indirizzo della routine di servizio del generico interrupt n del SO quindi, valori del vettore n di interrupt in memoria implementazione della routine di servizio dell interrupt n ciò non ha impatto sulle applicazioni che usano! " # ", purché la routine per! " # n continui a fornire lo stesso servizio. Viceversa, accedere a un servizio S di SO con $ % & & address non è pratico. address per S non può cambiare anche se deve mutare l immagine in memoria del SO, a causa di un aggiornamento o semplicemente di una riconfigurazione; oppure, se modificare l immagine del SO in memoria può cambiare address per S, bisognerebbe rifare il linking tra ogni applicazione che usa $ % & & address e il SO! I principali interrupt che danno accesso a parti del DOS sono: ' ( ) * +, ) : interrupt DOS (parti di MSDOS.SYS) - ( ) * -. ) : interrupt BIOS Si possono poi installare le proprie routine di servizio in / ( ) * / / ). P.es. uso di una routine di servizio installata per! " # / ( ) : code segment start: int 60H code mov int ends ah,4ch 21H Interrupt X86 20/01/00 15.29 5/9
Interrupt asincroni Gli interrupt software possono dirsi sincroni, nel senso che accadono quando previsto dal programmatore. Altri interrupt si verificano in modo non controllato dal programma interrotto e si dicono quindi asincroni; in risposta ad essi: la CPU completa l istruzione corrente e la CPU interrompe il flusso di istruzioni che aveva in corso e via 1-6,pag.4 va a eseguire la routine di servizio dell interrupt. Gli interrupt asincroni (salvo uno) si possono disabilitare ponendo IF (Interrupt enable Flag) a 0 con 0 1 2 (3 4 2 rimette IF a 1). Per ogni interrupt asincrono è definito un tipo associato (vedi oltre). Alcuni interrupt asincroni rispecchiano il verificarsi di eccezioni, cioè condizioni eccezionali interne alla CPU: divisione per 0 interrupt tipo 0 overflow interrupt tipo 4 opcode non valido interrupt tipo 6 FPU non disponibile interrupt tipo 7 Un altra causa asincrona interna di interrupt di tipo 1 è la fine dell istruzione corrente se iniziata con TF=1. 1. Il debugger installa le service routine degli interrupt 1 e 3 e carica il programma; 2. F7 pone TF a 1 ed esegue l istruzione corrente del programma caricato 3. la routine dell int. 1 rimette TF a 0, mostra il nuovo stato, attende un comando I debugger sfruttano anche l interrupt tipo 3 (opcode 5 5, equivale a 6 7 8 9 : 5 ; 9 : ): 1. il debugger sostituisce con 5 5 il 1 byte di un istruzione su cui si vuole un breakpoint 2. dopo il Run, se la CPU esegue 5 5 il controllo torna al debugger Interrupt X86 20/01/00 15.29 6/9
Interrupt esterni Vi sono altre 2 classi di interrupt asincroni, entrambe esterne (hw): interrupt mascherabile (disabilitabile ponendo IF a 0); si verifica quando il pin INTR (INT Request) vede un fronte 0 1; non-maskable interrupt (non disabilitabile); ha tipo 2; si verifica quando il pin NMI vede un fronte 0 1 (causa p.es. Low Power); Se la CPU è disponibile a servire INTR, risponde sul pin INTA (INT Acknowledgement) al componente interessato e, in risposta, questo deve porre sul bus dati D7-D0 il tipo dell interrupt. Dato che più periferiche hanno bisogno di una routine di servizio, tra linee di richiesta interrupt da periferiche e INTR c è l 8259 PIC: Bus Dati Port 1 Port 2 IR0 (max priority) INTR INTA IR7 (min priority) altri int. controller Messaggi di controllo 8259: ICW1-4 (inviati in sequenza) e OCW1-2: ICW1 (Initialization Control Word 1): montaggi in cascata e forma del segnale di interruzione (edge-triggered); ICW2: i bit 7-3 danno il tipo base per l interrupt (bit 2-0 a 0) cioè per IRk verrà messo sul bus dati ICW2[7..3] e i 3 bit di k; ICW3 specifica montaggi multicontrollore ICW4 specifica il modo fully-nested OCW1 (Operation CW 1): OCW1[k]=1 maschera IRk; OCW2: riceve la segnalazione End Of Int in modo fully-nested Interrupt X86 20/01/00 15.29 7/9
Interrupt controller nel PC Il PC ha 2x8259 in cascata con INTR di slave IR2 di master: master, con tipo base < = > (in? @ A B ) e port di indirizzi: B < > il port 1, per? @ A C, D @ A B E F B C > il port 2, per? @ A B E G e D @ A C slave, con tipo base H < > (in? @ A B ) e port di indirizzi: < I > il port 1, per? @ A C, D @ A B E F < J > il port 2, per? @ A B E G e D @ A C Le linee IR (o IRQ) sono allocate come segue: Linea IR Master Slave 0 Timer Real time clock 1 Keyboard Available 2 INTR Slave Available 3 COM2 Available 4 COM1 Serial Mouse 5 Available FPU 6 FD Controiler HD Controller 7 LPT1 Available Interrupt X86 20/01/00 15.29 8/9
Confltti tra IR - Modo fully-nested In modo non fully-nested, 8259 arbitra tra IR simultanee e IRn ha la precedenza su IRm sse n<m Si consideri però la sequenza di eventi: 1. 8259 riceve soltanto IRn, passa INTR e riceve INTA 2. 8259 comunica il tipo base 3. parte la ISR 4. 8259 riceve IRm Come dovrebbe reagire a (4) l 8259? a) se accetta IRm e passa INTR rischia di interrompere ISR per IRn (e n<m), se questa è ancora in corso b) se vuole aspettare che ISR termini, come fa a saperlo? In modalità standard (non fully nested): l 8259 fa (a) se la ISR di IRn non vuole ricevere INTR per una IRm, n<m deve lasciare IF=0 inizialmente o mascherare IRm con OCW1 In modalità fully nested invece: 8259 maschera ogni IRm, m>n, se IRn è l ultima richiesta accettata dalla CPU e per cui presume sia in corso il servizio la ISR per IRn deve comunicare a 8259 quando finisce, ponendo K L M (N O P ) nel port L ora 8259 invierà le IRm che aveva mascherate (e memorizzate) Interrupt X86 20/01/00 15.29 9/9