CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Multiple Interrupt Queueing on 18Fxxxx

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Steve Stolen



Joined: 17 Nov 2003
Posts: 2
Location: Seattle WA USA

View user's profile Send private message

Multiple Interrupt Queueing on 18Fxxxx
PostPosted: Mon Nov 17, 2003 9:13 pm     Reply with quote

I am planning on adding an external interrupt to the INT line on an 18F452, then later on an 18F8720. Other interrupts are being serviced as well, like Int on RB change, timer1, etc. Currently I am using PCH v3.179 compiler. My confusion centers around the queueing of new interrupts while one interrupt is being serviced. Ideally I would like for no interrupt to be forgotten. I do use the priority statement for ordering high to low priorities of the interrupts. It is unclear, however, if any interrupts are ever lost when another interrupt arrives. Clarity on this will be much appreciated.
_________________
Steve S
Ttelmah
Guest







Re: Multiple Interrupt Queueing on 18Fxxxx
PostPosted: Tue Nov 18, 2003 3:57 am     Reply with quote

Steve Stolen wrote:
I am planning on adding an external interrupt to the INT line on an 18F452, then later on an 18F8720. Other interrupts are being serviced as well, like Int on RB change, timer1, etc. Currently I am using PCH v3.179 compiler. My confusion centers around the queueing of new interrupts while one interrupt is being serviced. Ideally I would like for no interrupt to be forgotten. I do use the priority statement for ordering high to low priorities of the interrupts. It is unclear, however, if any interrupts are ever lost when another interrupt arrives. Clarity on this will be much appreciated.

Once any interrupt flag is set, it remains set until cleared. Hence when the first interrupt handler exits, the 'waiting' interrupt will be serviced.
Interrupts can be lost, when two occur from one 'source', before the first is serviced. So if (for instance), there is an interrupt on the RS232 at a high data rate, and the code goes into an interrupt handler for an external interrupt, that takes several mSec to run, then the RS232 interrupt flag will still be set when this code has finished, but their may now be a comm overrun error, or a second character waiting in the serial buffer. Hence the RS232 handler should keep extracting characters, for as long as there are characters to read, and check the overrun status.
In general, this is why it is best to keep all handlers as short as possible, since it massively reduces the risk of a second interrupt occuring like this.
Unfortunately, the handler code for the interrupts, has a very significant 'overhead' to save/restore a number of registers, and check which interrupt has occured. This is in the order of 40-50 instruction times on the 18F chips (worse than on the older 16 chips), which increases the effective length of the entire service routine...

Best Wishes
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 18, 2003 6:39 am     Reply with quote

I use to do a little trick with my interrupts where I placed a jump back to the beginning of the "flag" tests in the interrupt handler. This saved the Restoring and then Saving again when servicing multiple interrupts.

Code:

#INT_SSP
void ABus_Int(void)
{
  bit_clear(*PIR1, SSPIF);             /* clear interrupt flag since we are going to bypass the it with out jump below */

  /* Make sure the buffer has not overflowed */
  if (bit_test(*SSPCON,OVERFLOW_BIT))
  {
    I2CStatus = *SSPBUF;
    /* Clear the register */
    bit_clear(*SSPCON,OVERFLOW_BIT);
    I2CStatus = I2CIDLE;
  }
  else
  {
//    Wait_Time = 5;
    if (Rx_Msg.hdr.stat != PROCESS_OK)   /* don't recieve a byte              */
      ABUS_Rx_Byte();                    /* if we have a msg                  */
  }

/* Check the int's again */
  #asm
    BCF    0x0A,3  /* clear 2 MSB's of the PC */
    BCF    0x0A,4
    GOTO   0x18    /* goto the ISR handler  */
  #endasm
}
Jerry I



Joined: 14 Sep 2003
Posts: 96
Location: Toronto, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Nov 18, 2003 5:30 pm     Reply with quote

Hi Mark;

Do you this trick for all enabled interrupts.

eg.

#INT_RDA
void rs232in()
{
char tmpchr;

bit_clear(*PIR1, RDA); /* clear interrupt flag for serial int. */
/* Just an example */

tmpchr = getc();
char_rcv = TRUE;


/* Check the int's again */
#asm
BCF 0x0A,3 /* clear 2 MSB's of the PC */
BCF 0x0A,4
GOTO 0x18 /* goto the ISR handler */
#endasm
}

#INT_EXT
void rcv_extint()
{

bit_clear(*PIR1, EXT); /* clear interrupt flag for external int. */
/* Just an example */

process_ext = TRUE;


/* Check the int's again */
#asm
BCF 0x0A,3 /* clear 2 MSB's of the PC */
BCF 0x0A,4
GOTO 0x18 /* goto the ISR handler */
#endasm
}


as in the above examples for the serial and external interrupt routines.


Thanks.

Mark wrote:
I use to do a little trick with my interrupts where I placed a jump back to the beginning of the "flag" tests in the interrupt handler. This saved the Restoring and then Saving again when servicing multiple interrupts.

Code:

#INT_SSP
void ABus_Int(void)
{
  bit_clear(*PIR1, SSPIF);             /* clear interrupt flag since we are going to bypass the it with out jump below */

  /* Make sure the buffer has not overflowed */
  if (bit_test(*SSPCON,OVERFLOW_BIT))
  {
    I2CStatus = *SSPBUF;
    /* Clear the register */
    bit_clear(*SSPCON,OVERFLOW_BIT);
    I2CStatus = I2CIDLE;
  }
  else
  {
//    Wait_Time = 5;
    if (Rx_Msg.hdr.stat != PROCESS_OK)   /* don't recieve a byte              */
      ABUS_Rx_Byte();                    /* if we have a msg                  */
  }

/* Check the int's again */
  #asm
    BCF    0x0A,3  /* clear 2 MSB's of the PC */
    BCF    0x0A,4
    GOTO   0x18    /* goto the ISR handler  */
  #endasm
}
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 18, 2003 8:06 pm     Reply with quote

Yes, I did. Sometimes, it will cost you the processing time of unnecessarily checking the flag bits when no other interrupts are triggered. The fewer the number of ints the lower the cost. On the other hand, if you know that you are experiencing multiple ints occurring, it greatly reduces the overhead. I used this technique on a 4MHz part to reduce communication errors (overflows and timeouts) on one of our systems. The 20MHz parts eliminated the need for this technique for me. Keep in mind that you will need to look at the lst file to find the right value to use for the jump.
Steve Stolen



Joined: 17 Nov 2003
Posts: 2
Location: Seattle WA USA

View user's profile Send private message

PostPosted: Tue Nov 18, 2003 8:23 pm     Reply with quote

OK, it looks like I'm doing everything right. I set flags to inform the rest of the software that I have read data from the interrupting device and handle the rest in the normal processing loop. My big concern was to attempt to reduce the possibility of interrupts disturbing software serial data I send to an ascii serial display. I disable global interrupts while servicing the output display activities and re-enable afterwards. Disturbing the output data with interrupt activity can underrun characters going to the display and yield ugly consequences on the display. Most interrupts I service are timers and switch hit interrupts, no serial input data to queue up. Now I am adding an external elapsed time timer to the INT line and am attempting to analyze my concerns and avoid problems.

Thanks for the advice. Not sure I want to go as far as twiddling interrupt bits, but that may be useful for future projects.
_________________
Steve S
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group