2021-10-21 06:26 AM
Hello,
So we are building a ball shooting robot which self detects the speed the ball was launched. The average speed is in range of 80mph. To get speed we are using two light gates, one on PF9 and one on PF10. So I set up EXTI interrupts on these two input rising edges. Most of the times the logic works just fine and the speed calculated seems believable, but sometimes the interrupt is triggered on falling edge instead of rising edge. Tried the other way around and got the same result - some times interrupt is triggered on rising edge although its set to be triggered on falling edge.
I hooked up digital logic analyzer to actually see if the problem is with light gates or with STM32 interrupt. And since I'm here you already should know where the problem was.
I explicitly checked the register setup if somehow trigger for both edges is set up but also in registers everything seems okay.
So the question is whats happening?
Why sometimes interrupt is triggered on rising edge instead of falling even if it isn't enabled in registers?
How to fix this issue?
Setup:
I'm running FreeRTOS and STM32 system clock is set to 40MHz. EXTI interrupt priority is set to highest in the whole system. The interrupt service routine is as short as I could make - checks some flags, registers time, resets interrupt flag. The time between rising/falling edges is at least a millisecond.
Interrupt init code and ISR below:
void SpeedReader::init()
{
//clang-format off
/* Hardware interrupt selection
* Configure the corresponding mask bit in the EXTI_IMR register.
* Configure the Trigger Selection bits of the Interrupt line (EXTI_RTSR
and EXTI_FTSR)
* Configure the enable and mask bits that control the NVIC IRQ channel
mapped to the EXTI so that an interrupt coming from one of the EXTI line
can be correctly acknowledged.
*/
//clang-format on
/* Enable SYSCFG clock */
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
/* Set interrupt source pin */
SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI9_PF + SYSCFG_EXTICR3_EXTI10_PF;
/* Configure Interrupt */
EXTI->IMR |= EXTI_IMR_MR9 + EXTI_IMR_MR10;
EXTI->RTSR |= EXTI_RTSR_RT9 + EXTI_RTSR_RT10;
NVIC_SetPriority(EXTI9_5_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_SetPriority(EXTI15_10_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(EXTI9_5_IRQn);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
extern "C" {
void EXTI9_5_IRQHandler(void)
{
if (!new_shot && !shot_start)
{
/* us before ms after */
start_time = TIM6->CNT / 1e3 + TIM1->CNT;
shot_start = true;
}
/* Clear interrupt flag*/
EXTI->PR |= EXTI_PR_PR9;
}
void EXTI15_10_IRQHandler(void)
{
if (shot_start && !new_shot)
{
/* us before ms after , */
end_time = TIM6->CNT / 1e3 + TIM1->CNT;
new_shot = true;
shot_start = false;
}
/* Clear interrupt flag*/
EXTI->PR |= EXTI_PR_PR10;
}
}
I'm not able to test if this issue still exists if I'm not using FreeRTOS because it's a complex system but I'm pretty convinced that FreeRTOS does not have any impact on this since there is always an ongoing USART communication which works fine and most of the time the interrupts are fired correctly! The problem seems that STM32 sometimes misinterprets on which edge interrupt should be triggered.
If any other information is necessary please let me know!
Regards,
Kuchx
Solved! Go to Solution.
2021-10-22 04:08 AM
>> The "edges" are quite likely bouncy.
>That's why I'm using some basic flag logic to register timestamp of the first edge.
What is that and how does it debounce?
> So here are the timings between 2 rising edges and falling/rising edge.
> The ISR's captured that delta time is 1.7ms and I can't understand why.
Because your LA is to slow to show that there are bounces at what you see to be a falling edge, i.e
at the 1.7ms mark there is a rapid succession of falling-rising-falling edge and that riding edge is what triggers the EXTI.
Debounce in hardware, or in software, out instead of EXTI use TIM Input Capture, there are adjustable digital files there.
JW
2021-10-21 07:18 AM
> The problem seems that STM32 sometimes misinterprets on which edge interrupt should be triggered.
How are you determining this?
You should clear the flag as the first thing in the interrupt in order to prevent spurious re-entry into the handler.
2021-10-21 08:31 AM
The "edges" are quite likely bouncy.
[EDIT]
> You should clear the flag as the first thing in the interrupt in order to prevent spurious re-entry into the handler.
.. or, better, qualify the interrupt source.
JW
2021-10-21 11:59 PM
> How are you determining this?
So I connected digital logic analyzer to light gate signals and then I checked the delta time between interrupts reported by MCU and compared it with the waveform. The time between two signal falling and rising edge was the same delta time reported by MCU so basically meaning that interrupt fired on falling edge instead of rising.
> You should clear the flag as the first thing in the interrupt in order to prevent spurious re-entry into the handler.
I changed the ISR to firstly clear the interrupt flag. 80% of the time interrupts are fired correctly but still some errors exist. Take a look at the false speed reading waveform below
So here are the timings between 2 rising edges and falling/rising edge. The ISR's captured that delta time is 1.7ms and I can't understand why. As I mentioned these two ISR's have the highest priority. It's pretty confusing that most of the time speed readings are correct and sometimes aren't. I'll read about FreeRTOS interrupt handling a bit more, maybe I'm missing something.
2021-10-22 12:03 AM
> The "edges" are quite likely bouncy.
That's why I'm using some basic flag logic to register timestamp of the first edge.
> .. or, better, qualify the interrupt source.
Will try to implement this, thanks
2021-10-22 04:08 AM
>> The "edges" are quite likely bouncy.
>That's why I'm using some basic flag logic to register timestamp of the first edge.
What is that and how does it debounce?
> So here are the timings between 2 rising edges and falling/rising edge.
> The ISR's captured that delta time is 1.7ms and I can't understand why.
Because your LA is to slow to show that there are bounces at what you see to be a falling edge, i.e
at the 1.7ms mark there is a rapid succession of falling-rising-falling edge and that riding edge is what triggers the EXTI.
Debounce in hardware, or in software, out instead of EXTI use TIM Input Capture, there are adjustable digital files there.
JW
2021-10-22 05:37 AM
Thanks for you replay!
About the debounce - I dont think that it might be the case because we recently migrated from Atmega 256 to STM32 and previously Atmega had basically the same logic I'm trying to implement here without any hardware nor software debounce implemented and the interrupts worked fine 100% of the time until the light gates got dusty.
But thanks for the possible workarounds, I'll try to get oscilloscope to check the signal again to see if it's actually bouncing or possibly another reason of the error might be noise on the input lines (just now thought about that)!
2021-10-22 06:08 AM
> we recently migrated from Atmega 256 to STM32
In ATMega256x, interrupts 0..3 are asynchronous and the minimum pulse is 50ns (and interrupts 4..7 are sampled by the system clock and won't be much faster); whereas in 'F303 all EXTI are asynchronous and the minimum pulse is 10ns. That's some difference.
JW
2021-10-22 07:20 AM
Improper debounce is almost certainly the problem here as suggested by JW. There are not massive bugs in the silicon.
> I dont think that it might be the case because we recently migrated from Atmega 256 to STM32 and previously Atmega had basically the same logic I'm trying to implement here without any hardware nor software debounce implemented and the interrupts worked fine 100% of the time until the light gates got dusty.
I would not expect code on the ATMega to be 1:1 compatible with the STM32. Different hardware, different software. "It worked before" or "It worked somewhere else" doesn't mean it's correct.
You should be able to toggle a GPIO during the ISR to gain more insight into how the micro is behaving and when/where it's being triggered.
2021-10-26 01:30 AM
Thanks for your help TDK and JW
Added a hardware low pass filter as well as software debounce and interrupt qualifying logic and everything seems to work fine!