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

Question about interrupt enabling

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



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

Question about interrupt enabling
PostPosted: Wed Mar 02, 2022 5:08 pm     Reply with quote

I have A0 set up to wake up a 16F18323 which works fine:
Code:
enable_interrupts(INT_RA0);

This works without using enable_interrupts(GLOBAL).

But a timer0 overflow interrupt (during non-sleep) does not work without enabling interrupts "GLOBAL".
Code:

#int_timer0
T0ISR()
{
 output_toggle(PIN_A2);
}

...

  setup_timer_0(T0_INTERNAL | T0_DIV_16 |T0_16_BIT);
  enable_interrupts(INT_TIMER0 );
  enable_interrupts(GLOBAL);  //must have


Why the different requirements?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 02, 2022 6:31 pm     Reply with quote

Look at Figure 8-1: Interrupt Logic on page 85 in the PIC data sheet.
The diagram shows that Wake Up does not require the GIE signal.
But if you want to interrupt the CPU when it's running, then the GIE
signal is required. GIE = Global interrupts enabled.

16F18323 data sheet:
https://ww1.microchip.com/downloads/en/DeviceDoc/40001799F.pdf
johnl



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PostPosted: Wed Mar 02, 2022 9:11 pm     Reply with quote

Thanks PCM. That explains it.

I have a loop that takes pin input from timer1, reads eeprom and outputs highs and lows on pins to flash LEDs with delays from delay_ms and delay_us, but if I set up timer0 and enable interrupts global, it doesn't work. I'll post code after I simplify the long loop, but in the meantime, can you think of any reason why enable global would cause the loop to not run properly?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 03, 2022 1:38 am     Reply with quote

Please post your test program that demonstrates the failure.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Mar 03, 2022 3:17 am     Reply with quote

Having an interrupt enabled, without a handler being present for that
interrupt will cause complete disaster. This is probably the most likely
one. It results in the code jumping into the middle of the wrong
location... Sad
Understand, if an interrupt 'event' occurs it sets that interrupts 'flag',
If the interrupt itself is 'enabled' at this point, this can wake a chip.
If the global enable if also set, then when this happens the code will
call the 'handler'. This is a hardware call to a specific location at the
bottom of the memory. If no 'handler' exists at this point, then you
have just 'derailed' the program...

Or having an interrupt that doesn't clear the 'event'. This doesn't apply
to the timer, but does to things like INT_RDA. If you don't read the
character in the interrupt, this will immediately re-trigger.
Result main code will stop.

The timer could do the same, if (for example), you had a timer interrupt
handler that set the timer count to just one less that the 'wrap' value,
by the time the code got out of the interrupt it'd have triggered again.
Again result main code will stop.
johnl



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PostPosted: Thu Mar 03, 2022 6:49 am     Reply with quote

Is there something missing in this handler? It does repeatedly toggle the output as expected.

Code:

#int_timer0
T0ISR()
{
 output_toggle(PIN_A2);
}

...

  setup_timer_0(T0_INTERNAL | T0_DIV_16 |T0_16_BIT);
  enable_interrupts(INT_TIMER0 );
  enable_interrupts(GLOBAL); 
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Mar 03, 2022 10:26 am     Reply with quote

That looks perfectly reasonable.
With obviously caveats about if any other interrupts are enabled. For
example if your RA0 interrupt gets left enabled, then a handler needs to
exist for this. Important therefore to make sure that when you are using
this to wake, you disable_interrupts(GLOBAL), before you enable this,
and then disable this when you wake, before you enable_interrupts(GLOBAL).
If you don't do this, then a handler must exist (with will need to read PortA
to clear the interrupt flag). This will be called when the chip wakes if the
global interrupt is enabled.
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Fri Mar 04, 2022 12:55 pm     Reply with quote

Most of the chips I use (PIC24) don't require the interrupt to even be enabled specifically to wake. It just wakes from any source that can wake it from sleep (defined in the data sheet) and the only usage of enable_interrupts() disable_interrupts() is purely for the ISR.

I don't know if the OP's chip is the same as the ones I use though.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 04, 2022 1:12 pm     Reply with quote

johnl wrote:

I'll post code after I simplify the long loop.
Question Rolling Eyes
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 04, 2022 3:32 pm     Reply with quote

complicated main() ??
johnl



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PostPosted: Fri Mar 04, 2022 7:05 pm     Reply with quote

I think the problem is that the external pin wake-up interrupt does not have a handler and/or the interrupt flag never gets cleared. It works fine to wake the chip up but when the timer0 int is set up later, it requires an enable_interrupts(GLOBAL) and that tries to process the external int flag. As Ttelmah mentioned , an interrupt that's not handled can wreak havoc. Am I thinking about this correctly?



Code:
void main()
   {
   init();
   do {
      clear_interrupt(INT_RA);
      enable_interrupts(INT_RA0);
 
      sleep();
      delay_cycles(1);
      disable_interrupts(INT_RA0); //////(INT_RA);  //Now turn  interrupt off
 
           }
      run_mode();    //timer0 int is set up in run_mode() along with enable_interrupts(GLOBAL)
      } while (TRUE);
}//end of main()
johnl



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PostPosted: Fri Mar 04, 2022 7:19 pm     Reply with quote

Yep that did it. Adding a clear_interrupt(INT_RA0) did the trick:

Code:

Code:
void main()
   {
   init();
   do {
      clear_interrupt(INT_RA);
      enable_interrupts(INT_RA0);
 
      sleep();
      delay_cycles(1);
      disable_interrupts(INT_RA0); //////(INT_RA);  //Now turn  interrupt off
      clear_interrupt(INT_RA0) ;
           }
      run_mode();    //timer0 int is set up in run_mode() along with enable_interrupts(GLOBAL)
      } while (TRUE);
}//end of main()
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sat Mar 05, 2022 6:58 am     Reply with quote

That makes total sense. Smile
Glad you have found it.
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