How to setup MQX to respond to 2 GPIO ISRs on the same port

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

How to setup MQX to respond to 2 GPIO ISRs on the same port

Jump to solution
2,093 Views
waynetaylor
Contributor II

I recently experience a nasty bite in the butt from a misunderstanding I had regarding how MQX handles GPIO and ISR callback functions.

You see after watching this Embedded Access video, MQX RTOS Part 6: MQX Interrupts|Freescale, reading the MQXRM & MQXIOUG, and working the lab I discovered that it doesn't work if more than one pin is assigned from the same port.

Here is the problem, the tutorial shows how each pin can have its own ISR callback assigned. From InputTask.c:

void sw1_isr(void * param){

    LWGPIO_STRUCT_PTR sw = (LWGPIO_STRUCT_PTR) param;

    APPLICATION_MESSAGE * msg;

    lwgpio_int_clear_flag(sw);

    msg = _msg_alloc_system(sizeof(*msg));

    if (msg != NULL) {

        msg->HEADER.TARGET_QID =  _msgq_get_id(0, HEALTH_QUEUE);

        msg->MESSAGE_TYPE = SW1_MESSAGE;

        msg->DATA = 0;

        _msgq_send(msg);

    }

}

void sw2_isr(void * param){

    LWGPIO_STRUCT_PTR sw = (LWGPIO_STRUCT_PTR) param;

    APPLICATION_MESSAGE * msg;

    lwgpio_int_clear_flag(sw);   

    msg = _msg_alloc_system(sizeof(*msg));

    if (msg != NULL) {

        msg->HEADER.TARGET_QID =  _msgq_get_id(0, HEALTH_QUEUE);

        msg->MESSAGE_TYPE = SW2_MESSAGE;

        msg->DATA = 0;        

        _msgq_send(msg);

    }

}

void init_switch( LWGPIO_STRUCT_PTR sw, LWGPIO_PIN_ID pin, uint32_t mux, INT_ISR_FPTR sw_isr){

    lwgpio_init(sw, pin, LWGPIO_DIR_INPUT, LWGPIO_VALUE_NOCHANGE);

    lwgpio_set_functionality(sw, mux );   

    lwgpio_set_attribute( sw, LWGPIO_ATTR_PULL_UP, LWGPIO_AVAL_ENABLE);   

    lwgpio_int_init( sw, LWGPIO_INT_MODE_FALLING);   

    _int_install_isr( lwgpio_int_get_vector(sw), sw_isr, sw);   

    lwgpio_int_enable(sw, TRUE);   

    _bsp_int_init(lwgpio_int_get_vector(sw), 4, 0, TRUE);

}

 

void Input_task(uint32_t initial_data){

    init_switch( &sw1, BSP_SW1, BSP_SW1_MUX_GPIO, sw1_isr);

    init_switch( &sw2, BSP_SW2, BSP_SW2_MUX_GPIO, sw2_isr);

}

 

The previous example clearly shows how each pin can have its own ISR callback, namely sw1_isr() and sw2_isr(). But in truth, if both of these pins, BSP_SW1 & BSP_SW2 were on the same port, then only the last pin's ISR would be added into the user defined ISR call backs by _int_install_isr(). If five pins were all on the same port, 2 would replace 1, 3 would replace 2 and so forth until only ISR for pin 5 would remain.

On the Kinetis chip, the right way to make this work is to have one master ISR per port. If there are two possible sources for the IRQ, then it should read the PORTx_PCRn register for each possible pin and take action based on the ISF bit. MQX makes this easy. Just call lwgpio_int_get_flag() with the LWGPIO_STRUCT pin.

 

The master port ISR could look like the following example, but there are some things that don't quite work right. The param sent to PortxISR will always be a pointer to the last pin struct that was installed, not the pin that actually creates the IRQ. This means that clearing the IRQ must be done manually, and that param is virtually useless. The previous sw1_isr() and sw2_isr() will need to have the line that clears the ISF bit removed as it is now done manually in PortxISR(). Also, "void* param" should be removed with the new function declarations being: sw1_isr(void) and sw2_isr(void).

void PortxISR(void* param){

    if (lwgpio_int_get_flag(&sw1)){

         sw1_isr();

         lwgpio_int_clear_flag(&sw1);

    }

    if (lwgpio_int_get_flag(&sw2)){

         sw2_isr();

         lwgpio_int_clear_flag(&sw);

    }

}

I hope this save some of you the week it took me to figure out this pitfall. If it is documented somewhere in the MQX manuals, I didn't find it.

Wayne

Original Attachment has been moved to: InputTask.c.txt.zip

Tags (4)
1 Solution
999 Views
waynetaylor
Contributor II

I have included what I think is a reasonable work around for this MQX shortfall.

- Wayne

View solution in original post

0 Kudos
6 Replies
999 Views
F50SC
Contributor III

Hi Wayne

Thanks...you saved me some valuable time.

I too had already spent a couple days looking for answers in the MQX documents & found nothing.

My only clue was after reading the MK21F12.h header file & found the single interrupt index for the PORT registers.

i'm very surprised it hasn't been detected sooner by Freescale or Embedded Access.

I wonder if Freescale will bother to update the MQX Tutorials & videos now?

I only found one error in your InputTask-2c code, INT_ISR_FPTR sw_isr in init_switch function..

Other than that your solution works perfect!

Regards

Jerome

0 Kudos
999 Views
waynetaylor
Contributor II

Jerome, I think I intended to make the callbacks flexible at first but realized that there could only be one callback per port. Funny that the IAR compiler never flagged the extra, unused parameter (INT_ISR_FPTR sw_isr) for me. Good catch and I hope I save you some grief.

0 Kudos
999 Views
keno
Contributor II

Hi waynetaylor,

My thanks as well.  I encountered the same GPIO problem last week and your post quickly led me to the answer after troubleshooting it for a day.  Our workaround was to move one of the inputs to a GPIO pin on a different port.

I think in a perfect world MQX would have a main handler for each GPIO port (i.e. gpio0_isr, gpio1_isr, gpio2_isr).  When an application registers a GPIO interrupt handler MQX would store a pointer to the handler in an array for the port.  When an interrupt occurs the main handler is called which then figures out which pin caused the interrupt and calls the application's handler.

It might add some overhead to the interrupt handling, but it would take away the need to be diligent about shared GPIO interrupts and would be transparent to application developers.

0 Kudos
1,000 Views
waynetaylor
Contributor II

I have included what I think is a reasonable work around for this MQX shortfall.

- Wayne

0 Kudos
999 Views
DavidS
NXP Employee
NXP Employee

Hi Wayne,

Sorry for the confusion and we appreciate your honest and constructive feedback.

I have forwarded it to our MQX marketing and development teams.

Regards,

David

999 Views
anandask
Contributor I

On Jan 15, 2015 11:19 PM, "David E Seymour" <admin@community.freescale.com>

0 Kudos