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() })
+ }
+ })
}
}