330 likes | 474 Views
Lecture 11 MPC 555 Interrupt Programming Details. Programming Perspective on Interrupt States. SIPEND : State of USIU interrupt levels and IRQ pins SIMASK : USIU interrupt mask SIVEC : Interrupt vector code UIPEND : State of IMB3 interrupt levels MSR : Machine state
E N D
Programming Perspective on Interrupt States • SIPEND: State of USIU interrupt levels and IRQ pins • SIMASK: USIU interrupt mask • SIVEC: Interrupt vector code • UIPEND: State of IMB3 interrupt levels • MSR: Machine state • MSR[EE]: Enable/disable external interrupts • MSR[RI]: Whether machine status is recoverable • SSR0 PC of interrupted routine • SSR1 MSR bits before interrupt (SRR0, SRR1: Machine status Save/Restore Registers)
Interrupt Initialization • Module Specific Initialization • PIT example: Set up PITC • Level Assignment (for IMB3 or USIU interrupt sources) • PIT example: Assign level value to PIRQ of PISCR (bits 0:7) • Interrupt level = 4 PIRQ = b’00001000 = 0x08 • Using unique interrupt level reduces processing time • Enable Interrupt at device-level • PIT example: Set PIE of PISCR (Bit 13) • Set Appropriate Mask Bits in SIMASK • PIT example: Interrupt Level = 4 Priority level = 9 • Setting bit 9 of SIMASK • Enable external interrupt • Setting MSR[EE] (and MSR[RI]) Bits
Recognizing Interrupt Request An interrupt request is served when • External Interrupt is enabled • MSR[EE] is set • If MSR[RI] is not set, interrupt may not return correctly • The interrupt is not masked • The mask bit in SIMASK is set • The interrupt has the highest priority among all requested, unmasked interrupts • Lowest level in SIPEND has the highest priority
Interrupt exception occurs Completes current inst Saves NPC and MSR to SRR0 and SRR1 Branches to exception vector address for interrupt Saves machine context SRR0:1 Set MSR[RI] and/or MSR[EE] Saves other context (registers) Determines interrupt source, usually by getting SIVEC code Branches to ISR; may negate the interrupt request Restores contexts Returns by executing “rfi” Interrupt Event Sequence System behavior Typical Software Steps • Restores return address, MSR, enable interrupts • Resumes execution at original NPC in SRR
Set Up Exception Vector Table ; using exception table base 0xfff00000 ; reset exception handler .section .abs.FFF00100 b reset_exception ; external interrupt exception handler .section .abs.FFF00500 b external_interrupt_exception ; decrementer handler .section .abs.FFF0900 b decrementer_exception Tell assembler to put the following code at this absolute address Jump to the handler code for external interrupt exception;code can also be put here if it is small enough
Initializing MPC555 Interrupts ; minimal initialization for using PIT .equ A_SIUBASE 0x2F .equ SYPCR 0xC004 init555: … ; prologue code not shown lis r3, A_SIUBASE lis r4, 0xffff ori r4, 0xff03 sth r4, SYPCR(r3) … ; epilogue code not shown Load base address for USIU registers • SYPCR: system protection control reg • reset bit 28-29 to disable software watchdog
External Interrupt Exception – Prologue ; STEP 1: SAVE "MACHINE CONTEXT" stwu sp, -36 (sp) stw r3, 24 (sp) mfsrr0 r3 stw r3, 12 (sp) mfsrr1 r3 stw r3, 16 (sp) ; STEP 2: make execution recoverable and enable ; external interrupt mtspr EIE, r3 • Create stack frame, saving r3, SRR0, SRR1 • Must use r3 or some other GPR because SRR0:1 cannot be saved directly • MSR[EE] and MSR[RI] are cleared, i.e., Interrupt disabled and execution notrecoverable • Set MSR[EE] and MSR[RI] bits; others: • EIE: set MSR[EE] and MSR[RI] • EID: set MSR[RI] only
External Interrupt Exception – Prologue (Continue) ; STEP 3: SAVE OTHER APPROPRIATE CONTEXT mflr r3 stw r3, 8 (sp) mfcr r3 stw r3, 20 (sp) stw r4, 28 (sp) stw r5, 32 (sp) stw r6, 36 (sp) • Save LR and CR • LR will be changed when calling ISR • ISR will have branches that change CR • r3 is used because CR and LR cannot be saved into memory directly • Save other registers • assume that any ISR uses only r3-r6 • must save more if ISR is written in C
External Interrupt Exception – Prologue (Continue) ; STEP 4: DETERMINE INTERRUPT SOURCE lis r3, SIVEC@ha lbz r3, SIVEC@l (r3) lis r4, IRQ_table@h ori r4, r4, IRQ_table@l add r4, r3, r4 lwz r4, 0(r4) mtlr r4 ; STEP 5: BRANCH TO INTERRUPT HANDLER blrl • Load 8-bit SIVEC into r3 • SIVEC here is a 32-bit constant 0x2FC01C • Set up jump inst address in a jump table • use lis and ori to load IRQ table base • add offset to get the ISR address • move jump inst address to LR • blrl: branch to address in LR and save PC+4 in LR • basically this is a function call using function pointer • at target address: b kth_isr_addr
External Interrupt Exception – Epilogue ; STEP 6: RESTORE CONTEXT lwz r4, 28 (sp) lwz r5, 32 (sp) lwz r6, 36 (sp) lwz r3, 28 (sp) mtcrf 0xff, r3 lwz r3, 20 (sp) mtlr r3 Restore r4, r5, r6, which were savedin prologue • Restore CR and LR • again use r3 as a bridge • CR and LR (and any other SPR) cannot be loaded directly with data from memory
External Interrupt Exception – Epilogue (Continue) • Clear MSR[RI] and MSR[EE] • cannot beinterrupted from now on; • NRI: SPR for fast clearing MSR[EE] and MSR[RI] ; STEP 6: RESTORE CONTEXT mtspr NRI, r3 lwz r3, 12 (sp) mtsrr0 r3 lwz r3, 16 (sp) mtsrr1 r3 lwz r3, 24 (sp) addi sp, sp, 36 ; STEP 7: RETURN TO PROGRAM rfi ; End of Interrupt • Restore SRR0, SRR1 and r3 • again use r3 as a bridge in restoring SRR0 and SRR1 • r3 is the first to be saved and the last one to be restored • rfi (return from interrupt): • restores MSR bits saved in SRR1 • restores next-PC saved in SRR0
Set Up ISR Addresses Use Jump table: IRQ_jump_table: b irq0_handler ; interrupt pin 0 b level0_handler ; interrupt level 0 b irq1_handler ; interrupt pin 1 b level1_handler ; interrupt level … b irq7_handler ; interrupt pin 7 b level7_handler ; interrupt level 7 … irq0_hanlder: ; IRQ0 ISR put here …
Set Up ISR Addresses Use address table IRQ_table: .long irq0_handler ; interrupt pin 0 .long level0_handler ; interrupt level 0 .long irq1_handler ; interrupt pin 1 .long level1_handler ; interrupt level 1 … ; .long irq7_handler ; interrupt pin 7 .long level7_handler ; interrupt level 7 … irq0_hanlder: ; IRQ0 ISR put here …
Need to know Device programming model Addresses for memory mapped control/status registers and data registers PIT example: PICSR: PIT control and select register What are PS, PREQ, PIE, PTE and PITF? PITC: #cycles in PIT counting period PITR: leftover count in PIT counter in current countingperiod lis r4, SIU_BASE_UPPER ; use level 4, enable ; PIT, clear PITF li r0,0x0804 sth r0,PICSR_OFFSET(r4) ; set PiTC li r5,0x80e8 sth r5,PITC_OFFSET(r4) ; enable PIT counting ori r0, 0x1 sth r0,PICSR_OFFSET(r4) Initializing Device
General Initialization steps Module specific initialization: • For timers – clock divisor, period etc. • For serial I/O – baud rate. • For TPU – functions. Interrupt Level assignment: assign levels to each active interrupt source. • Lower levels have higher priority. • external pins (IRQ[0:7]) have fixed priority levels. • Lower response time (latency) when there is at most one interrupt source per level. Enable Interrupts: every device has some kind of interrupt enable • Example: PIE for PIT
General Initialization steps Set Mask bits in SIMASK: Allow for the mapped (active) interrupt levels to interrupt by making SIMASK for that level equal to 1. Final step: enable external interrupts: After the initialization for all the sources succeeds • enable external interrupts by MSR[EE] 1, also • indicate that the current state is recoverable by MSR[RI] 1. • Shortcut: EIE any thing, “mtspr EIE, r0”
Initialization Examples main() { init555(); initPIT(); asm(mtspr EIE, r3); while(1) { loopctr++ }; } System initialization Module initialization Codewarrior inline assembly
Writing ISR in C C vs. Assembly: • More productive, especially for complicated interrupt processing • Less efficient (slightly) Exception service routine for ISR in C: • If in assembly: save whatever GPRs you use. • When calling a C procedure in EABI: save all volatile registers • GPRs: R0, R3-R12 • FPRs: F0-F13 (if any ISR uses floating point) • SPRs: CR, LR, XER, FPSCR and CTR Have no control on what compiler could have used.
Writing ISR in C #include “defines.h" char * p_g7Seg = (char *) IO_DIGITAL_OUTPUT_7SEG; char gVal = 0; int gSlowVal = 0; void level4_handler (void) { short *pPISCR = (short *) 0x002FC240; long *pPITC = (long *) 0x002FC244; long *pPITR = (long *) 0x002FC248; Set up C pointers to PIT registers
Writing ISR in C Increment slow counter: track the number of interrupts gSlowVal++; *p_g7Seg = ++gVal; nPISCR = *pPISCR; nPISCR = nPISCR | 0x0080; *pPISCR = nPISCR; } Increment the number on LCD display: 00=>01=>...=>FF=>00=>… • Reset PISCR[PS] • Otherwise, the interrupt keeps being raised • Reset PISCR[PS] is done in a special way: • Writing bit 1 to PISCR[PS] negates its value • PISCR[PS] = 1 when the interrupt is raised, thus negating it will make it cleared • “nPISCR = nPISCR | 0x0080;” is redundant and can be removed
Using C Bit Field Union: describe a memory variable in different formats union { VUINT16 R; struct { VUINT16 PIRQ:8; VUINT16 PS:1; VUINT16:4; VUINT16 PIE:1; VUINT16 PITF:1; VUINT16 PTE:1; } B; } PISCR; Bit field: define variable of a certain bit length Unnamed bit field: provides padding PISCR format PIRQ PS PIE PTE 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 padding PITF
PITC definition union { VUINT32 R; struct { VUINT32 PITC:16; VUINT32:16; } B; } PITC; PITR definition union { VUINT32 R; struct { VUINT32 PIT:16; VUINT32:16; } B; } PITR; Using C Bit Field • How to use bit fields? Examples: • USIU.PITC.B.PITC = 33000; • if (USIU.PISCR.B.PS) … VUINT32: Volatile unsigned 32-bit integer; see slide 29 for volatile variables.
USIU Interface In C struct USIU_tag { … // other fields union { // offset 0x0240 … // previous definition for PISCR } PISCR; VINT16 res6a; union { // offset 0x0244 … // previous definition for PITC } PITC; union { // offset 0x248 … // previous definition for PITR } PITR; … // other definitions, e.g. SIPEND, SIMASK }; #define USIU (*(struct USIU_tag *) 0x2FC000) Defined in “mpc555.h” and “m_usiu.h”; see “Motorola Interrupts”.
USIU Interface In C The following statements are equivalent: • *pPISCR = 0x0804; • USIU.PISCR.B.PIRQ = 0x08; // use level 4USIU.PISCR.B.PS = 0;USIU.PISCR.B.PIE = 1; // enable interruptUSIU.PISCR.B.PITF = 0; // no freezingUSIU.PISCR.B.PTE = 0; // disable counting • USIU.PISCR.R = 0x0804;
USIU Interface In C The following statements are equivalent: • *pPISCR = (*pPISCR)| 0x1; • USIU.PISCR.B.PTE = 1; // enable counting • *pPISCR = ((*PISCR) & 0x00ff) | 0x4000; • USIU.PISCR.B.PIRQ = 0x40; // change PIRQ to 4
Initialization in C void init555() { //disable watchdog timer USIU.SYPCR.R = 0xffffff03; //run at 40MHz USIU.PLPRCR.B.MF = 0x009; //stabilize clock while (USIU.PLPRCR.B.SPLS == 0); //run IMB at full clock speed UIMB.UMCR.B.HSPEED = 0; }
Initialization in C Void initPIT() { USIU.PITC.B.PITC = 1000; // set count value USIU.PISCR.B.PITF = 1; // set freezing USIU.PISCR.B.PTE = 1; // enable interrupt USIU.PISCR.B.PIRQ = 0x80; // use Level 0 USIU.PISCR.B.PIE = 1; // enable interrupt USIU.SIMASK.R=0x40000000; // unmask priority 1 }
C Volatile Qualifier Use volatilequalifier to inform compiler to avoid optimization that assumes only the program may change the variable Use volatile qualifier for a variable if • I/O may change the variable because of memory mapping • ISR may change the variable because of sharing Examples: volatile int counter; volatile short *pPISCR = 0x2FC240;
Variable changed by I/O short *pPISCR = 0x2FC240; while (1) { if (*pPISCR & 0x0080) … } Optimized code: // read memory var into // register before loop lis r3, 0x2F lhz r4, 0xC240(r3) loop: andi. r4, 0x0080 beq false … b loop C Volatile Qualifier • Compiler tends to remove “redundant” executions of load/store instructions • assumes only the program may change a variable, if not told otherwise • won’t do the optimization if the variable is declared as volatile
C Volatile Qualifier Variable changed by ISR volatile int counter; int threshold = …; void my_handler(void) { counter++; } main() { while (counter < threshold) … } • Memory accesses to non-volatile variables, e.g. threshold, may be optimized • Memory accesses to volatile variables, e.g. counter, cannot be reduced Advanced issue: If both the ISR and the main process change shared variables, they may need to use synchronization.
Summary MPC555 Interrupt System • Hardware organization • Machine-level interface and programming • C interface and programming Interrupt Programming Overview • System initialization, exception service routine and exception vector table • Module initialization, ISR and ISR table • Selection of interrupt level, masking, and disable/enable interrupts
What’s Next Programming for more complicated modules • A/D converter (QADC64) • Time processor unit (TPU3) I/O programming modes are different, but interrupt processing and memory mapping methods are similar