1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*********************************************************************************************************************** 
 * Copyright (c) 2019 by the authors
 * 
 * Author: André Borrmann 
 * License: Apache License 2.0
 **********************************************************************************************************************/
#![doc(html_root_url = "https://docs.rs/ruspiro-lock/0.2.1")]
#![no_std]
#![feature(asm)]

//! # Atomic locks for Raspberry Pi baremetal systems
//! 
//! This crate provides two options of locks. [Spinlock] and [Semaphore]. They provide mechanisms to secure cross core
//! access to shared data like MMIO registers of peripherals. As the locks depend on low level atomics they do only work
//! on the Raspberry Pi if the MMU is properly configured. Otherwise using either of the lock functions will hang the 
//! core it has been used on.
//! 
//! # Usage
//! 
//! Using a Spinlock to ensure exclusive access.
//! ```
//! use ruspiro_lock::*;
//! 
//! static SPIN: Spinlock = Spinlock::new();
//! 
//! fn main() {
//!     SPIN.aquire();
//!     // following code is only executed if the lock could be aquired, the executing core pause till then
//!     let _ = 10 + 3;
//!     SPIN.release();
//! }
//! ```
//! 
//! Using a Semaphore to specify how often specific access is valid.
//! 
//! ```
//! use ruspriro_lock::*;
//! 
//! static mut SEMA: Semaphore = Semaphore::new(1);
//! 
//! fn main() {
//!     unsafe { // unsafe necessary as accessing mut static's is unsafe
//!         if SEMA.try_down().is_ok() {
//!             // we gained access to the semaphore, do something
//!             let _ = 20 /4;
//!             SEMA.up();
//!         }
//!     }
//! }
//! ```
//! 
//! Using data container with atmic lock guard.
//! ```
//! use ruspiro_lock::*;
//! 
//! static DATA: DataLock<u32> = DataLock::new(0);
//! 
//! fn main() {
//!     if let Some(mut data) = DATA.try_lock() {
//!         *data = 20;
//!     }
//!     // once the data goes ot of scope the lock will be released
//!     if let Some(data) = DATA.try_lock() {
//!         println!("data: {}", *data);
//!     
//!         // another lock should fail inside this scope
//!         assert_eq!(DATA.try_lock(), None);
//!     }
//! }
//! ```
//! 


// re-export the spinlock
pub mod spinlock;
pub use spinlock::*;

// re-export the semaphore
pub mod semaphore;
pub use semaphore::*;

// re-export the data-lock
pub mod datalock;
pub use datalock::*;

use ruspiro_interrupt_core::*;