MMM
MMM

Reputation: 43

STM32F4 EXTI interrupts interfere with each other

I am working with STM32F407VGT6 MCU and I am having problem with external interrupts (EXTI). I have configured two pins as EXTI and they are PE7 and PE15. They are connected to HALL sensors driver and are detecting toot edges of trigger wheel. Ones is primary source with multiple tooth and other wheel is single tooth wheel which confirms position. The thing is they can work individually on their own without issues, but if I connect both of them, they start to interfere with each other and I am loosing position sync, because MCU is detecting false edges. I can recreate same behavior by connecting either pin to low signal and other to HALL driver. But if I disable EXTI and leave pin as a input the problem goes away. I have no idea what's going on here.

Also, I had issues with PE15 and EXTI before and it might be related to this. The EXTI was working only in EXTI_Trigger_Rising and EXTI_Trigger_Rising_Falling mode, but EXTI_Trigger_Falling was giving random edge detection, and only solution to this was to listen for both edges and debounce the one that I don't need. I couldn't find anything about this in datasheet.

This STM32F4 is giving me head aches and I running out of options. Well, the last option is to reroute the hall drivers to other pins and use input capture/timer.

Primary wheel config:

void Trigger_Configure_Primary(void) {
  // GPIO
  GPIOE->OSPEEDR |= (0x03 << (2 * 15)); // high speed

  // EXTI
  SYSCFG->EXTICR[3] = SYSCFG_EXTICR4_EXTI15_PE; // Tell system that you will use PE15 for EXTI15
  EXTI->RTSR |= (1 << 15); // rising edge
  EXTI->FTSR |= (1 << 15); // falling edge
  EXTI->IMR |= (1 << 15); // Unmask EXTI15 interrupt
  EXTI->PR |= (1 << 15); // Clear pending bit

  /* Add IRQ vector to NVIC */
  NVIC_SetPriority(EXTI15_10_IRQn, 0);
  NVIC_EnableIRQ(EXTI15_10_IRQn);
}

Secondary wheel config:

void Trigger_Configure_Secondary(void) {
  // GPIO
  GPIOE->OSPEEDR |= (0x03 << (2 * 7)); // high speed

  // EXTI
  SYSCFG->EXTICR[1] = SYSCFG_EXTICR2_EXTI7_PE; // Tell system that you will use PE7 for EXTI7
  EXTI->RTSR |= (1 << 7); // rising edge
  EXTI->FTSR |= (1 << 7); // falling edge
  EXTI->IMR |= (1 << 7); // Unmask EXTI7 interrupt
  EXTI->PR |= (1 << 7); // Clear pending bit

  /* Add IRQ vector to NVIC */
  NVIC_SetPriority(EXTI9_5_IRQn, 0);
  NVIC_EnableIRQ(EXTI9_5_IRQn);
}

IRQ handlers:

void EXTI9_5_IRQHandler(void) {
  __disable_irq();
  /* Make sure that interrupt flag is set */
  if ((EXTI->PR & EXTI_Line7) != 0) {
    // Secondary trigger IRQ
    uint32_t now_nt = GET_TIMESTAMP();

    uint8_t edge = ((GPIOE->IDR & SECONDARY_PIN) == 0 ? 0 : 1);
    TD_Decode_Secondary_Trigger_Event(
      now_nt,
      edge
    );

#ifdef DEBUG
    // Stats
    secondary_ticks = (GET_TIMESTAMP() - now_nt);
#endif

    /* Clear interrupt flag */
    EXTI->PR |= EXTI_Line7;

    ++s_cnt;
  }
  __enable_irq();
}

void EXTI15_10_IRQHandler(void) {
  __disable_irq();
  /* Make sure that interrupt flag is set */
  if ((EXTI->PR & EXTI_Line15) != 0) {
    // Primary trigger IRQ
    uint32_t now_nt = GET_TIMESTAMP();

    uint8_t edge = ((GPIOE->IDR & PRIMARY_PIN) == 0 ? 0 : 1);
    if (primary_edge == edge) {
      TD_Decode_Primary_Trigger(now_nt);
    }

#ifdef DEBUG
    // Stats
    primary_ticks = (GET_TIMESTAMP() - now_nt);
#endif

    /* Clear interrupt flag */
    EXTI->PR |= EXTI_Line15;

    ++p_cnt;
  }
  __enable_irq();
}

Upvotes: 4

Views: 7647

Answers (1)

ReAl
ReAl

Reputation: 1301

RM0090, 12.3.6 Pending register (EXTI_PR):

This bit is cleared by programming it to ‘1’.

Thus, this code

/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;

Clears not only EXTI_Line7 but all pending interrupts because it reads EXTI-PR with 1 for all triggered interrupts, then OR bit EXTI_Line7 and writes all the 1-es back.

Use

/* Clear interrupt flag */
EXTI->PR = EXTI_Line7;

Upvotes: 5

Related Questions