GPIO interrupt happens twice per one event

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

GPIO interrupt happens twice per one event

2,103 Views
isaotakashima
Contributor IV

I'm writing the GPIO interrupt handler for K60_100 using KSDK 1.3.0.

I also refer gpio_example project in the \KSDK_1.3.0\examples\twrk60d100m\driver_examples\gpio\iar.

To reduce execution time of GPIO interrupt handler, I modified the BOARD_SW_IRQ_HANDLER() as below.

void BOARD_SW_IRQ_HANDLER(void)

{

    isButtonPress = true;

    // Toggle LED1.

    GPIOA_PTOR = (1 << 11);

    PORTA_ISFR = PORTA_ISFR;

}

 

After that GPIO interrupt occur twice even if press switch one time.

Before modification, GPIO interrupt occur once.

In addition, after add dummy() routine as below, GPIO interrupt occur once.

void dummy(void)

{

}

void BOARD_SW_IRQ_HANDLER(void)

{

    dummy();

    isButtonPress = true;

    // Toggle LED1.

    GPIOA_PTOR = (1 << 11);

    PORTA_ISFR = PORTA_ISFR;

}

 

Please advise to fix this issue as soon as possible.

 

Best regards,

Takashima

Labels (1)
Tags (1)
8 Replies

1,490 Views
pavel_krenek
NXP Employee
NXP Employee

Hi Takashima,

if the dummy routine is inside the interrupt handler routine add some time for the pin state  "regeneration". That should be the reason. Could you share the settings of Pin Control Register and what interrupt configuration IRQC is selected ?

Best regards,

Pavel

1,490 Views
isaotakashima
Contributor IV

Dear Pavel

Thank you for your reply.

I attached original main.c. I believe that this code set correct value to Pin Control Register.

Please advise to fix this issue as soon as possible.

Best regards,

Takashima

0 Kudos

1,489 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hello Takashima,

what hardware are you using? TWR board?

Please, check whether your input button pin includes capacitor to reduce oscilation at pin when released. As far as I rememeber our older TWR-K60 boards did not included capacitances on buttons. In such case it can happend that even after first enter into the port interrupt handler and clearing adequate pin flag the oscilation can re-generate (set) interrupt flag. If you configured compiler for the highest speed optimization then the interrupt handler considering your code can run trought quite quickly. And may be it is just a luck that default KSDK code includes enough timing to jump over the oscillation time.

You can easily check it by setting the breakpoint before your code clear pin flag and then run the code agian. If program enter interrupt handler again then something is wrong, if not then it is clear that there were some additional oscilations after clearing the flag.

regards

R.

1,489 Views
isaotakashima
Contributor IV

Dear Pavel

Thank you for your reply.

I can reproduce this issue using TWR-K60D100M board, and I already checked it by setting the breakpoint at first code (isButtonPress = true;).

void BOARD_SW_IRQ_HANDLER(void)

  {

->    isButtonPress = true;

      // Toggle LED1.

      GPIOA_PTOR = (1 << 11);

      PORTA_ISFR = PORTA_ISFR;

  }

After pressed SW1, code break at breakpoint (isButtonPress = true;), and then run the code again, unfortunately code break at breakpoint again.

If you have the TWR-K60D100M, you will reproduce this issue.

What do you think this issue? Is this issue caused by PORT (port control and interrupt) module? Or caused by NVIC?

Please let us know root cause and advise how to solve this issue as soon as possible.

Best regards,

Takashima

0 Kudos

1,489 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hi Takashimare,

I was not able to reproduce it on my board. The true is that one press of button generate more that 1 interrupt. However, with the beakpoint i executed irq handler just once.

I am still considering that you want to execute this interrupt routine as fast as posssible, right? The possible problem of your case can be some special high speed compiler configuration which at the end clears port flag before stoping at breakpoint.

Please, check in disassembly whether PORTA_ISFR flag is cleared after steping a program after breakpoint.

regards

R.

1,489 Views
isaotakashima
Contributor IV

Dear Rastislav Pavlanin,

Thank you for your reply.

I'm using IAR EWARM Ver 7.60.1. If you use another tool, you will not reproduce this issue.

I have the additional information, this issue depends on return instruction to main() routine.

If I don't call any function in ISR, return instruction is "BX LR".

The following picture is ISR after press SW1, then ISFR = 0x00080000.

pastedImage_2.png

The following picture is ISR after click RUN icon, unfortunately ISFR = 0x00000000.

pastedImage_4.png

If I call dummy() function in ISR, return instruction is "POP  {R0, PC}.

pastedImage_5.png

Could you please explain reason why cause this issue if return instruction is "BX   LR".

Best regards,

Takashima

1,489 Views
rastislav_pavlanin
NXP Employee
NXP Employee

Hi Takashima,

well, the exception (interrupt) return can be provided by to approaches:

- POP intruction that load PC

- BX instruction using any register

During the exception (interrupt handler) execution LR register holds the EXC_RETURN value indicating how to return (if return to the handler, what stack to use etc.). For example: the value looks like 0xFFFFFFF9 representing return to the Thread mode with main stack pointer. Very important thing is that BX instruction (e.g. BX R) resutl in hardfault if the bit[0] of R is 0 (due to thumb mode of instruction decoding).

However, I believe that is not you case as your program doesn not resutl in hardfault but just in second execution of exception (interrupt). Hence, you problem I see in non proper sequence of PORT interrupt bit clrearing. I guess that the interrupt execution with dummy function takes a bit more clock cycles.

regards

R.

1,489 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Isao Takashima

I don't know if you are still interested in this, but if so, the problem is not the instruction BX LR; LR is a special register which holds the address to return to when a function call completes, as long as you are using a function inside your handler that use this register (dummy()), your handler cannot use this register so it use the PC register.

But as I mentioned before this doesn't relate with your initial question, problem here is that your last instruction in the interrupt handler is when you clear the flag, this instruction doesn't have time to execute when the interrupt service is "attended again". Normally the first thing that you do in the handler (after check if the interrupt occurred as expected) is clear the flag, so:

  if (PORTA_ISFR & (1<<19))
  {
    //clear flag
    PORTA_ISFR |= (1<<19);
    isButtonPress = true;
    // Toggle LED1.
    GPIOA_PTOR = (1 << 11);
  }‍‍‍‍‍‍‍‍

Even you could try some test, the trick here is not to put the clear instruction at the end, for example:

// Toggle LED1.
GPIOA_PTOR = (1 << 11);
PORTA_ISFR |= (1<<19);
isButtonPress = true;
 ‍‍‍‍‍

Should works.

Hope this helps
Have a great day,
Jorge Alcala

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

0 Kudos