How To: Using Interrupt Handlers in MQX with KSDK

cancel
Showing results for 
Search instead for 
Did you mean: 

How To: Using Interrupt Handlers in MQX with KSDK

No ratings

How To: Using Interrupt Handlers in MQX with KSDK

Introduction

The KSDK provides a high level API for peripheral drivers and OS functions in MQX. A key aspect of the peripheral driver implementation involves the use of interrupts. These interrupt events are handled by specific IRQ handlers in the KSDK peripheral driver. However, the standard CMSIS style IRQ hander naming cannot be used by an application running in MQX because those names are reserved. This document provides a guide to implementing the IRQ handlers provided by the KSDK in MQX.

IRQ Naming

The device startup assembly code provided in KSDK defines weak instances of the IRQHandlers for each of the interrupt vectors on the device. In bare metal applications, when using KSDK peripheral drivers these IRQHandler names are re-declared in the associated ‘fsl_xxx_irq.c’ file. This then points the NVIC to use those functions over the weak functions with the same name.

However, when using MQX this is no longer possible as the MQX kernel requires those IRQHandler names for its own interrupt handling. It is therefore necessary for the application developer to use a different name for the peripheral driver IRQ handler. The convention used in KSDK is pre-append the IRQHandler name with MQX_. For example,

/* IRQ Handler prototypes */

void MQX_SPI0_IRQHandler(void);

The function prototype above can now be installed in MQX by the application developer to handle peripheral driver interrupts. We will cover interrupt handler installation in the next section.

IRQ Handler Installation

In MQX it is required for the application to install IRQ handlers. KSDK provides a function to handle this in the OSA (Operating System Abstraction) layer. The following function allows the application developer to install the appropriate IRQ handler to the interrupt that will be triggered.

//Install IRQ handlers

OSA_InstallIntHandler(SPI0_IRQn, MQX_SPI0_IRQHandler);

The ‘OSA_InstallIntHandler’ function requires the vector table number for the interrupt in question, as well as the name of the IRQ handler that will be used in the application. Once installed, MQX will execute this handler when the related interrupt is triggered.

IRQ Priorities

Setting appropriate interrupt priorities is important in MQX applications. MQX uses 8 priority levels that are mapped to the interrupt priority levels in the Cortex-M4 core. Table 1 illustrates the mapping between MQX and hardware.

Table 1: MQX to Hardware priority mapping.

MQX Priority

BASEPRI

0

Not Allowed

1

0x20 (Priority 2 in NVIC_SetPriority)

2

0x40 (Priority 4 in NVIC_SetPriority)

3

0x60 (Priority 6 in NVIC_SetPriority)

4

0x80 (Priority 8 in NVIC_SetPriority)

5

0xA0 (Priority 10 in NVIC_SetPriority)

6

0xC0 (Priority 12 in NVIC_SetPriority)

7

0xE0 (Priority 14 in NVIC_SetPriority)

>7

0x00 (Lowest priority)

To ensure proper MQX application behavior it is recommended to adhere to the following when using NVIC_SetPriority to set interrupt priorities:

  • Priority should be an even number
  • Priority level should be greater or equal to 2 times the value of MQX_HARDWARE_INTERUPT_LEVEL_MAX

MQX_HARDWARE_INTERRUPT_LEVEL_MAX is located in the MQX_init_struct structure. In the MQX examples provided by the KSDK installation the MQX_init_struct structure is defined in ‘mqx_main.c’ as follows:

const _WEAK_SYMBOL(MQX_INITIALIZATION_STRUCT MQX_init_struct) =

/*! \endcond */

{

/* PROCESSOR_NUMBER                */  BSP_DEFAULT_PROCESSOR_NUMBER,

/* [KPSDK-2559] Workaround to make TAD happy. With new version of TAD START_OF_KERNEL_MEMORY and END_OF_KERNEL_MEMORY can be removed */

/* START_OF_KERNEL_MEMORY          */ &kernel_data_prv,

/* END_OF_KERNEL_MEMORY            */ BSP_DEFAULT_END_OF_HEAP,

/* INTERRUPT_STACK_SIZE            */ BSP_DEFAULT_INTERRUPT_STACK_SIZE,

#if MQX_CUSTOM_MAIN

/* TASK_TEMPLATE_LIST              */  NULL,

#else

/* TASK_TEMPLATE_LIST              */ MQX_template_list,

#endif /* MQX_CUSTOM_MAIN */

/* MQX_HARDWARE_INTERRUPT_LEVEL_MAX*/  BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX,

/* MAX_MSGPOOLS                    */  BSP_DEFAULT_MAX_MSGPOOLS,

/* MAX_MSGQS                       */  BSP_DEFAULT_MAX_MSGQS,

/* IO_CHANNEL                      */  BSP_DEFAULT_IO_CHANNEL,

/* IO_OPEN_MODE                    */  BSP_DEFAULT_IO_OPEN_MODE,

#if MQXCFG_PREALLOCATED_SYSTEM_STACKS

/* INTERRUPT_STACK_LOCATION        */ mqx_interrupt_stack,

#else

0,

#endif

/* START_OF_HEAP                   */  BSP_DEFAULT_START_OF_HEAP,

/* END_OF_HEAP                     */  BSP_DEFAULT_END_OF_HEAP,

};

The MQX_HARDWARE_INTERUPT_LEVEL_MAX constant is defined as BSP_DEFAULT_ MQX_HARDWARE_INTERUPT_LEVEL_MAX in this MQX_init_struct structure. Where BSP_DEFAULT_ MQX_HARDWARE_INTERUPT_LEVEL_MAX is defined in ‘bsp_config.h’ as:

#ifndef BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX

    #define BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX        (2L)

#endif

For the interrupt we have shown examples for above, the interrupt priority would be set as such:

//Set IRQ priorities

NVIC_SetPriority(SPI0_IRQn, 6U);

Priority 6 is greater than 2 times the value set in the MQX_init_struct by BSP_DEFAULT_ MQX_HARDWARE_INTERUPT_LEVEL_MAX.

Example

Included with this document is a source file called ‘hello.c’. This file is a direct replacement for the ‘hello.c’ source file in the ‘hello’ example provided by the KSDK installation of MQX. The project can be located in the following directories (based on default installation settings):

  • Windows
    • C:\Freescale\KSDK_1.1.0\rtos\mqx\mqx\examples\hello
  • Linux
    • ~/Freescale/KSDK_1.1.0/rtos/mqx/mqx/examples/hello

All that is required to run the new demo is to replace the ‘hello.c’ located in the directory above with the ‘hello.c’ included with document and a rebuild of the project.

The concepts we have touched in this document are implemented in the new ‘hello.c’. Interrupt handler prototypes are declared near the top of the file, and the functions are defined at the end of the file. The OSA layer of KSDK is used to install interrupt handlers in the ‘dspi_task’ function. In addition, the ‘NVIC_SetPriority’ function is also used in ‘dspi_task’ to properly configure the interrupt priorities.

The new ‘hello.c’ will work in IAR EWARM, Keil MDK-ARM, Kinetis Design Studio, Atollic TrueSTUDIO, and with command line ARM GCC tools. No changes are made to the serial connection configuration.

Successful completion of the example should show the following in the terminal window.

Hello_dspi_loopback_success.PNG.png

Figure 1: Example of successful execution.

NOTE: The demo uses the DSPI_DRV_EdmaMaster driver. Therefore, it is necessary to have a Kinetis device that supports this driver. The new source code was tested on FRDM-K64F. To successfully complete the DSPI eDMA loopback pins J2-8 and J2-10 need to be connected together on the FRDM-K64F.

Conclusion

This document should serve to help MQX application developers configure their code to make effective use of the interrupt driven KSDK peripheral drivers.

Attachments
Comments

Hi,

Is there more example of configuring GPIO ports interrupt?

Sorry, i dont think that helps. I am trying to do it on MQX, so it would be slightly different and also tried to the same as this one before. It didnt work.

Hi Yaran,

I have a KDS+KSDK baremetal example working on the frdm-k22f I can post someplace and will try to generate MQX equivalent.

Regards,

David

Hello Martyn,

Thank you for putting this together.

The description of the process is excellent however the attached code raised more questions for me than it answers :smileyconfused:

I am trying to setup multiple UARTS such that were receiving data on one UART, transforming it and sending it back out another UART (think of a multi-port protocol converter, or a router)

When looking at the sample code I am finding it difficult to understand which parts are 'essential' for 'my' ISR handlers and which are specifics to _this_ SPI+DMA implementation.

Specifically it is not clear to me -

* how to determine _which_ MQX_xxx_IRQHander() functions need to be implemented for UARTS

* and why do they simply call the the xxx_DRV_IRQHandler() 

* what do the EDMA_DRV_IRQHandler() and EDMA_DRV_ErrorIRQHandler() actually do? Where are the implemented?

* which is the actual 'custom handler code' that is ultimately invoked by the ISR (ie. the bit of code that, in my case, would be receiving the data, transforming it, and arranging for another ISR to transmit is out again - the whole point of installing custom ISRs). :smileyconfused:

Any recommendations on how to approach this would be much appreciated.

(A sample project using uarts would be 'fantastic! :smileywink:

Thank you again for your efforts.

Regards,

Ivan Vernot

//realtimedesigns.com.au

Hello Ivan:

The guide in the next link may help you understand better:

Interrupt handling with KSDK and Kinetis Design Studio

Regards!

Jorge Gonzalez

Hello David,

I'm also looking for an example of how to work with GPIO interrupts (e.g. button press) within MQX. Do you guys now have a resource we can refer to?

Hi Farhan,

I have example of using the FRDM-K64F Freedom board with a GPIO configured interrupt.

The PTC6 GPIO is connected to the SW2 on the board.

The ISR will clear interrupt and toggle the Green LED each time pressed.

Need to find location I can post and link this post to it.

EDITed:

I added the mqx hello world modified example code above under original post with following name:

hello_frdmk64f_gpio_isr_mqx.c.zip

Regards,

David

Version history
Revision #:
1 of 1
Last update:
‎03-09-2015 09:45 AM
Updated by: