GPIO Interrupt does not enter the Interrupt Serivce Routine (ISR)

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

GPIO Interrupt does not enter the Interrupt Serivce Routine (ISR)

Jump to solution
1,560 Views
abdelrahmanzaye
Contributor III

Hello everybody,

 

I was testing the GPIO Interrupt using the supported SDK for iMX6q and faced a problem that the GPIO Interrupt does not enter the Interrupt Serivce Routine (ISR).

I tried different GPIO banks and pins which made me trying different IRQs like IMX_INT_GPIO1_INT3 and IMX_INT_GPIO1_INT15_0 for GPIO1. I even tired Interrupts on the Low level and on the Negative edge.

 

What happens is that the interrupt status changes from 0 to 1 when the interrupt occurs but It never enters the ISR.

I removed the commands for registering the IRQ and enabling the Interrupt and the same thing happened.

 

I tested the interrupt in the PWM driver to see if there is a general problem in the interrupt but it worked well which I was sure by putting a printf in its ISR.

I attached the code If anyone can help to debug.

 

Thanks in advance.

Original Attachment has been moved to: gpio_int_test.c.zip

0 Kudos
1 Solution
976 Views
abdelrahmanzaye
Contributor III

Hello igorpadykov

I found where the error was, there is a bug in the SDK concerning the "gpio_set_interrupt_mask()" function in the source file "gpio.c" in the directory "…\iMX6_Platform_SDK\sdk\drivers\gpio\src".

the bugged function is as follows:

------------------------------------------------------

int32_t gpio_set_interrupt_mask(int32_t port, int32_t pin, int32_t mask)

{

    if ((port > HW_GPIO_INSTANCE_COUNT) || (port < 1))

    {

        debug_printf("Invalid GPIO Instance GPIO_PORT%d parameter. GPIO_PORT1~GPIO_PORT%d is allowed.\n",

        port, HW_GPIO_INSTANCE_COUNT);

        return INVALID_PARAMETER;

    }

    if ((pin > 31) || (pin < 0))

    {

        debug_printf("Invalid GPIO Pin %d parameter. Pin 0~31 is allowed.\n", pin);

        return INVALID_PARAMETER;

    }

    uint32_t value = HW_GPIO_IMR_RD(port);

    if (mask == GPIO_IMR_MASKED)  <<<< (2) also the if conditions are swapped

        value &= ~(1 << pin);

    else

        value |= 1 << pin;

    HW_GPIO_GDIR_WR(port, value);  <<<< (1) Here is the main bug; it writes to the register GDIR instead of IMR

    return 0; //SUCCESS;

}

And the corrected function should be as follows:

-------------------------------------------------------------------

int32_t gpio_set_interrupt_mask(int32_t port, int32_t pin, int32_t mask)

{

    if ((port > HW_GPIO_INSTANCE_COUNT) || (port < 1))

    {

        debug_printf("Invalid GPIO Instance GPIO_PORT%d parameter. GPIO_PORT1~GPIO_PORT%d is allowed.\n",

        port, HW_GPIO_INSTANCE_COUNT);

        return INVALID_PARAMETER;

    }

    if ((pin > 31) || (pin < 0))

    {

        debug_printf("Invalid GPIO Pin %d parameter. Pin 0~31 is allowed.\n", pin);

        return INVALID_PARAMETER;

    }

    uint32_t value = HW_GPIO_IMR_RD(port);

    if (mask == GPIO_IMR_MASKED)

         value |= 1 << pin;

    else

    value &= ~(1 << pin);

    HW_GPIO_IMR_WR(port, value);

   

    return 0; //SUCCESS;

}

Regards,

Abdelrahman

View solution in original post

0 Kudos
6 Replies
975 Views
igorpadykov
NXP Employee
NXP Employee

Hi Abdelrahman

please look at attached example based on SDK, it uses

Vol-Up,Dn buttons on i.MX6Q SDP board.

Best regards

igor

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

-----------------------------------------------------------------------------------------------------------------------

0 Kudos
975 Views
abdelrahmanzaye
Contributor III

Hi igorpadykov,

Thanks for your reply and the attachment.

I already saw that example and made my testing code based on it, but the

same problem occurs.

What I noticed is that function in the example, setup_interrupts_in_RAM();

which is not defined in the interrupt.c in the supported SDK v1.1,

So I think vectors.S may take its place in the SDK.

I already tried to add this function in interrupt.c in the SDK, then called

it in the test but the same problem occurs.

Do you know if anything can help in this case ?

Thanks in advance.

Regards,

Abdelrahman

0 Kudos
976 Views
igorpadykov
NXP Employee
NXP Employee

Hi Abdelrahman

I think you can debug it, using good test and not good, executing

both step by step.

Best regards

igor

0 Kudos
976 Views
abdelrahmanzaye
Contributor III

Dear Igor,

I also have seen this discussion,

https://community.freescale.com/thread/319294

what's your opinion about this answer ? :

{

For default, the platform SDK code doesn't support interrupt, when

interrupt happens, it will goto dead loop.

To support interrupt, you need modify the file "src\init\vectors.S", add

the interrupt serveice function:

The original code is as followed, it means when interrupt happens, it will

just do dead loop:

IRQ_Handler:

B IRQ_Handler

You can change it to:

IRQ_Handler:

bl Do_Irq

You can inplement the Do_Irq() fucntion in your C code to handle your

interrupts.

}

The problem is that I didn't find this line in "vectors.S"

IRQ_Handler:

B IRQ_Handler

also I didn't understand how to implement the Do_Irq() fucntion in my C

code.

Regards,

Abdelrahman

On Tue, Sep 8, 2015 at 2:18 PM, igorpadykov <admin@community.freescale.com>

0 Kudos
976 Views
igorpadykov
NXP Employee
NXP Employee

Hi Abdelrahman

in my copy web SDK rev.2 I found:

file : vectors.S

.Lirq_addr:     .word     IRQ_HDLR

file interrupt.c:

void IRQ_HDLR(void) {...}

One can look at iMX6_Firmware_Guide.pdf in doc folder

sect.4.4.12 GIC test code

Best regards

igor

0 Kudos
977 Views
abdelrahmanzaye
Contributor III

Hello igorpadykov

I found where the error was, there is a bug in the SDK concerning the "gpio_set_interrupt_mask()" function in the source file "gpio.c" in the directory "…\iMX6_Platform_SDK\sdk\drivers\gpio\src".

the bugged function is as follows:

------------------------------------------------------

int32_t gpio_set_interrupt_mask(int32_t port, int32_t pin, int32_t mask)

{

    if ((port > HW_GPIO_INSTANCE_COUNT) || (port < 1))

    {

        debug_printf("Invalid GPIO Instance GPIO_PORT%d parameter. GPIO_PORT1~GPIO_PORT%d is allowed.\n",

        port, HW_GPIO_INSTANCE_COUNT);

        return INVALID_PARAMETER;

    }

    if ((pin > 31) || (pin < 0))

    {

        debug_printf("Invalid GPIO Pin %d parameter. Pin 0~31 is allowed.\n", pin);

        return INVALID_PARAMETER;

    }

    uint32_t value = HW_GPIO_IMR_RD(port);

    if (mask == GPIO_IMR_MASKED)  <<<< (2) also the if conditions are swapped

        value &= ~(1 << pin);

    else

        value |= 1 << pin;

    HW_GPIO_GDIR_WR(port, value);  <<<< (1) Here is the main bug; it writes to the register GDIR instead of IMR

    return 0; //SUCCESS;

}

And the corrected function should be as follows:

-------------------------------------------------------------------

int32_t gpio_set_interrupt_mask(int32_t port, int32_t pin, int32_t mask)

{

    if ((port > HW_GPIO_INSTANCE_COUNT) || (port < 1))

    {

        debug_printf("Invalid GPIO Instance GPIO_PORT%d parameter. GPIO_PORT1~GPIO_PORT%d is allowed.\n",

        port, HW_GPIO_INSTANCE_COUNT);

        return INVALID_PARAMETER;

    }

    if ((pin > 31) || (pin < 0))

    {

        debug_printf("Invalid GPIO Pin %d parameter. Pin 0~31 is allowed.\n", pin);

        return INVALID_PARAMETER;

    }

    uint32_t value = HW_GPIO_IMR_RD(port);

    if (mask == GPIO_IMR_MASKED)

         value |= 1 << pin;

    else

    value &= ~(1 << pin);

    HW_GPIO_IMR_WR(port, value);

   

    return 0; //SUCCESS;

}

Regards,

Abdelrahman

0 Kudos