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 | |
31 | extern crate vcell; |
32 | |
33 | use vcell::VolatileCell; |
34 | |
35 | /// Read-Only register |
36 | #[repr (transparent)] |
37 | pub struct RO<T> |
38 | where T: Copy |
39 | { |
40 | register: VolatileCell<T>, |
41 | } |
42 | |
43 | impl<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)] |
55 | pub struct RW<T> |
56 | where T: Copy |
57 | { |
58 | register: VolatileCell<T>, |
59 | } |
60 | |
61 | impl<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)] |
91 | pub struct WO<T> |
92 | where T: Copy |
93 | { |
94 | register: VolatileCell<T>, |
95 | } |
96 | |
97 | impl<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 | } |
108 | |