Skip to content

Commit 215ec91

Browse files
committed
raw_read_write
1 parent 9dc99c5 commit 215ec91

File tree

7 files changed

+356
-172
lines changed

7 files changed

+356
-172
lines changed

CHANGELOG.md

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

88
## [Unreleased]
99

10+
- Add `raw-access` and `raw-read-write` options
11+
1012
- Yet more clean field & register `Debug`
1113

1214
## [v0.33.2] - 2024-05-07

src/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct Config {
3636
pub field_names_for_enums: bool,
3737
pub base_address_shift: u64,
3838
pub raw_access: bool,
39+
pub raw_read_write: bool,
3940
}
4041

4142
#[allow(clippy::upper_case_acronyms)]

src/generate/device.rs

+7
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
140140
}
141141

142142
let generic_file = include_str!("generic.rs");
143+
let generic_reg_file = if config.raw_read_write {
144+
include_str!("generic_reg_raw.rs")
145+
} else {
146+
include_str!("generic_reg_vcell.rs")
147+
};
143148
let generic_atomic_file = include_str!("generic_atomic.rs");
144149
if config.generic_mod {
145150
let mut file = File::create(
@@ -150,6 +155,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
150155
.join("generic.rs"),
151156
)?;
152157
writeln!(file, "{generic_file}")?;
158+
writeln!(file, "{generic_reg_file}")?;
153159
if config.atomics {
154160
if let Some(atomics_feature) = config.atomics_feature.as_ref() {
155161
writeln!(file, "#[cfg(feature = \"{atomics_feature}\")]")?;
@@ -167,6 +173,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
167173
}
168174
} else {
169175
let mut tokens = syn::parse_file(generic_file)?.into_token_stream();
176+
syn::parse_file(generic_reg_file)?.to_tokens(&mut tokens);
170177
if config.atomics {
171178
if let Some(atomics_feature) = config.atomics_feature.as_ref() {
172179
quote!(#[cfg(feature = #atomics_feature)]).to_tokens(&mut tokens);

src/generate/generic.rs

-172
Original file line numberDiff line numberDiff line change
@@ -95,178 +95,6 @@ pub trait Resettable: RegisterSpec {
9595
}
9696
}
9797

98-
/// This structure provides volatile access to registers.
99-
#[repr(transparent)]
100-
pub struct Reg<REG: RegisterSpec> {
101-
register: vcell::VolatileCell<REG::Ux>,
102-
_marker: marker::PhantomData<REG>,
103-
}
104-
105-
unsafe impl<REG: RegisterSpec> Send for Reg<REG> where REG::Ux: Send {}
106-
107-
impl<REG: RegisterSpec> Reg<REG> {
108-
/// Returns the underlying memory address of register.
109-
///
110-
/// ```ignore
111-
/// let reg_ptr = periph.reg.as_ptr();
112-
/// ```
113-
#[inline(always)]
114-
pub fn as_ptr(&self) -> *mut REG::Ux {
115-
self.register.as_ptr()
116-
}
117-
}
118-
119-
impl<REG: Readable> Reg<REG> {
120-
/// Reads the contents of a `Readable` register.
121-
///
122-
/// You can read the raw contents of a register by using `bits`:
123-
/// ```ignore
124-
/// let bits = periph.reg.read().bits();
125-
/// ```
126-
/// or get the content of a particular field of a register:
127-
/// ```ignore
128-
/// let reader = periph.reg.read();
129-
/// let bits = reader.field1().bits();
130-
/// let flag = reader.field2().bit_is_set();
131-
/// ```
132-
#[inline(always)]
133-
pub fn read(&self) -> R<REG> {
134-
R {
135-
bits: self.register.get(),
136-
_reg: marker::PhantomData,
137-
}
138-
}
139-
}
140-
141-
impl<REG: Resettable + Writable> Reg<REG> {
142-
/// Writes the reset value to `Writable` register.
143-
///
144-
/// Resets the register to its initial state.
145-
#[inline(always)]
146-
pub fn reset(&self) {
147-
self.register.set(REG::RESET_VALUE)
148-
}
149-
150-
/// Writes bits to a `Writable` register.
151-
///
152-
/// You can write raw bits into a register:
153-
/// ```ignore
154-
/// periph.reg.write(|w| unsafe { w.bits(rawbits) });
155-
/// ```
156-
/// or write only the fields you need:
157-
/// ```ignore
158-
/// periph.reg.write(|w| w
159-
/// .field1().bits(newfield1bits)
160-
/// .field2().set_bit()
161-
/// .field3().variant(VARIANT)
162-
/// );
163-
/// ```
164-
/// or an alternative way of saying the same:
165-
/// ```ignore
166-
/// periph.reg.write(|w| {
167-
/// w.field1().bits(newfield1bits);
168-
/// w.field2().set_bit();
169-
/// w.field3().variant(VARIANT)
170-
/// });
171-
/// ```
172-
/// In the latter case, other fields will be set to their reset value.
173-
#[inline(always)]
174-
pub fn write<F>(&self, f: F)
175-
where
176-
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
177-
{
178-
self.register.set(
179-
f(&mut W {
180-
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
181-
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
182-
_reg: marker::PhantomData,
183-
})
184-
.bits,
185-
);
186-
}
187-
}
188-
189-
impl<REG: Writable> Reg<REG> {
190-
/// Writes 0 to a `Writable` register.
191-
///
192-
/// Similar to `write`, but unused bits will contain 0.
193-
///
194-
/// # Safety
195-
///
196-
/// Unsafe to use with registers which don't allow to write 0.
197-
#[inline(always)]
198-
pub unsafe fn write_with_zero<F>(&self, f: F)
199-
where
200-
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
201-
{
202-
self.register.set(
203-
f(&mut W {
204-
bits: REG::Ux::default(),
205-
_reg: marker::PhantomData,
206-
})
207-
.bits,
208-
);
209-
}
210-
}
211-
212-
impl<REG: Readable + Writable> Reg<REG> {
213-
/// Modifies the contents of the register by reading and then writing it.
214-
///
215-
/// E.g. to do a read-modify-write sequence to change parts of a register:
216-
/// ```ignore
217-
/// periph.reg.modify(|r, w| unsafe { w.bits(
218-
/// r.bits() | 3
219-
/// ) });
220-
/// ```
221-
/// or
222-
/// ```ignore
223-
/// periph.reg.modify(|_, w| w
224-
/// .field1().bits(newfield1bits)
225-
/// .field2().set_bit()
226-
/// .field3().variant(VARIANT)
227-
/// );
228-
/// ```
229-
/// or an alternative way of saying the same:
230-
/// ```ignore
231-
/// periph.reg.modify(|_, w| {
232-
/// w.field1().bits(newfield1bits);
233-
/// w.field2().set_bit();
234-
/// w.field3().variant(VARIANT)
235-
/// });
236-
/// ```
237-
/// Other fields will have the value they had before the call to `modify`.
238-
#[inline(always)]
239-
pub fn modify<F>(&self, f: F)
240-
where
241-
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
242-
{
243-
let bits = self.register.get();
244-
self.register.set(
245-
f(
246-
&R {
247-
bits,
248-
_reg: marker::PhantomData,
249-
},
250-
&mut W {
251-
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
252-
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
253-
_reg: marker::PhantomData,
254-
},
255-
)
256-
.bits,
257-
);
258-
}
259-
}
260-
261-
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
262-
where
263-
R<REG>: core::fmt::Debug
264-
{
265-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
266-
core::fmt::Debug::fmt(&self.read(), f)
267-
}
268-
}
269-
27098
#[doc(hidden)]
27199
pub mod raw {
272100
use super::{marker, BitM, FieldSpec, RegisterSpec, Unsafe, Writable};

src/generate/generic_reg_raw.rs

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

0 commit comments

Comments
 (0)