Avbrott i 65xx-processorer
65xx-familjen av mikroprocessorer , bestående av MOS Technology 6502 och dess derivat, WDC 65C02 , WDC 65C802 och WDC 65C816 och CSG 65CE02 , hanterar alla avbrott på ett liknande sätt. Det finns tre hårdvaruavbrottssignaler gemensamma för alla 65xx-processorer och ett mjukvaruavbrott, BRK - instruktionen. WDC 65C816 lägger till ett fjärde hårdvaruavbrott – AVBRYT , användbart för att implementera virtuella minnesarkitekturer – och COP -programvaruavbrottsinstruktionen (finns också i 65C802), avsedd för användning i ett system med en samprocessor av någon typ (t.ex. en flyttal). processor ).
Avbrottstyper
Avbryta | Vektor (hexadecimal) | |
---|---|---|
LSB | MSB | |
IRQ / BRK | FFFE | F F F F |
ÅTERSTÄLLA | FFFC | FFFD |
NMI | FFFA | FFFB |
AVBRYTA | FFF8 | FFF9 |
POLIS | FFF4 | FFF5 |
Hårdvaruavbrottssignalerna är alla aktiva låga och är som följer:
- ÅTERSTÄLL
- en återställningssignal , nivåutlöst
- NMI
- ett icke-maskerbart avbrott , kantutlöst
- IRQ
- ett maskerbart avbrott , nivåutlöst
- AVBORT
- ett icke-maskerbart avbrott för specialändamål (endast 65C816, se nedan), nivåutlöst
Detekteringen av en RESET- signal får processorn att gå in i en systeminitieringsperiod på sex klockcykler, varefter den ställer in flaggan för avaktivering av avbrottsbegäran i statusregistret och laddar programräknaren med värdena lagrade i processorinitieringsvektorn ( $00FFFC – $00FFFD ) innan exekvering påbörjas. Om 65C816/65C802 arbetar i inbyggt läge, växlas de tillbaka till emuleringsläge och stannar där tills de återgår till inbyggt läge under mjukvarukontroll.
Avbryta | Vektor (hexadecimal) | |
---|---|---|
LSB | MSB | |
IRQ | 00FFEE | 00FFEF |
ÅTERSTÄLLA | Ingen | |
NMI | 00FFEA | 00FFEB |
AVBRYTA | 00FFE8 | 00FFE9 |
BRK | 00FFE6 | 00FFE7 |
POLIS | 00FFE4 | 00FFE5 |
Detekteringen av en NMI- eller IRQ -signal, såväl som exekveringen av en BRK -instruktion, kommer att orsaka samma övergripande sekvens av händelser, som är i ordning:
- Processorn slutför den aktuella instruktionen och uppdaterar register eller minne efter behov innan den svarar på avbrottet.
- 65C816/65C802 vid drift i native-läge: Programbankregistret ( PB , A16 -A23- delen av adressbussen ) skjuts in på hårdvarustacken .
- Den mest signifikanta byten (MSB) av programräknaren ( PC ) skjuts in i stacken.
- Programräknarens minst signifikanta byte (LSB) skjuts in i stacken.
- Statusregistret ( SR ) skjuts upp på stapeln.
- Avbrottsavstängningsflaggan sätts i statusregistret.
- 65C816/65C802: PB laddas med $00 .
- PC laddas från den relevanta vektorn (se tabeller).
Beteendet hos 65C816 när ABORT hävdas skiljer sig i vissa avseenden från ovanstående beskrivning och diskuteras separat nedan.
Observera att processorn inte trycker på ackumulator- och indexregistren till stacken – koden i avbrottshanteraren måste utföra den uppgiften, samt återställa registren vid avbrottsbehandlingens slut, om nödvändigt. Observera också att vektorn för IRQ är densamma som för BRK i alla åtta bitars 65xx-processorer, såväl som i 65C802/65C816 när de arbetar i emuleringsläge. När 65C802/65C816 arbetar i inbyggt läge tillhandahåller separata vektorer för IRQ och BRK .
När den är inställd kommer flaggan för avaktivering av avbrottsbegäran ( I -biten i statusregistret) att inaktivera detektering av IRQ- signalen, men kommer inte att ha någon effekt på några andra avbrott (se dock nedan avsnitt om WAI -instruktionen implementerad i WDC CMOS-processorer) . Dessutom, med 65(c)02 eller 65C816/65C802 i emuleringsläge, kommer kopian av statusregistret som skjuts upp i stacken att ha B-flaggan inställd om ett BRK ( programvaruavbrott ) var orsaken till avbryta eller rensas om en IRQ var orsaken. Följaktligen måste avbrottsservicerutinen hämta en kopia av det sparade statusregistret varifrån det trycktes på stacken och kontrollera statusen för B -flaggan för att skilja mellan en IRQ och en BRK . Detta krav elimineras när du använder 65C802/65C816 i inbyggt läge, på grund av de separata vektorerna för de två avbrottstyperna.
AVBRYT avbrott
65C816:s ABORTB- avbrottsingång är avsedd att tillhandahålla medel för att omdirigera programkörning när ett hårdvaruundantag upptäcks, såsom ett sidfel eller ett minnesåtkomstbrott . Därför är processorns svar när ABORTB- ingången hävdas (negeras) annorlunda än när IRQB och/eller NMIB hävdas. För att uppnå korrekt funktion som svar på ABORTB krävs också att avbrottet inträffar vid rätt tidpunkt under maskincykeln, medan inget sådant krav finns för IRQB eller NMIB .
När ABORTB hävdas under en giltig minnescykel, det vill säga när processorn har hävdat VDA- och/eller VPA -statusutgångarna, kommer följande händelsesekvens att inträffa:
- Processorn slutför den aktuella instruktionen men ändrar inte registren eller minnet på något sätt - beräkningsresultaten för den slutförda instruktionen förkastas. Ett avbrytande avbrott avbryter inte bokstavligen en instruktion.
- Programbanken ( PB , se ovan) skjuts till stacken.
- Den mest signifikanta byten (MSB) av den avbrutna instruktionens adress skjuts in i stacken.
- Den minst signifikanta byten (LSB) av den avbrutna instruktionens adress skjuts in i stacken.
- Statusregistret skjuts upp på stapeln.
- Avbrottsavstängningsflaggan sätts i statusregistret.
- PB är laddat med $00 .
- Programräknaren laddas från ABORT -vektorn (se tabeller).
Eftersom adressen som skjuts till stacken är adressen för den avbrutna instruktionen snarare än innehållet i programräknaren, kommer exekvering av en RTI ( R e T urn from I nterrupt) efter ett AVBORT- avbrott att få processorn att återgå till den avbrutna instruktionen, snarare än nästa instruktion, vilket skulle vara fallet med de andra avbrotten.
För att processorn ska kunna svara korrekt på ett avbrott måste systemlogiken hävda (negera) ABORTB- ingången så snart en giltig adress har placerats på bussen och det har fastställts att adressen utgör ett sidfel, minnesåtkomstbrott eller annan anomali (t.ex. försök att utföra en privilegierad instruktion). Därför får logiken inte hävda ABORTB förrän processorn har hävdat VDA- eller VPA -signalerna. Dessutom ABORTB förbli hävdat tills fas två-klockan faller och sedan omedelbart släppas. Om dessa tidsbegränsningar inte observeras, kan avbrytningsavbrottshanteraren själv avbrytas, vilket orsakar att register och/eller minne ändras på ett möjligen odefinierat sätt.
Avbryt anomalier
I NMOS 6502 och derivator (t.ex. 6510) togs inte hänsyn till det samtidiga påståendet om en hårdvaruavbrottslinje och exekvering av BRK i designen – BRK -instruktionen kommer att ignoreras i ett sådant fall. Statusen för decimalmodsflaggan i processorstatusregistret är också oförändrad efter ett avbrott av något slag. Detta beteende kan potentiellt resultera i en svår att lokalisera bugg i avbrottshanteraren om decimalläge råkar vara aktiverat vid tidpunkten för ett avbrott. Dessa anomalier korrigerades i alla CMOS- versioner av processorn.
Avbryt hanterare överväganden
En väl utformad och kortfattad avbrottshanterare eller avbrottsservicerutin (ISR) kommer inte bara att snabbt serva varje händelse som orsakar ett avbrott, den kommer att göra det utan att på något sätt störa den avbrutna förgrundsuppgiften – ISR måste vara "transparent" för den avbrutna uppgiften (även om undantag kan gälla i särskilda fall). Detta betyder att ISR måste bevara mikroprocessorns (MPU) tillstånd och inte störa något i minnet som den inte ska störa. Dessutom bör ISR:n vara helt återinträdande , vilket betyder att om två avbrott kommer i tät följd, kommer ISR:n att kunna återuppta behandlingen av det första avbrottet efter att det andra har betjänats. Återinträde uppnås vanligtvis genom att endast använda MPU-hårdvarustacken för lagring (även om det finns andra möjliga metoder).
Att bevara MPU-tillståndet innebär att ISR:n måste försäkra sig om att alla värden som fanns i MPU-registren vid tidpunkten för avbrottet finns där när ISR:n avslutas. En del av bevarandeprocessen hanteras automatiskt av MPU när den bekräftar avbrottet, eftersom den kommer att skjuta programräknaren (och programbanken i 65C816/65C802) och statusregistret till stacken innan ISR exekveras. Vid slutförandet av ISR, när RTI- instruktionen exekveras, kommer MPU:n att reversera processen. Ingen medlem i 65xx-familjen skickar några andra register till stacken.
I de flesta ISR:er måste ackumulator- och/eller indexregistren bevaras för att säkerställa transparens och senare återställas som de sista stegen före exekvering av RTI . I fallet med 65C816/65C802 måste man överväga om den körs i emulerings- eller native-läge vid tidpunkten för avbrottet. Om det senare kan vara nödvändigt att bevara databanken ( DB ) och direktregistret (nollsidan) ( DP ) för att garantera transparens. Dessutom kan ett 65C816-operativsystem med ursprungligt läge använda en annan stackplats än applikationsmjukvaran, vilket innebär att ISR måste bevara och därefter återställa stackpekaren ( SP ) . Ytterligare komplicerande saker med 65C816/65C802 är att storlekarna på ackumulator- och indexregistren kan vara antingen 8 eller 16 bitar när de arbetar i inbyggt läge, vilket kräver att deras storlekar bevaras för senare återställning.
Metoderna med vilka MPU-tillståndet bevaras och återställs inom en ISR kommer att variera med de olika versionerna av 65xx-familjen. För NMOS-processorer (t.ex. 6502, 6510, 8502, etc.) kan det bara finnas en metod genom vilken ackumulator- och indexregistren bevaras, eftersom endast ackumulatorn kan skjutas till och dras från stapeln. Därför är följande ISR-inmatningskod typisk:
PHA ; spara ackumulator TXA PHA ; spara X-registret TYA PHA ; spara Y-register CLD ; säkerställ binärt läge genom att rensa decimalflaggan
CLD - instruktionen är nödvändig eftersom, som tidigare noterats, NMOS-versioner av 6502 inte rensar D -flaggan (decimalläge) i statusregistret när ett avbrott inträffar.
När ackumulator- och indexregistren väl har bevarats kan ISR använda dem efter behov. När ISR har avslutat sitt arbete skulle den återställa registren och sedan återuppta den avbrutna förgrundsuppgiften. Återigen, följande NMOS-kod är typisk:
PLA TAY ; återställa Y-register PLA TAX ; återställa X-register PLA ; återställa ackumulator RTI ; återuppta avbruten uppgift
En konsekvens av RTI -instruktionen är att MPU:n återgår till decimalläge om det var dess tillstånd vid tidpunkten för avbrottet.
65C02 och 65C816/65C802 när de arbetar i emuleringsläge kräver mindre kod , eftersom de kan trycka och dra indexregistren utan att använda ackumulatorn som mellanhand. De rensar också automatiskt decimalläge innan ISR körs. Följande är typiskt:
PHA ; spara ackumulator PHX ; spara X-registret PHY ; spara Y-register
När det är klart, skulle ISR vända processen:
PLY ; återställ Y-register PLX ; återställa X-register PLA ; återställa ackumulator RTI ; återuppta avbruten uppgift
Som tidigare nämnts är det lite mer komplexitet med 65C816/65C802 när den arbetar i inbyggt läge på grund av de variabla registerstorlekarna och nödvändigheten av att ta hänsyn till DB- och DP - registren. När det gäller indexregistren kan de pushas utan hänsyn till deras storlekar, eftersom ändrade storlekar automatiskt sätter den mest signifikanta byten (MSB) i dessa register till noll och ingen data kommer att gå förlorad när det pushade värdet återställs, förutsatt att indexregister har samma storlek som när de trycktes.
Ackumulatorn är dock egentligen två register: betecknade .A och .B . Att trycka på ackumulatorn när den är inställd på 8 bitar kommer inte att bevara .B , vilket kan resultera i förlust av transparens om ISR ändras .B på något sätt. Därför måste ackumulatorn alltid ställas in på 16 bitar innan den trycks eller dras om ISR kommer att använda .B . Det är också mer effektivt att ställa in indexregistren på 16 bitar innan du trycker på dem. I annat fall måste ISR sedan trycka på en extra kopia av statusregistret så att den kan återställa registerstorlekarna innan de dras ur stacken.
För de flesta ISR:er kommer följande inträdeskod att uppnå målet om transparens:
PHB ; spara aktuell databank PHD ; spara direkt sidpekare REP #%00110000 ; välj 16-bitars register PHA ; spara ackumulator PHX ; spara X-registret PHY ; spara Y-register
I ovanstående kodfragment är symbolen % MOS Technology och WDC standard assembly language syntax för en bitvis operand .
Om ISR har sin egen tilldelade stackplats, måste bevarandet av stackpekaren ( SP ) ske i minnet efter att ovanstående push har skett – det bör vara uppenbart varför det är så. Följande kod, tillagd till ovanstående sekvens, skulle hantera detta krav:
TSC ; kopiera stackpekaren till ackumulatorn STA stkptr ; spara någonstans i säkert RAM LDA isrptr ; hämta ISR:s stackpekare &... TCS ; ange ny stackplats
Vid slutförandet av ISR skulle ovanstående processer vändas enligt följande:
REP #%00110000 ; välj 16-bitars register TSC ; spara ISR:s SP... STA isrptr ; för efterföljande användning LDA isstkptr ; hämta förgrundsuppgiftens SP &... TCS ; ställ in det PLY ; återställa Y-register PLX ; återställa X-register PLA ; återställa ackumulator PLD ; återställa direkt sidpekare PLB ; återställa aktuell databank RTI ; återuppta avbruten uppgift
Observera att när RTI körs kommer 65C816/65C802 automatiskt att återställa registerstorlekarna till vad de var när avbrottet inträffade, eftersom dragning av det tidigare sparade statusregistret ställer in eller rensar båda registerstorleksbitarna till vad de var vid tidpunkten för avbrottet .
Även om det är möjligt att byta 65C816/65C802 från native-läge till emuleringsläge inom en ISR, är detta behäftat med fara. Förutom att tvinga ackumulatorn och indexregistren till 8 bitar (som orsakar en förlust av den mest signifikanta byten i indexregistren), kommer ett emuleringsläge att trunkera stackpekaren till 8 bitar och flytta själva stacken till sidan 1 RAM . Resultatet är att stacken som fanns vid tidpunkten för avbrottet kommer att vara otillgänglig om den inte också fanns i sid 1 RAM och inte större än 256 byte. Generellt sett är lägesväxling under service av ett avbrott inte en rekommenderad procedur, men kan vara nödvändig i specifika driftsmiljöer.
Använder BRK och COP
Som tidigare noterats är BRK och COP mjukvaruavbrott och kan som sådana användas på en mängd olika sätt för att implementera systemfunktioner.
En historisk användning av BRK har varit att hjälpa till med att patcha PROMs när buggar upptäcktes i ett systems firmware . En typisk teknik som ofta användes under firmwareutveckling var att ordna så att BRK -vektorn pekar på ett oprogrammerat "patchområde" i PROM. I händelse av att en bugg upptäcktes, skulle patchningen åstadkommas genom att "blåsa" alla säkringar på adressen där den felaktiga instruktionen fanns, vilket ändrade instruktionens opkod till $00 . Vid exekvering av den resulterande BRK , skulle MPU:n omdirigeras till patchområdet, i vilket lämplig patchkod skulle skrivas. Ofta började patchens riktnummer med att "sniffa stacken" för att bestämma adressen där felet påträffades, vilket möjligen möjliggjorde närvaron av mer än en patch i PROM. Användningen av BRK för PROM-patchning minskade när EPROM och EEPROM blev allmänt tillgängliga.
En annan användning av BRK i mjukvaruutveckling är som ett felsökningshjälpmedel i kombination med en maskinspråksmonitor . Genom att skriva över en op-kod med BRK ( $00 ) och dirigera BRK- hårdvaruvektorn till monitorns ingångspunkt, kan man få ett program att stanna vid vilken punkt som helst, vilket gör att monitorn kan ta kontroll. Då kan man undersöka minnet, se processorns registervärden, patchkod etc. Debugging, som förespråkas av Kuckes och Thompson, kan underlättas genom att rikligt sprinkla sin kod med NOP-instruktioner (opcode $EA ) som kan ersättas av BRK instruktioner utan att ändra det faktiska beteendet för programmet som felsöks.
Ett kännetecken för BRK- och COP -instruktionerna är att processorn behandlar endera av dem som en tvåbyte-instruktion: själva opkoden och följande byte, som hänvisas till som "signaturen". Vid körning av BRK eller COP kommer processorn att lägga till två till programräknaren innan den skjuts till stacken. När RTI ( R e T urn from I nterrupt) exekveras, kommer det avbrutna programmet att fortsätta på adressen omedelbart efter signaturen. Om BRK används som en felsökningsenhet, kan programräknaren behöva justeras för att peka på signaturen för att exekveringen ska återupptas där det förväntas. Alternativt kan en NOP infogas som en signatur "platshållare", i vilket fall ingen programräknarejustering kommer att krävas.
Det faktum att BRK och COP dubbelinkrementerar programräknaren innan den skjuts till stacken underlättar tekniken att behandla dem som supervisor call instruktioner, som finns på vissa stordatorer . Den vanliga proceduren är att behandla signaturen som ett operativsystems tjänstindex. Operativsystemet BRK eller COP -hanteraren skulle hämta värdet på programräknaren som skjutits till stacken, minska det och läsa från den resulterande minnesplatsen för att få signaturen. Efter omvandling av signaturen till ett nollbaserat index kan en enkel uppslagstabell konsulteras för att ladda programräknaren med adressen till den korrekta servicerutinen. Efter fullbordandet av servicerutinen RTI- instruktionen användas för att återställa kontrollen till programmet som gjorde operativsystemet anrop. Observera att signaturen för BRK kan vara vilket värde som helst, medan signaturen för COP bör begränsas till intervallet $00 - $7F .
Användningen av BRK och/eller COP för att begära en operativsystemtjänst innebär att användarapplikationer inte behöver känna till ingångsadressen för varje operativsystemfunktion, bara den korrekta signaturbyten för att anropa den önskade operationen. Därför kommer omplacering av operativsystemet i minnet inte att bryta kompatibiliteten med befintliga användarapplikationer. Eftersom exekvering av BRK eller COP alltid vektorer processorn till samma adress, kan enkel kod användas för att bevara registren på stacken innan kontrollen övergår till den begärda tjänsten. Den här programmeringsmodellen kommer dock att resultera i något långsammare exekvering jämfört med att anropa en tjänst som en subrutin , främst ett resultat av stackaktiviteten som inträffar med något avbrott. Dessutom kommer avbrottsbegäranden att ha inaktiverats genom att köra BRK eller COP , vilket kräver att operativsystemet återaktiverar dem.
WAI och STP instruktioner
WAI ( WA it for I nterrupt, opcode $CB ) är en instruktion tillgänglig på WDC-versionen av 65C02 och 65C816/65C802 mikroprocessorer (MPU) som stoppar MPU:n och placerar den i ett semi-katatoniskt tillstånd tills ett hårdvaruavbrott av någon form förekommer. Den primära användningen för WAI är i inbyggda system med låg effekt där MPU:n inte har något att göra förrän en förväntad händelse inträffar och minimal strömförbrukning önskas då systemet väntar, och/eller ett snabbt svar krävs. Ett typiskt exempel på kod som skulle använda WAI är följande:
SEI ; inaktivera IRQs WAI ; vänta på hårdvaruavbrott ; ... körningen återupptas här
I ovanstående kodfragment kommer MPU:n att stanna vid exekvering av WAI och gå in i ett tillstånd för mycket låg strömförbrukning. Trots att avbrottsbegäranden (IRQ) har inaktiverats före WAI -instruktionen, kommer MPU:n att svara på alla hårdvaruavbrott medan den väntar. Vid mottagande av ett avbrott kommer MPU:n att "vakna" i en klockcykel och återuppta exekveringen vid instruktionen omedelbart efter WAI . Därför avbrottslatens att vara mycket kort (70 nanosekunder vid 14 megahertz), vilket resulterar i snabbast möjliga svar på en extern händelse.
På vissa sätt liknar WAI instruktionen STP ( ST o P , opcode $DB ), som helt stänger av MPU:n medan den väntar på en enda avbrottsingång. När STP exekveras stoppar MPU:n sin interna klocka (men behåller all data i sina register) och går in i ett lågeffekttillstånd. MPU:n förs ur detta tillstånd genom att dra dess återställningsingångsstift ( RESB , som klassificeras som en avbrottsingång) lågt. Exekveringen kommer sedan att återupptas på adressen som är lagrad på platserna $00FFFC-$00FFFD , hårdvaruåterställningsvektorn. Precis som med WAI är STP avsedd för användning i lågeffekts inbäddade applikationer där långa tidsperioder kan förflyta mellan händelser som kräver MPU-uppmärksamhet och ingen annan bearbetning krävs . STP skulle inte användas i normal programmering, eftersom det skulle leda till att behandlingen upphör totalt.
Fotnoter
- ^ a b ABORT - ingången är endast tillgänglig med W65C816S.
- ^ a b COP - instruktionen är tillgänglig i båda driftlägena.
- ^ 65C816/65C802 har ingen avbrottsvektor för native mode för RESET- signalen, eftersom en återställning alltid återställer processorn till emuleringsläge.
- ^ Värdet på B -flaggan i själva statusregistret är alltid 1 , oavsett avbrottstyp. B är meningsfull endast i kopian av statusregistret som skjuts upp på stacken som svar på ett avbrott, och existerar faktiskt inte i flaggregistret.
- ^ a b c d e Anderson, JS (1994). Mikroprocessorteknik . Butterworth-Heinemann. s. 143–144. ISBN 9780750618397 .
- ^ a b c d e f g h i j k l m n o p q r s t u v w x y z aa David Eyes och Ron Lichty (1992-04-28). "Programmera 65816" (PDF) . The Western Design Center, Inc. Arkiverad från originalet (PDF) 2012-07-23 . Hämtad 2012-11-29 .
- ^ a b "Grundläggande arkitektur" . 6502 . 2002-01-02.
- ^ a b Leo J. Scanlon (1980). 6502 Mjukvarudesign . HW Sams. s. 172–173 . ISBN 9780672216565 .
- ^ a b c Lance A. Leventhal (1986). 6502 Assembly Language Programmering . Osborne/McGraw-Hill. ISBN 9780078812163 .
- ^ Ronald J. Tocci och Lester P. Laskowski (1979). Mikroprocessorer och mikrodatorer: Hårdvara och programvara . Prentice-Hall. sid. 379 . ISBN 9780135813225 .
- ^ Kuckes, Arthur F.; Thompson, BG (1987). Apple II i laboratoriet . UP Arkiv. sid. 93 . ISBN 9780521321983 . LCCN 86-21531 .
- ^ Harrod, Dennette A. (oktober 1980). "6502 får mikroprogrammerbara instruktioner" . BYTE . Vol. 5, nr. 10. McGraw Hill . s. 282–285. Arkiverad från originalet 2006-05-25 . Hämtad 2009-05-31 .
- ^ Richard R. Smardzewski (1984). Mikroprocessorprogrammering och tillämpningar för vetenskapsmän och ingenjörer . Elsevier. sid. 125 . ISBN 97804444424075 .
Vidare läsning
- Interner av BRK/IRQ/NMI/RESET på en MOS 6502
- Brad Taylor. "6502 'B' flagga & BRK Opcode" .
- 6502 Familjens mikroprocessorresurser och forum
- 65xx Interrupt Primer – En omfattande diskussion om 65xx-familjens avbrottsbearbetning.
- Undersöka 65C816-avbrott – En omfattande diskussion om avbrottsbearbetning som är specifik för 65C816-native mode-drift.