Skip to content

Commit

Permalink
stm32xx-sys: add interrupt acking to gpio_irq_control (#1712)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
hawkw committed Apr 5, 2024
1 parent 274b51f commit c464bb3
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 144 deletions.
2 changes: 1 addition & 1 deletion app/demo-stm32h7-nucleo/app-h743.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ stacksize = 896

[kernel]
name = "demo-stm32h7-nucleo"
requires = {flash = 24000, ram = 5120}
requires = {flash = 24736, ram = 5120}
features = ["h743", "dump"]

[tasks.jefe]
Expand Down
2 changes: 1 addition & 1 deletion app/demo-stm32h7-nucleo/app-h753.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ stacksize = 896

[kernel]
name = "demo-stm32h7-nucleo"
requires = {flash = 24704, ram = 5120}
requires = {flash = 24736, ram = 5120}
features = ["h753", "dump"]

[tasks.jefe]
Expand Down
35 changes: 35 additions & 0 deletions drv/stm32xx-sys-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ pub enum Edge {
Both = 0b11,
}

/// Describes which operation is performed by the [`Sys::gpio_irq_control`] IPC.
#[derive(
Copy, Clone, FromPrimitive, PartialEq, Eq, AsBytes, serde::Deserialize,
)]
// repr attribute is required for the derived `AsBytes` implementation
#[repr(u8)]
pub enum IrqControl {
/// Disable any interrupts mapped to the provided notification mask.
Disable = 0,
/// Enable any interrupts mapped to the provided notification mask.
Enable,
/// Check if any interrupts mapped to the provided notification mask have
/// been triggered, *without* enabling or disabling the interrupt.
///
/// If an interrupt is currently enabled, it will remain enabled, while if
/// it is currently disabled, it will remain disabled.
Check,
}

impl Sys {
/// Requests that the clock to a peripheral be turned on.
///
Expand Down Expand Up @@ -331,4 +350,20 @@ impl core::ops::BitOr for Edge {
}
}

impl From<bool> for IrqControl {
fn from(value: bool) -> Self {
if value {
IrqControl::Enable
} else {
IrqControl::Disable
}
}
}

impl From<Option<bool>> for IrqControl {
fn from(value: Option<bool>) -> Self {
value.map(Self::from).unwrap_or(Self::Check)
}
}

include!(concat!(env!("OUT_DIR"), "/client_stub.rs"));
Loading

0 comments on commit c464bb3

Please sign in to comment.