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 support@ccsinfo.com

PIC24EP512 - Disable interrupt within its own interrupt

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



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PIC24EP512 - Disable interrupt within its own interrupt
PostPosted: Tue Feb 16, 2021 8:05 pm     Reply with quote

Compiler: 5.026
Device: PIC24EP512GP806

Hi all,

I realize this is probably a redundant / common question and I will admit I feel like an amateur asking this because I know I've read about this topic elsewhere but searching this forum returns way too many results (and my patience is growing thin). Anyhow....

This is my interrupt routine:

Code:
#INT_RDA LEVEL=7
void My_RDA_Interrupt( void )
{
   // Code here
}


When the interrupt is entered, should I call disable_interrupts( INT_RDA ); and just before exiting, call enable_interrupts( INT_RDA ); like this:

Code:
#INT_RDA LEVEL=7
void My_RDA_Interrupt( void )
{
   disable_interrupts( INT_RDA );

   // Code here

   enable_interrupts( INT_RDA );
}


Is there any value in doing this? Or is it just redundant code because it is already done internally (sorry, I don't speak assembly language)?

In other words, when any interrupt occurs, is _that_ interrupt automatically disabled when the code jumps into the ISR and re-enabled when the ISR is exit? Or is this something I must manage?

Thanks.

Ben
newguy



Joined: 24 Jun 2004
Posts: 1899

View user's profile Send private message

PostPosted: Tue Feb 16, 2021 8:52 pm     Reply with quote

Putting in the extra disable and then enable interrupt is redundant because while the ISR is being executed, that particular interrupt can't be interrupted again by that same source (RDA in your example). If you have a processor that supports interruptible interrupts, and you don't want a particular higher priority interrupt to be able to interrupt a lower priority interrupt, then you can add code like you've shown to prevent that.

The confusing part is the hidden code the compiler automatically adds for each interrupt to clear that interrupt.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Feb 17, 2021 1:55 am     Reply with quote

It is both simpler and more complex than you may think.

By default, the compiler does not clear the interrupt till you exit the handler.
There is no 'stacking' of interrupt bits, so the already set bit can't get
set again while you are in the handler.

Now there are situations, where you might deliberately 'want' to let the
interrupt become set again. This is handled by coding like:
Code:

#INT_RDA CLR_FIRST
void My_RDA_Interrupt( void )
{
   //handler code
}

This then clears the interrupt at the entry point to the handler. With this,
the interrupt can become triggered again. Normally you would want this,
if you wanted to ensure an event cannot be missed. However on the
PIC16/18 you then need to be careful, since in fact the RDA interrupt
cannot actually be cleared, until the character has been read. So on these
chips you instead have to behave like:
Code:

#INT_RDA NOCLEAR
void My_RDA_Interrupt( void )
{
   chr=getc(); //physically get the character
   clear_interrupt(INT_RDA); //then immediately clear the interrupt
   //now the rest of the handler code
}


So here, you physically handle the 'event' (get the character), 'ASAP', and
clear the interrupt just one instruction later, which then allows the
interrupt to trigger again after this point.
Now the interrupt bit being set at the exit of the routine, then simply means
that the routine will then be called again. Throughout the handling, the
physical chip hardware 'makes sure' an interrupt cannot be called inside
itself. On the PIC16/18, as soon as an interrupt is called the GIE bit
(for the applicable 'level' on the PIC18), gets turned off when an interrupt
is called, and is not re-enabled until the RETFIE at the end of the handler.
On the PIC24/30/33, it is instead handled by the processor priority
mechanism. An interrupt can only interrupt code that is at a lower priority
level than the CPU is currently running. The normal CPU code is level0.
Note the 'lower', not 'equal'. This is why if you assign an interrupt to
level0, it is effectively disabled, since it can never actually interrupt
anything. Now in your interrupt at level7, it can only be interrupted by
trap events (so things like address errors), not by any other user interrupt
(since they will all be 'below' this level), including itself, since the level
is the same.

There is though another 'caveat' here.
In the PIC24/30/33, there is a character buffer for the RDA event,
that is several characters deep. The interrupt will not re-trigger if
another character arrives in the buffer before an existing character
is read. So on these, the RDA handler needs to be coded as:

Code:

#INT_RDA
void character(void)
{
   uint16_t chr;
   //receive characters from serial 
   do
   {   
      chr=fgetc(RDAROURCE); //whatever your stream name is
      //your handler code to save character here
   } while (kbhit(RDAROURCE)); 
}


Otherwise characters can gradually build in the receive hardware buffer.
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Thu Feb 18, 2021 1:11 pm     Reply with quote

Fair enough, thanks for the detailed info, I will look into it.

Cheers,

Ben
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