Handling GPIO Interrupt after pin wake-up via LLWU Interrupt

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

Handling GPIO Interrupt after pin wake-up via LLWU Interrupt

303 Views
aberger
Contributor V

I'm using the FRDM-K32L2B3 Demo board and experimenting with the power_manager demo included with the SDK. There seems to be some conflicting information out there regarding what happens following a wake from LLS mode, particular when waking on a pin event.

I would like to answer the question posed originally by https://community.nxp.com/t5/Kinetis-Microcontrollers/LLWU-PORT-interrupt/m-p/266530/highlight/true#...

Following an LLS wakeup from a wake-up pin that is also configured for GPIO interrupts (for simplicity, let's assume both the LLS wakeup and the GPIO interrupt are configured to detect a falling edge), is there a way to make sure the GPIO IRQ Handler is triggered after the LLWU IRQ Handler completes? 

From https://community.nxp.com/t5/Kinetis-Microcontrollers/LLWU-PORT-interrupt/m-p/266535/highlight/true#... 

While in LLS mode, the port interrupt logic is not even powered up. So, when the edge that wakes the MCU from LLS occurs the only logic that sees the edge is in the LLWU module. The port interrupt flag is not set and therefore the port interrupt function will not be called.  I hope that clears up some confusion that I might have caused. My statement in Rev. 1, 11/2012 of AN4503, that said that the ISF of the port pin is cleared with the clearing of the LLWU pin flag is incorrect. Sorry.

If there is a critical edge that you must catch, you need to use a pin that had both functions pin interrupt and LLWU wakeup.  Enable the edge interrupt logic with the PORTx_PCRxx register and the LLWU edge detect logic in the LLEU_PEx registers. Then you will not ever miss an edge.

Those paragraphs seem to conflict with one another. The first paragraph says that the PORT interrupt will never fire because the NVIC is disabled, while the second paragraph implies that it is possible to trigger the PORT interrupt.

This answer (marked as the solution from the same thread) implies that only the LLWU IRQ Handler is triggered. But it also says

If at this time [upon completion of the LLWU ISR], GPIO interrupt generation condition is still matched, GPIO interrupt flag will be set.

What does that even mean for falling-edge detection? (i.e. this seems to imply that falling-edge detection will never be detected by the GPIO circuitry.)

AN4503 states:

Internal module flags can be cleared in the LLWU exception handlers (ISR) or if you leave the module flag set then after the LLWU ISR is complete you enter the module ISR to clear the flag. If you clear the module flag and do not want to enter the module ISR the NVIC clear pending interrupt flag bit must be cleared for the module. Serialization of operations is necessary to ensure the flag are cleared before returning from the LLWU or module ISRs.

So this seems to draw a distinction between a wake-up interrupt generated by an internal module vs a pin.

However, in 3.1.4 Exiting Low Leakage Stop (LLS low-power mode) (which demonstrates an example where the wakeup is generated by a pin, not an internal module), AN4503 provides this note:

If interrupts are enabled, the execution resumes with the appropriate interrupt service
routine. If interrupts are disabled, the execution resumes with the instruction after the
WFI, or STOP instruction.

That seems to imply that I can reasonably expect the GPIO pin's ISR to fire after exiting the LLWU ISR.

The demo code for power_manager also seems to imply that the PORT ISR may fire after the LLWU ISR. From within the LLWU_IRQHandler, the code makes sure to clear the PORT interrupt flag. 

 

/* If wakeup by external pin. */
if (LLWU_GetExternalWakeupPinFlag(LLWU, LLWU_WAKEUP_PIN_IDX))
{
PORT_SetPinInterruptConfig(APP_WAKEUP_BUTTON_PORT, APP_WAKEUP_BUTTON_GPIO_PIN, kPORT_InterruptOrDMADisabled);
PORT_ClearPinsInterruptFlags(APP_WAKEUP_BUTTON_PORT, (1U << APP_WAKEUP_BUTTON_GPIO_PIN));
LLWU_ClearExternalWakeupPinFlag(LLWU, LLWU_WAKEUP_PIN_IDX);
}

 

It is difficult to sort out the flow of execution following exit from low power modes using breakpoints because the debugger often crashes, presumably due to issues related to debugging during/after low power mode. So instead I added global variables that simply count the number of times that LLWU_IRQHandler() and APP_WAKEUP_BUTTON_IRQ_HANDLER() are called (llwuCount and buttonIsrCount, respectively). For these tests, I did not disable PORT interrupts or clear the PORT interrupt flag in the LLWU ISR. I used SW3 button presses to wake from the low power mode. Results are tabulated below:

With the PORT interrupt set for kPORT_InterruptLogicZero

Wake from

llwuCount

buttonIsrCount

Conclusion

VLPS

0

1

Wake via AWIC (not LLWU). Button interrupt is handled (even though NVIC is disabled during low power mode)

LLS

1

2

Logic low condition is still true when LLWU ISR completes, so the GPIO interrupt is triggered after the wake actually occurs

VLLS0

1

0

Expected behavior for wake via reset. Globals are reset to zero, and then LLWU ISR increments llwuCount. GPIO interrupts are not re-enabled until next iteration of low power mode is selected

 

With the PORT interrupt set for kPORT_InterruptFallingEdge

Wake from

llwuCount

buttonIsrCount

Conclusion

VLPS

0

1

Same as above

LLS

1

1

No new edge is detected by the PORT, since the falling edge condition is not still true on exit of LLWU ISR

 

So in conclusion, I do not believe it is possible to catch an edge interrupt while in LLS and have the PORT ISR fire in response.

0 Kudos
0 Replies