Inconsistency on interrupt detection

Briefly, I'm struggling understanding why my RTIC hardware task inconsistently detects an interrupt generated by an external manual push-button. Basically, too few presses are detected, sometimes none at all. It's never the case that I have too many detections.
The most common scenario is that the first press of the button works, but subsequent presses either don't work, or they do only after multiple attempts or after some time.
Here's the task:

#[task(binds = EXTI0, shared = [event_queue], local = [button])]
    fn interrupt(mut cx : interrupt::Context) {
        defmt::info!("Interrupt!!!!!!!!!!");
        cx.shared.event_queue.lock(|shared| {shared.signal()});
        // clear interrupt
        cx.local.button.clear_interrupt_pending_bit();
    }

As you can see, I also clear the pending bit.
But, if I force this interrupt via software, it works every time. I do it with this code:

#[task(priority = 20, shared = [&activation_manager], local = [exti])]
    async fn force_interrupt(cx : force_interrupt::Context) {
        let mut next_time : Time = cx.shared.activation_manager.activation_cyclic().await;
        loop {
            next_time = next_time.checked_add_duration(force_inter::get_period()).unwrap();   
            cx.local.exti.swier.write(|w| w.swier0().set_bit());
            Mono::delay_until(next_time).await;
         }
    }

The period is 5 seconds and every 5 seconds, "Interrupt!!!!!" is printed.
So why the hardware way presents this inconsistency?
I'm using STM32F407VG as a board and this is how I configure the interrupt button:

let dp: Peripherals = cx.device;
let gpioa = dp.GPIOA.split();
let mut _button = gpioa.pa0.into_pull_down_input();
let mut syscfg = dp.SYSCFG.constrain();
let mut _exti = dp.EXTI;
_button.make_interrupt_source(&mut syscfg);
_button.trigger_on_edge(&mut _exti, Edge::Rising);
_button.enable_interrupt(&mut _exti);

Have you configured a pull-up on your input pin?

No, just a pull-down. Should I configure a pull-up too?

It depends how your pushbutton is wired. If the button is connected between the pin and Vcc then you need a pull-down and the pin will be high when the button is pressed. If the button is connected between the pin and ground then you need a pull-up and the pin will be low when the button is pressed.

You also need to make sure your interrupt is configured to fire on the appropriate level (high or low).

The reason I asked is that if your input is floating when the switch is not pressed (as it would be given neither pull-up nor pull-down) that would be a potential cause of inconsistent behavior.

1 Like

When you say inconsistently, do you mean too few detections or too many detections? Or a bit of both?

If it is too many detections it could be due to bouncing and you would need to debounce it (either in circuit or with software). (Surprisingly Wikipedia doesn't seem to have an article on this, but What is Switch Bouncing and How to prevent it using Switch Debounce Circuit seems reasonable).

It might be worth checking with a scope that your button presses have reasonable wave forms and that the button triggers every time. If you don't have a scope, consider trying another input and another button just to rule out faulty hardware.

1 Like

I mean too few detection, sometimes none at all. It's never the case that I have too many detections.
The most common scenario is that the first press of the button works, but subsequent presses either don't work, or they do only after multiple attempts or after some time.
I'm sorry for being inaccurate, I will edit the main question.

Do you mean it could be an hardware problem?

From my hobby electronics days, experience says that it can always be a hardware problem. In this case, if the input line has a high impedance for whatever reason (despite the pull-down setting), there may be enough stray capacitance for the voltage to remain high for some time after the button is released.

Additional ways you can investigate without a scope include:

  • Use a voltmeter to verify that the input pin actually goes to 0V when the button is released
  • When you observe a button press not working, short the input to ground briefly with a jumper wire and see if that consistently makes the next press work
  • Measure the pin-to-ground resistance with a multimeter while a program is active that has configured the input (NB: this may trigger interrupts and such, so be careful what code you're running when you try this)
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.