Reputation: 43
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
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