Monday March 10, 2014 - Interrupts, Cont’d - Review for Midterm - Continue Lab4 1 Interrupts Von Neumann MSP430 Architecture Instructions and Data Processing Unit (CPU) Input / Output 3 MSP430 Architecture I/O 4 MSP430F5438A Architecture Let’s take a closer look… Mostly just adding more peripherals with each generation. CPU doesn’t change much. 5 Can I use a port to interrupt my program? Yes! How…? 6 Maybe the User Guide is a good place to start… I count three “and” qualifiers. Let’s take Them one at a time, in reverse order… …and by the way, what’s that? 7 What has to happen for an interrupt to occur. 1. An interrupt has to be requested by the peripheral (IRQ). 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. 8 Let’s tackle the hard part first: 1. An interrupt has to be requested by the peripheral. 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. An ISR is a subroutine pointed to by the Interrupt Vector. 9 Interrupt Vectors Each peripheral device is assigned an address. It is device dependent, hard-wired, not changeable. A vector is basically a pointer: It points to an address. 10 First, find it’s interrupt vector address. 0xFFD4 This memory location is very special (if you’re Port2): It is assigned to Port2 forever. How do I know this… 11 So which interrupt vector is mine? Look at the Interrupt Vector Address Table: Scrolling thru the table… 12 Practical Consideration: How does CCS know this? My_ISR: <code> RETI Linker cmd file: MEMORY INT42 : origin = 0xFFD4, length = 0x0002 SECTION Label must match <code> .sect “.int42” .short My_ISR PORT2 : { * ( .int42 ) } > INT42 type = VECT_INIT 13 Let’s go back to the peripheral slide 0x5c2c: My_ISR 0x5c2e: <code> 0x5c2c 0xFFD4 This memory location is very special (if you’re Port2): It is assigned to Port2 forever. 14 What has to happen for an interrupt to occur. 1. An interrupt has to be requested by the peripheral (IRQ). 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. 15 Step 1: Set the GIE General Interrupt Enable must be set for any maskable interrupt to be serviced. Three ways to do it: bis.w #0x04,SR OR… eint OR They alldo the same thing bis.w #GIE,SR 16 OK, GIE set, what next? Let’s look at the Peripheral IE (PIE) next… Check! 17 What has to happen for an interrupt to occur. 1. An interrupt has to be requested by the peripheral (IRQ). 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. 18 Now that I’ve set the GIE, it looks like I need to get peripheral-specific. TI calls them modules. OK, so which module am I…? 19 Looking further down the User Guide… Device Specific? That’s not very helpful! 20 Let’s look at the Digital I/O Section in the User’s Guide: Getting closer…! 21 22 Step 1: Set the GIE Step 2: Set the PxIE Peripheral Interrupt Enable must also be set for any maskable interrupt to be serviced. Example: Set P2.6 IE: Two ways to do it: bis.w #0x40,&P2IE OR… bis.w #BIT6,&P2IE They both do the same thing 23 OK, GIE and PIE set, what next? PIE Check! GIE Check! eint ;GIE set bis.w #BIT6,&P2IE ;P2.6 IE set 24 What has to happen for an interrupt to occur. 1. An interrupt has to be requested by the peripheral (IRQ). 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. 25 Interrupt Request 26 What has to happen for an interrupt to occur. 1. An interrupt has to be requested by the peripheral (IRQ). 2. The peripheral interrupt enable (PIE) bit must be set. 3. The General Interrupt Enable (GEI) bit must be set. 4. An Interrupt Service Routine (ISR) has to be run. First.asm 27 Interrupts Processing an Interrupt… 1. 2. 3. 4. 5. 6. 7. Processor completes execution of current instruction. Master Clock (MCLK) started (if CPU was off). Processor pushes Program Counter (PC) on stack. Processor pushes Status Register (SR) on stack. Interrupt w/highest priority is selected. Interrupt request flag cleared (if single sourced). Status Register is cleared: Disables further maskable interrupts (GIE cleared) Terminates low-power mode 8. Processor fetches interrupt vector and stores it in the program counter. 9. User ISR must do the rest! 28 Interrupts Interrupt Vectors 0xFFFF 0xFFC0 0xFFBF • The CPU must know where to fetch the next instruction following an interrupt. • The address of an ISR is defined in an interrupt vector. 16 vectors • The MSP430 uses vectored (ISR Addresses) interrupts where each ISR has its own vector stored in a vector table located at the end of program memory. • Note: The vector table is at a fixed location (defined by the processor data sheet), but the ISRs can be located anywhere in memory. Interrupt Vector Table Program Code 0xC000 0xBFFF 0x0400 0x03FF 0x0200 0x01FF 0x0000 Stack Input/Output 29 Interrupt Process Interrupt Flag Ie, save Activation Record to Stack 30 Interrupts Interrupt Flags • Each interrupt has a flag that is raised (set) when the interrupt is pending. Each interrupt flag has a corresponding enable bit – setting this bit allows a hardware module to request an interrupt. Most interrupts are maskable, which means they can only interrupt if 1) Individually enabled and 2) general interrupt enable (GIE) bit is set in the status register (SR). Reset and Non-Maskable Interrupts (NMI) are reserved for system interrupts such as power-up (PUC), external reset, oscillator fault, illegal flash access, watchdog, and illegal instruction fetch. Device Interrupt Interrupt Enable Interrupt MPU General Interrupt Enable (GIE) Reset / Non-Maskable (NMI) 31 Interrupts MSP430 Interrupt Vectors INTERRUPT SOURCE Power-up External reset Watchdog NMI Oscillator fault Flash memory violation Timer_B3 Timer_B3 INTERRUPT FLAG PORIFG RSTIFG WDTIFG NMIIFG OFIFG ACCDVIFG TBCCR0 CCIFG TBCCR1 CCIFG TBCCR2 CCIFG, TBIFG SYSTEM INTERRUPT Non-Maskable Interrupts Reset ADDRESS SECTION PRIORITY 0xFFFE .reset 15, highest Non-maskable 0xFFFC .int14 14 Maskable 0xFFFA .int13 13 0xFFF8 .int12 12 0xFFF6 .int11 11 Timers Maskable Watchdog Timer WDTIFG Maskable 0xFFF4 .int10 10 Timer_A3 Maskable 0xFFF2 .int09 9 Maskable 0xFFF0 .int08 8 USCI_A0/USCI_B0 Rx TACCR0 CCIFG TACCR1 CCIFG, TACCR2 CCIFG, TAIFG UCA0RXIFG, USB0RXIFG Maskable 0xFFEE .int07 7 USCI_Z0/USCI_B0 Tx UCA0TXIFG, UCB0TXIFG Maskable 0xFFEC .int06 6 ADC10 ADC10IFG Maskable Ports 0xFFEA .int05 5 0xFFE8 .int04 4 Timer_A3 I/O Port P2 P2IFG.0 – P2IFG.7 Maskable 0xFFE6 .int03 3 I/O Port P1 P1IFG.0 – P1IFG.7 Maskable 0xFFE4 .int02 2 0xFFE2 0xFFE0 .int01 .int00 1 0 32 Interrupts Interrupt Stack Item 1 Item 2 SP Prior to Interrupt PC add.w jnc add.w r4,r7 main #1,r6 add.w r5,r6 Interrupt (hardware) Item 1 Item 2 PC SR SP Program Counter pushed on stack Status Register pushed on stack Interrupt vector moved to PC Further interrupts disabled Interrupt flag cleared PC xor.b reti #1,&P1OUT Execute Interrupt Service Routine (ISR) Item 1 Item 2 PC SR SP Return from Interrupt (reti) PC Status Register popped from stack Program Counter popped from stack add.w jnc add.w r4,r7 main #1,r6 add.w r5,r6 33 Reset Vector Another way to figure out how to use interrupt vectors…just look at the one that’s already in use by default in CCS when you start an assembly-only project: ;------------------------------------------------------------------------------RESET mov.w #__STACK_END,SP ; Initialize stackpointer ;------------------------------------------------------------------------------; Main loop here ;------------------------------------------------------------------------------- ;------------------------------------------------------------------------------; Interrupt Vectors ;------------------------------------------------------------------------------.sect ".reset" ; MSP430 RESET Vector .short RESET 34 Interrupt Service Routine Return From Interrupt • Single operand instructions: Mnemonic Operation Description PUSH(.B or .W) src SP-2SP, src@SP Push byte/word source on stack CALL dsttmp ,SP-2SP, PC@SP, tmpPC Subroutine call to destination TOSSR, SP+2SP TOSPC, SP+2SP Return from interrupt dst RETI • Emulated instructions: Mnemonic Operation Emulation Description RET @SPPC SP+2SP MOV @SP+,PC Return from subroutine POP(.B or .W) dst @SPtemp SP+2SP tempdst MOV(.B or .W) @SP+,dst Pop byte/word from stack to destination 35 Interrupt Service Routine Interrupt Latency • The time between the interrupt request and the start of the ISR is called latency – MSP430 requires 6 clock cycles before the ISR begins executing – An ISR may be interrupted if interrupts are enabled in the ISR • Well-written ISRs: – Should be short and fast – get in and get out – Require a balance between doing very little – thereby leaving the background code with lots of processing – and doing a lot and leaving the background code with nothing to do • Applications that use interrupts should: – Disable interrupts as little as possible – Respond to interrupts as quickly as possible 36 Multi-Source Interrupt Handlers 8 Interrupt Flags 1 Vector Address 37 Multi-Source Interrupt Handlers IRQ[7:0] 8-bit bus shared by Port2 Interrupt Vector 38 Multi-Source Interrupt Handlers Solution: poll the interrupt flags to determine which port issued the interrupt. For example: port2_ISR: bit.b #BIT6,&P2IFG ; S1 Interrupt? jz end ; if not, exit 39