Interrupts

The dsPIC30/33 and PIC24 interrupt controller module reduces numerous peripheral interrupt request signals to a single interrupt request signal to the dsPIC30/33 and PIC24 CPU and has the following features:

ISRs are organized in IVT. ISR is defined as a standard function but with the iv directive afterwards which connects the function with specific interrupt vector. For example iv IVT_ADDR_T1INTERRUPT is IVT address of Timer1 interrupt source of the dsPIC 30F3014 MCU. For more information on IVT refer to the dsPIC30/33 and PIC24 Family Reference Manual.

Function Calls from Interrupt

Calling functions from within the interrupt routine is possible. The compiler takes care about the registers being used, both in "interrupt" and in "main" thread, and performs "smart" context-switching between two of them, saving only the registers that have been used in both threads. It is not recommended to use a function call from interrupt. In case of doing that take care of stack depth.

Disable Context Saving

Use the #pragma disablecontextsaving to instruct the compiler not to automatically perform context-switching.
This means that no register will be saved/restored by the compiler on entrance/exit from interrupt service routine, except STATUS, WREG and BSR registers in high priority interrupt ('Fast Register Stack').

This exception can be overrided by placing an asm RETFIE, 0 instruction at the end of the high priority interrupt routine (with redirecting all routine exits to this instruction).
Thus, #pragma disablecontextsaving pragma enables the user to manually write code for saving registers upon entrance and to restore them before exit from interrupt.

Interrupt Handling

Interrupt service routine is defined in this way :

void interrupt() iv IVT_ADDR_U1RXINTERRUPT ics ICS_AUTO {
  // Interrupt service routine code
}

where :

User can explicitly declare starting interrupt routine address using org directive :

void interrupt() org 0x600 iv IVT_ADDR_U1RXINTERRUPT ics ICS_AUTO {
  // Interrupt service routine code
}  

For the sake of backward compatibility, user may write also :

void interrupt() org IVT_ADDR_U1RXINTERRUPT {
  // Interrupt service routine code
}

which is equivalent to :

void interrupt() iv IVT_ADDR_U1RXINTERRUPT {
  // Interrupt service routine code
}

Is is recommended that interrupts are handled in this way for the sake of better readability of the user projects.

Interrupt Example

Here is a simple example of handling the interrupts from Timer1 (if no other interrupts are allowed):

//  Interrupt routine
void Timer1Int() iv IVT_ADDR_T1INTERRUPT ics ICS_AUTO {
  //** it is necessary to clear manually the interrupt flag:
  IFS0 = IFS0 & 0xFFF7;   // Clear TMR1IF

  //** user code starts here
  LATB = ~ PORTB;         // Invert PORTB
  //** user code ends here
}
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code