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
Solved! Go to Solution.
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
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!
-----------------------------------------------------------------------------------------------------------------------
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
Hi Abdelrahman
I think you can debug it, using good test and not good, executing
both step by step.
Best regards
igor
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>
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
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