Skip to content

Commit a28111e

Browse files
bors[bot]burrbull
andcommitted
Merge #365
365: fix docs+examples, work without reset, fixes r=therealprof a=burrbull r? @therealprof Add more docs as @Disasm proposed. Restore `unsafe` on `W::bits()` I somewhere lost. Don't generate `write` if `reset_value` is not present. #258 Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
2 parents 0a027e4 + fe27531 commit a28111e

File tree

4 files changed

+107
-42
lines changed

4 files changed

+107
-42
lines changed

CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- `variant()` method for field reader and `Variant` enum for fields with reserved values
1313

14+
- Update documentation, add examples for register access methods
15+
16+
- Add `write_with_zero` method for registers without reset value
17+
1418
### Changed
1519

16-
- Field readers and writers use one enum where it is possible
20+
- Field readers and writers use one enum where it is possible
21+
22+
- Replace register and its reader/writer by generic types
1723

18-
- Replace register and its reader/writer by generic types
24+
- Restore `unsafe` marker on register writer `bits()` method
1925

2026
## [v0.15.2] - 2019-07-29
2127

src/generate/generic.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,16 @@ where
4242
{
4343
///Reads the contents of `Readable` register
4444
///
45-
///See [reading](https://rust-embedded.github.io/book/start/registers.html#reading) in book.
45+
///You can read the contents of a register in such way:
46+
///```ignore
47+
///let bits = periph.reg.read().bits();
48+
///```
49+
///or get the content of a particular field of a register.
50+
///```ignore
51+
///let reader = periph.reg.read();
52+
///let bits = reader.field1().bits();
53+
///let flag = reader.field2().bit_is_set();
54+
///```
4655
#[inline(always)]
4756
pub fn read(&self) -> R<U, Self> {
4857
R {bits: self.register.get(), _reg: marker::PhantomData}
@@ -55,6 +64,8 @@ where
5564
U: Copy,
5665
{
5766
///Writes the reset value to `Writable` register
67+
///
68+
///Resets the register to its initial state
5869
#[inline(always)]
5970
pub fn reset(&self) {
6071
self.register.set(Self::reset_value())
@@ -68,7 +79,19 @@ where
6879
{
6980
///Writes bits to `Writable` register
7081
///
71-
///See [writing](https://rust-embedded.github.io/book/start/registers.html#writing) in book.
82+
///You can write raw bits into a register:
83+
///```ignore
84+
///periph.reg.write(|w| unsafe { w.bits(rawbits) });
85+
///```
86+
///or write only the fields you need:
87+
///```ignore
88+
///periph.reg.write(|w| w
89+
/// .field1().bits(newfield1bits)
90+
/// .field2().set_bit()
91+
/// .field3().variant(VARIANT)
92+
///);
93+
///```
94+
///Other fields will have reset value.
7295
#[inline(always)]
7396
pub fn write<F>(&self, f: F)
7497
where
@@ -84,6 +107,8 @@ where
84107
U: Copy + Default
85108
{
86109
///Writes Zero to `Writable` register
110+
///
111+
///Similar to `write`, but unused bits will contain 0.
87112
#[inline(always)]
88113
pub fn write_with_zero<F>(&self, f: F)
89114
where
@@ -100,7 +125,21 @@ where
100125
{
101126
///Modifies the contents of the register
102127
///
103-
///See [modifying](https://rust-embedded.github.io/book/start/registers.html#modifying) in book.
128+
///E.g. to do a read-modify-write sequence to change parts of a register:
129+
///```ignore
130+
///periph.reg.modify(|r, w| unsafe { w.bits(
131+
/// r.bits() | 3
132+
///) });
133+
///```
134+
///or
135+
///```ignore
136+
///periph.reg.modify(|_, w| w
137+
/// .field1().bits(newfield1bits)
138+
/// .field2().set_bit()
139+
/// .field3().variant(VARIANT)
140+
///);
141+
///```
142+
///Other fields will have value they had before call `modify`.
104143
#[inline(always)]
105144
pub fn modify<F>(&self, f: F)
106145
where
@@ -112,6 +151,9 @@ where
112151
}
113152

114153
///Register/field reader
154+
///
155+
///Result of the [`read`](Reg::read) method of a register.
156+
///Also it can be used in the [`modify`](Reg::read) method
115157
pub struct R<U, T> {
116158
pub(crate) bits: U,
117159
_reg: marker::PhantomData<T>,
@@ -141,6 +183,7 @@ where
141183
U: PartialEq,
142184
FI: ToBits<U>
143185
{
186+
#[inline(always)]
144187
fn eq(&self, other: &FI) -> bool {
145188
self.bits.eq(&other._bits())
146189
}
@@ -165,16 +208,18 @@ impl<FI> R<bool, FI> {
165208
}
166209

167210
///Register writer
211+
///
212+
///Used as an argument to the closures in the [`write`](Reg::write) and [`modify`](Reg::modify) methods of the register
168213
pub struct W<U, REG> {
169214
///Writable bits
170-
pub bits: U,
215+
pub(crate) bits: U,
171216
_reg: marker::PhantomData<REG>,
172217
}
173218

174219
impl<U, REG> W<U, REG> {
175220
///Writes raw bits to the register
176221
#[inline(always)]
177-
pub fn bits(&mut self, bits: U) -> &mut Self {
222+
pub unsafe fn bits(&mut self, bits: U) -> &mut Self {
178223
self.bits = bits;
179224
self
180225
}

src/generate/register.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,28 @@ pub fn render(
5454
}
5555

5656
if can_write {
57-
let rv = register
58-
.reset_value
59-
.or(defs.reset_value)
60-
.map(|v| util::hex(v as u64))
61-
.ok_or_else(|| format!("Register {} has no reset value", register.name))?;
62-
6357
let desc = format!("Writer for register {}", register.name);
64-
let doc = format!("Register {} `reset()`'s with value {}", register.name, &rv);
6558
mod_items.push(quote! {
6659
#[doc = #desc]
6760
pub type W = crate::W<#rty, super::#name_pc>;
68-
#[doc = #doc]
69-
impl crate::ResetValue for super::#name_pc {
70-
type Type = #rty;
71-
#[inline(always)]
72-
fn reset_value() -> Self::Type { #rv }
73-
}
7461
});
75-
methods.push("reset");
76-
methods.push("write");
62+
let res_val = register
63+
.reset_value
64+
.or(defs.reset_value)
65+
.map(|v| util::hex(v as u64));
66+
if let Some(rv) = res_val {
67+
let doc = format!("Register {} `reset()`'s with value {}", register.name, &rv);
68+
mod_items.push(quote! {
69+
#[doc = #doc]
70+
impl crate::ResetValue for super::#name_pc {
71+
type Type = #rty;
72+
#[inline(always)]
73+
fn reset_value() -> Self::Type { #rv }
74+
}
75+
});
76+
methods.push("reset");
77+
methods.push("write");
78+
}
7779
methods.push("write_with_zero");
7880
}
7981

src/lib.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,14 @@
226226
//! ..
227227
//! }
228228
//! }
229+
//! impl crate::ResetValue for CR2 {
230+
//! type Type = u32;
231+
//! fn reset_value() -> Self::Type { 0 }
232+
//! }
229233
//! ```
230234
//!
235+
//! ## `read`
236+
//!
231237
//! The `read` method "reads" the register using a **single**, volatile `LDR` instruction and
232238
//! returns a proxy `R` struct that allows access to only the readable bits (i.e. not to the
233239
//! reserved or write-only bits) of the `CR2` register:
@@ -236,10 +242,10 @@
236242
//! /// Value read from the register
237243
//! impl R {
238244
//! /// Bit 0 - Slave address bit 0 (master mode)
239-
//! pub fn sadd0(&self) -> SADD0R { .. }
245+
//! pub fn sadd0(&self) -> SADD0_R { .. }
240246
//!
241247
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
242-
//! pub fn sadd1(&self) -> SADD1R { .. }
248+
//! pub fn sadd1(&self) -> SADD1_R { .. }
243249
//!
244250
//! (..)
245251
//! }
@@ -256,26 +262,30 @@
256262
//! }
257263
//! ```
258264
//!
265+
//! ## `reset`
266+
//!
267+
//! The `ResetValue` trait provides `reset_value` which returns the value of the `CR2`
268+
//! register after a reset. This value can be used to modify the
269+
//! writable bitfields of the `CR2` register or reset it to its initial state.
270+
//! Usage looks like this:
271+
//!
272+
//! ```ignore
273+
//! if i2c1.c2r.write().reset()
274+
//! ```
275+
//!
276+
//! ## `write`
277+
//!
259278
//! On the other hand, the `write` method writes some value to the register using a **single**,
260279
//! volatile `STR` instruction. This method involves a `W` struct that only allows constructing
261280
//! valid states of the `CR2` register.
262281
//!
263-
//! The only constructor that `W` provides is `reset_value` which returns the value of the `CR2`
264-
//! register after a reset. The rest of `W` methods are "builder-like" and can be used to modify the
265-
//! writable bitfields of the `CR2` register.
266-
//!
267282
//! ```ignore
268-
//! impl CR2W {
269-
//! /// Reset value
270-
//! pub fn reset_value() -> Self {
271-
//! CR2W { bits: 0 }
272-
//! }
273-
//!
283+
//! impl W {
274284
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
275-
//! pub fn sadd1(&mut self) -> _SADD1W { .. }
285+
//! pub fn sadd1(&mut self) -> SADD1_W { .. }
276286
//!
277287
//! /// Bit 0 - Slave address bit 0 (master mode)
278-
//! pub fn sadd0(&mut self) -> SADD0R { .. }
288+
//! pub fn sadd0(&mut self) -> SADD0_W { .. }
279289
//! }
280290
//! ```
281291
//!
@@ -300,6 +310,8 @@
300310
//! // field; instead, `6 & 3` (i.e. `2`) will be written to the bitfield.
301311
//! ```
302312
//!
313+
//! ## `modify`
314+
//!
303315
//! Finally, the `modify` method performs a **single** read-modify-write
304316
//! operation that involves **one** read (`LDR`) to the register, modifying the
305317
//! value and then a **single** write (`STR`) of the modified value to the
@@ -327,16 +339,16 @@
327339
//! The new `read` API returns an enum that you can match:
328340
//!
329341
//! ```ignore
330-
//! match gpioa.dir.read().pin0() {
331-
//! gpioa::dir::PIN0R::Input => { .. },
332-
//! gpioa::dir::PIN0R::Output => { .. },
342+
//! match gpioa.dir.read().pin0().variant() {
343+
//! gpioa::dir::PIN0_A::Input => { .. },
344+
//! gpioa::dir::PIN0_A::Output => { .. },
333345
//! }
334346
//! ```
335347
//!
336348
//! or test for equality
337349
//!
338350
//! ```ignore
339-
//! if gpioa.dir.read().pin0() == gpio::dir::PIN0R::Input {
351+
//! if gpioa.dir.read().pin0().variant() == gpio::dir::PIN0_A::Input {
340352
//! ..
341353
//! }
342354
//! ```
@@ -366,8 +378,8 @@
366378
//! write from an `enum`eration of the possible ones:
367379
//!
368380
//! ```ignore
369-
//! // enum DIRW { Input, Output }
370-
//! gpioa.dir.write(|w| w.pin0().variant(gpio::dir::PIN0W::Output));
381+
//! // enum PIN0_A { Input, Output }
382+
//! gpioa.dir.write(|w| w.pin0().variant(gpio::dir::PIN0_A::Output));
371383
//! ```
372384
//!
373385
//! There are convenience methods to pick one of the variants without having to

0 commit comments

Comments
 (0)