KL17 LLWU wakeup gets stuck on interrupt handler

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

KL17 LLWU wakeup gets stuck on interrupt handler

1,520 次查看
paulinikula
Contributor II

Hi,

I have encountered problem with KL17Z256 chip I'm working with. I have setup the MCU to go to VLLS1 mode, and wake up from external accelerometer pin interrupt, LPTMR0 interrupt and also RTC alarm. LPTMR0 and RTC interrupt is currently disabled as the problem seems to be caused by the interrupt pin. Problem is that if I generate one interrupt by tapping my table next to the chip (accelerometer is very sensitive), MCU wakes up normally and everything seems to work fine. But if I do multiple taps in rapid fashion, MCU might keep up usually 3-5 times (wakeup and go back to sleep quickly), but then crashes and stops doing anything. 

By using debugger I can see that MCU gets stuck in the LLWU IRQ handler. I suppose I'm clearing all the flags properly. To me the problem looks like that too rapid interrupts cause the LLWU to function abnormally during wake up. Here is my LLWU IRQhandler:

void LLWU_IRQHandler()
{

/* If wakeup by LPTMR. */
if ( LLWU->F3 & 0x01)

   wake = 1;
   CLOCK_EnableClock(kCLOCK_Lptmr0);
   LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;

}
else if (LLWU->F3 & 0x20) //if wakeup from RTC alarm
{
   wake = 3;
   CLOCK_EnableClock(kCLOCK_Rtc0); //enable RTC bus clock so we can write registers
   RTC->TAR = RTC_REPORT_INTERVAL; //write to alarm register to clear interrupt flag
}

else if ( LLWU->F1 & 0x20) //if wakeup from accelerometer pin(LLWU P5)

   wake = 2;
   LLWU->F1 |= 0x20;
   LLWU->FILT1 |= 0x80;
   while(LLWU ->F1 & 0x20);
}


}

From debugger I can see that on the stuck state, MCU is continuously running on LLWU_IRQHandler, but is not entering any of my if conditions regarding the flags, which is quite puzzling.

Here is my initialization code:

int main(void)
{

   NVIC_SetPriority(LLWU_IRQn,0);
   NVIC_EnableIRQ(LLWU_IRQn);//enable LLWU interrupts. if we wake up from VLLS mode, it means that next MCU
   //will jump to the LLWU interrupt vector
   PMC->REGSC |= 0x08; //acknowledge wake up to voltage regulator module, this is needed with LLWU wake up


   BOARD_InitPins(); //init all physical pins
   BOARD_BootClockVLPR(); 

   SysTick_Config(BOARD_DEBUG_UART_CLK_FREQ / 1000); //setup SysTick timer for 1ms interval for delay functions(see timing.h)
   NVIC_SetPriority(SysTick_IRQn,6);
   delay_ms(50);

   configureSleepMode(); //set power mode protection and LLWU wakeup sources here
   initUART();
   NVIC_SetPriority(RTC_IRQn,5);
   EnableIRQ(RTC_IRQn);

if (wake == 2) //wakeup by accelerometer
{
   disableUartInterrupts();

   blinkLed(50);

   PCprint("Woken by accelerometer\r\n");
   initTimer();

   SMC_PreEnterStopModes();
   SMC_SetPowerModeVlls(SMC, &smc_power_mode_vlls_config);
   SMC_PostExitStopModes();

   printInterruptFlags();  //sometimes something prevents entry to stop mode, try to catch here what it was

}

 

2 回复数

1,213 次查看
paulinikula
Contributor II

I have fixed my problem. I had misunderstood how LLWU pin interrupt works. I had enabled pin rising edge on both PE and FILT registers, I had thought that FILT is needed to select the edge sensitivity, but actually they are separate interrupt sources and thus I had FILT generate interrupt also which caused it to get stuck. Interesting that there is 2 sources for every pin interrupt, I don't quite get the purpose.

0 项奖励
回复

1,213 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi Pauli,

    Thank you for your updated information.

    So, it's better to clear all the LLWU flag in the LLWU interrupt, just like this code:

#ifdef CMSIS
void LLW_IRQHandler(void) {
#else
void llwu_isr(void){
#endif
   //printf("\n [LLWU ISR] ");
   if (LLWU_F1 & LLWU_F1_WUF5_MASK) {
   //    printf("****WUF5 was set *****\r\n");
       LLWU_F1 |= LLWU_F1_WUF5_MASK;   // write one to clear the flag
   }
   if (LLWU_F1 & LLWU_F1_WUF6_MASK) {
   //    printf("****WUF6 was set *****\r\n");
       LLWU_F1 |= LLWU_F1_WUF6_MASK;   // write one to clear the flag
    }
   if (LLWU_F1 & LLWU_F1_WUF7_MASK) {
   //    printf("****WUF7 was set from PTC3 input  *****\r\n");
       LLWU_F1 |= LLWU_F1_WUF7_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF8_MASK) {
   //    printf("****WUF8 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF8_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF9_MASK) {
   //    printf("****WUF9 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF9_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF10_MASK) {
   //    printf("****WUF10 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF10_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF11_MASK) {
   //    printf("****WUF11 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF11_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF12_MASK) {
   //    printf("****WUF12 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF12_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF13_MASK) {
   //    printf("****WUF13 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF13_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF14_MASK) {
   //    printf("****WUF14 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF14_MASK;   // write one to clear the flag
   }
   if (LLWU_F2 & LLWU_F2_WUF15_MASK) {
   //    printf("****WUF15 was set *****\r\n");
       LLWU_F2 |= LLWU_F2_WUF15_MASK;   // write one to clear the flag
   }
   
   /************************************************************************
    * Note: This ISR does not write to the LLWU_F3 register because these
    * are peripheral module wakeups.  The flags contained in the LLWU_F3
    * register should be cleared through the associated module interrupt
    * and not through the LLWU_F3 per the Kinetis L Family Reference
    * Manual (LLWU Chapter)
    **********************************************************************/
  if (LLWU_F3 & LLWU_F3_MWUF0_MASK) {
    //   printf("****WUF3_MWUF0 IF  LPTMR  *****\r\n");
         SIM_SCGC5 |= SIM_SCGC5_LPTMR_MASK;
         LPTMR0_CSR |=  LPTMR_CSR_TCF_MASK;   // write 1 to TCF to clear the LPT timer compare flag
         LPTMR0_CSR = ( LPTMR_CSR_TEN_MASK | LPTMR_CSR_TIE_MASK | LPTMR_CSR_TCF_MASK  );
   }
   if(LLWU_FILT1 & LLWU_FILT1_FILTF_MASK){
       
       LLWU_FILT1 |= LLWU_FILT1_FILTF_MASK;
   }
   if(LLWU_FILT2 & LLWU_FILT2_FILTF_MASK){
       
       LLWU_FILT2 |= LLWU_FILT2_FILTF_MASK;
   }
   NVIC_ICPR |= 1 << (LLWU_irq_no%32);
}

Wish it helps you!


Have a great day,
Kerry

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