Skip to content
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

Adds IRQ State types #3

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2024 Jonathan 'theJPster' Pallant <[email protected]>
#
# SPDX-License-Identifier: MIT OR Apache-2.0

name: Clippy

on: [push, pull_request]

jobs:
cargo-clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Clippy
run: cargo clippy
15 changes: 15 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2024 Jonathan 'theJPster' Pallant <[email protected]>
#
# SPDX-License-Identifier: MIT OR Apache-2.0

name: Format

on: [push, pull_request]

jobs:
cargo-fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup component add rustfmt
- run: cargo fmt -- --check
44 changes: 44 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# SPDX-FileCopyrightText: 2024 Jonathan 'theJPster' Pallant <[email protected]>
#
# SPDX-License-Identifier: MIT OR Apache-2.0

name: Build and Test

on: [push, pull_request]

jobs:
cargo-build-native:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
cargo build
cargo build --all-features
cargo-build-cross:
runs-on: ubuntu-latest
strategy:
matrix:
target: [thumbv6m-none-eabi, riscv32i-unknown-none-elf, thumbv7m-none-eabi, thumbv7em-none-eabi, thumbv8m.base-none-eabi, thumbv8m.main-none-eabi, riscv32imac-unknown-none-elf]
steps:
- uses: actions/checkout@v4
- run: rustup target add ${{ matrix.target }}
- run: |
cargo build --target=${{ matrix.target }}
cargo build --target=${{ matrix.target }} --features=cas,critical-section
cargo-build-cross-with-cas:
runs-on: ubuntu-latest
strategy:
matrix:
target: [thumbv7m-none-eabi, thumbv7em-none-eabi, thumbv8m.base-none-eabi, thumbv8m.main-none-eabi, riscv32imac-unknown-none-elf]
steps:
- uses: actions/checkout@v4
- run: rustup target add ${{ matrix.target }}
- run: |
cargo build --target=${{ matrix.target }} --features=cas
cargo-test-native:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
cargo test
cargo test --all-features
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ documentation = "https://docs.rs/grounded/"
version = "1.3"
default-features = false

[dependencies.critical-section]
version = "1.1"

[dev-dependencies.critical-section]
version = "1.1"
features = ["std"]

[features]
default = []
# components that require compare-and-swap operations
Expand Down
105 changes: 105 additions & 0 deletions src/irq_sharing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//! Types for handling data that needs to be moved into an interrupt handler or
//! thread.
//!
//! Written by Ferrous Systems.
//!
//! They are designed to work with the
//! [`cortex-m`](https://crates.io/crates/cortex-m) `#[interrupt]` macro.
//!
//! ```rust, ignore
//! use grounded::irq_sharing::{Global, Local};
//! static GLOBAL_UART0: Global<Uart0> = Global::empty();
//!
//! #[entry]
//! fn main() -> {
//! let p = hal::init();
//! GLOBAL_UART0.load(p.uart);
//! p.enable_uart_interrupt();
//! loop {
//! // Do your main thread stuff
//! }
//! }
//!
//! #[interrupt]
//! fn UART0 {
//! // This is re-written to be safe by the #[interrupt] attribute
//! static mut UART0: Local<Uart0> = Local::empty();
//!
//! let uart0 = UART0.get_or_init(&GLOBAL_UART0);
//!
//! // can use uart0 here safely, knowing no other code has access
//! // to this object.
//! }
//! ```

/// The global type for sharing things with an interrupt handler
pub struct Global<T> {
inner: critical_section::Mutex<core::cell::RefCell<Option<T>>>,
}

impl<T> Global<T> {
/// Create a new, empty, object
pub const fn empty() -> Global<T> {
Global {
inner: critical_section::Mutex::new(core::cell::RefCell::new(None)),
}
}

/// Load a value into the global
///
/// Returns the old value, if any
pub fn load(&self, value: T) -> Option<T> {
critical_section::with(|cs| self.inner.borrow(cs).replace(Some(value)))
}
}

/// The local type for sharing things with an interrupt handler
pub struct Interrupt<T> {
inner: Option<T>,
}

impl<T> Interrupt<T> {
/// Create a new, empty, object
pub const fn empty() -> Interrupt<T> {
Interrupt { inner: None }
}

/// Grab a mutable reference to the contents.
///
/// If the value is empty, the contents are taken from a mutex-locked global
/// variable. That global must have been initialised before calling this
/// function. If not, this function panics.
pub fn get_or_init_with(&mut self, global: &Global<T>) -> &mut T {
let result = self.inner.get_or_insert_with(|| {
critical_section::with(|cs| global.inner.borrow(cs).replace(None).unwrap())
});
result
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn send_not_sync() {
// Is Send but !Sync
struct Racy {
inner: core::cell::Cell<u8>,
}

// Initialisation
static GLOBAL_TEST: Global<Racy> = Global::empty();
let racy = Racy {
inner: core::cell::Cell::new(0),
};
GLOBAL_TEST.load(racy);
// Usage - we don't have the static mut re-write here so use a stack
// variable
let mut local: Interrupt<Racy> = Interrupt::empty();
let local_ref = local.get_or_init_with(&GLOBAL_TEST);
assert_eq!(local_ref.inner.get(), 0);
}
}

// End of file
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![doc = include_str!("../README.md")]

pub mod const_init;
pub mod irq_sharing;
pub mod uninit;

#[cfg(feature = "cas")]
Expand Down