I/O addressen en interrupts op de PC
- I/O en IRQ’s, inleiding
- PC I/O en IRQ gebruik
- Register naar poort conversie tabel
- Interrupt gebruik op een PC
I/O en IRQ’s, inleiding
Seriële communicatie wordt uitgevoerd door het schrijven van output- en het lezen van input registers van een UART. Een UART (universal asynchronous receiver / transmitter) is een IC dat in staat is om parallelle informatie om te zetten naar seriële gegevens, die over een lijn te transporteren om ze aan de andere kant weer te ontvangen en terug te converteren naar parallelle informatie.
De UART registers op PC compatible computers zijn beschikbaar als I/O poorten die beginnen vanaf een gedefiniëerde plaats. Een UART is in staat om de aandacht van software te trekken door een processor interrupt te genereren. Op die manier is het niet noodzakelijk om continu de staat van de seriële communicatie te controleren binnen een applicatieprogramma.
PC I/O en IRQ gebruik
Op PC’s is de register set van een UART beschikbaar in de I/O adresruimte van de processor. De twaalf registers van een UART zijn via 8 adressen toegankelijk. Om dit te bereiken zijn registers die alleen gelezen of geschreven kunnen worden gecombineerd aanwezig op één I/O adres. In twee situaties wordt bovendien een bit (het divisor latch access bit DLAB) in een register gebruikt om verschillende registers te swappen op een I/O adres.
Vier seriële communicatie apparaten zijn voorgedefiniëerd op een PC. De UART’s voor deze apparaten hebben standaard adressen toegewezen gekregen waarop de registers toegankelijk zijn. De apparaten hebben de namen COM1 tot en met COM4 toegewezen gekregen. Naast een I/O adres is ook een standaard interrupt niveau aan de UART’s toegewezen. Omdat op een PC slechts een beperkte hoeveelheid interrupt lijnen beschikbaar zijn worden twee interruptlijnen gebruikt voor vier communicatiepoorten. De software moet de intelligentie bezitten om te detecteren welke UART aandacht nodig heeft als er een interrupt optreedt terwijl meer dan één UART van hetzelfde interruptniveau gebruik maakt.
Poort | I/O adressen | IRQ |
---|---|---|
COM1 | 0x3F8 – 0x3FF | 4 |
COM2 | 0x2F8 – 0x2FF | 3 |
COM3 | 0x3E8 – 0x3EF | 4 |
COM4 | 0x2E8 – 0x2EF | 3 |
Houd er rekening mee, dat in de tabel alleen de default I/O adressen staan van XT en AT compatible computers. Op een PS2 systeem worden andere adressen gebruikt. Bovendien zijn de genoemde waarden alleen maar aanbevelingen. Als andere hardware in de computer het noodzakelijk maakt kan het zijn dat een UART op een ander I/O adres of interrupt lijn geplaatst is.
De werkelijke I/O adressen van de eerste vier UART’s in de computer zijn opgeslagen in een tabel in het datagebied van het BIOS. Deze tabel start op geheugen adres 0000:0400 en bevat belangrijke apparatuur informatie. Helaas worden alleen de I/O adressen van de UART’s opgeslagen. Er is geen informatie aanwezig over de interrupt die wordt gebruikt door een bepaalde UART. Daarom is deze informatie slechts beperkt geschikt voor het identificeren van de seriële poorten op een computer systeem.
Geheugenadres | Waarde |
---|---|
0000:0400 | COM1 basis I/O poort |
0000:0402 | COM2 basis I/O poort |
0000:0404 | COM3 basis I/O poort |
0000:0406 | COM4 basis I/O poort |
Register naar poort conversie tabel
Zoals gezegd zijn acht I/O bytes noodzakelijk om alle registers van een UART te kunnen benaderen. In de volgende tabel is aangegeven op welke lokatie elk register kan worden gevonden. Het basis adres zoals dat in de tabel wordt gebruikt is het laagste I/O poort adres dat door de UART wordt gebruikt. Het schakel bit DLAB kan in het line control register LCR worden gevonden als bit 7 op I/O adres basis + 3.
I/O poort | Lezen (DLAB=0) | Schrijven (DLAB=0) | Lezen (DLAB=1) | Schrijven (DLAB=1) |
---|---|---|---|---|
base | RBR receiver buffer | THR transmitter holding | DLL divisor latch LSB | DLL divisor latch LSB |
base+1 | IER interrupt enable | IER interrupt enable | DLM divisor latch MSB | DLM divisor latch MSB |
base+2 | IIR interrupt identification | FCR FIFO control | IIR interrupt identification | FCR FIFO control |
base+3 | LCR line control | LCR line control | LCR line control | LCR line control |
base+4 | MCR modem control | MCR modem control | MCR modem control | MCR modem control |
base+5 | LSR line status | fabriekstest | LSR line status | fabriekstest |
base+6 | MSR modem status | niet gebruikt | MSR modem status | niet gebruikt |
base+7 | SCR scratch | SCR scratch | SCR scratch | SCR scratch |
Voor een beschrijving van elk afzonderlijk register:
RBR, THR, IER, IIR, FCR, LCR, MCR, LSR, MSR, SCR, DLL, DLM.
Interrupt gebruik op een PC
Het interruptmechanisme dat aanwezig is op een PC wordt geregeld door een interrupt management chip, de programmable interrupt controller PIC. De chip zoals die op de XT gebruikt is, is een 8259A chip geschikt voor het afhandelen van 8 hardware interrupts. Wanneer een interrupt optreedt op één van de PIC ingangen, dan wordt de INTR ingang van de processor geactiveerd. De PIC is verantwoordelijk van het afhandeling van prioriteiten wanneer twee of meer interrupts op nagenoeg hetzelfde tijdstip plaatsvinden.
Om meer hardware te kunnen gebruiken in combinatie met de computer is er vanaf de AT een tweede interrupt controller toegevoegd. Om dit te laten functioneren gebruikt deze tweede controller één van de originele ingangen van de reeds bestaande PIC. Dit betekent, dat in de AT configuratie slechts 7 interrupt lijnen beschikbaar zijn op de eerste controller en 8 op de tweede. Daardoor zijn er totaal 15 ingangen beschikbaar wat genoeg is voor de meeste toepassingen. Om compatible te blijven met oudere applicaties is de IRQ 2 lijn zoals die op de XT beschikbaar was naar de IRQ 9 ingang geleid van de tweede PIC. BIOS zorgt ervoor, dat bij het binnenkomen van een interrupt op ingang IRQ 9, deze automatisch softwarematig wordt omgeleid naar de originele IRQ 2. Op deze manier wordt de oorspronkelijke interrupt routine voor IRQ 2 aangeroepen, ook al komt het werkelijke signaal nu van IRQ 9.
De eerste PIC is toegankelijk op I/O poort 0x20 en 0x21, de tweede op 0xA0 en 0xA1. Deze poorten moeten door een applicatieprogramma dat interrupts gebruikt voor twee doeleinden worden gebruikt. Één is, dat de PIC moet worden verteld dat interrupts op een bepaalde ingang mogen worden gehonoreerd en doorgezonden naar de processor. Het andere doel is om de PIC te resetten wanneer bij het afhandelen van een interrupt alle noodzakelijke handelingen zijn uitgevoerd.
Prioriteit kan een belangrijk gegeven zijn bij seriële communicatie. De hoeveelheid interrupts die optreedt tijdens het communiceren kan aanzienlijk zijn. Als geen buffering wordt gebruikt zal elke binnenkomende byte worden aangekondigd met een trigger signaal op de interrupt lijn. Als buffering wel aanwezig is (zoals op de meeste op dit moment in gebruik zijnde UART’s) neemt dit aantal af tot ongeveer één interrupt op elke veertien binnenkomende bytes. Nog steeds een hoge hoeveelheid interrupts in verhouding tot de binnenkomende informatie. Dit aantal verdubbelt, wanneer ook het versturen van gegevens interrupt gestuurd gaat, laat staan wat er gebeurt als ook de modem signalen worden gecontroleerd door interrupts.
Interrupt service routines
Het stukje software dat wordt gestart als een interrupt optreedt wordt een interrupt service routine, of ISR genoemd. In het BIOS data gebied wordt een tabel bijgehouden
van het startadres van alle mogelijke routines. Deze tabel is opgeslagen in de adres range 0000:0000 tot 0000:0400. Er zijn totaal 256 routines aanroepbaar (waarvan de meesten alleen voor software toegankelijk zijn). Standaard worden de hardware interrupts afgevangen door een klein stukje BIOS routine dat de interrupt controller reset en dan stopt. Om in eigen software interrupts te kunnen gebruiken moet deze standaard routine door een eigen stuk software worden vervangen.
Het startadres van een ISR in de BIOS tabel kan worden veranderd door de bytes direct te veranderen op de geëigende geheugenplaats, maar het is beter om een DOS software interrupt toe te passen die daarvoor ontworpen is. Gebruik de handleiding van de compiler om uit te zoeken wat de beste manier is om het te doen. In de volgende tabel zijn de offsets in de BIOS tabel genoemd van alle hardware interrupts.
Hardware interrupt | Software interrupt | Standaard gebruik |
---|---|---|
0 | 0x08 | Klok |
1 | 0x09 | Toetsenbord |
2 | 0x0A | Tweede PIC cascade |
3 | 0x0B | COM2 en COM4 |
4 | 0x0C | COM1 en COM3 |
5 | 0x0D | LP2 / harddisk op de XT |
6 | 0x0E | Floppy disk |
7 | 0x0F | LPT1 |
8 | 0x70 | Real-time klok |
9 | 0x71 | Genereert software interrupt 0x0A |
10 | 0x72 | – |
11 | 0x73 | – |
12 | 0x74 | – |
13 | 0x75 | Mathematische co-processor |
14 | 0x76 | IDE harddisk controller |
15 | 0x77 | – |
De bijbehorende tabel ingang moet het gesegmenteerde start adres bevatten van de functie in het applicatieprogramma dat een binnenkomende interrupt moet afhandelen. Deze functie moet eindigen met een aanroep van de IRET assembly instructie. Dit betekent, dat een standaard functie in het programma niet zonder meer kan worden gebruikt als interrupt service routine. In C/C++ bijvoorbeeld, moet het woord interrupt in de functie declaratie worden gebruikt om de gewenste assembly instructies hiervoor te genereren. Raadpleeg de compiler handleiding voor meer details.
Wanneer een interrupt optreedt moet de software het IIR interrupt identification register bekijken om te controleren wat de oorzaak is van de optredende interrupt. Wanneer meer dan één UART op hetzelfde IRQ adres worden gebruikt, dan moeten de registers van al deze UART’s worden gecontroleerd door het applicatie programma. Raadpleeg de programmeervoorbeelden voor details.
Het prioriteiten schema
De PIC gebruikt een prioriteiten schema, waarbij de lage IRQ nummers een hogere prioriteit hebben dan de hoge. De PIC staat nieuwe interrupts toe wanneer de processor bezig is met het afhandelen van een vorige, zolang het IRQ nummer van de nieuwe interrupt lager is dan dat van de interrupt die op dit moment wordt afgehandeld. Daardoor kan het experimenteren met de interrupts die toegewezen zijn aan verschillende apparatuur in de PC de maximaal toegestane snelheid van seriële communicatie voordelig of nadelig beïnvloeden. Houd er rekening mee, dat het systeem aanneemt dat de meeste standaard apparatuur op een vastgestelde interrupt aanwezig is. Het wijzigen van het interrupt nummer van harddisks en floppy drives is meestal geen goed idee, maar het wijzigen van de interrupt van een netwerk kaart kan goede resultaten opleveren.
Interrupts toestaan
Een interrupt treedt niet op, tenzij de PIC verteld is dat het toegestaan is om een bepaalde interrupt door te laten. Dit betekent, dat de PIC moet worden geprogrammeerd alvorens een UART kan worden toegepast in een applicatie met interrupt gestuurde communicatie. Daarvoor dient het IMR interrupt mask register van de PIC te worden gebruikt. Dit register is toegankelijk op I/O poort 0x21 voor de eerste, en 0xA1 voor de tweede PIC.
De acht bits in het IMR interrupt mask register regelen elk het gedrag van één interrupt lijn van de PIC. Als een bit 0 is, dan zal de bijbehorende interrupt worden doorgegeven aan de processor. Hierbij is IRQ 2 een wat speciaal geval op AT compatible computers. Om deze interrupt te laten optreden moeten zowel de IRQ 2, als het IRQ 9 bit worden gecleard. Het IRQ 2 bit zal meestal al op 0 staan om ook andere interrupts van de tweede PIC mogelijk te maken. Het bit van IRQ 9 op de tweede PIC moet echter ook op 0 worden gezet. Dit is niet compatible met de originele methode om IRQ 2 te gebruiken op een XT compatible computer.
Vanwege dit verschil tussen de XT en AT computer kan oudere software die geschreven is voor de XT en gebruik maakt van IRQ toch in de praktijk geen gebruik maken van deze interrupt als de software op een AT compatible wordt gebruikt. Ontwerpers hebben bij de AT geprobeerd de PIC configuratie zo compatible als mogelijk te maken bij het doorsluizen van deze IRQ, zelfs door extra BIOS software, maar daarbij vergaten ze het IMR register dat de zichtbaarheid van een interrupt voor de software uiteindelijk
controleert.
Het IMR register kan eenvoudig gewijzigd worden. Eerst wordt de byte ingelezen vanaf I/O adres 0x21 of 0xA1, met de functie die daarvoor in de compiler of in assembly beschikbaar is. Vervolgens wordt het gewenste bit op 0 gezet waarna de byte wordt teruggeschreven naar dezelfde lokatie. Houd er rekening mee dat hetzelfde bit weer gezet wordt bij het beëindigen van de applicatie. Anders zal de PIC bij het binnenkomen van nieuwe karakters proberen de software interrupt routine aante roepen die niet meer aanwezig is. Dit kan tot vreemd gedrag van de computer leiden, inclusief een complete systeemcrash.
Het belangrijkste geval waar rekening mee gehouden moet worden is het drukken van de Ctrl-C toets. In de meeste applicaties zorgt deze toets voor het onmiddellijk stoppen van de applicatie, zonder dat de status van de IMR wordt teruggezet, en erger, zonder het terug veranderen van het startadres van de interrupt service routine. De interrupt service routine is de functie in het applicatieprogramma die wordt aangeroepen als een interrupt optreedt. Dit stuk software is na beeindiging van de applicatie niet meer in het geheugen aanwezig, maar vervangen door een willekeurig ander stuk software op dezelfde geheugenlokatie. Als het startadres in de BIOS tabel niet wordt veranderd, dan zal nog steeds een aanroep van de code op dezelfde geheugen lokatie worden gedaan als na afsluiten van het programma een interrupt optreedt. Moet ik nog meer uitleggen?
Afhandelen van interrupts
De PIC zorgt ervoor, dat er geen nieuwe interrupts van dezelfde of lagere prioriteit aan de processor worden doorgegeven, zolang de software niet klaar is met het afhandelen van de vorige. Dit betekent, dat de software de PIC moet aangeven dat nieuwe interrupts mogen plaatsvinden, anders zal de computer uiteindelijk hangen.
Het afhandelen van een interrupt richting de PIC kan worden gedaan door een zogenaamd non-specific end-of-interrupt commando naar het register van de PIC te sturen dat toegankelijk is op I/O adres 0x20 voor de eerste, en 0xA0 voor de tweede controller. Dit commando bestaat uit de byte waarde 0x20. Als een interrupt is opgetreden op de tweede PIC is het niet noodzaklijk om de status van beide controllers te resetten. Alleen voor de tweede controller is dit nodig. Het BIOS heeft voor de aanroep van de ISR reeds voor de afhandeling van de eerste controller gezorgd.
I don't want to achieve immortality through my work;
I want to achieve immortality through not dying. WOODY ALLEN
|