Skip to content

Commit 6cd9ead

Browse files
committed
add write_and, write_with_zero_and, and modify_and
1 parent 294e211 commit 6cd9ead

File tree

1 file changed

+126
-1
lines changed

1 file changed

+126
-1
lines changed

src/generate/generic_reg_vcell.rs

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,51 @@ impl<REG: Resettable + Writable> Reg<REG> {
8787
.bits,
8888
);
8989
}
90+
91+
/// Writes bits to a `Writable` register and produce a value.
92+
///
93+
/// You can write raw bits into a register:
94+
/// ```ignore
95+
/// periph.reg.write_and(|w| unsafe { w.bits(rawbits); });
96+
/// ```
97+
/// or write only the fields you need:
98+
/// ```ignore
99+
/// periph.reg.write_and(|w| {
100+
/// w.field1().bits(newfield1bits)
101+
/// .field2().set_bit()
102+
/// .field3().variant(VARIANT);
103+
/// });
104+
/// ```
105+
/// or an alternative way of saying the same:
106+
/// ```ignore
107+
/// periph.reg.write_and(|w| {
108+
/// w.field1().bits(newfield1bits);
109+
/// w.field2().set_bit();
110+
/// w.field3().variant(VARIANT);
111+
/// });
112+
/// ```
113+
/// In the latter case, other fields will be set to their reset value.
114+
///
115+
/// Values can be returned from the closure:
116+
/// ```ignore
117+
/// let state = periph.reg.write_and(|w| State::set(w.field1()));
118+
/// ```
119+
#[inline(always)]
120+
pub fn write_and<F, T>(&self, f: F) -> T
121+
where
122+
F: FnOnce(&mut W<REG>) -> T,
123+
{
124+
let mut writer = W {
125+
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
126+
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
127+
_reg: marker::PhantomData,
128+
};
129+
let result = f(&mut writer);
130+
131+
self.register.set(writer.bits);
132+
133+
result
134+
}
90135
}
91136

92137
impl<REG: Writable> Reg<REG> {
@@ -110,6 +155,30 @@ impl<REG: Writable> Reg<REG> {
110155
.bits,
111156
);
112157
}
158+
159+
/// Writes 0 to a `Writable` register and produces a value.
160+
///
161+
/// Similar to `write`, but unused bits will contain 0.
162+
///
163+
/// # Safety
164+
///
165+
/// Unsafe to use with registers which don't allow to write 0.
166+
#[inline(always)]
167+
pub unsafe fn write_with_zero<F, T>(&self, f: F) -> T
168+
where
169+
F: FnOnce(&mut W<REG>) -> T,
170+
{
171+
let mut writer = W {
172+
bits: REG::Ux::default(),
173+
_reg: marker::PhantomData,
174+
};
175+
176+
let result = f(&mut writer);
177+
178+
self.register.set(writer.bits);
179+
180+
result
181+
}
113182
}
114183

115184
impl<REG: Readable + Writable> Reg<REG> {
@@ -159,11 +228,67 @@ impl<REG: Readable + Writable> Reg<REG> {
159228
.bits,
160229
);
161230
}
231+
232+
/// Modifies the contents of the register by reading and then writing it
233+
/// and produces a value.
234+
///
235+
/// E.g. to do a read-modify-write sequence to change parts of a register:
236+
/// ```ignore
237+
/// let bits = periph.reg.modify(|r, w| {
238+
/// let new_bits = r.bits() | 3;
239+
/// unsafe {
240+
/// w.bits(new_bits);
241+
/// }
242+
///
243+
/// new_bits
244+
/// });
245+
/// ```
246+
/// or
247+
/// ```ignore
248+
/// periph.reg.modify(|_, w| {
249+
/// w.field1().bits(newfield1bits)
250+
/// .field2().set_bit()
251+
/// .field3().variant(VARIANT);
252+
/// });
253+
/// ```
254+
/// or an alternative way of saying the same:
255+
/// ```ignore
256+
/// periph.reg.modify(|_, w| {
257+
/// w.field1().bits(newfield1bits);
258+
/// w.field2().set_bit();
259+
/// w.field3().variant(VARIANT);
260+
/// });
261+
/// ```
262+
/// Other fields will have the value they had before the call to `modify`.
263+
#[inline(always)]
264+
pub fn modify_and<F, T>(&self, f: F) -> T
265+
where
266+
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> T,
267+
{
268+
let bits = self.register.get();
269+
270+
let mut writer = W {
271+
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
272+
_reg: marker::PhantomData,
273+
};
274+
275+
let result = f(
276+
&R {
277+
bits,
278+
_reg: marker::PhantomData,
279+
},
280+
&mut writer,
281+
);
282+
283+
self.register.set(writer.bits);
284+
285+
result
286+
}
162287
}
163288

164289
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
165290
where
166-
R<REG>: core::fmt::Debug
291+
R<REG>: core::fmt::Debug,
167292
{
168293
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
169294
core::fmt::Debug::fmt(&self.read(), f)

0 commit comments

Comments
 (0)