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
}
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.
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!
-----------------------------------------------------------------------------------------------------------------------