6/2/20151 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items during your presentation In Slide Show, click on the right mouse button Select “Meeting Minder” Select the “Action Items” tab Type in action items as they come up Click OK to dismiss this box This will automatically create an Action Item slide at the end of your presentation with your points entered. ENCM Interrupts “Review” and “C”-interrupts M. R. Smith, Electrical and Computer Engineering University of Calgary, Alberta, Canada ucalgary,ca
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 2 / 24 To be tackled today Subroutines and Interrupts Example “C” code (68K) subroutine assembly code interrupt service routine assembly Example “C” code (21K) The “C” wrapper interrupts using IRQ1 button interrupts using 21K timer
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 3 / 24 Subroutines and Interrupts Very similar in concept Very different in implementation Subroutines occur as part of your normal program flow. You tackle a certain task, written as a subroutine, at a certain location in your code. Time of starting plays no part in the design of a subroutine.
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 4 / 24 WAITING for an event to happen Sometimes your code must wait for an external event to occur before the code can proceed float array_in[200], array_out[200]; main( ) { For Ever { Wait till array_in() is filled; Process(array_in,array_out); DoRestOfCode(); } Stupid way to code -- unless this is the only thing the processor will do
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 5 / 24 POLLING to check for events int event1, event2, event3; float array_in[200], array_out[200]; main( ) { For Ever { if (event1 is TRUE) Process(array_in,array_out); if (event2 is TRUE) Proce???? if (event3 is TRUE) Proce???? DoRestofCodef(); } Problem -- what if many events? Problem -- what if DoRestofCode() takes a long time? Problem -- what if event2 must be handled THE MOMENT it occurs?
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 6 / 24 Solution -- Interrupts void InterruptServiceRoutine(void); char isr_count;// Semaphore float array_in[200], array_out[200]; void main() { SetUpInterrupts(pointer to InteruptServiceRoutine() ); ActivateInterrupts(Based on event1); isr_count = 0; while ( isr_count < 8 ) { // Totally un-exitable normally DoRestofCode(); }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 7 / 24 Sub-task as ISR (68K “C”) void InterruptServiceRoutine(void); extern char isr_count;// Semaphore #pragma interrupt() -- Signals to 68K compiler that InterruptServiceRoutine is not a subroutine void InterruptServiceRoutine(void);{ Acknowledge Interrupt(); This is a normal subroutine call isr_count++; Process(array_in, array_out); This is a normal subroutine call } HOWEVER -- InterruptServiceRoutine IS NOT a normal subroutine call!!!
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 8 / 24 Subroutines are not interrupts! Subroutines occur when the programmer wants them to occur Specific location in program code where called Specific location in code program where will return to Can prepare for when they will occur so can pass parameters to them Rules are -- save non-volatile registers to stack IF you are going to use them, otherwise use scratch (volatile) registers.
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 9 / 24 Interrupts are not subroutines Interrupts occur when the interrupt wants to occur NO Specific location in program code where called NO Specific location in program code where will return to Can’t prepare for when interrupts will occur so can’t pass normal parameters to them -- need to use semaphores and messages instead Interrupts may not want to stop Interrupts may want to use volatile registers but subroutines are already using them!
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 10 / 24 Interrupt response must be fast 68K interrupt -- not too fast to get into Finish current instruction (8 cycles) Save next instruction address (12 cycles) Save status register (4 cycles at least) Look in “Vector Table” to find the starting address of the ISR routine (8 cycles to fetch) Fetch the first instruction in ISR Save registers Just as slow to get out of the interrupt service routine! Reverse of above
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 11 / 24 Interrupts on 21K -- designed to be fast Finish current instruction (1 cycle) (but what about pipeline issues?) Save next instruction address (hardware) Save status register???? Starting address of the ISR routine at fixed location (0 cycles) Alternate set of registers available (sometimes) Some interrupts simply steal cycles on the bus (DMA) and don’t cause “interrupts” as we know them! Other issues -- Remember 3 PC’s in sequencer?
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 12 / 24 Rough Code for 68K style main( ) #define SIZE 200 float buffer1[SIZE], buffer2[SIZE], buffer3[SIZE]; int event1 =1, event2 = 1, event3 = 1; main( ) { SetUpInterrupts(pointer to ISR() ); ActivateInterrupts(Based on Timer); forever { while (event1 = = 1) /* Do nothing */ ; Process(buffer1); /* ISR is filling buffer2 at this time */ while (event2 = = 1) /* Do nothing */; Process(buffer2); etc; }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 13 / 24 The ISR routine (68K style “C”) int count = 0; float *whichbuff = buffer1; int *whichevent = &event1; #pragma interrupt() void ISR(void) { *whichbuff = ReadD2A(); whichbuff++; count++; if (count = = SIZE) { count = 0; whichbuff = buffer2; *whichevent = 0; etc; }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 14 / 24 SECTIONcode XDEF_ISR _ISR MOVEM.LD0/D1/A0/A1,-(A7) _81BSR_ReadD2A;*whichbuff = ReadD2A(); MOVE.L_whichbuff,-(A7) BSR__sltos _82ADDQ.L#4,_whichbuff;whichbuff++; _83ADDQ.L#1,_count;count++; _84CMP.L#0xC8,_count;if (count == SIZE) { BNE_10 _85CLR.L_count;count = 0; _86MOVE.L#_buffer2,_whichbuf;whichbuff = buffer2; _87MOVE.L_whichevent,A0;*whichevent = 0; CLR.L(A0) _10MOVEM.L(A7)+,D0/D1/A0/A1 RTE 68K ISR code (defined with #pragma)
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 15 / 24 The ISR built as subroutine Unintentional Error int count = 0; float *whichbuff = buffer1; int *whichevent = &event1; // #pragma interrupt() --- Now becomes a subroutine void ISR(void) { *whichbuff = ReadD2A(); whichbuff++; count++; if (count = = SIZE) { count = 0; whichbuff = buffer2; *whichevent = 0; etc; }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 16 / 24 SECTIONcode XDEF_ISR _ISRNo volatile register saves made since compiler thinks is subroutine _81BSR_ReadD2A;*whichbuff = ReadD2A(); MOVE.L_whichbuff,-(A7) BSR__sltos _82ADDQ.L#4,_whichbuff;whichbuff++; _83ADDQ.L#1,_count;count++; _84CMP.L#0xC8,_count;if (count == SIZE) { BNE_10 _85CLR.L_count;count = 0; _86MOVE.L#_buffer2,_whichbuf;whichbuff = buffer2; _87MOVE.L_whichevent,A0;*whichevent = 0; CLR.L(A0) No volatile register recovery made since compiler thinks is subroutine RTS --- HOWEVER -- WRONG THINGS ON THE STACK 68K ISR code AS A SUBROUTINE (no #pragma was used) -- BIG PROBLEMS
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 17 / 24 “C” interrupts running on 21K We KNOW that exactly the same thing must be happening on 21K as 68K Need to set up interrupt vector equivalent Need to enable interrupts Need to do RTE equivalent HOWEVER, EVERYTHING IS HIDDEN BY A “C” WRAPPER Details on 21K interrupts are only needed if we want to go for “REAL SPEED”
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 18 / 24 The ISR subroutine (21K style) Only works because of hidden “C” wrapper int count = 0; float *whichbuff = buffer1; int *whichevent = &event1; void ISR(void) { *whichbuff = ReadD2A(); whichbuff++; count++; if (count = = SIZE) { count = 0; whichbuff = buffer2; *whichevent = 0; etc; }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 19 / 24 Remember “SOMEWHERE” In the 21K “C” model, there is some TRUE ISR code that is executed when the interrupt occurs. In that ISR Registers are saved Then your “ISR” is called as a SUBROUTINE Registers are recovered Interrupt is cleared Equivalent to RTE occurs AND YOU KNOW NOTHING ABOUT IT (and you don’t normally care -- unless speed is important!) And I think there is a bug in “earlier “C” wrapper -- funny code experiences and also phone messages from Alberta Users
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 20 / 24 Setting up an interrupt to occur on the 21K IRQ1 flag -- one of the buttons on the board main( ) { asm(“include ”); asm(“bit set mode2 IRQ1E;”); interrupt(SIG_IRQ1, irq1_handler); forever { while (event1 = = 1) /* Do nothing -- ISR is filling Buffer 1 */ ; Process(buffer1); /* ISR is filling buffer2 at this time */ while (event2 = = 1) /* Do nothing */; Process(buffer2); etc; } void irq1_handler(int sig_num) { /* This is still a subroutine */ ISR( ); }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 21 / 24 Setting up an interrupt to occur on the 21K internal Timer main( ) { int data; interruptf(SIG_TMZ, timer_int);/* There’s intterupt, interruptf and interrupts */ data = 20000;/* Every ticks */ timer_set(data, data);/* That’s the first and reload values */ timer_on(); forever { while (event1 = = 1) /* Do nothing */ ; Process(buffer1); /* ISR is filling buffer2 at this time */ while (event2 = = 1) /* Do nothing */; Process(buffer2); etc; } void timer_int(int sig_num) { /* This is still a subroutine */ ISR( ); /* Being used to fill a buffer -- perhaps 1 point at a time) }
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 22 / 24 Setting up the SPORTs interrupt is nasty Have to set up the CODEC to the right values, sample rate etc Set up the CODEC to cause interrupts on the SPORT lines Then interruptf(SIG_SPTOI, spt0_asserted); /* transmit */ interruptf(SIG_SPROI, spr0_asserted); /* receive */ And everything works like magic -- Not going to worry about the details in this lab.
6/2/2015 ENCM Interrupts Review -- Part 1 Copyright 23 / 24 Tackled today Subroutines and Interrupts Example “C” code (68K) subroutine assembly code interrupt service routine assembly Example “C” code (21K) The “C” wrapper interrupts using IRQ1 button interrupts using 21K timer