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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
pub use bit_field::*;
use Volatile;
#[macro_export]
macro_rules! is_bit_set {
($field:expr, $bit:expr) => {
$field.get() & (1 << $bit) > 0
};
}
#[macro_export]
macro_rules! bit_get_fn {
($doc:meta, $fun:ident, $bit:expr) => (
#[$doc]
pub fn $fun(&self) -> bool {
is_bit_set!(self.0, $bit)
}
)
}
#[macro_export]
macro_rules! bit_set_fn {
($doc:meta, $fun:ident, $bit:expr) => (
#[$doc]
pub fn $fun(&mut self) {
let current = self.0.get();
self.0.set(current | 1 << $bit);
}
)
}
#[macro_export]
macro_rules! bit_clear_fn {
($doc:meta, $fun:ident, $bit:expr) => (
#[$doc]
pub fn $fun(&mut self) {
let current = self.0.get();
self.0.set(current & !(1 << $bit)) ;
}
)
}
pub fn bits_get(r: Volatile<u32>, from: usize, to: usize) -> u32 {
assert!(from <= 31);
assert!(to <= 31);
assert!(from <= to);
let mask = match to {
31 => u32::max_value(),
_ => (1 << (to + 1)) - 1,
};
(r.get() & mask) >> from
}
pub fn bits_set(r: &mut Volatile<u32>, from: usize, to: usize, bits: u32) {
assert!(from <= 31);
assert!(to <= 31);
assert!(from <= to);
let mask = match to == 31 {
true => u32::max_value() << from,
false => ((1 << (to + 1)) - 1) << from,
};
let current = r.get();
r.set((current & !mask) | ((bits << from) & mask));
}
pub fn bits_set_16(r: &mut Volatile<u16>, from: usize, to: usize, bits: u16) {
assert!(from <= 15);
assert!(to <= 15);
assert!(from <= to);
let mask = match to == 15 {
true => u16::max_value() << from,
false => ((1 << (to + 1)) - 1) << from,
};
let current = r.get();
r.set((current & !mask) | ((bits << from) & mask));
}
#[cfg(test)]
mod tests {
use bitops::*;
#[test]
fn bits_set_from_to() {
for from in 0..32 {
for to in from..32 {
let mut r: Volatile<u32> = Volatile::with_value(0);
let all_ones: usize = (1 << (to - from + 1)) - 1;
bits_set(&mut r, from, to, all_ones as u32);
for check in 0..32 {
if check >= from && check <= to {
assert!(is_bit_set!(r, check));
} else {
assert!(!is_bit_set!(r, check));
}
}
assert!(bits_get(r, from, to) == all_ones as u32);
}
}
}
}