ruspiro_register/lib.rs
1/***********************************************************************************************************************
2 * Copyright (c) 2019 by the authors
3 *
4 * Author: André Borrmann <pspwizard@gmx.de>
5 * License: Apache License 2.0 / MIT
6 **********************************************************************************************************************/
7#![doc(html_root_url = "https://docs.rs/ruspiro-register/0.5.5")]
8#![no_std]
9
10//! # RusPiRo Register
11//!
12//! The crate provides the definitions to conviniently work with register field values that are typically presented by
13//! a set of bit fields. This crate will likely be used in other crates that specifies the actual registers and their
14//! structure using macros. Examples can be found at
15//! [ruspiro-mmio-register](https://crates.io/crates/ruspiro-mmio-register) and
16//! [ruspiro-arch-aarch64](https://crates.io/crates/ruspiro-arch-aarch64)
17
18use core::cmp::PartialEq;
19use core::fmt;
20use core::ops::{BitAnd, BitOr, Not, Shl, Shr};
21
22mod macros;
23
24/// This trait is used to describe the register size/length as type specifier. The trait is only implemented for the
25/// internal types **u8**, **u16**, **u32** and **u64** to ensure safe register access sizes with compile time checking
26pub trait RegisterType:
27 Copy
28 + Clone
29 + PartialEq
30 + BitOr<Output = Self>
31 + BitAnd<Output = Self>
32 + Not<Output = Self>
33 + Shl<Self, Output = Self>
34 + Shr<Self, Output = Self>
35{
36}
37
38// Internal macro to ease the assignment of the custom trait to supported register sizes
39#[doc(hidden)]
40macro_rules! registertype_impl {
41 // invoke the macro for a given type t as often as types are provided when invoking the macro
42 ($( $t:ty ),*) => ($(
43 impl RegisterType for $t { }
44 )*)
45}
46
47// implement the type trait for specific unsigned types to enable only those register types/sizes
48registertype_impl![u8, u16, u32, u64];
49
50/// Definition of a field contained inside of a register. Each field is defined by a mask and the bit shift value
51/// when constructing the field definition the stored mask is already shifted by the shift value
52#[derive(Copy, Clone)]
53pub struct RegisterField<T: RegisterType> {
54 mask: T,
55 shift: T,
56}
57
58/// Definition of a specific fieldvalue of a regiser. This structure allows to combine field values with bit operators
59/// like ``|`` and ``&`` to build the final value that should be written to a register
60#[derive(Copy, Clone)]
61pub struct RegisterFieldValue<T: RegisterType> {
62 /// register field definition
63 field: RegisterField<T>,
64 /// register field value
65 value: T,
66}
67
68// Internal helper macro to implement:
69// - ``RegisterField``struct for all relevant basic types
70// - ``FieldValue`` struct for all relevant basic types
71// - the operators for ``FieldValue``struct for all relevant basic types
72#[doc(hidden)]
73macro_rules! registerfield_impl {
74 ($($t:ty),*) => ($(
75 impl RegisterField<$t> {
76 /// Create a new register field definition with the mask and the shift offset for this
77 /// mask. The offset is the bit offset this field begins.
78 #[inline]
79 #[allow(dead_code)]
80 pub const fn new(mask: $t, shift: $t) -> RegisterField<$t> {
81 Self {
82 mask,
83 shift,
84 }
85 }
86
87 /// retrieve the current mask of the field shifted to its correct position
88 #[inline]
89 #[allow(dead_code)]
90 pub fn mask(&self) -> $t {
91 self.mask.checked_shl(self.shift as u32).unwrap_or(0)
92 }
93
94 /// retrieve the current shift of the field
95 #[allow(dead_code)]
96 #[inline]
97 pub fn shift(&self) -> $t {
98 self.shift
99 }
100 }
101
102 impl fmt::Debug for RegisterField<$t> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 let mut high_bit = self.shift;
105 let mut mask = self.mask;
106 while mask > 0 {
107 high_bit += 1;
108 mask >>= 1;
109 };
110 high_bit -= 1;
111 write!(f, "RegisterField {{\n Bits: [{}:{}]\n Mask: {:#b}\n}}",
112 high_bit, self.shift, self.mask.checked_shl(self.shift as u32).unwrap_or(0))
113 }
114 }
115
116 impl RegisterFieldValue<$t> {
117 /// Create a new fieldvalue based on the field definition and the value given
118 #[inline]
119 #[allow(dead_code)]
120 pub const fn new(field: RegisterField<$t>, value: $t) -> Self {
121 RegisterFieldValue {
122 field,
123 value: value & field.mask
124 }
125 }
126
127 /// Create a new fieldvalue based on the field definition and the raw value given
128 #[inline]
129 #[allow(dead_code)]
130 pub const fn from_raw(field: RegisterField<$t>, raw_value: $t) -> Self {
131 RegisterFieldValue {
132 field,
133 value: (raw_value >> field.shift) & field.mask
134 }
135 }
136
137 /// Retrieve the register field value
138 #[inline]
139 #[allow(dead_code)]
140 pub fn value(&self) -> $t {
141 self.value //>> self.field.shift()
142 }
143
144 /// Retrieve the register field raw value, means the value is returned in it's position
145 /// as it appears in the register when read with the field mask applied but not
146 /// shifted
147 #[inline]
148 #[allow(dead_code)]
149 pub fn raw_value(&self) -> $t {
150 self.value.checked_shl(self.field.shift as u32).unwrap_or(0)
151 }
152
153 /// Retrieve the field mask used with this register field. The mask is shifted to it's
154 /// corresponding field position
155 #[inline]
156 #[allow(dead_code)]
157 pub fn mask(&self) -> $t {
158 self.field.mask()
159 }
160 }
161
162 impl fmt::Debug for RegisterFieldValue<$t> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.debug_struct("RegisterFieldValue")
165 .field("field", &self.field)
166 .field("value", &self.value)
167 .field("raw_value", &self.raw_value())
168 .finish()
169 }
170 }
171
172 impl PartialEq for RegisterFieldValue<$t> {
173 fn eq(&self, other: &Self) -> bool {
174 self.value() == other.value()
175 }
176 }
177
178 impl BitOr for RegisterFieldValue<$t> {
179 type Output = RegisterFieldValue<$t>;
180
181 #[inline]
182 #[allow(dead_code)]
183 fn bitor(self, rhs: RegisterFieldValue<$t>) -> Self {
184 let field = RegisterField::<$t>::new( self.field.mask() | rhs.field.mask(), 0);
185 RegisterFieldValue {
186 field,
187 value: (self.raw_value() | rhs.raw_value()),
188 }
189 }
190 }
191
192 impl BitAnd for RegisterFieldValue<$t> {
193 type Output = RegisterFieldValue<$t>;
194 #[inline]
195 #[allow(dead_code)]
196 fn bitand(self, rhs: RegisterFieldValue<$t>) -> Self {
197 let field = RegisterField::<$t>::new( self.field.mask() & rhs.field.mask(), 0);
198 RegisterFieldValue {
199 field,
200 value: (self.raw_value() & rhs.raw_value()),
201 }
202 }
203 }
204 )*);
205}
206
207registerfield_impl![u8, u16, u32, u64];