volatile_register/
lib.rs

1//! Volatile access to memory mapped hardware registers
2//!
3//! # Usage
4//!
5//! ``` no_run
6//! use volatile_register::RW;
7//!
8//! // Create a struct that represents the memory mapped register block
9//! /// Nested Vector Interrupt Controller
10//! #[repr(C)]
11//! pub struct Nvic {
12//!     /// Interrupt Set-Enable
13//!     pub iser: [RW<u32>; 8],
14//!     reserved0: [u32; 24],
15//!     /// Interrupt Clear-Enable
16//!     pub icer: [RW<u32>; 8],
17//!     reserved1: [u32; 24],
18//!     // .. more registers ..
19//! }
20//!
21//! // Access the registers by casting the base address of the register block
22//! // to the previously declared `struct`
23//! let nvic = 0xE000_E100 as *const Nvic;
24//! // Unsafe because the compiler can't verify the address is correct
25//! unsafe { (*nvic).iser[0].write(1) }
26//! ```
27
28#![deny(missing_docs)]
29#![no_std]
30
31extern crate vcell;
32
33use vcell::VolatileCell;
34
35/// Read-Only register
36#[repr(transparent)]
37pub struct RO<T>
38    where T: Copy
39{
40    register: VolatileCell<T>,
41}
42
43impl<T> RO<T>
44    where T: Copy
45{
46    /// Reads the value of the register
47    #[inline(always)]
48    pub fn read(&self) -> T {
49        self.register.get()
50    }
51}
52
53/// Read-Write register
54#[repr(transparent)]
55pub struct RW<T>
56    where T: Copy
57{
58    register: VolatileCell<T>,
59}
60
61impl<T> RW<T>
62    where T: Copy
63{
64    /// Performs a read-modify-write operation
65    ///
66    /// NOTE: `unsafe` because writes to a register are side effectful
67    #[inline(always)]
68    pub unsafe fn modify<F>(&self, f: F)
69        where F: FnOnce(T) -> T
70    {
71        self.register.set(f(self.register.get()));
72    }
73
74    /// Reads the value of the register
75    #[inline(always)]
76    pub fn read(&self) -> T {
77        self.register.get()
78    }
79
80    /// Writes a `value` into the register
81    ///
82    /// NOTE: `unsafe` because writes to a register are side effectful
83    #[inline(always)]
84    pub unsafe fn write(&self, value: T) {
85        self.register.set(value)
86    }
87}
88
89/// Write-Only register
90#[repr(transparent)]
91pub struct WO<T>
92    where T: Copy
93{
94    register: VolatileCell<T>,
95}
96
97impl<T> WO<T>
98    where T: Copy
99{
100    /// Writes `value` into the register
101    ///
102    /// NOTE: `unsafe` because writes to a register are side effectful
103    #[inline(always)]
104    pub unsafe fn write(&self, value: T) {
105        self.register.set(value)
106    }
107}