MQX GPIO interrupt

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

MQX GPIO interrupt

5,889 Views
doublev724
Contributor I

Hi

 

I want to assign an interrupt handler to a button but this handler cannot be invoked when I pressed the button.

The following are the main code and can someone take a look and give some advice? I use MCF52235evb

 

//define the pin list button1

FILE_PTR btn_file;

 

 #define BTN1
    static const GPIO_PIN_STRUCT btn1[] = {
       BSP_BUTTON1 | GPIO_PIN_IRQ,
       GPIO_LIST_END
    };

 

//open file

btn_file = fopen("gpio:read", (char_ptr) &btn1)

 

//enable interrupt, I am not sure if it's necessary

ioctl(btn_file, GPIO_IOCTL_ENABLE_IRQ, NULL)

 

//register callback function

ioctl(btn_file, GPIO_IOCTL_SET_IRQ_FUNCTION, (char_ptr)&btn1_callback)

 

I really cannot find out what's wrong with this code.

 

Thanks a lot!!!!!!

Tags (2)
0 Kudos
Reply
12 Replies

1,947 Views
JuroV
NXP Employee
NXP Employee

Why dont you check what do ioctl's return?

0 Kudos
Reply

1,947 Views
w2vy
Contributor V

On page 43 of MQXIOUG.pdf (rev 5 06/2010) is says:

 

GPIO_IOCTL_SET_IRQ_FUNCTION Sets the callback function which is invoked for any

IRQ event coming from any file pin.

 

GPIO_IOCTL_ENABLE_IRQ Enables IRQ functionality for all IRQ pins in the file.

 

GPIO_IOCTL_DISABLE_IRQ Disables IRQ functionality for all IRQ pins in the file.

 

That seems inconsistent; SET_IRQ_FUNCTION is Global (Any Pin File), ENABLE_IRQ is file specific.

 

I only need one IRQ at the moment, but I am curious...

 

tom

0 Kudos
Reply

1,947 Views
DavidS
NXP Employee
NXP Employee

Hi All,

We ran into this issue with a developer of ours and did find we have an errata for the GPIO interrupt capability.

I've just verified the solution with the FSLMQX development team and have attached the file (io_pgio_mcf5225.c).  Please copy this in the following path:

~Freescale MQX 3.6\mqx\source\io\gpio\mcf5225\io_gpio_mcf5225.c

If you want to see the fix it is in the function gpio_cpu_open().

#if 0  //DES 1=original code from FSLMQX3.6
   /* check which irq pin to be opened and prepare interrupt service routine */
    for (i = 1; i < 8; i++) {
        if (i & 0x01)
            continue;
        if ((dev_data_ptr->irqp_map.reg.portnq | dev_data_ptr->irqn_map.reg.portnq) & (1 << i)) {
            if (MQX_init_struct.MQX_HARDWARE_INTERRUPT_LEVEL_MAX < i)
                return IO_ERROR; /* hardware level must be higher than interrupt level */
            if (NULL == _int_install_isr(MCF5225_INT_EPORT0_EPF1 - 1 + i, gpio_eport_irq, NULL))
                return IO_ERROR; /* could not install interrupt routine */
        }
    }
#else  //DES fix for GPIO interrupt issue of FSLMQX3.6 initiail release
    /* check which irq pin to be opened and prepare interrupt service routine */

    for (i = 1; i < 8; i++) {

        if ((i & 0x01) == 0)

            continue;

        if ((dev_data_ptr->irqp_map.reg.portnq | dev_data_ptr->irqn_map.reg.portnq) & (1 << i)) {

            if (MQX_init_struct.MQX_HARDWARE_INTERRUPT_LEVEL_MAX < i)

                return IO_ERROR; /* hardware level must be higher than interrupt level */

            if (NULL == _int_install_isr(MCF5225_INT_EPORT0_EPF1 - 1 + i, gpio_eport_irq, NULL))

                return IO_ERROR; /* could not install interrupt routine */

            /* this is only to enable the interrupt source, level and sublevel values are hardwired */               

            _mcf5225_int_init(MCF5225_INT_EPORT0_EPF1 - 1 + i, i, BSP_EPORT_EPFX_INT_SUBLEVEL_MIDPOINT, TRUE);

        }

    }
   
#endif

 

 

Regards,

David

0 Kudos
Reply

1,947 Views
anthony_huereca
NXP Employee
NXP Employee

I'd also like to note that this issue only affects MQX 3.6 and there will be an official patch out shortly to correct this. It should only affect MCF52XXX devices.

0 Kudos
Reply

1,947 Views
w2vy
Contributor V

Upon first glance it appears that the only change is:

 

if ((i & 0x01) == 0) continue;

 

Why skip all the even pins?

The global pin configuration disables any pins that are not supported, so why do we need this (strange) check in here?

 

irqp_map/irqn_map gets populated in _io_gpio_open and enforces gpio_global_pin_map so that test seems redundent and cryptic.

 

tom

0 Kudos
Reply

1,947 Views
w2vy
Contributor V

Ok Here is what I am doing:

MQX_FILE_PTR irq_fd;const GPIO_PIN_STRUCT pins_irq[] = {   GPIO_SYNC | GPIO_PIN_IRQ_FALLING,   GPIO_LIST_END};void fpga_sync_irq(void) {   fpga_sync++;}init function:irq_fd = fopen("gpio:input", (char *)&pins_irq);err = ioctl(irq_fd, GPIO_IOCTL_SET_IRQ_FUNCTION, (char_ptr)&fpga_sync_irq);err = ioctl(irq_fd, GPIO_IOCTL_ENABLE_IRQ, NULL);

 

 

I can read the NQ1 (IRQ1) pin and see it change with the input, but not interrupt is generated.

 

ie. gpio_eport_irq() is never called

 

I do see it installing the handler: (i = 1)

 

if (NULL == _int_install_isr(MCF5225_INT_EPORT0_EPF1 - 1 + i, gpio_eport_irq, NULL))

 

tom

0 Kudos
Reply

1,947 Views
anthony_huereca
NXP Employee
NXP Employee

Attached is a sample IRQ program I wrote for the MCF52259Demo board.

 

Make sure the GPIO_SYNC pin you're using is an IRQ pin for the device you are using, as not all GPIO pins are IRQ enabled.

 

Also there are two new lines in the fixed code for the MCF52259.

 

  _mcf5225_int_init(MCF5225_INT_EPORT0_EPF1 - 1 + i, i, BSP_EPORT_EPFX_INT_SUBLEVEL_MIDPOINT, TRUE);

is also new. That was part of the bug, as the IRQ wasn't being unmasked in the interrupt controller module.

 

Hope that helps!

 

-Anthony

 

 

0 Kudos
Reply

1,947 Views
w2vy
Contributor V

That fixed it!

 

in mqx 3.6/mqx/source/io/gpio/mcf5225/io_gpio_mcf5225.c around line 289 I added

 

_mcf52xx_int_init(MCF5225_INT_EPORT0_EPF1 - 1 + i, i, BSP_EPORT_EPFX_INT_SUBLEVEL_MIDPOINT, TRUE);

 

See below

 

    /* check which irq pin to be opened and prepare interrupt service routine */    for (i = 1; i < 8; i++) {        //if (i & 0x01)        //    continue;        if ((dev_data_ptr->irqp_map.reg.portnq | dev_data_ptr->irqn_map.reg.portnq) & (1 << i)) {            if (MQX_init_struct.MQX_HARDWARE_INTERRUPT_LEVEL_MAX < i)                return IO_ERROR; /* hardware level must be higher than interrupt level */            if (NULL == _int_install_isr(MCF5225_INT_EPORT0_EPF1 - 1 + i, gpio_eport_irq, NULL))                return IO_ERROR; /* could not install interrupt routine */            _mcf52xx_int_init(MCF5225_INT_EPORT0_EPF1 - 1 + i, i, BSP_EPORT_EPFX_INT_SUBLEVEL_MIDPOINT, TRUE);        }    }

 

Thanks!

0 Kudos
Reply

1,947 Views
admin
Specialist II

Hello. I am having some troubles trying to configure GPIO_PORT_TA  (PIN0, PIN1 and PIN3) as input with interrupts.

 

the source code I have written is the following:

 

#define SYSTEM_INPUT0 (GPIO_PORT_TA | GPIO_PIN3 | GPIO_PIN_IRQ_FALLING)
#define SYSTEM_INPUT1 (GPIO_PORT_TA | GPIO_PIN1 | GPIO_PIN_IRQ_FALLING)
#define SYSTEM_INPUT2 (GPIO_PORT_TA | GPIO_PIN0 | GPIO_PIN_IRQ_FALLING)


const uint_32 SystemInputPort[] = {  SYSTEM_INPUT0,
                SYSTEM_INPUT1,
                SYSTEM_INPUT2,
                GPIO_LIST_END};

 

static FILE_PTR SystemInputPortFile = NULL;

 

void SystemInputInterrupt(pointer)
{
  printf("\nSystem Input Interrupt generated\n");
}

 

void SystemInputInit(void)
{
    /* Open and set port TA as input to check SYSTEM INPUTS status */
   SystemInputPortFile = fopen("gpio:read", (char_ptr) &SystemInputPort); 
   if(SystemInputPortFile!= NULL)
    {
       printf("\r\nSystem Input Port init OK\r\n");
  
       ioctl(SystemInputPortFile, GPIO_IOCTL_SET_IRQ_FUNCTION, (pointer)&SystemInputInterrupt);
       ioctl(SystemInputPortFile, GPIO_IOCTL_ENABLE_IRQ, NULL);
  
    }
 else
 {
    printf("\r\nSystem Input Port init ERROR\r\n");
 }
 
}

The fopen function call returns NULL.

 

When I delete the GPIO_PIN_IRQ_FALLING configuration from all the SYSTEM_INPUT definitions as following:

 

#define SYSTEM_INPUT0 (GPIO_PORT_TA | GPIO_PIN3)
#define SYSTEM_INPUT1 (GPIO_PORT_TA | GPIO_PIN1)
#define SYSTEM_INPUT2 (GPIO_PORT_TA | GPIO_PIN0)

 

The fopen function call returns a non-NULL result and therefore everything seems to work. But I need to configure those inputs with Interrupt enabled

 

Can anyone tell what I am doing wrong or if it is not possible to configure PIN0, PIN1 and PIN3 of GPIO_PORT_TA  as inputs with interrupts enabled?

 

Any help or advice will be very appreciated. Thank you so much and my best regards.

 

 

0 Kudos
Reply

1,947 Views
MuratGunal
Contributor II

Hello everyone,
I tried many examples on my own board with MCF52259. I am using MQX3.7 and CW10.1. I added;
I am also using USB Host bootloader with the design examle of AN4368
So I am using with;
#define MQX_ROM_VECTORS 0 //DES 1=ROM, 0=RAM vector table...used with bootloaders
in "user_config.h"
and I am using the lines
{
interrupts (RX) : ORIGIN = 0x00010000, LENGTH = 0x00000400
cfmprotrom (RX) : ORIGIN = 0x00010400, LENGTH = 0x0000010
code (RX) : ORIGIN = 0x00010410, LENGTH = 0x0006FBF0
}
in "intflash.lcf" file.
It is OK up to here.

for NQ7 usage I added
#define BSP_SW3     (GPIO_PORT_NQ | GPIO_PIN7)
line to the "m52259demo.h" file.
and I used the codes below;
The program gives me "Failed input" error when try to open "input_port" with Pin7 interrupt. But it is OK when I use NQPin1 and NQPin5.

Is anyone konws that how to use NQ7 pin interrupt? Or there a problem with MQX3.7.
I also tried _int_install_kernel_isr(MCF5225_INT_EPORT0_EPF7, new_irq7or1_isr); but it also not worked anymore.
Please help..


/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved                      
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: gpio.c$
* $Version : 3.6.25.0$
* $Date    : Jun-4-2010$
*
* Comments:
*
*   This file contains the source for the gpio example program.
*
*END************************************************************************/

#include <mqx.h>
#include <bsp.h>
#include <io_gpio.h>

#if ! BSPCFG_ENABLE_IO_SUBSYSTEM
#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined non-zero in user_config.h. Please recompile BSP with this option.
#endif

#if ! BSPCFG_ENABLE_GPIODEV
#error This application requires BSPCFG_ENABLE_GPIODEV defined non-zero in user_config.h. Please recompile BSP with this option.
#endif


/* Task IDs */
#define MAIN_TASK 5

/* Function prototypes */
extern void main_task(uint_32);
void irq_callback(pointer);

int i;
static FILE_PTR input_port=NULL, output_port=NULL;


const TASK_TEMPLATE_STRUCT  MQX_template_list[] =
{
  /* Task Index,   Function,  Stack,  Priority, Name,      Attributes,          Param, Time Slice */
   { MAIN_TASK,    main_task, 1500,    5,        "service", MQX_AUTO_START_TASK, 0,     0 },
   { 0 }
};

/* Example IRQ callback. Place breakpoint in function to determine if gets called */
static void irq_callback(pointer)
{
   i++;
}

 

/*TASK*-----------------------------------------------------
**
** Task Name    : main_task
** Comments     :
** This task performs various open - close operation on
** several sets of pins. The purpose of this demo is to
** explain and demonstrate the use of "pin files" as the output
** of GPIO fopen command. The demonstration is focused mainly
** on debugging and realising what we are performing on which
** set of pins.
** At the end of this task, neverending loop runs and reads
** status of pin connected to SWITCH_1 and the same value writes
** on output pin connected to LED D10.
*END*-----------------------------------------------------*/


void main_task (uint_32 initial_data)
{
 //Create GPIO structures for input and output
 const uint_32 output_set[] = {
   (BSP_LED1 | GPIO_PIN_STATUS_0),
   (BSP_LED2 | GPIO_PIN_STATUS_0),
   (BSP_LED3 | GPIO_PIN_STATUS_0),
   (BSP_LED4 | GPIO_PIN_STATUS_0),
  GPIO_LIST_END
 };
 
 const uint_32 input_set[] = {
  (BSP_SW1 | GPIO_PIN_IRQ_FALLING),
  (BSP_SW3 | GPIO_PIN_IRQ_FALLING),
  //(BSP_SW2 | GPIO_PIN_IRQ_FALLING),
  GPIO_LIST_END
 };

 /* Open and set port pins as output to drive LEDs (LED10 - LED13) */
 output_port = fopen("gpio:write", (char_ptr) &output_set);

 /* Open and set port pins as input to read value from switches */
 input_port = fopen("gpio:read", (char_ptr) &input_set);

 if(input_port==NULL)
  printf("Failed input\n");
 if(output_port==NULL)
  printf("Failed output\n");
 
 if (output_port)
  ioctl(output_port, GPIO_IOCTL_WRITE_LOG0, NULL); 
 
 
 /* Configure input pins as interrupts */
 ioctl(input_port, GPIO_IOCTL_SET_IRQ_FUNCTION, (pointer) &irq_callback);
 ioctl(input_port, GPIO_IOCTL_ENABLE_IRQ, NULL);

   /* It is not easy to generalize switch: every board has its own switch names */
   printf("Use SWITCH on board to switch LED on or off\n");
   while (TRUE)
   {
       /* read pin/signal status to pin list */
       if (IO_OK != ioctl(input_port, GPIO_IOCTL_READ, (char_ptr) &input_set))
       {
           printf("Reading pin status from file3 to pins4 list failed.\n");
          _mqx_exit(-1);
       }
       /* test first's pin of file binary value */      
       if (input_set[1] & GPIO_PIN_STATUS)
       {
           printf("LED OFF.\n");
           /* clear pin to 0 (fast) */
           if (IO_OK != ioctl(output_port, GPIO_IOCTL_WRITE_LOG0, NULL))
           {
               printf("Clearing pins2 to log 0 failed.\n");
              _mqx_exit(-1);
           }
       }
       else
       {
           printf("LED ON.\n");
           /* set pin to 1 (fast) */
           if (IO_OK != ioctl(output_port, GPIO_IOCTL_WRITE_LOG1, NULL))
           {
               printf("Setting pins2 to log 1 failed.\n");
              _mqx_exit(-1);
           }
       }
       _time_delay(100);
       printf("%d\n",i);
   }
    _mqx_exit(-1);

/* EOF */

 

0 Kudos
Reply

1,947 Views
MuratGunal
Contributor II

Hello everyone again,

I have updated from MQX3.7 to MQX3.8 which release notes for MQX3.8 says that some IRQ functions fixed for MCF522xx series. But it did not worked at all. 

Still gives me "Failed input" when I try to open GPIO interrupt. 

I also tried the following code to open interrupt for NQ7 pin. It worked!!!,  but in this case, after some seconds the microcontroller stops.

Please help me about how to use NQ7 irq pin

 

 

 

 


 

void ExternalIntOpen(void){
_mqx_uint result;
VMCF5225_STRUCT_PTR mcf5225_ptr;
// Get the register structure based on IPSBAR
mcf5225_ptr = _PSP_GET_IPSBAR();
// Get the base of GPIO and EPORT registers
mcf5225_gpio_ptr = &mcf5225_ptr->GPIO;
mcf5225_eport_ptr = &mcf5225_ptr->EPORT[0];
// Initialize pins
mcf5225_gpio_ptr->PNQPAR = 0; 
mcf5225_gpio_ptr->PNQPAR |= 0x4000; // set  for primary function (IRQ)
// Set IRQ7 to detect rising edges
mcf5225_eport_ptr->EPPAR = MCF522XX_EPORT_EPPAR_EPPA7_RISING;
// Enable IRQ7 Interrupt
mcf5225_eport_ptr->EPIER = MCF522XX_EPORT_EPIER_EPIE7;
// Initialize IRQ7 ISR and backup the previous isr pointer
isr_ptr = _mem_alloc_zero(sizeof(IO_ISR_STRUCT));
isr_ptr->OLD_ISR_DATA = _int_get_isr_data(MCF5225_INT_EPORT0_EPF7);
isr_ptr->OLD_ISR = _int_get_isr(MCF5225_INT_EPORT0_EPF7);
_int_install_isr(MCF5225_INT_EPORT0_EPF7, intIOIsr, isr_ptr);
// Initialize IRQ7
result = _mcf52xx_int_init(MCF5225_INT_EPORT0_EPF7, 1, 1, TRUE);
if (result != MQX_OK) {
// On error, free all resources
_int_install_isr(MCF5225_INT_EPORT0_EPF7, isr_ptr->OLD_ISR,
isr_ptr->OLD_ISR_DATA);
if (isr_ptr != NULL)
_mem_free(isr_ptr);
}
}


0 Kudos
Reply

1,947 Views
ipa
Contributor III
Hi, GPIO pins cannot generate interrupts, with some exceptions. Check the electrical diagram of your board and if the button is not physically linked to some IRQx pins then you must think to another solution. Another question: did you configured the port/pin to be used as GPIO? the interrupt controller? the interrupt vector was installed? Regards, Ipa
0 Kudos
Reply