Positron Compiler Documentation

Isr, EndIsr

Positron16 · Revision 1.1.3.5 · PDF pages 458–461

Isr Interrupt Name, {UnHandled} Interrupt handler BASIC code goes here EndIsr

Indicate the start and end of an interrupt handling subroutine.

Interrupt Name is the name of the interrupt being handled by the subroutine. Unhandled is an optional parameter that will disable context saving and restoring of the WREG SFRs and key SFRs, as well as compiler system variables. Use this option with caution and only when you know that the interrupt handler’s code will not disturb any other SFRs or variables.

Unlike 8-bit PIC® microcontroller’s, PIC24® and dsPIC33® devices have a separate vector for each type of interrupt. Each interrupt has a specific name, and there are up to 128 of them. A typical interrupt vector name list is shown below:

Interrupt Name Interrupt Cause

OscillatorFailOscillator Failure (Non-Maskable)
StackErrorAddress Error(Non-Maskable)
AddressErrorStack Error(Non-Maskable)
MathErrorMath Error(Non-Maskable)
DMACErrorDMA Error(Non-Maskable)
INT0InterruptExternal Interrupt 0
IC1InterruptInput Capture 1
OC1InterruptOutput Compare 1
T1InterruptTimer1
DMA0InterruptDMA Channel 0
IC2InterruptInput Capture 2
OC2InterruptOutput Compare 2
T2InterruptTimer2
T3InterruptTimer3
SPI1ErrInterruptSPI1 Error
SPI1InterruptSPI1 Transfer Done
U1RXInterruptUART1 Receiver
U1TXInterruptUART1 Transmitter
ADC1InterruptADC 1
DMA1InterruptDMA Channel 1
SI2C1InterruptI2C1 Slave Events
MI2C1InterruptI2C1 Master Events
CNInterruptChange Notification Interrupt
INT1InterruptExternal Interrupt 1
IC7InterruptInput Capture 7
IC8InterruptInput Capture 8
DMA2InterruptDMA Channel 2
OC3InterruptOutput Compare 3
OC4InterruptOutput Compare 4
View original PDF page 458Open page in PDFOriginal PDF page 458

Interrupt Name Interrupt Cause

T4InterruptTimer4
T5InterruptTimer5
INT2InterruptExternal Interrupt 2
U2RXInterruptUART2 Receiver
U2TXInterruptUART2 Transmitter
SPI2ErrInterruptSPI2 Error
SPI2InterruptSPI1 Transfer Done
DMA3InterruptDMA Channel 3
IC3InterruptInput Capture 3
IC4InterruptInput Capture 4
IC5InterruptInput Capture 5
IC6InterruptInput Capture 6
OC5InterruptOutput Compare 5
OC6InterruptOutput Compare 6
OC7InterruptOutput Compare 7
OC8InterruptOutput Compare 8
DMA4InterruptDMA Channel 4
T6InterruptTimer6
T7InterruptTimer7
SI2C2InterruptI2C2 Slave Events
MI2C2InterruptI2C2 Master Events
T8InterruptTimer8
T9InterruptTimer9
INT3InterruptExternal Interrupt 3
INT4InterruptExternal Interrupt 4
U1ErrInterruptUART1 Error
U2ErrInterruptUART2 Error

There are commonalities for the names on all PIC24® and dsPIC33® devices, however, interrupt vector names will be added if the device has a specific peripheral. A full list of the interrupt names for a specific device can be found within the device’s PPI file, under the [ISRSTART] section. The PPI files can be found within the compiler’s “PDS\Includes\PPI” directory.

The first 5 names in the list are interrupts that cannot be disabled. i.e. Non-Maskable, and are used for exception handling within the microcontroller. The others in the list are Maskable, meaning they can be enabled or disabled accordingly.

The interrupt handler, unless otherwise indicated, will first disable any other interrupts, then save key SFRs (Special Function Registers) such as SR (STATUS on 8-bit devices), COR- CON, RCOUNT, WREG0 to WREG14, then if available on the device being used, PSVPAG, DSRPAG, DCOUNT, DOSTART, and DOEND. If the device has more than 65K or code memory, the TBLPAG SFR will also be saved. Saving is accomplished by pushing the SFRs or variables onto the microcontroller’s stack, which will expand to accommodate them.

It will then save any compiler system variables that are used within the interrupt handler, before re-enabling interrupts and handing control to the code within the interrupt handler. The reverse is accomplished when the interrupt is exited, and the Retfie mnemonic issued. Note that the interrupt handler will not reset any associated interrupt flag.

This means that pretty much any BASIC code can be placed inside an interrupt as long as it handles any peripheral conflicts, such as Port re-use etc...

View original PDF page 459Open page in PDFOriginal PDF page 459

If additional SFRs or variables need to be saved within the interrupt handler, they can by Pushed onto the stack then Popped from it before the interrupt exits. For example:

  Isr T1Interrupt
     Push TRISB                       ' Save 16-bit TRISB on the stack
     Push PORTB                        ' Save 16-bit PORTB on the stack
     Toggle PORTB                   ' Use TRISB and PORTB
     Pop PORTB                         ' Restore 16-bit PORTB from the stack
     Pop TRISB                         ' Restore 16-bit TRISB from the stack
     IFS0bits_T1IF = 0               ' Reset the Timer1 interrupt flag
  EndIsr                              ' Exit the interrupt

Note that the compiler can only track its system variable use when the code is between Isr and EndIsr. It cannot track any code that is called as a subroutine or a procedure from the ISR handler.

An asm Bra mnemonic is placed before the Isr directive, that jumps over the handler code past the EndIsr directive. This means that the interrupt handler can be placed in the line of code without having to jump over it manually. However, this behaviour can be altered by adding a dash after the Isr and EndIsr directives: Isr- and EndIsr-. This will save two bytes of code space for every interrupt handler used in the BASIC program, but measures should be taken to make sure that the program does not run the interrupt code directly, such as a GoTo to the main program loop.

'
' Timer interrupt demo
'
    Device = 24FJ64GA002
    Declare Xtal = 16
    Declare Hserial_Baud = 9600        ' UART1 Baud rate
    Declare Hrsout1_Pin = PORTB.14     ' Select which pin for TX with USART1

    Dim FloatOut1 As Float
    Dim FloatOut2 As Float

'-------------------------------------------------------------------------
    GoTo Main                          ' Jump over the interrupt handlers
'-------------------------------------------------------------------------
' Timer1 interrupt handler
' Transmit a floating point value serially
'
Isr- T1Interrupt                       ' Context save
    HRSOut "Timer1 ", Dec1 FloatOut1, 13
    FloatOut1 = FloatOut1 + 0.1
    IFS0bits_T1IF = 0                  ' Reset the Timer1 interrupt flag
EndIsr-                                ' Context restore and exit the interrupt
'-------------------------------------------------------------------------
' Timer2 interrupt handler
' Transmit a floating point value serially
'
Isr - T2Interrupt                    ' Context save
    HRSOut "Timer2 ", Dec1 FloatOut2, 13
    FloatOut2 = FloatOut2 + 0.1
    IFS0bits_T2IF = 0                  ' Reset the Timer2 interrupt flag
EndIsr-                                ' Context restore and exit the interrupt
View original PDF page 460Open page in PDFOriginal PDF page 460
'-------------------------------------------------------------------------
Main:
    RPOR7 = 3                   ' Make PPS Pin RP14 U1TX
    FloatOut1 = 0
    FloatOut2 = 0
'
' Configure Timer1
'
     TMR1 = 0
     PR1 = 8192                   ' Load Timer1 period
     T1CON = %1010000000101001    ' Start Timer1
                                  ' Discontinue operation in Idle mode
                                  ' Gated time accumulation disabled
                                  ' 1:64 prescaler
                                  ' Do not synchronise external clock input
                                  ' Internal clock

     IFS0bits_T1IF = 0            ' Clear Timer1 interrupt flag
     IPC0bits_T1IP0 = 0           ' Set priority
     IEC0bits_T1IE = 1            ' Enable the Timer1 interrupt
'
' Configure Timer2
'
     TMR2 = 0
     PR2 = 8192                   ' Load Timer2 period
     T2CON = %1010000000110101    ' Start Timer2
                                  ' Discontinue operation in Idle mode
                                  ' Gated time accumulation disabled
                                  ' 1:256 prescaler
                                 ' Timer2 as 16-bit timer
                                  ' Internal clock

     IFS0bits_T2IF = 0            ' Clear Timer2 interrupt flag
     IPC1bits_T2IP0 = 0           ' Set priority
     IEC0bits_T2IE = 1            ' Enable the Timer2 interrupt

The program above shows a worse case scenario of each interrupt calculating and displaying floating point variables, which are among the most processor intensive operations.

Adding another interrupt is as simple as placing Isr and EndIsr directives with a given name, and configuring the microcontroller to initiate the interrupt. The compiler will take care of the rest as much as it can.

Nesting of Isr and EndIsr directives is not allowed.

The naming of the interrupts is taken from the official Microchip™ documentation and are the names used by the Linker application.

View original PDF page 461Open page in PDFOriginal PDF page 461