PIC32 Multiple interrupts issue

Thread Starter

kasula4

Joined Apr 9, 2010
4
Hello,
I am trying to use multiple interrupts in PIC32 microcontroller. When I use 2 interrupts lets say UART and 1 timer the microcontroller is working fine but when I use UART and 2 timer interrupts the microcontroller freezes. I have the following code in the interrupts.

#include "Tao4ch_defs.h"
// UART 2 interrupt handler
// it is set at priority level 2

void __ISR(_UART_2A_VECTOR, ipl3) _U2ARXInterrupt(void)
{ char ch;

IFS1bits.U2ARXIF = 0; // Reset the RX interrupt flag.

ch = U2ARXREG;

Char_in = ch;

Char_cap = 1; // Flag to indicate a character has been received.
// 0x0A is a line feed. Some terms attach linefeeds so must discard them.

if (ch != 0x0D && ch != 0x0A) { // If the rx'd char is not 'enter' or lf

Rx_buff [Rx_index] = ch; // load the rx buffer with the char and

Rx_index++; // increment the index.

if (Rx_index >= RX_BUF_LEN)

Rx_index = 0;
}

if (ch == 13) { // When the 'enter' char is received

Rx_buff[Rx_index] = 0; // put a null char in the string.

Rx_index = 0; // and reset the index.

Com_flag = 1; // Com flag should be reset after the
} // buffer has been read.
// string is processed.

}


// interrput code for the timer 1

void __ISR( _TIMER_1_VECTOR, ipl2) _T1Interrupt( void)
{
int i;

asm("ei"); //To enable interrupts
// clear interrupt flag and exit

IFS0bits.T1IF = 0;

sampleBuffer[sampleIndex].re = read_ext_adc1(5) - 25485; // read the ADC into the real part of the samplebuffer

// increment the sampleIndex
if (sampleIndex == (N-1))
{
sampleIndex = 0;
}
else
{
sampleIndex++;
}




} // T3 Interrupt


void __ISR( _TIMER_3_VECTOR, ipl1) _T3Interrupt( void)
{ asm("ei");

IFS0bits.T3IF = 0;

//do something

}


Thanks
 

rjenkins

Joined Nov 6, 2005
1,013
Try to avoid doing any complex processing within an interrupt, keep it short so you do not have to re-enable interrupts while one is active.

Another speed-up is to make buffers power-of-two lengths and simply do
rx_index++;
rx_index &= 0x1f; to limit the index to 0-31 or whatever.

I usually poll any i/o within a timer routine, cycling fast enough to ensure no overruns.

I'd generally run it at about 10KHz, but I have used in excess of 250KHz on PIC16.

Examples, comments added for info:
Rich (BB code):
// Storage declarations
int     cd_tbuf[32]; // The data buffer
int     cd_tbufi; // Buffer Input pointer
int     cd_tbufo; // Buffer Output pointer
int     cd_tbufc; // Buffer Count

// Initialisation
void rs_clear(void) {
    rs_tbufi = 0;
    rs_tbufo = 0;
    rs_tbufc = 0;
}            

// Routine to buffer TX characters
void rs_tput(int i) {
    rs_tbuf[rs_tbufi++] = i; // Store data, inc pointer
    rs_tbufc++; // Inc buffer count
    rs_tbufi &= 0x1f;  // Pointer roll-over to zero.
}

// TX poll routine called from within RTC interrupt
void rs_send(void) {
// If nothing to send, quit.
    if(rs_tbufi == rs_tbufo) { 
        rs_tbufc = 0;
        return;
    }

// Otherwise, if UART is not busy,
    if(rs_tx_rdy())    {                
        putchar(rs_tbuf[rs_tbufo++]); // Send character & inc pointe
        rs_tbufo &= 0x1f; // Roll-over
        rs_tbufc--; // Dec buffer count
     }    
}
(Note - naming - That's pulled out of a program that has multiple comms routines named with different prefixes, that particular one just happened to be rs_... ).
 

BMorse

Joined Sep 26, 2009
2,675
Do you have Multi vector Interrupts Enabled??

here is a code snippet I used with the Pic32 interrupts.....
at the bottom of the code, you can see my Interrupt initialization routine where I enable the Multi vector interrupts..... and as RJenkins had said, try not to do too much in an interrupt routine, You could very well miss a different interrupt....
Rich (BB code):
/*
// Interrupts
*/
//****************************************************************
#ifndef _bINT_HEADER_FILE
#define _bINT_HEADER_FILE

//****************************************************************
void __ISR( _RTCC_VECTOR,ipl1) RTCCInterrupt( void)
{
    MODE_CHANGED=1;
    RtccAlarmDisable();
    SYS_MODE++;                //Increment SYS_MODE to reflect current state of system
    mRTCCClearIntFlag();    //Clear Interrupt Flag
    
}//RTCC Interrupt

void __ISR(_UART1_VECTOR,ipl2) IntUart1Handler(void)
{
    //is this an RX interrupt??
    if (mU1RXGetIntFlag())
    {//clear the RX interrupt flag
        mU1RXClearIntFlag();
        //putcUART2(ReadUART1();
    }//RX Interrupt
    if (mU1TXGetIntFlag())
    {//we dont care for it so just clear it
        mU1TXClearIntFlag();
    }//End TX Interrupt
}

void __ISR( _EXTERNAL_2_VECTOR,ipl3) INT2InterruptHandler(void)    //PIR Sensor Interrupt
{
    //mPORTDToggleBits(BIT_0);
    asm ("ei");
        Motion=1;            //Set Flag
        Vanity_On=1;        //Set Flag
        mSSR1_ON();            //Turn On Vanity Light
        LOD=0;                //Reset Light On Delay
        mINT2ClearIntFlag();
}//End INT2

void __ISR( _EXTERNAL_1_VECTOR,ipl5) INT1InterruptHandler(void)    //MPR084Q Interrupt Source, 
                                                                //Not used right now, using polling method instead
{
    asm ("ei");
    mINT1ClearIntFlag();
}//End INT1

//****************************************************************
#endif

Init_Interrupts()
{
    mRTCCSetIntPriority(1);                //Set Real Time Clock And Calendar Priority Level
    mRTCCClearIntFlag();                //Clear RTCC Interrupt Flag
    mINT2SetIntPriority(3);                //Set Interrupt Priority for External Int Source 0    
    mINT1SetIntPriority(5);                //Set Interrupt Priority for External Int Source 1
    INTEnableSystemMultiVectoredInt();        //Enable Multi vectored Interrupts
    mINT2IntEnable(1);                //Enable External Interrupt 0
    mINT1IntEnable(1);                //Enable External Interrupt 1
}//End Init Interrupts
P.S.
I also noticed when I was working with the Pic32, that you have to start with the lowest priority first..... if you notice in my code ipl1 is the first routine, all the way down to ipl5....

B. Morse
 
Last edited:

Thread Starter

kasula4

Joined Apr 9, 2010
4
Thanks for the replies. I have a question for BMORSE. I think IPL7 is the highest priority so I think asm(ei) should be used in lower priorities IPL(0) etc.., were you able to run the same code successfully.
 

BMorse

Joined Sep 26, 2009
2,675
Thanks for the replies. I have a question for BMORSE. I think IPL7 is the highest priority so I think asm(ei) should be used in lower priorities IPL(0) etc.., were you able to run the same code successfully.

You are right ipl7 is the highest priority level, I used the asm (ei), just to make sure other interrupts are still enabled when entering that ISR.....

And yes, the way I have the ISR's set up, seems to work very well for me....

B. Morse
 
Top