William Sandqvist Övning 7 Interrupt, Exeption, Trap
William Sandqvist Trådar, synkronisering Datorteknik övning 7
William Sandqvist Polling och Interrupt Antag att Du sitter i en skön fåtölj och läser en bok. Plötsligt blir Du avbruten av att telefonen ringer, Du markerar med en blyertspenna var i boken Du befann dig och svarar. Under samtalet ringer det på dörrklockan och Du ber den Du talar med i telefonen med att dröja kvar medan Du går till dörren.
William Sandqvist Interrupt När Du är färdig med ärendet vid dörren återupptar Du telefonsamtalet. När Du efter ett tag har talat färdigt i telefonen och avslutat telefonsamtalet kan Du återvända till fåtöljen och fortsätta med att läsa den goda boken - vid blyertsmärket.
William Sandqvist Polling Om inte interrupt funnes vore man tvungen att rusa runt mellan dörren – står någon där? – telefonen – någon där? och soffan. Det som kallas för polling.
William Sandqvist Interruptmekanismer Global och Local Enable Vill Du inte bli störd kan Du sätta på dig öronproppar – Du har då omöjliggjort interrupt, disable interrupt. Tar Du bort öronpropparna har Du åter möjliggjort interrupt, enable interrupt. Detta kallas för Global Enable. Du har även möjlighet på lokal nivå enabla/disabla inter- rupt, Local Enable. Du kan tex. disabla telefonen genom att dra ur jacket. Då hör Du fortfarande dörrklockan.
William Sandqvist Avbrottssystemet i Nios II Det normala programflödet avbryts. Tre tänkbara orsaker (med samlingsnamnet exeptions): Interrupt, avbrottssignal från enhet utanför processorn Exeption, felavbrott vid exekvering av instruktion division med 0 (ej med labdatorn) oimplementerad instruktion (ej med labdatorn) Trap, instruktionen trap, mjukvaruavbrott
William Sandqvist Återhoppsadress vid avbrott Vid avbrott sparar hårdvaran återhoppsadress i R29, EA exeption return adress register.. Register R31 kan innehålla en returadress som det avbrutna programmet behöver. Måste därför sparas. Avbrottsrutinen kommer att innehålla egna subrutinanrop.
William Sandqvist
Trap-instruktion En trap instruktion leder alltid till avbrott. Alla avbrott hanteras av samma hanteringsrutin, som i vårt labsystem ligger på adressen 0x Eftersom alla avbrott hanteras av samma hanteringsrutin så måste den först av allt ta reda på vad det är som hänt, för att kunna göra rätt åtgärd.
William Sandqvist Interrupt, avbrotts-signal Ett interrupt, en avbrotts-signal, kan inträffa vid vilken instruktion som helst i programmet. Om hanteringsrutinen upptäcker att det gäller ett interrupt, så måste alla register sparas. Återhoppsadressen är en instruktion för stor, så även detta måste då justeras.
William Sandqvist Registeranvändning i avbrottsrutinen Interrupt orsakas av händelser utanför processorn, elektriska signaler Kan hända när som helst under programkörningen Omöjligt att veta vilka register som är lediga Bara R24 får användas (et, exeption temporary) Andra register måste skyddas, sparas på stacken Använd makron PUSHMOST och POPMOST sparar respektive återställer R1…R15 samt R31 skydda även andra register om Du använder dem
William Sandqvist Vid interrupt! Skyddar Du de register Du använder. Använder Du dessutom subrutin så måste DU skydda alla dessa register! Makron PUSHMOST POPMOST Skydda! Om Du använder. Registerhantering vid Interrupt!
William Sandqvist PUSHMOST POPMOST.macro PUSH reg subi sp,sp,4 stw \reg,0(sp).endm.macro POP reg ldw \reg,0(sp) addi sp,sp,4.endm.macro PUSHMOST PUSH r1 # at PUSH r2... PUSH r14 PUSH r15 PUSH r31 # ra.endm.macro POPMOST POP r31 # ra POP r15... POP r3 POP r2 POP r1 # at.endm Observera! Omvänd ordning!
William Sandqvist Exeption, felavbrott I vårt labsystem tar vi inte hand om några felavbrott. Eftersom Nios-II-processorn är en softprocessor där användaren har möjlighet att skapa upp till 256 egna (oprövade?) instruktioner, så är felavbrott i allmänhet en nödvändig del av avbrotts-hanteringen. Detta är anledningen till att vi nämner felavbrott.
William Sandqvist 16 st Control-register CTL0 status, med bit 0 PIE CTL1 estatus, med bit 0 EPIE ( EPIE är sparad kopia av PIE ) CTL3 ienable, 32 interrupt enable bits CTL4 ipending, 32 pending interrupt bits Bara fyra av de 16 kontrollregistren är av intresse för oss. Kontrollregistren läses med instruktionen rdctl ReadControl, och skrives med instruktionen wrctl WriteControl.
William Sandqvist 7.1 Avbrottshanteringen Sammanfattning. Hårdvaran gör följande: Programräknarens värde kopieras till R29 (ea, exeption address register) så programmet kan hitta tillbaka. STATUS (CTL0) kopieras till ESTATUS (CTL1) så att programmet kan undersöka värdet STATUS ändras så att PIE = 0, vidare avbrott avstängda Programräknaren sätts till 0x800020, och programkörningen fortsätter därifrån.
Interrupt-logiken Device Enable, Local Enable, och Global Enable Kopia av PIE från innan avbrottet! Interrupt eller TRAP ? 0-ställs vid avbrott! William Sandqvist
7.2 En ”stub” Vid avbrott styrs exekveringen till adressen 0x800020, men där finns inte plats för någon omfattande hanteringsrutin. Vi måste vidarebefordra anropet från denna adress till en annan adress i vår text-area.
William Sandqvist ”Eftersändning” av avbrottet Vi måste placera följande ”eftersändningskod” på adress 0x movia et,exc_handler # adress till hanteringsfunktionen jmp et Observera att ET, exception temporary, R21, är det enda register som får ändras vid avbrott. Först placerar vi denna kod före main (så att den aldrig körs): stub: movia et,exc_handler jmp et Därefter får main vid starten kopiera koden från ”stub” word för word till rätt plats (0x800020).
William Sandqvist
stub: movia et,exc_handler # denna kod körs ej, det är jmp et # instruktionerna vi behöver! main: movia r8,stub # adressen till stub-koden movia r9,0x # eftersändningsadressen ldw r10,0(r8) stw r10,0(r9) ldw r10,4(r8) stw r10,4(r9) ldw r10,8(r8) stw r10,8(r9) # klart, stubben är tre instruktioner mainloop:... # här är vårt omfattande main-program br mainloop exc_handler:... # här är den omfattande hanteringsfunktionen eret
William Sandqvist stub: movia et,exc_handler # körs ej, det är bara koden jmp et # vi är ute efter! main: movia r8,stub # adressen till stub-koden movia r9,0x # eftersändningsadressen ldw r10,0(r8) stw r10,0(r9) ldw r10,4(r8) stw r10,4(r9) ldw r10,8(r8) stw r10,8(r9) # klart, stubben är tre instruktioner mainloop:... # här är vårt omfattande main-program br mainloop exc_handler:... # här är den omfattande hanteringsfunktionen eret Tror Du att det skulle gå att använda br i stället för jmp ? stub: br exc_handler main: movia r8, stub movia r9,0x ldw r10,0(r8) stw r10,0(r9) Nej! br är självrelativ, hoppet sker relativt där instruktionen står, och det fungerar ju inte om instruktionen flyttas någon annanstans!
William Sandqvist 7.3 Avbrottsrutinen Avbrottsrutinen kontrollerar orsaken Interrupt, trap (eller felavbrott) Om det var Interrupt, dvs. avbrotts-signal: subtrahera 4 från det sparade programräknarvärdet behandla avbrottet (tex. hämta indata) kvittera avbrottet (nollställ enhetens avbrotts-signal) returnera från avbrottet med instruktionen ERET
William Sandqvist Överblick över avbrottsrutinen Tvåstegs -test! 1) 2) 1) 2)
William Sandqvist Vad hände? Var det interrupt? Dubbeltestet: Är interrupt enablat? Läs ctl1, estatus, (kopia av statusregistret) och biten EPIE (kopia av PIE ). Är EPIE =0 så är interrupt inte enablat! – måste varit en Trap (eller annat). Finns väntande interrupts? Läs ctl4 ipending. Är ipending = 0 har inga interrupt skett! – måste varit en Trap (eller annat). Om vi passerar båda testen så rör det sig om ett interrupt! 1) 2)
William Sandqvist Assemblerkod, interrupt?.text.align 2 exchand: rdctl et,estatus # ctl1 med bit EPIE andi et,et,0b01 # maska EPIE-biten beq et,r0,not_int # interrupt ej enablat rdctl et,ipending # ctl4 med ev väntande interrupt beq et,r0,not_int # inga väntande interrupt br exc_was_interrupt # det var ett interrupt! not_int:... # inget interrupt, testa mer... 1) 2)
William Sandqvist assemblerkod, Trap? not_int: PUSH r8 movia r8,0x003b683a # detta är maskinkoden för TRAP! ldw et,-4(ea) # läs instruktionen före returadressen cmpeq et,et,r8 # jämför, 1 i et om TRAP-instruktion! POP r8 bne et,r0, exc_was_trap # det var en trap-instruktion spurious: # vi vet inte vad som hände, störning?... eret exc_was_trap:... # trap-action eret Varför stämmer inte siffrorna!
William Sandqvist ( assemblerkod, Trap ) = = B A Varför stämmer inte siffrorna! movia r8,0x003b683a # detta är maskinkoden för TRAP!
William Sandqvist Vilket interrupt var det? exc_was_interrupt: subi ea,ea,4 # justera returadress först som sist! rdctl et,ipending andi et,et,0b0100 bne et,r0,keys4 rdctl et,ipending andi et,et,0b01000 bne et,r0,toggles18... rdctl et,ipending andi et,et,0b bne et,r0,timer1 br spurious # inget känt avbrott ? Delrutinerna för alla de möjliga avbrotten avslutas med eret. Prioriteten avgörs av ordningen på ”testen”.
William Sandqvist Interrupt-logiken Device Enable, Local Enable, och Global Enable
William Sandqvist Device Enable KEYS Device Enable. Varje IO-enhet har möjlighet att generera interrupt. För KEYS4 kan man enabla varje tryck-knapp eller varje strömställare var för sig. Detta gör man genom att skriva ”1” i motsvarande bitpositioner i interrupt mask registren. Device Capture. Undersöka orsaken till interruptet på device-nivå. Varje förändring (trycka/släppa, byta läge) genererar interrupt. Den/de bitpositioner som har förändrats, har ”1” i edge capture registren. Data registren ”1” / ”0” visar om en knapp är uppe/nere. Device Acknowledge. Kvittera interruptet. Genom att skriva vad som helst till edge capture registret 0-ställs bitarna.
William Sandqvist Device Enable TOGGLES Device Enable. Varje IO-enhet har möjlighet att generera interrupt. För TOGGLES18 kan man enabla varje tryck-knapp eller varje strömställare var för sig. Detta gör man genom att skriva ”1” i motsvarande bitpositioner i interrupt mask registren. Device Capture. Undersöka orsaken till interruptet på device-nivå. Varje förändring (trycka/släppa, byta läge) genererar interrupt. Den/de bitpositioner som har förändrats, har ”1” i edge capture registren. Data registren ”1” / ”0” visar om en knapp är uppe/nere. Device Acknowledge. Kvittera interruptet, genom att skriva vad som helst till edge capture registret 0-ställs bitarna.
William Sandqvist Device Enable TIMER Device Enable. Varje IO-enhet har möjlighet att generera interrupt. För TIMER1 kan man enabla interrupt vid Timeout. Detta gör man genom att skriva ”1” till ITO biten. Device Capture. Undersöka orsaken till interruptet på device-nivå. TO Timeoutbiten sätts vid timeout. Device Acknowledge. Kvittera interruptet. Genom att skriva vad som helst till status registret 0-ställs TO biten (flaggan).
William Sandqvist Device Enable UART Device Enable. Varje IO-enhet har möjlighet att generera interrupt. För UART kan man enabla interrupt för mottaget tecken, RxRdy eller för tomt i sändar-registret, TxRdy. Detta gör man genom att skriva ”1” till motsvarande bit i control registret. Device Capture. Undersöka orsaken till interruptet på device-nivå. Bitarna RxRdy eller TxRdy, i status registret markerar orsaken. Device Acknowledge. Genom att läsa RxData eller skriva till TxData 0-ställs respektive bitar (flaggor) i status registret. Man behöver inte göra någon ytterligare åtgärd för att kvittera interruptet.
William Sandqvist Local Enable Local Enable. Skriv ”1” i de positioner som skall enablas. Använd instruktionen ori eftersom man inte vill påverka andra bitpositioner oavsiktligt. rdctl et,ctl3 ori et,et,0b wrctl ctl3,et
William Sandqvist IPENDING registret Bitarna i IPENDING registret talar om från vilket device avbrottet kommer. rdctl et,ctl4 andi et,et,0b bne et,r0,TimerInt # det var timern!
William Sandqvist Global Enable Tillåt Globalt Enable först när alla enheter är initialiserade och allt övrigt Enablat. wrctl status,r0 # Disable interrupt PIE=0 movi et,0b01 wrctl status,et # Enable interrupt PIE=1
William Sandqvist 7.4 Interrupt från Timer IO är mappade till minnesadresser. 0x920 … 0x934 timer_1 IRQ index 10 En klocka i bakgrunden … 12:54 Vi ska programmera en klocka som körs i ”bakgrunden” ( Windows har en i högra hörnet av skärmen … )
William Sandqvist 7.4 main, initiering stub: movia et,exchandler jmp et main: movia r8,stub movia r9,0x ldw r10,0(r8) stw r10,0(r9) ldw r10,4(r8) stw r10,4(r9) ldw r10,8(r8) stw r10,8(r9) # instruktionerna movia och jmp # kopieras till avbrottsadressen! Instruktioner som eftersänder avbrottet Koden kopieras och flyttas under runtime
William Sandqvist (5.6) inittimer().equ timer, 0x920.text.align 2.global inittimer # synlig i andra filer inittimer: movia r8,timer # basadressen till timern movia r9, # R9 = srli r10,r9,16 # 16 höga bitar kvar stw r10,12(r8) # periodh 16 höga bitar andi r9,r9,0xFFFF # behåll 16 låga bitar stw r9,8(r8) # periodl 16 låga bitar movi r9,0b0111 # R9 = 0b0111 (start=1 cont=1 ito=1) stw r9,4(r8) # skriv till control ret Denna gång skall vi ha interrupt vid timeout! Device Enable Vi har initierat en timer tidigare i kursen se (5.6) Klocka: Interrupt var sekund
William Sandqvist 7.4 Lokalt Enable i main rdctl et,ienable # ctl3 ori et,et,0b wrctl ienable,et Ettställ bit 10 i IENABLE (CTL3), men bara denna bit! Här använder vi et i main – är ledigt innan interuptet blivit globalt enablat.
William Sandqvist 7.4 Globalt Enable i main movi et,0b01 wrctl status,et # Enable interrupt PIE=1 Ettställ PIE bit 0 i STATUS (CTL0) Här använder vi et i main innan interuptet blivit globalt enablat. Därefter får et endast användas i avbrottsrutinen!
William Sandqvist 7.4 Huvudloop i main Huvudloop – fortsättningen på main # initiation done... mainloop: br mainloop....end 12:54 Självgående klocka i bakgrunden Avbrott varje sekund! Ett exempelprogram finns i lösningarna. Du ska skriva ett ”liknande” program till interrupt-laborationen.
William Sandqvist 7.4 Avbrottsrutinen exchandler: rdctl et,estatus # för att undersöka EPIE andi et,et,1 beq et,r0,noint # interrupt är disablat rdctl et,ipending beq et,r0,noint # inga väntande interrupt inthandler: subi ea,ea,4 # glöm inte justera returadress rdctl et,ipending # vilket interrupt väntar? andi et,et,0b bne et,r0,TimerInt # det var timern! noint: # trap-instruktionen ej med i detta exempel error: eret # spurious interrupt?
William Sandqvist 7.4 TimerInt TimerInt: PUSHMOST # spara de flesta register movia r8,0x920 # basadress till timer1 # kvittera interruptet genom att ”skriva” # något till device status register stw r0,0(r8) # device acknowledge movia r4,mytime call tick movia r4,mytime call puttime POPMOST # återställ register eret Eftersom vi använder subrutiner måste vi skydda de flesta registren med PUSHMOST/POPMOST 12:54
William Sandqvist 7.8 Avbrott i avbrott?
William Sandqvist 7.8 Avbrott i avbrott Spara 1-ställ sist!
William Sandqvist 7.8 Avbrott i avbrott
William Sandqvist 7.8 Avbrott i avbrott Om rutinen får avbryta sig själv: Spara ESTAUS och EA Kvittera det egna avbrottet (device acknowledge) Sist: ettställ PIE, Globalt Enable … Här kan rutinen bli avbruten … Nollställ PIE, Globalt Disable Återställ ESTATUS och EA ERET Om rutinen får avbrytas av andra (ej sig själv): Spara ESTAUS och EA Kvittera det egna avbrottet (device acknowledge) Förbjud det egna avbrottet i IENABLE, Lokalt Disable Sist: ettställ PIE, Globalt Enable … Här kan rutinen bli avbruten … Nollställ PIE, Globalt Disable Återställ ESTATUS och EA ERET Omfattande beräkning – vi kan behöva ”släppa fram” andra interrupt.
William Sandqvist 7.11 Vektoriserat avbrott
William Sandqvist 7.11 Vad gör Alteras ”Wrapper” Altera gör således i stort sätt som vi ….
William Sandqvist 7.11 Hanteringsrutin i C Device Acknowledge
William Sandqvist 7.11 Funktionsprototyp för Hanteringsrutin
William Sandqvist 7.11 Initialisering
William Sandqvist Serieport 4
William Sandqvist 7.14 initfix_int()
William Sandqvist Avbrott i avbrott
William Sandqvist Anrop (avbrott i avbrott)
William Sandqvist ienable (ctl3) 0 Gamla ienable är funktionens returvärde så att det kan sparas och senare återinsättas
William Sandqvist