-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stm32xx-sys: add interrupt acking to gpio_irq_control
#1712
Conversation
Hmm, so, after trying to integrate this change with my WIP branch #1696 (see c29e5ef), I'm not actually sure if combining the "enable/disable IRQ" and "check if IRQ was triggered" behaviors in the same API is always the Right Thing. It's nice for cases where code intends to receive an interrupt in a loop, as in the Nucleo user button demo: hubris/task/nucleo-user-button/src/main.rs Lines 88 to 126 in 1d44ab8
However, for code that only wants to wait for a single interrupt and then go back to doing something else, such as In that case, what we really want is a way to check if the IRQ was triggered, leaving it disabled if it was triggered, but leaving it enabled if the notification was spurious. Right now, because we don't have that, we always perform the check by disabling the IRQ, and then re-enable it if it was not actually received. This means we actually have to do more IPCs than we would otherwise. I think the interface from a6c9163, where I had a new If we want to go back to that design, we could still hang this off of If we wanted to continue using
On the other hand, an additional IPC has the downside of "adding another IPC", complicating the interface and probably resulting in more code, but I think it results in a somewhat less weird API surface. And, it has the side benefit of letting us leave the @cbiffle, I'd love to get your opinion on this (and maybe also @bcantrill's, as a potential consumer of this API). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks great! One opportunity for deduplication noted below.
I wish I could think of a better pattern to show in examples than unwrap_lite
here, because I know people are just going to copy it, which will generate panic sites that aren't probably what they actually want. But I'm not sure what to suggest in the general case, so, this is probably a fine start.
drv/stm32xx-sys/src/main.rs
Outdated
@@ -690,17 +715,16 @@ impl idl::InOrderSysImpl for ServerImpl<'_> { | |||
|
|||
if mask & enable_mask != 0 { | |||
// Record that these bits meant something. | |||
used_bits |= mask; | |||
let bit = 1 << i; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ought to be able to factor bit
here out (it's duplicated on line 701)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to avoid doing the bit shift in the case where we don't do anything with the entry. But, bit shifts are cheap...right?
Hmm, that's a good point; in this case there is a way that a task could reasonably handle the death of the |
Restarting the client is generally a reliable way of ensuring things get reconfigured, and can sometimes be the right call -- however, it's also quite expensive, and we've had cases of programs relying on it for mundane errors. It's also a bit of a fault-multiplier in that, if the task in question is also a server (and most are), it propagates the panic out to its callers, etc. If we can conveniently show how to retry, that would be neat; if it would be a pain and make the example less useful, I'd say don't worry about it. |
1d44ab8
to
c800a4c
Compare
Currently, there is no mechanism for a task woken by a notification mapped to an EXTI GPIO interrupt to determine whether the pin it cares about has actually changed state, rather than receiving a notification posted by some other task (see #1700). In order to make this possible, @cbiffle [suggested] that the `stm32xx-sys` task provide an IPC interface that a task receiving an EXTI notification can call to ack that the IPC actually was caused by a pin state transition. This branch extends the `Sys::gpio_irq_control` IPC to return a bool if any EXTI IRQs mapped to the notifications in a task's notification maskhave triggered since the last time `gpio_irq_control` was called. Adding this functionality to `gpio_irq_control` --- which a task that wishes to receive another EXTI notification must call anyway --- allows us to keep the number of IPC roundtrips the same when a task receives such notifications in a loop. In order to support other cases, where a task only cares about one such notification, the `gpio_irq_control` interface has been changed to determine whether to enable or disable the IRQs in the mask based on a second argument, rather than taking two masks as it did previously, in order to allow a third operation which *only* checks the state of the interrupt, leaving it enabled if it has not been triggered but not re-enabling it if it has. We no longer have the ability to both enable and disable disjunct sets of IRQs in one IPC, but in practice, no task we have currently even *uses* more than one GPIO IRQ anyway. And, getting rid of the double-mask interface also fixes #1714. I've implemented this by tracking a 16-bit bitmap in the `Sys` task that mirrors the EXTI pending register. This is because `sys` must clear the pending bit in order to receive another interrupt from _any_ EXTI source. Closes #1700 Closes #1714 [suggested]: #1700 (comment)
Currently, there is no mechanism for a task woken by a notification
mapped to an EXTI GPIO interrupt to determine whether the pin it cares
about has actually changed state, rather than receiving a notification
posted by some other task (see #1700). In order to make this possible,
@cbiffle suggested that the
stm32xx-sys
task provide an IPCinterface that a task receiving an EXTI notification can call to ack
that the IPC actually was caused by a pin state transition.
This branch extends the
Sys::gpio_irq_control
IPC to return a bool ifany EXTI IRQs mapped to the notifications in a task's notification
maskhave triggered since the last time
gpio_irq_control
was called.Adding this functionality to
gpio_irq_control
--- which a task thatwishes to receive another EXTI notification must call anyway --- allows
us to keep the number of IPC roundtrips the same when a task receives
such notifications in a loop. In order to support other cases, where a
task only cares about one such notification, the
gpio_irq_control
interface has been changed to determine whether to enable or disable the
IRQs in the mask based on a second argument, rather than taking two
masks as it did previously, in order to allow a third operation which
only checks the state of the interrupt, leaving it enabled if it has
not been triggered but not re-enabling it if it has. We no longer have
the ability to both enable and disable disjunct sets of IRQs in one IPC,
but in practice, no task we have currently even uses more than one
GPIO IRQ anyway. And, getting rid of the double-mask interface also
fixes #1714.
I've implemented this by tracking a 16-bit bitmap in the
Sys
task thatmirrors the EXTI pending register. This is because
sys
must clear thepending bit in order to receive another interrupt from any EXTI
source.
Closes #1700
Closes #1714