<docere>http://www.docere.ro/ |

Porturi şi întreruperi
Am vizat anterior două elemente: microprocesorul şi memoria internă; CPU accesează memoria prin intermediul magistralelor, realizând operaţii de citire sau scriere şi prelucrând datele conform setului propriu de instrucţiuni.
Pentru introducere în memorie, sau extragere - sunt angrenate diverse dispozitive I/O (de intrare/ieşire): tastatură, unităţi de disc, display, printer, etc. Un astfel de echipament conţine circuite proprii care pot fi programate pentru a asigura funcţionarea specifică; pe de altă parte, el este cuplat la magistrale (fie direct printr-unul dintre circuitele proprii, fie prin intermediul unei plăci adaptoare).
Fiecărui dispozitiv extern conectat astfel cu CPU, îi este rezervată una sau mai multe "adrese" (porturi de comunicare); CPU poate accesa dispozitivul respectiv prin intermediul porturilor şi magistralelor: se depune adresa de port pe magistrala de adrese şi se emite pe magistrala de comenzi semnalul de citire (sau de scriere - caz în care data de transmis va fi depusă pe magistrala de date).
Astfel, accesul la un dispozitiv I/O decurge analog accesului CPU la memorie; iar evitarea confuziei între adresă de memorie şi adresă de port este asigurată prin existenţa unui semnal de comandă special: un anumit pin al CPU - notat cu M/IO - este pus pe "1" pentru acces la memorie, respectiv pe "0" pentru acces la un port I/O.
Circuitul (controler) care asigură astfel legătura între CPU şi dispozitivele I/O, dispune de un registru de stare, de un registru de comandă, de regiştri de date şi fiecăruia dintre aceşti regiştri îi este rezervată o anumită adresă de port. Pentru CPU (şi pentru programator), circuitul respectiv şi însuşi dispozitivul I/O aferent este reprezentat de porturile de comunicare ce i-au fost atribuite.
CPU poate citi în acumulator (adică în AL, în AX, sau în EAX) cuvântul de stare curentă a dispozitivului, sau datele emise de acesta - depunnând pe magistrala de adrese numărul portului respectiv, fie NrPort; pentru NrPort = 0..255 (de tip byte), instrucţiunea IN AL, NrPort realizează selectarea portului respectiv - valoarea NrPort este înscrisă pe magistrala de adrese, se activează semnalul de citire, iar semnalul M/IO este pus pe "0" - şi totodată obţine în AL valoarea emisă pe calea de date de către registrul de port selectat. Pentru NrPort > 255, adresarea portului respectiv are loc prin intermediul registrului DX: se încarcă valoarea NrPort în DX şi apoi se foloseşte instrucţiunea IN AX, DX - conţinutul lui DX va fi depus pe magistrala de adrese, iar acumulatorul va prelua cuvântul de pe calea de date.
Analog, CPU poate emite o dată sau un cuvânt de comandă (pentru a selecta un anumit mod de lucru, sau a specifica anumiţi parametri de funcţionare a dispozitivului), prin OUT NrPort, acumulator (sau OUT DX, acumulator).
Folosind instrucţiuni IN, OUT şi cunoscând porturile necesare, se vor putea programa operaţiile I/O adecvate. Fiindcă mai toate aplicaţiile implică numeroase operaţii I/O, programele necesare au fost standardizate şi incluse împreună într-o bibliotecă de bază - BIOS Basic Input Output System.
Însă BIOS-ul este o memorie de tip read only; astfel că, pentru a asigura posibilitatea ca programatorul însuşi (sau sistemul de operare) să administreze sau să extindă unele operaţii I/O - în loc să apeleze la serviciile standardizate minimale oferite de BIOS - s-a adoptat ideea de a "vedea" BIOS-ul nu în mod direct, ci prin intermediul unei anumite "staţii de comunicare" instituite în memoria RAM (de tip Read/Write). Şi anume, odată cu "iniţializarea sistemului" - sarcină distinctă, realizată direct de anumite rutine din BIOS - are loc înscrierea în memoria RAM a unor puncte de intrare în rutinele incluse în BIOS (precum şi a unor date rezultate din testarea echipamentelor existente).
Exemplificând pe I8086, zona respectivă dispune de 1024 octeţi şi înregistrează maximum 1024/4 = 256 de adrese Segment:Offset; fiecare intrare în acest tabel este un vector de 4 octeţi (vectorul 0 indică primii patru octeţi din tabel; vectorul 5 indică cei patru octeţi începând de la octetul de rang 5×4 din tabel); vectorul respectiv înregistrează adresa unei anumite rutine (una din BIOS, sau una din nucleul sistemului de operare).
Această zonă RAM este denumită tabelul vectorilor de întrerupere, sau tabela descriptorilor de întrerupere IDT; dacă programatorul va opta uneori pentru o tratare proprie în locul celei standard oferite de BIOS (sau de sistemul de operare), atunci el nu are decât să înlocuiască adresa existentă la intrarea respectivă în tabel, cu adresa propriei rutine. Desigur, înlocuirea unei adrese "oficiale" din IDT cu adresa unei rutine proprii necesită multă precauţie; de exemplu, adresa originală trebuie salvată pentru a o înregistra înapoi la momentul potrivit - altfel, după execuţia programului propriu, zona de memorie aferentă este de regulă eliberată, încât adresa care a fost lăsată în IDT în locul celei originale nu mai poate deservi corect o eventuală solicitare ulterioară.
Instrucţiunea INT vector va determina apelarea rutinei a cărei adresă este conţinută în vectorul precizat de instrucţiune ca intrare în IDT (la offsetul egal cu 4×vector, faţă de baza IDT); este vorba într-adevăr de o INTrerupere (şi anume, o întrerupere soft), pentru că rutina apelată astfel nu este de obicei, parte a programului din care este apelată. INT vector realizează întâi salvarea stării curente a programului (registrul flagurilor şi adresa de revenire) şi apoi lansează rutina externă indicată de intrarea respectivă din IDT; revenirea în programul din care s-a cerut serviciul respectiv este provocată de instrucţiunea IRET - aceasta, spre deosebire de RET, asigură şi reconstituirea registrului flagurilor.
Am descris mai sus mecanismul întreruperilor doar ca posibilitate de utilizare a serviciilor existente în BIOS (sau a celor oferite de sistemul de operare). Dar sorgintea acestui mecanism este în primul rând de natură hardware, având la bază perceperea dispozitivelor I/O ca elemente active care dispun de o anumită autonomie funcţională; în fond, s-a dorit ca CPU să fie scutit de a le purta de grijă - prevăzând pentru aceasta un circuit special, PIC Programmable Interrupt Controller.
Pentru a evidenţia aspectele tipice ale mecanismului întreruperilor, considerăm circuitul I8259 - controlerul programabil de întreruperi introdus de Intel în 1980. La un circuit I8259 sunt conectate până la 8 dispozitive I/O (ca surse de întreruperi), prin linii desemnate prin IRQ0, IRQ1, ..., IRQ7; pe aceste linii, dispozitivele respective pot emite controlerului cereri de întrerupere.
În registrul IRR Interrupt Request Register (registrul cererilor în aşteptare) al lui I8259, bitul 0 (sau nivelul 0 de întrerupere - cel cu prioritate maximă) corespunde liniei IRQ0; bitul 1 (nivelul 1 de întrerupere) corespunde liniei IRQ1; ş.a.m.d. Fiecărei surse de întrerupere îi este asociat astfel câte un cod unic 0002...1112 - acesta va fi depus la un anumit moment pe magistrala de date, iar CPU îl va prelua drept selector (tipul întreruperii) de intrare în tabela vectorilor de întrerupere (în octetul de tip-întrerupere, I8259 are de poziţionat numai ultimii 3 biţi, corespunzător uneia dintre cele 8 linii; primii 5 biţi au valoarea implicită "00001"):
| linia | nivel | Tip | Adresa intrării în IDT (= 4×Tip) | dispozitiv deservit |
| IRQ0 | 0 | 00001000 = 08 | 0000:0020 | contor de timp |
| IRQ1 | 1 | 00001001 = 09 | 0000:0024 | tastatură |
| IRQ2 | 2 | 00001010 = 0A | 0000:0028 | placă video |
| IRQ3 | 3 | 00001011 = 0B | 0000:002C | port serial 2 |
| IRQ4 | 4 | 00001100 = 0C | 0000:0030 | port serial 1 |
| IRQ5 | 5 | 00001101 = 0D | 0000:0034 | harddisk |
| IRQ6 | 6 | 00001110 = 0E | 0000:0038 | floppy disk |
| IRQ7 | 7 | 00001111 = 0F | 0000:003C | port paralel 1 |
De exemplu, la acţionarea unei taste, dispozitivul deservit este tastatura; controlerul tastaturii va activa linia de întrerupere care-i corespunde, IRQ1; sesizat astfel, I8259 va genera codul 09, pe baza căruia CPU va selecta din IDT vectorul al 9×4 = 36-lea, adică cei 4 octeţi consecutivi de la offsetul 0x0024, reprezentând adresa rutinei care va deservi întreruperea.
Întreruperile controlate de I8259 sunt mascabile - ele pot fi dezactivate sau activate în mod selectiv, prin setarea sau resetarea biţilor corespunzători din registrul IMR Interrupt Mask Register al controlerului. Totodată, CPU poate inhiba temporar toate întreruperile mascabile, prin ştergerea bitului IF Interrupt Flag din cadrul registrului de flaguri - în urma executării instrucţiunii CLI CLear Interrupt; efectul invers, de permitere a întreruperilor mascabile (IF = 1) este asigurat prin instrucţiunea STI SeT Interrupt.
Sunt prevăzute de asemenea, întreruperi externe nemascabile - care nu îşi au originea în I8259 şi nu sunt afectate de starea flagului IF; ele "vin" direct la CPU, pe pinul NMI Non-Maskable Interrupt - semnalând un eveniment critic, care necesită atenţie imediat (scăderea tensiunii de alimentare, apariţia unei erori la memorie, o excepţie de operare).
În sfârşit, unele întreruperi sunt generate intern, de către CPU însuşi - ca urmare a producerii unei situaţii de excepţie prevăzute pentru anumite instrucţiuni (împărţire la 0, depăşire), sau pentru a permite urmărirea execuţiei "pas cu pas".
În principiu, elementele angajate în mecanismul de tratare prin întreruperi pot fi sintetizate astfel:

Pinul COD/INTA Code / Interrupt Acknowledge al CPU - pe lângă faptul că serveşte disocierii între citire de cod al unei instrucţiuni şi citire a unei date - permite lansarea unor impulsuri de recunoaştere (sau confirmare) a întreruperii. Când primeşte prin pinul INTA confirmarea acceptării de întrerupere, I8259 scoate pe magistrala de date codul întreruperii respective, resetează în registrul IRR bitul corespunzător acesteia (ceea ce asigură dispozitivului respectiv posibilitatea de a depune eventual o nouă cerere de întrerupere, "în aşteptare") şi înscrie 1 în bitul corespunzător nivelului întreruperii din registrul ISR In-Service Register (registrul întreruperilor în curs de tratare); bitul respectiv din ISR va fi şters în final - ca urmare a recepţionării unui semnal EOI End-Of-Interrupt - şi controlerul va trece la tratarea următoarei cereri de întrerupere.
I8259 poate fi configurat prin program să funcţioneze în diverse moduri de operare, emiţând cuvinte de comandă şi cuvinte de mod corespunzătoare; astfel, se pot masca unele întreruperi, se poate fixa un alt lanţ de priorităţi decât cel implicit, se poate alege între a aştepta semnalul EOI de la CPU sau a genera un semnal AEOI (Automatic EOI); un anumit cuvânt, va permite citirea de către CPU, de la portul respectiv, a registrului IRR, sau a registrului ISR.
CPU răspunde la o întrerupere mascabilă după următorul scenariu general:
ORAR orarul şcolii
SitSco situaţie şcolară
ŞAH prin corespondenţă
doChess a Javascript chess engine
doPGN a Javascript PGN-browser
Cal++ ambiţiile Calului
aşaAzis momente lingvistice
Comentarii
—cum ar trebui calculată Media şcolară?
completely rethink the browser:
Google chrome