I have a LLWU set up on PTB0/LLWU_P5 which works fine, generates the interrupt. I tried adding another one on PTE4/LLWU_P2 without any success.
My setup code is,
LLWU_PE1_WUPE2(0x03) in init_lpm.c under LPM_OPERATION_MODE_STOP
GPIOE_PDDR 0x00000000;
#define TW_WAKE_ID (GPIO_PORT_E | GPIO_PIN4)
#define TW_WAKE_MUX LWGPIO_MUX_E4_GPIO
My initialisation code is,
static void tw_isr (void *pin)
{
// lwgpio_toggle_value (&led1);
lwgpio_int_clear_flag (pin);
_lwevent_set (&app_event, PIN_EVENT_MASK);
}
static void tw_interrupt_init (void)
{
static LWGPIO_STRUCT sw;
printf("Going to init tw interrupt\n");
//PTE4 llwu p2
//************************************************************************************
/* Set the pin to input */
if (!lwgpio_init(&sw, TW_WAKE_ID, LWGPIO_DIR_INPUT, LWGPIO_VALUE_NOCHANGE))
{
printf("\nSW initialization failed.\n");
_task_block();
}
/* Set functionality to GPIO mode */
lwgpio_set_functionality(&sw, TW_WAKE_MUX);
/* Enable pull up */
lwgpio_set_attribute(&sw, LWGPIO_ATTR_PULL_UP, LWGPIO_AVAL_ENABLE);
/* Setup the pin interrupt mode */
if (!lwgpio_int_init(&sw, LWGPIO_INT_MODE_FALLING))
{
printf("Initializing SW for interrupt failed.\n");
_task_block();
}
/* Install gpio interrupt service routine */
_int_install_isr(lwgpio_int_get_vector(&sw), tw_isr, (void *) &sw);
/* Set interrupt priority and enable interrupt source in the interrupt controller */
_bsp_int_init(lwgpio_int_get_vector(&sw), 3, 0, TRUE);
/* Enable interrupt for pin */
lwgpio_int_enable(&sw, TRUE);
}
void initLowPower()
{
//configure pin interrupts
tw_interrupt_init();
_int_install_unexpected_isr();
_lpm_register_wakeup_callback(BSP_LLWU_INTERRUPT_VECTOR, BSP_LLWU_INTERRUPT_PRIORITY, NULL);
/* Install interrupt for timer wakeup */
install_timer_interrupt();
/* Create global event */
if (_lwevent_create(&app_event, 0) != MQX_OK)
{
printf("\nCreating app_event failed.\n");
_task_block();
}
if (_lpm_get_reset_source() != MQX_RESET_SOURCE_LLWU)
printf("\nNormal hardware wakeup\n");
else
printf("\nWake up by reset from LLWU\n");
}
The llwu code on the PORTB seems to work fine and is similar, not sure if there are any bsp specific changes needed for PORTE llwu.
Thanks,
Rahul
Hi Rahul
Since the location of the LLWU pins are not the same on all devices it is important to specify which part you are using - presumably a Kinetis K part.
Below is how I verify all 16 K64 LLWU interrupt (for example):
// Configure all 16 K64 LLWU pins
//
INTERRUPT_SETUP interrupt_setup; // interrupt configuration parameters
interrupt_setup.int_type = PORT_INTERRUPT; // identifier to configure port interrupt
interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON | ENABLE_PORT_MODE);
interrupt_setup.int_type = WAKEUP_INTERRUPT; // configure as wake-up interrupt
interrupt_setup.int_handler = test_irq_5;
interrupt_setup.int_port = PORTA; // the port that the interrupt input is on
interrupt_setup.int_port_bits = (PORTA_BIT4 | PORTA_BIT13);
fnConfigureInterrupt((void *)&interrupt_setup); // configure wakeup pins on this port
interrupt_setup.int_port = PORTB; // the port that the interrupt input is on
interrupt_setup.int_port_bits = PORTB_BIT0;
fnConfigureInterrupt((void *)&interrupt_setup); // configure wakeup pins on this port
interrupt_setup.int_port = PORTC; // the port that the interrupt input is on
interrupt_setup.int_port_bits = (PORTC_BIT1 | PORTC_BIT3 | PORTC_BIT4 | PORTC_BIT5 | PORTC_BIT6 | PORTC_BIT11);
fnConfigureInterrupt((void *)&interrupt_setup); // configure wakeup pins on this port
interrupt_setup.int_port = PORTD; // the port that the interrupt input is on
interrupt_setup.int_port_bits = (PORTD_BIT0 | PORTD_BIT2 | PORTD_BIT4 | PORTD_BIT6);
fnConfigureInterrupt((void *)&interrupt_setup);// configure wakeup pins on this port
interrupt_setup.int_port = PORTE; // the port that the interrupt input is on
interrupt_setup.int_port_bits = (PORTE_BIT1 | PORTE_BIT2 | PORTE_BIT4);
fnConfigureInterrupt((void *)&interrupt_setup); // configure wakeup pins on this port
fnSetLowPowerMode(LLS_MODE);
This is the LLWU method as used in the uTasker project - µTasker LLWU Support
whereby this attaches each LLWU pin to the same interrupt (they can however each have their own or share interrupts in groups).
Notice that the interrupt sense is controlled by
interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON | ENABLE_PORT_MODE);
and all pins are set to falling edge sensitive.
At the same time the control flags PULLUP_ON and ENABLE_PORT_MODE are used. The first means that the pins characteristics are set to have a pullup (this is set in its GPIO mode) so that unconnected pins are held at '1' so that the falling edge can function.
The second (ENABLE_PORT_MODE) is also important because it specifies that the pin should be set to its GPIO mode.
First I'll give two examples to explain why this is useful and then also explain why it can also be critical for the LLWU to operate correctly.
If a LLUW pin is used as a peripheral input - eg. UART0_RX (some chips share UART Rx with LLWU) I configure with interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON); [pull up is optional] so that the original peripheral function is not disturbed. When in a low leakage mode the LLWU pin function becomes active and then it will wake on a falling edge on the input.
If the pin is not used for other functions it may default to disabled or an analogue peripheral function - in this case I use interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON | ENABLE_PORT_MODE); which configures the pull-up AND sets the pin function to the GPIO mode (moving from an analogue or disabled mux setting).
A potentially important fact about using the LLWU is to ensure that the LLWU is connected because what I find is that if the ENABLE_PORT_MODE control is not used on some pins (those that are disabled by default) the LLWU also doesn't operate. In the case of analogue inputs the pull-up is not connected, which can also mean that the wakeup doesn't operate because no falling edge is possible (in my test setup).
I don't know the methods that you are using but suggest that you examine the PORTx_CRn setting used to ensure that the pin MUX is not in the disabled state. My tests show that I can either get all LLWU inputs to work or else only a select few operate, the difference being pulely in the MUX setting used!
Regards
Mark
Kinetis: µTasker Kinetis support
LLWU: µTasker LLWU Support
For the complete "out-of-the-box" Kinetis experience and faster time to market