[S12ZVC] HVI Interrupt is working but can't wake up

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

[S12ZVC] HVI Interrupt is working but can't wake up

Jump to solution
976 Views
daehyeonkim
Contributor II

Hello,

 

Thank you for your assistance.

I want to make MCU waking up when I push the button on the evaluation board.

This button is connected to HVI0 directly, it is pulled down to ground if I push the button.

So I configured this working by falling edge as wake up interrupt source. (PPSL)

Anyway, the HVI interrupt seems to be working properly and I can see the led toggling.

But after 10 sec, MCU enter the stop mode, this interrupt does't work.

is there anything I missed?

 

 

//////////////////////////////////////////////// HVI TEST CODE /////////////////////////////////////////////////

#include <hidef.h>
#include "derivative.h"

int m_sec = 0;
int sec = 0;

void interrupt 12 TIM_OutputCompare_ISR(void)
{
 TIM0TC0 = TIM0TCNT + 1000;
 TIM0TFLG1 = 0b00000001;
  
 m_sec++;
 if(m_sec == 250) {
  PTP_PTP0 ^= 1;
  sec++;
  m_sec = 0;
  if(sec == 10) {

   sec = 0;
   asm STOP;
  }
 }
}

interrupt 79 void HVI_ISR(void)
{
 PTP_PTP6 ^= 1;
 PIFL = 0x01;
}

void TIM_init(void)
{
 TIM0TIOS = 0b00000001;
 TIM0TCTL1 = 0b00000000;
 TIM0TCTL2 = 0b00000000;
 TIM0TFLG1 = 0b11111111;
 TIM0TTOV = 0b00000000;
 TIM0TIE = 0b00000001;
 TIM0PTPSR = 31;
 TIM0TC0 = TIM0TCNT + 1000;
  
 TIM0TSCR1 = 0b11101000;
}

void main(void)
{
 CPMUCLKS_PLLSEL = 1;   //FBUS = FPLL/2.   FBUS = 32MHz,
 CPMUREFDIV_REFFRQ = 1;   //Reference clock between 2MHZ and 6MHZ. 
 CPMUREFDIV_REFDIV = 0x1;  //FREF=8/(1+1) = 4MHZ  
 CPMUSYNR_VCOFRQ = 0x1;          //FVCO is between 48MHZ and 80MHZ 
 CPMUSYNR_SYNDIV = 0x7;   //FVCO = 2xFREFx(SYNDIV+1)   =   FVCO = 2x4x(7+1) = 64MHZ
 CPMUPOSTDIV_POSTDIV = 0x0;  //FPLL = FVCO/(POSTDIV+1).  FPLL = 64MHZ/(0+1)    FPLL = 64MHz 
 CPMUOSC_OSCE = 1;    //External oscillator enable. 8MHZ.        FREF=FOSC/(REFDIV+1)  
 while(!CPMUIFLG_LOCK){}   //Wait for LOCK.       
 CPMUIFLG = 0xFF; 
 
 TIM_init();
 
 asm ANDCC #0x7F;
 
 DDRP_DDRP0 = 1;
 DDRP_DDRP4 = 1;
 DDRP_DDRP5 = 1;
 DDRP_DDRP6 = 1;
 
 PTP_PTP0 = 1;
 PTP_PTP4 = 1;
 PTP_PTP5 = 1;
 PTP_PTP6 = 1;
 
 PPSL_PPSL0 = 0;
 PTAENL_PTAENL0 = 0;
 DIENL_DIENL0 = 1;
 PIEL_PIEL0 = 1;
 
 EnableInterrupts;
  
 for(;;)
 {
 
 }
}

Labels (1)
Tags (3)
1 Solution
635 Views
RadekS
NXP Employee
NXP Employee

Hi Daehyeon,

The problem is in the place where you execute asm STOP; command.

For successful wake-up, the appropriate interrupt must be enabled and if this interrupt is I-bit maskable, also I-bit must be cleared prior enter stop mode.

The port L interrupt is I-bit maskable interrupt and you correctly used EnableInterrupts; in the main loop for enabling interrupts.

When a timer interrupt occurs, the I-bit is set for preventing another interrupt. The I-bit is automatically cleared by last instruction (RTI) in interrupt routine (except cases where interrupt routine continues by next interrupt routine).

Since, you call asm STOP; inside the interrupt routine, the I-bit maskable interrupts are disabled during stop mode and you cannot wake-up MCU by port L interrupt event (the MCU may be wake-up by reset or any non-maskable interrupt like XIRQ).

 

So, you have two basic option where I recommend rather the first one:

1. You should just set some flag instead asm STOP; command in TIM_OutputCompare_ISR() ISR and periodically check that flag in the main loop.

For example:

Unsigned char go_stop = 0;
//…
void interrupt 12 TIM_OutputCompare_ISR(void)
{
//…
go_stop = 1;
//…
} 
//…
void main(void)
{
//…
for(;;)
 {
  If (go_stop)
    {
      asm STOP;
      go_stop = 0;
     }
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

2. You may use interrupt nesting. When you clear I-bit inside the interrupt routine, the interrupt routine can be interrupted by an interrupt request with a higher priority. So, you should place EnableInterrupts; prior asm STOP command; and configure port L interrupt for a higher priority than TC0 interrupt.

For example:

void interrupt 12 TIM_OutputCompare_ISR(void)
{
//…
EnableInterrupts;
asm STOP;
//…
} 
//…
void main(void)
{
//…
INT_CFADDR = 0x70;
INT_CFDATA3_PRIOLVL = 0x01; /*Priority level of TIM0_C0I*/
INT_CFADDR = 0x30;
INT_CFDATA0_PRIOLVL = 0x02; /*Priority level of Port L*/
//…
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I hope it helps you.

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

1 Reply
636 Views
RadekS
NXP Employee
NXP Employee

Hi Daehyeon,

The problem is in the place where you execute asm STOP; command.

For successful wake-up, the appropriate interrupt must be enabled and if this interrupt is I-bit maskable, also I-bit must be cleared prior enter stop mode.

The port L interrupt is I-bit maskable interrupt and you correctly used EnableInterrupts; in the main loop for enabling interrupts.

When a timer interrupt occurs, the I-bit is set for preventing another interrupt. The I-bit is automatically cleared by last instruction (RTI) in interrupt routine (except cases where interrupt routine continues by next interrupt routine).

Since, you call asm STOP; inside the interrupt routine, the I-bit maskable interrupts are disabled during stop mode and you cannot wake-up MCU by port L interrupt event (the MCU may be wake-up by reset or any non-maskable interrupt like XIRQ).

 

So, you have two basic option where I recommend rather the first one:

1. You should just set some flag instead asm STOP; command in TIM_OutputCompare_ISR() ISR and periodically check that flag in the main loop.

For example:

Unsigned char go_stop = 0;
//…
void interrupt 12 TIM_OutputCompare_ISR(void)
{
//…
go_stop = 1;
//…
} 
//…
void main(void)
{
//…
for(;;)
 {
  If (go_stop)
    {
      asm STOP;
      go_stop = 0;
     }
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

2. You may use interrupt nesting. When you clear I-bit inside the interrupt routine, the interrupt routine can be interrupted by an interrupt request with a higher priority. So, you should place EnableInterrupts; prior asm STOP command; and configure port L interrupt for a higher priority than TC0 interrupt.

For example:

void interrupt 12 TIM_OutputCompare_ISR(void)
{
//…
EnableInterrupts;
asm STOP;
//…
} 
//…
void main(void)
{
//…
INT_CFADDR = 0x70;
INT_CFDATA3_PRIOLVL = 0x01; /*Priority level of TIM0_C0I*/
INT_CFADDR = 0x30;
INT_CFDATA0_PRIOLVL = 0x02; /*Priority level of Port L*/
//…
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I hope it helps you.

Have a great day,
Radek

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------