Skip to content

Commit 7c5a312

Browse files
committed
always raw access
1 parent bb9a5c7 commit 7c5a312

File tree

7 files changed

+498
-55
lines changed

7 files changed

+498
-55
lines changed

CHANGELOG.md

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

1010
## [v0.34.0] - 2024-11-05
1111

12+
- Add `raw-access` options
13+
1214
- Revert #711
1315
- Add `defmt` impls for `TryFromInterruptError`, riscv interrupt enums
1416
- Fix calculating `modifiedWriteValues` bitmasks with field arrays
@@ -924,10 +926,7 @@ peripheral.register.write(|w| w.field().set());
924926

925927
- Initial version of the `svd2rust` tool
926928

927-
[Unreleased]: https://github.com/rust-embedded/svd2rust/compare/v0.34.0...HEAD
928-
[v0.34.0]: https://github.com/rust-embedded/svd2rust/compare/v0.33.5...v0.34.0
929-
[v0.33.5]: https://github.com/rust-embedded/svd2rust/compare/v0.33.4...v0.33.5
930-
[v0.33.4]: https://github.com/rust-embedded/svd2rust/compare/v0.33.3...v0.33.4
929+
[Unreleased]: https://github.com/rust-embedded/svd2rust/compare/v0.33.3...HEAD
931930
[v0.33.3]: https://github.com/rust-embedded/svd2rust/compare/v0.33.2...v0.33.3
932931
[v0.33.2]: https://github.com/rust-embedded/svd2rust/compare/v0.33.1...v0.33.2
933932
[v0.33.1]: https://github.com/rust-embedded/svd2rust/compare/v0.33.0...v0.33.1

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 html_url: Option<url::Url>,
39+
pub raw_access: bool,
3940
/// Path to YAML file with chip-specific settings
4041
pub settings: Option<PathBuf>,
4142
}

src/generate/device.rs

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

7777
out.extend(quote! {
7878
use core::ops::Deref;
79-
use core::marker::PhantomData;
8079
});
80+
if !config.raw_access {
81+
out.extend(quote! {
82+
use core::marker::PhantomData;
83+
});
84+
}
8185

8286
// Retaining the previous assumption
8387
let mut fpu_present = true;
@@ -153,7 +157,11 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
153157
}
154158

155159
let generic_file = include_str!("generic.rs");
156-
let generic_reg_file = include_str!("generic_reg_vcell.rs");
160+
let generic_reg_file = if config.raw_access {
161+
include_str!("generic_reg_raw.rs")
162+
} else {
163+
include_str!("generic_reg_vcell.rs")
164+
};
157165
let generic_atomic_file = include_str!("generic_atomic.rs");
158166
if config.generic_mod {
159167
let mut file = File::create(

src/generate/generic_reg_raw.rs

+301
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
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) -> REG::Ux
84+
where
85+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
86+
{
87+
let value = f(&mut W {
88+
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
89+
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
90+
_reg: marker::PhantomData,
91+
})
92+
.bits;
93+
self.as_ptr().write_volatile(value);
94+
value
95+
}
96+
97+
/// Writes bits to a `Writable` register and produce a value.
98+
///
99+
/// You can write raw bits into a register:
100+
/// ```ignore
101+
/// periph.reg.write_and(|w| unsafe { w.bits(rawbits); });
102+
/// ```
103+
/// or write only the fields you need:
104+
/// ```ignore
105+
/// periph.reg.write_and(|w| {
106+
/// w.field1().bits(newfield1bits)
107+
/// .field2().set_bit()
108+
/// .field3().variant(VARIANT);
109+
/// });
110+
/// ```
111+
/// or an alternative way of saying the same:
112+
/// ```ignore
113+
/// periph.reg.write_and(|w| {
114+
/// w.field1().bits(newfield1bits);
115+
/// w.field2().set_bit();
116+
/// w.field3().variant(VARIANT);
117+
/// });
118+
/// ```
119+
/// In the latter case, other fields will be set to their reset value.
120+
///
121+
/// Values can be returned from the closure:
122+
/// ```ignore
123+
/// let state = periph.reg.write_and(|w| State::set(w.field1()));
124+
/// ```
125+
#[inline(always)]
126+
pub fn from_write<F, T>(&self, f: F) -> T
127+
where
128+
F: FnOnce(&mut W<REG>) -> T,
129+
{
130+
let mut writer = W {
131+
bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP
132+
| REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
133+
_reg: marker::PhantomData,
134+
};
135+
let result = f(&mut writer);
136+
137+
self.as_ptr().write_volatile(writer.bits);
138+
139+
result
140+
}
141+
}
142+
143+
impl<REG: Writable> Reg<REG> {
144+
/// Writes 0 to a `Writable` register.
145+
///
146+
/// Similar to `write`, but unused bits will contain 0.
147+
///
148+
/// # Safety
149+
///
150+
/// Unsafe to use with registers which don't allow to write 0.
151+
#[inline(always)]
152+
pub unsafe fn write_with_zero<F>(&self, f: F)
153+
where
154+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
155+
{
156+
let value = f(&mut W {
157+
bits: REG::Ux::default(),
158+
_reg: marker::PhantomData,
159+
})
160+
.bits;
161+
self.as_ptr().write_volatile(value);
162+
value
163+
}
164+
165+
/// Writes 0 to a `Writable` register and produces a value.
166+
///
167+
/// Similar to `write`, but unused bits will contain 0.
168+
///
169+
/// # Safety
170+
///
171+
/// Unsafe to use with registers which don't allow to write 0.
172+
#[inline(always)]
173+
pub unsafe fn from_write_with_zero<F, T>(&self, f: F) -> T
174+
where
175+
F: FnOnce(&mut W<REG>) -> T,
176+
{
177+
let mut writer = W {
178+
bits: REG::Ux::default(),
179+
_reg: marker::PhantomData,
180+
};
181+
182+
let result = f(&mut writer);
183+
184+
self.as_ptr().write_volatile(writer.bits);
185+
186+
result
187+
}
188+
}
189+
190+
impl<REG: Readable + Writable> Reg<REG> {
191+
/// Modifies the contents of the register by reading and then writing it.
192+
///
193+
/// E.g. to do a read-modify-write sequence to change parts of a register:
194+
/// ```ignore
195+
/// periph.reg.modify(|r, w| unsafe { w.bits(
196+
/// r.bits() | 3
197+
/// ) });
198+
/// ```
199+
/// or
200+
/// ```ignore
201+
/// periph.reg.modify(|_, w| w
202+
/// .field1().bits(newfield1bits)
203+
/// .field2().set_bit()
204+
/// .field3().variant(VARIANT)
205+
/// );
206+
/// ```
207+
/// or an alternative way of saying the same:
208+
/// ```ignore
209+
/// periph.reg.modify(|_, w| {
210+
/// w.field1().bits(newfield1bits);
211+
/// w.field2().set_bit();
212+
/// w.field3().variant(VARIANT)
213+
/// });
214+
/// ```
215+
/// Other fields will have the value they had before the call to `modify`.
216+
#[inline(always)]
217+
pub unsafe fn modify<F>(&self, f: F)
218+
where
219+
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
220+
{
221+
let bits = self.as_ptr().read_volatile();
222+
let value = f(
223+
&R {
224+
bits,
225+
_reg: marker::PhantomData,
226+
},
227+
&mut W {
228+
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
229+
_reg: marker::PhantomData,
230+
},
231+
)
232+
.bits;
233+
self.as_ptr().write_volatile(value);
234+
value
235+
}
236+
237+
/// Modifies the contents of the register by reading and then writing it
238+
/// and produces a value.
239+
///
240+
/// E.g. to do a read-modify-write sequence to change parts of a register:
241+
/// ```ignore
242+
/// let bits = periph.reg.modify(|r, w| {
243+
/// let new_bits = r.bits() | 3;
244+
/// unsafe {
245+
/// w.bits(new_bits);
246+
/// }
247+
///
248+
/// new_bits
249+
/// });
250+
/// ```
251+
/// or
252+
/// ```ignore
253+
/// periph.reg.modify(|_, w| {
254+
/// w.field1().bits(newfield1bits)
255+
/// .field2().set_bit()
256+
/// .field3().variant(VARIANT);
257+
/// });
258+
/// ```
259+
/// or an alternative way of saying the same:
260+
/// ```ignore
261+
/// periph.reg.modify(|_, w| {
262+
/// w.field1().bits(newfield1bits);
263+
/// w.field2().set_bit();
264+
/// w.field3().variant(VARIANT);
265+
/// });
266+
/// ```
267+
/// Other fields will have the value they had before the call to `modify`.
268+
#[inline(always)]
269+
pub fn from_modify<F, T>(&self, f: F) -> T
270+
where
271+
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> T,
272+
{
273+
let bits = self.as_ptr().read_volatile();
274+
275+
let mut writer = W {
276+
bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP,
277+
_reg: marker::PhantomData,
278+
};
279+
280+
let result = f(
281+
&R {
282+
bits,
283+
_reg: marker::PhantomData,
284+
},
285+
&mut writer,
286+
);
287+
288+
self.as_ptr().write_volatile(writer.bits);
289+
290+
result
291+
}
292+
}
293+
294+
impl<REG: Readable> core::fmt::Debug for crate::generic::Reg<REG>
295+
where
296+
R<REG>: core::fmt::Debug,
297+
{
298+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
299+
unsafe { core::fmt::Debug::fmt(&self.read(), f) }
300+
}
301+
}

0 commit comments

Comments
 (0)