cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupt pending registers not cleared

stenasc
Senior
Posted on December 20, 2012 at 21:50

I have a number of switches which generate interrupts. When I Flick switch A it goes from High to Low

and the A interrupt occurs(EXTI_PR is now 0x00000200 as expected). I then clear the pending register (EXTI_PR is now 0x00000000).

At this time switch A is still at low which is what I require.

Now while switch A is still low, I switch B from High to Low. Instead of entering the B interrupt routine,

which is what I expect, the processor still enters the A routine. I can understand this because when I

check EXTI_PR, its value is 0x00000600. How can I avoid this situation? I need to keep A switched low while

B is switched. I would not have expected this as the interrupts are edge triggered. What is keeping the pending registers

from being properly cleared?

The pending register only changes to 0x00000400 when I switch A on and off. When I activate the switches by

flicking them ON and OFF, the interrupts behave accordingly. However, my system doesn't allow this.

I appreciate any help.

Bob

  /* Configure PC9 pin as input floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 

  /* Connect EXTI0 Line to PC9 pin */

  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource9);

    

  /* Connect EXTI0 Line to PC10 pin */

  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource10);

 

  /* Configure EXTI9 line */

  EXTI_InitStructure.EXTI_Line = EXTI_Line9;

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

    

  /* Configure EXTI10 line */

  EXTI_InitStructure.EXTI_Line = EXTI_Line10;

  EXTI_Init(&EXTI_InitStructure);

 

  /* Enable and set EXTI4_15 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);  

 

void EXTI4_15_IRQHandler(void)

{

   if(EXTI_GetITStatus(EXTI_Line9) != RESET)        

     {

     printf(''\n\r Interrupt A'');

     EXTI_ClearITPendingBit(EXTI_Line9);

     }

   else if (EXTI_GetITStatus(EXTI_Line10) != RESET)

     {

     printf(''\n\r Interrupt B'');

     EXTI_ClearITPendingBit(EXTI_Line10);

     }

}
9 REPLIES 9
zzdz2
Associate II
Posted on December 21, 2012 at 14:27

Maybe it just works this way, I don't know butI think you can use software filter in the handler to make it work as expected.

Not tested:

static uint32_t last_pr = 0;
uint32_t new_pr = (EXTI_PR ^ last_pr) & EXTI_PR;
last_pr = EXTI_PR;
if (new_pr & EXTI_Line9)
{
// interrupt A
}
if (new_pr & EXTI_Line10)
{
// interrupt B
}

stenasc
Senior
Posted on December 21, 2012 at 17:46

This almost works perfectly except that if I switch B on so that it jumps into the B routine (works fine), and then switch it off. If I now switch B on again, it no longer jumps into the B routine.

It works if swich A is followed by switch B or vice versa. When there is two consecutive interrupts from the same switch, the second isn't caught.

However, this solved it.

    if (last_pr == EXTI->PR)

      {        

        new_pr = EXTI->PR;

        last_pr = new_pr;

      }

  else

      {        

      new_pr = (EXTI->PR ^ last_pr) & EXTI->PR;

    last_pr = EXTI->PR;

    }

Many thanks for your advice.

Bob

stenasc
Senior
Posted on December 21, 2012 at 21:11

After some more testing with another switch C, this is still not working correctly. If A is left ON, then if C is activated, the A routine is entered. How are interrupts meant to work with switches or are switches expected to be polled instead of using interrupts?

Posted on December 22, 2012 at 03:51

I'd expect the device to be able to detect each independently, but mechanical switches tend to be awfully noisy, so if you are edge triggering I wouldn't be surprised if you saw glitches. Consider using debouncing logic.

If you're feeling experimental try driving them with GPIO pins.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
zzdz2
Associate II
Posted on December 22, 2012 at 09:59

Yes, there may be glitches. Usually you can filter them out with a capacitor.

stenasc
Senior
Posted on December 22, 2012 at 13:51

I thought that debouncing was causing the issue. However on this board there is no debounce filters between switch and pin. Is there a way that I can implement some debounce logic between the pin and interrupt mechanism

e.g

GPIO_Pin_9 ----> debounce function ----> Debounced_GPIO_Pin9

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  // Configure PC9 pin as input floating

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 

  // Connect EXTI0 Line to PC9 pin

  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, Debounced_GPIO_Pin9);

  EXTI_InitStructure.EXTI_Line = EXTI_Line9;

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

etc

zzdz2
Associate II
Posted on December 22, 2012 at 14:25

You can use SysTick or timer interrupt to check pin state, e.g. 100 Hz.

logic is something like this:

static uint8_t pin1last = 0;

static uint8_t pin1cnt = 0;

if ((pin1last != 0) ^ (pin1 != 0))

pin1cnt++;

else

pin1cnt = 0;

if (pin1cnt > thr) // pin1 state changed

{

pin1cnt = 0;

if (pin1) // rising

if (!pin1) // falling   pin1last = pin1; }  

stenasc
Senior
Posted on December 23, 2012 at 01:25

The debouncing logic isn't a problem. However, you need to connect the debounced pin to the interrupt logic so that there is only one clean edge feeding the interrupt mechanism and thats where I believe the issue is.

The debouncing logic looks to apply only to pin polling, and not  interrupts. To me it looks as if the switch must be debounced before being connected to the input ports. Would this be a fair assumption?

Bob

zzdz2
Associate II
Posted on December 23, 2012 at 11:12

Yes, you can use hardware debouncing and it may work well.

I was talking about software debouncing, you need to enable some periodic irq, e.g. SysTick or timer, about 100 per second should be ok, I think.

In the handler you poll the switches and you can debounce it in software.