~ruther/avr-device

4d71c0ee76cee0bee651eb7b131bdad6a3c259b5 — Rahix 6 years ago 769efac
Add interrupts and use cfg-if

Signed-off-by: Rahix <rahix@rahix.de>
4 files changed, 98 insertions(+), 15 deletions(-)

M Cargo.toml
M src/devices/mod.rs
A src/interrupt.rs
M src/lib.rs
M Cargo.toml => Cargo.toml +2 -1
@@ 5,9 5,10 @@ authors = ["Rahix <rahix@rahix.de>"]
edition = "2018"

[features]
attiny85 = []
atmega32u4 = []
attiny85 = []

[dependencies]
bare-metal = "0.2.4"
vcell = "0.1.0"
cfg-if = "0.1.7"

M src/devices/mod.rs => src/devices/mod.rs +7 -4
@@ 1,4 1,7 @@
#[cfg(feature = "attiny85")]
pub mod attiny85;
#[cfg(feature = "atmega32u4")]
pub mod atmega32u4;
cfg_if::cfg_if! {
    if #[cfg(feature = "atmega32u4")] {
        pub mod atmega32u4;
    } else if #[cfg(feature = "attiny85")] {
        pub mod attiny85;
    }
}

A src/interrupt.rs => src/interrupt.rs +68 -0
@@ 0,0 1,68 @@
//! Interrupts
//!
//! For the most part, [interrupt::free] is what you want:
//!
//! ```
//! atmega32u4::interrupt::free(|cs| {
//!     // Interrupts are disabled here
//! })
//! ```

pub use bare_metal::{CriticalSection, Mutex, Nr};

#[inline]
/// Disables all interrupts
pub fn disable() {
    unsafe {
        asm!(
            "cli" :::: "volatile"
        );
    }
}

#[inline]
/// Enables all the interrupts
///
/// # Safety
///
/// - Do not call this function inside an `interrupt::free` critical section
pub fn enable() {
    unsafe {
        asm!(
            "sei" :::: "volatile"
        );
    }
}

/// Execute closure `f` in an interrupt-free context.
///
/// This as also known as a "critical section".
pub fn free<F, R>(f: F) -> R
where
    F: FnOnce(&CriticalSection) -> R,
{
    let sreg: u8;

    // Store current state
    unsafe {
        asm!(
            "in $0,0x35"
            : "=r"(sreg)
            :
            :
            : "volatile"
        );
    }

    // Disable interrupts
    disable();

    let r = f(unsafe { &CriticalSection::new() });

    // Restore interrupt state
    if sreg & 0x80 != 0x00 {
        enable();
    }

    r
}

M src/lib.rs => src/lib.rs +21 -10
@@ 1,21 1,32 @@
#![no_std]
#![feature(asm)]

#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, unused_attributes)]
mod devices;

#[cfg(feature = "attiny85")]
pub use crate::devices::attiny85::*;
#[cfg(feature = "atmega32u4")]
pub use crate::devices::atmega32u4::*;
pub mod interrupt;

cfg_if::cfg_if! {
    if #[cfg(feature = "atmega32u4")] {
        pub use crate::devices::atmega32u4::*;
    } else if #[cfg(feature = "attiny85")] {
        pub use crate::devices::attiny85::*;
    } else {
        compile_error!("You need to select exactly one chip as a feature!");
    }
}

#[cfg(any(feature = "attiny85", feature = "atmega32u4"))]
impl Peripherals {
    /// Returns all the peripherals *once*
    #[inline]
    pub fn take() -> Option<Self> {
        if unsafe { DEVICE_PERIPHERALS } {
            None
        } else {
            Some(unsafe { Peripherals::steal() })
        }
        interrupt::free(|_| {
            if unsafe { DEVICE_PERIPHERALS } {
                None
            } else {
                Some(unsafe { Peripherals::steal() })
            }
        })
    }
}

Do not follow this link