Skip to content

Commit 5356990

Browse files
bors[bot]couchand
andauthored
Merge #464
464: Register spec & traits r=therealprof a=couchand Part 1 of #463. - Publishes the register spec zero-sized type and moves all relevant register traits to that struct, which fixes #459 and improves generated documentation. - Removes the extra type parameter on `Reg`, making the register spec the sole authority on the shape of the register (but not its address). One thing that's changed since the previous PR, this renames the spec struct so that it won't cause a conflict on NXP, Freescale, and possibly other architectures. I've gone with `register::REGISTER_SPEC` since that seems reasonably clear and I can't think of how it would cause a conflict (but I'm ready to be proven wrong since I've tried several ideas only to be stymied by various architectures' oddball register naming patterns). I'd prefer the spec to be in the parent module, but I can't come up with a way to do that which guarantees that the generated code will be free from naming conflicts. This seems good enough, plus it maintains the rule that when we make up a name it belongs in the child mod (except for `RegisterBlock`). There is potential for breaking changes here, though the impact seems pretty minimal. Specifically: - If users referred to the traits in `mod generic`, their usage would break. Writing code referring to those traits was previously pretty awkward (see #463), and this PR makes such usage much more ergonomic, so it would seem to be a net benefit. - If users named the full reader/writer incantation the reference would break. It doesn't seem users are likely to name the readers/writers at all, but if they do it seems very likely they would use the type alias. - If users named the previously `#[docs(hidden)] ` spec struct the reference would break. I don't see why they would have done so. - If users patched something in to the generated module with the same name as our new register spec, it would break. That case seems highly unlikely. r? @burrbull Co-authored-by: Andrew Dona-Couch <hi@andrewcou.ch>
2 parents 69fb8f2 + 9f0df96 commit 5356990

File tree

2 files changed

+125
-116
lines changed

2 files changed

+125
-116
lines changed

src/generate/generic.rs

Lines changed: 86 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,53 @@
11
use core::marker;
22

3+
/// Raw register type
4+
pub trait RegisterSpec {
5+
/// Raw register type (`u8`, `u16`, `u32`, ...).
6+
type Ux: Copy;
7+
}
8+
39
/// Trait implemented by readable registers to enable the `read` method.
410
///
511
/// Registers marked with `Writable` can be also `modify`'ed.
6-
pub trait Readable {}
12+
pub trait Readable: RegisterSpec {}
713

814
/// Trait implemented by writeable registers.
915
///
1016
/// This enables the `write`, `write_with_zero` and `reset` methods.
1117
///
1218
/// Registers marked with `Readable` can be also `modify`'ed.
13-
pub trait Writable {}
14-
19+
pub trait Writable: RegisterSpec {}
1520

16-
/// Raw register type (autoimplemented for `Reg` type)
17-
pub trait RawType {
18-
/// Raw register type (`u8`, `u16`, `u32`, ...).
19-
type Ux: Copy;
20-
}
2121
/// Reset value of the register.
2222
///
2323
/// This value is the initial value for the `write` method. It can also be directly written to the
2424
/// register by using the `reset` method.
25-
pub trait ResetValue: RawType {
25+
pub trait Resettable: RegisterSpec {
2626
/// Reset value of the register.
2727
fn reset_value() -> Self::Ux;
2828
}
2929

3030
/// This structure provides volatile access to registers.
31-
pub struct Reg<U, REG> {
32-
register: vcell::VolatileCell<U>,
31+
pub struct Reg<REG: RegisterSpec> {
32+
register: vcell::VolatileCell<REG::Ux>,
3333
_marker: marker::PhantomData<REG>,
3434
}
3535

36-
unsafe impl<U: Send, REG> Send for Reg<U, REG> {}
36+
unsafe impl<REG: RegisterSpec> Send for Reg<REG> where REG::Ux: Send {}
3737

38-
impl<U, REG> Reg<U, REG>
39-
where
40-
U: Copy,
41-
{
38+
impl<REG: RegisterSpec> Reg<REG> {
4239
/// Returns the underlying memory address of register.
4340
///
4441
/// ```ignore
4542
/// let reg_ptr = periph.reg.as_ptr();
4643
/// ```
4744
#[inline(always)]
48-
pub fn as_ptr(&self) -> *mut U {
45+
pub fn as_ptr(&self) -> *mut REG::Ux {
4946
self.register.as_ptr()
5047
}
5148
}
5249

53-
impl<U, REG> Reg<U, REG>
54-
where
55-
Self: Readable,
56-
U: Copy,
57-
{
50+
impl<REG: Readable> Reg<REG> {
5851
/// Reads the contents of a `Readable` register.
5952
///
6053
/// You can read the raw contents of a register by using `bits`:
@@ -68,40 +61,23 @@ where
6861
/// let flag = reader.field2().bit_is_set();
6962
/// ```
7063
#[inline(always)]
71-
pub fn read(&self) -> R<U, Self> {
64+
pub fn read(&self) -> R<REG> {
7265
R {
7366
bits: self.register.get(),
7467
_reg: marker::PhantomData,
7568
}
7669
}
7770
}
7871

79-
impl<U, REG> RawType for Reg<U, REG>
80-
where
81-
U: Copy,
82-
{
83-
type Ux = U;
84-
}
85-
86-
impl<U, REG> Reg<U, REG>
87-
where
88-
Self: ResetValue + RawType<Ux = U> + Writable,
89-
U: Copy,
90-
{
72+
impl<REG: Resettable + Writable> Reg<REG> {
9173
/// Writes the reset value to `Writable` register.
9274
///
9375
/// Resets the register to its initial state.
9476
#[inline(always)]
9577
pub fn reset(&self) {
96-
self.register.set(Self::reset_value())
78+
self.register.set(REG::reset_value())
9779
}
98-
}
9980

100-
impl<U, REG> Reg<U, REG>
101-
where
102-
Self: ResetValue + RawType<Ux = U> + Writable,
103-
U: Copy
104-
{
10581
/// Writes bits to a `Writable` register.
10682
///
10783
/// You can write raw bits into a register:
@@ -120,46 +96,41 @@ where
12096
#[inline(always)]
12197
pub fn write<F>(&self, f: F)
12298
where
123-
F: FnOnce(&mut W<U, Self>) -> &mut W<U, Self>,
99+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
124100
{
125101
self.register.set(
126102
f(&mut W {
127-
bits: Self::reset_value(),
103+
bits: REG::reset_value(),
128104
_reg: marker::PhantomData,
129105
})
130106
.bits,
131107
);
132108
}
133109
}
134110

135-
impl<U, REG> Reg<U, REG>
111+
impl<REG: Writable> Reg<REG>
136112
where
137-
Self: Writable,
138-
U: Copy + Default,
113+
REG::Ux: Default,
139114
{
140115
/// Writes 0 to a `Writable` register.
141116
///
142117
/// Similar to `write`, but unused bits will contain 0.
143118
#[inline(always)]
144119
pub fn write_with_zero<F>(&self, f: F)
145120
where
146-
F: FnOnce(&mut W<U, Self>) -> &mut W<U, Self>,
121+
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
147122
{
148123
self.register.set(
149124
f(&mut W {
150-
bits: U::default(),
125+
bits: REG::Ux::default(),
151126
_reg: marker::PhantomData,
152127
})
153128
.bits,
154129
);
155130
}
156131
}
157132

158-
impl<U, REG> Reg<U, REG>
159-
where
160-
Self: Readable + Writable,
161-
U: Copy,
162-
{
133+
impl<REG: Readable + Writable> Reg<REG> {
163134
/// Modifies the contents of the register by reading and then writing it.
164135
///
165136
/// E.g. to do a read-modify-write sequence to change parts of a register:
@@ -180,7 +151,7 @@ where
180151
#[inline(always)]
181152
pub fn modify<F>(&self, f: F)
182153
where
183-
for<'w> F: FnOnce(&R<U, Self>, &'w mut W<U, Self>) -> &'w mut W<U, Self>,
154+
for<'w> F: FnOnce(&R<REG>, &'w mut W<REG>) -> &'w mut W<REG>,
184155
{
185156
let bits = self.register.get();
186157
self.register.set(
@@ -199,16 +170,70 @@ where
199170
}
200171
}
201172

202-
/// Register/field reader.
173+
/// Register reader.
203174
///
204175
/// Result of the `read` methods of registers. Also used as a closure argument in the `modify`
205176
/// method.
206-
pub struct R<U, T> {
177+
pub struct R<REG: RegisterSpec> {
178+
pub(crate) bits: REG::Ux,
179+
_reg: marker::PhantomData<REG>,
180+
}
181+
182+
impl<REG: RegisterSpec> R<REG> {
183+
/// Reads raw bits from register.
184+
#[inline(always)]
185+
pub fn bits(&self) -> REG::Ux {
186+
self.bits
187+
}
188+
}
189+
190+
impl<REG: RegisterSpec, FI> PartialEq<FI> for R<REG>
191+
where
192+
REG::Ux: PartialEq,
193+
FI: Copy + Into<REG::Ux>,
194+
{
195+
#[inline(always)]
196+
fn eq(&self, other: &FI) -> bool {
197+
self.bits.eq(&(*other).into())
198+
}
199+
}
200+
201+
/// Register writer.
202+
///
203+
/// Used as an argument to the closures in the `write` and `modify` methods of the register.
204+
pub struct W<REG: RegisterSpec> {
205+
///Writable bits
206+
pub(crate) bits: REG::Ux,
207+
_reg: marker::PhantomData<REG>,
208+
}
209+
210+
impl<REG: RegisterSpec> W<REG> {
211+
/// Writes raw bits to the register.
212+
#[inline(always)]
213+
pub unsafe fn bits(&mut self, bits: REG::Ux) -> &mut Self {
214+
self.bits = bits;
215+
self
216+
}
217+
}
218+
219+
/// Used if enumerated values cover not the whole range.
220+
#[derive(Clone, Copy, PartialEq)]
221+
pub enum Variant<U, T> {
222+
/// Expected variant.
223+
Val(T),
224+
/// Raw bits.
225+
Res(U),
226+
}
227+
228+
/// Field reader.
229+
///
230+
/// Result of the `read` methods of fields.
231+
pub struct FieldReader<U, T> {
207232
pub(crate) bits: U,
208233
_reg: marker::PhantomData<T>,
209234
}
210235

211-
impl<U, T> R<U, T>
236+
impl<U, T> FieldReader<U, T>
212237
where
213238
U: Copy,
214239
{
@@ -221,14 +246,14 @@ where
221246
}
222247
}
223248

224-
/// Reads raw bits from register/field.
249+
/// Reads raw bits from field.
225250
#[inline(always)]
226251
pub fn bits(&self) -> U {
227252
self.bits
228253
}
229254
}
230255

231-
impl<U, T, FI> PartialEq<FI> for R<U, T>
256+
impl<U, T, FI> PartialEq<FI> for FieldReader<U, T>
232257
where
233258
U: PartialEq,
234259
FI: Copy + Into<U>,
@@ -239,7 +264,7 @@ where
239264
}
240265
}
241266

242-
impl<FI> R<bool, FI> {
267+
impl<FI> FieldReader<bool, FI> {
243268
/// Value of the field as raw bits.
244269
#[inline(always)]
245270
pub fn bit(&self) -> bool {
@@ -256,30 +281,3 @@ impl<FI> R<bool, FI> {
256281
self.bit()
257282
}
258283
}
259-
260-
/// Register writer.
261-
///
262-
/// Used as an argument to the closures in the `write` and `modify` methods of the register.
263-
pub struct W<U, REG> {
264-
///Writable bits
265-
pub(crate) bits: U,
266-
_reg: marker::PhantomData<REG>,
267-
}
268-
269-
impl<U, REG> W<U, REG> {
270-
/// Writes raw bits to the register.
271-
#[inline(always)]
272-
pub unsafe fn bits(&mut self, bits: U) -> &mut Self {
273-
self.bits = bits;
274-
self
275-
}
276-
}
277-
278-
/// Used if enumerated values cover not the whole range.
279-
#[derive(Clone, Copy, PartialEq)]
280-
pub enum Variant<U, T> {
281-
/// Expected variant.
282-
Val(T),
283-
/// Raw bits.
284-
Res(U),
285-
}

0 commit comments

Comments
 (0)