Skip to content

Commit d499901

Browse files
committed
raw_read_write
1 parent e48c975 commit d499901

File tree

5 files changed

+409
-72
lines changed

5 files changed

+409
-72
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
77

88
## [Unreleased]
99

10+
- Add `raw-access` options
1011
- Move `Reg` in separate file
1112
- Use `warning` class in docs
1213
- Refactor `Accessor`

src/generate/device.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,12 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
6363

6464
out.extend(quote! {
6565
use core::ops::Deref;
66-
use core::marker::PhantomData;
6766
});
67+
if !config.raw_access {
68+
out.extend(quote! {
69+
use core::marker::PhantomData;
70+
});
71+
}
6872

6973
// Retaining the previous assumption
7074
let mut fpu_present = true;
@@ -140,7 +144,11 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
140144
}
141145

142146
let generic_file = include_str!("generic.rs");
143-
let generic_reg_file = include_str!("generic_reg_vcell.rs");
147+
let generic_reg_file = if config.raw_access {
148+
include_str!("generic_reg_raw.rs")
149+
} else {
150+
include_str!("generic_reg_vcell.rs")
151+
};
144152
let generic_atomic_file = include_str!("generic_atomic.rs");
145153
if config.generic_mod {
146154
let mut file = File::create(

src/generate/generic_reg_raw.rs

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/// This structure provides unsafe volatile access to registers.
2+
pub struct Reg<REG: RegisterSpec> {
3+
ptr: *mut u8,
4+
_marker: marker::PhantomData<REG>,
5+
}
6+
7+
unsafe impl<REG: RegisterSpec> Send for Reg<REG> where REG::Ux: Send {}
8+
9+
impl<REG: RegisterSpec> Reg<REG> {
10+
#[inline(always)]
11+
pub const fn new(ptr: *mut u8) -> Self {
12+
Self {
13+
ptr,
14+
_marker: marker::PhantomData,
15+
}
16+
}
17+
/// Returns the underlying memory address of register.
18+
///
19+
/// ```ignore
20+
/// let reg_ptr = periph.reg.as_ptr();
21+
/// ```
22+
#[inline(always)]
23+
pub const fn as_ptr(&self) -> *mut REG::Ux {
24+
self.ptr.cast()
25+
}
26+
}
27+
28+
impl<REG: Readable> Reg<REG> {
29+
/// Reads the contents of a `Readable` register.
30+
///
31+
/// You can read the raw contents of a register by using `bits`:
32+
/// ```ignore
33+
/// let bits = periph.reg.read().bits();
34+
/// ```
35+
/// or get the content of a particular field of a register:
36+
/// ```ignore
37+
/// let reader = periph.reg.read();
38+
/// let bits = reader.field1().bits();
39+
/// let flag = reader.field2().bit_is_set();
40+
/// ```
41+
#[inline(always)]
42+
pub unsafe fn read(&self) -> R<REG> {
43+
R {
44+
bits: self.as_ptr().read_volatile(),
45+
_reg: marker::PhantomData,
46+
}
47+
}
48+
}
49+
50+
impl<REG: Resettable + Writable> Reg<REG> {
51+
/// Writes the reset value to `Writable` register.
52+
///
53+
/// Resets the register to its initial state.
54+
#[inline(always)]
55+
pub unsafe fn reset(&self) {
56+
self.as_ptr().write_volatile(REG::RESET_VALUE)
57+
}
58+
59+
/// Writes bits to a `Writable` register.
60+
///
61+
/// You can write raw bits into a register:
62+
/// ```ignore
63+
/// periph.reg.write(|w| unsafe { w.bits(rawbits) });
64+
/// ```
65+
/// or write only the fields you need:
66+
/// ```ignore
67+
/// periph.reg.write(|w| w
68+
/// .field1().bits(newfield1bits)
69+
/// .field2().set_bit()
70+
/// .field3().variant(VARIANT)
71+
/// );
72+
/// ```
73+
/// or an alternative way of saying the same:
74+
/// ```ignore
75+
/// periph.reg.write(|w| {
76+
/// w.field1().bits(newfield1bits);
77+
/// w.field2().set_bit();
78+
/// w.field3().variant(VARIANT)
79+
/// });
80+
/// ```
81+
/// In the latter case, other fields will be set to their reset value.
82+
#[inline(always)]
83+
pub unsafe fn write<F>(&self, f: F)
84+
where
85+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
86+
{
87+
self.as_ptr().write_volatile(
88+
f(&mut W {
89+
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
90+
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
91+
_reg: marker::PhantomData,
92+
})
93+
.bits,
94+
);
95+
}
96+
}
97+
98+
impl<REG: Writable> Reg<REG> {
99+
/// Writes 0 to a `Writable` register.
100+
///
101+
/// Similar to `write`, but unused bits will contain 0.
102+
///
103+
/// # Safety
104+
///
105+
/// Unsafe to use with registers which don't allow to write 0.
106+
#[inline(always)]
107+
pub unsafe fn write_with_zero<F>(&self, f: F)
108+
where
109+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
110+
{
111+
self.as_ptr().write_volatile(
112+
f(&mut W {
113+
bits: REG::Ux::default(),
114+
_reg: marker::PhantomData,
115+
})
116+
.bits,
117+
);
118+
}
119+
}
120+
121+
impl<REG: Readable + Writable> Reg<REG> {
122+
/// Modifies the contents of the register by reading and then writing it.
123+
///
124+
/// E.g. to do a read-modify-write sequence to change parts of a register:
125+
/// ```ignore
126+
/// periph.reg.modify(|r, w| unsafe { w.bits(
127+
/// r.bits() | 3
128+
/// ) });
129+
/// ```
130+
/// or
131+
/// ```ignore
132+
/// periph.reg.modify(|_, w| w
133+
/// .field1().bits(newfield1bits)
134+
/// .field2().set_bit()
135+
/// .field3().variant(VARIANT)
136+
/// );
137+
/// ```
138+
/// or an alternative way of saying the same:
139+
/// ```ignore
140+
/// periph.reg.modify(|_, w| {
141+
/// w.field1().bits(newfield1bits);
142+
/// w.field2().set_bit();
143+
/// w.field3().variant(VARIANT)
144+
/// });
145+
/// ```
146+
/// Other fields will have the value they had before the call to `modify`.
147+
#[inline(always)]
148+
pub unsafe fn modify<F>(&self, f: F)
149+
where
150+
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
151+
{
152+
let bits = self.as_ptr().read_volatile();
153+
self.as_ptr().write_volatile(
154+
f(
155+
&R {
156+
bits,
157+
_reg: marker::PhantomData,
158+
},
159+
&mut W {
160+
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
161+
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
162+
_reg: marker::PhantomData,
163+
},
164+
)
165+
.bits,
166+
);
167+
}
168+
}
169+
170+
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
171+
where
172+
R<REG>: core::fmt::Debug,
173+
{
174+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175+
unsafe { core::fmt::Debug::fmt(&self.read(), f) }
176+
}
177+
}

0 commit comments

Comments
 (0)