Maclain Lobdell

How To: use Kinetis SDK drivers within MQX apps - handling interrupts

Discussion created by Maclain Lobdell Employee on Aug 25, 2014

Hi,

I am creating an app for MQX RTOS that is built on top of the Kinetis SDK.  For info on this new version of MQX see post Beta version of MQX RTOS for Kinetis SDK - Now Available

I originally made a mistake that drove me nuts for a few hours.  Here is the solution. 

 

When I wanted to use the low power timer, I copied the code from the KSDK lptmr_demo example into my MQX application.

 

This included the interrupt callback function that I copied straight from the KSDK lptmr_demo example. 

 

void lptmr_isr_callback(void)

{

    gLPTMR_counter++;

    printf("%d ",gLPTMR_counter);

}

 

MQX handles interrupts differently than KSDK bare-metal examples, so I changed the installation of the interrupt to the MQX way.  Basically, MQX funnels most interrupts to a single short ISR to let the RTOS know an interrupt is being handled, then calls the user ISR.   

 

/* Specify the callback function when a LPTMR interrupt occurs */

//    LPTMR_DRV_InstallCallback(LPTMR_INSTANCE,lptmr_isr_callback);

   _int_install_isr(LPTimer_IRQn, lptmr_isr_callback,  0);

 

So I installed the callback function as the ISR. 


When I ran my app, the result on the terminal was:

*** UNHANDLED INTERRUPT ***

Vector #: 0x4a

 

The problem was that the callback function is not the complete ISR.  Non-MQX apps for KSDK use a separate ISR within the low power timer driver (and other drivers) that first clear the interrupt flag and then calls the user callback.  So by installing the callback function as the ISR, I was missing the critical step to clear the interrupt. 


I added the line to clear the interrupt and now it works great.

 

void lptmr_isr_callback(void)

{

    gLPTMR_counter++;

    printf("%d ",gLPTMR_counter);

 

       /* Clear interrupt flag */

LPTMR_HAL_ClearIntFlag(LPTMR0_BASE);

 

}

 

Update with Alternative Solution

A colleague pointed out that you can still use the Kinetis SDK ISR and callback function unmodified.  Just install the callback function to the driver (same as Kinetis SDK example) and then install the driver's ISR, which is LPTMR_DRV_IRQHandler.

 

So the callback looks like this:

void lptmr_isr_callback(void)

{

    gLPTMR_counter++;

    printf("%d ",gLPTMR_counter);

}

 

And the initialization looks like this:

    /* Specify the callback function when a LPTMR interrupt occurs */

    LPTMR_DRV_InstallCallback(LPTMR_INSTANCE,lptmr_isr_callback);

 

    /* Install interrupt to MQX RTOS for Kinetis SDK v1.0 BETA */

       _int_install_isr(LPTimer_IRQn, LPTMR_DRV_IRQHandler,  0);

 

 

For reference, here is the LPTMR_DRV_IRQHandler, which clears the interrupt before calling the callback.


void LPTMR_DRV_IRQHandler(uint32_t instance)

{

    assert(instance < HW_LPTMR_INSTANCE_COUNT);

 

    uint32_t baseAddr = g_lptmrBaseAddr[instance];

 

    /* Clear interrupt flag */

    LPTMR_HAL_ClearIntFlag(baseAddr);

 

    if (lptmr_state_ptrs[instance])

    {

        if (lptmr_state_ptrs[instance]->userCallbackFunc)

        {

            /* Execute user-defined callback function. */

            (*(lptmr_state_ptrs[instance]->userCallbackFunc))();

        }

    }

}


 

If you have any tips like this please share!

Mac L

Outcomes