Skip to content

Commit 56e0ef0

Browse files
author
Jorge Aparicio
committed
update the crate level documentation
1 parent 714143f commit 56e0ef0

File tree

1 file changed

+123
-38
lines changed

1 file changed

+123
-38
lines changed

src/lib.rs

Lines changed: 123 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
//!
3131
//! ```
3232
//! $ svd2rust -i STM32F30x.svd rcc | head
33-
//! /// Reset and clock control
34-
//! #[repr(C)]
33+
//! //! Reset and clock control
34+
//!
35+
//! /// Register block
36+
//! # [ repr ( C ) ]
3537
//! pub struct Rcc {
3638
//! /// 0x00 - Clock control register
3739
//! pub cr: Cr,
@@ -44,14 +46,14 @@
4446
//!
4547
//! # API
4648
//!
47-
//! The `svd2rust` generates the following API for each peripheral:
49+
//! `svd2rust` generates the following API for each peripheral:
4850
//!
4951
//! ## Register block
5052
//!
5153
//! A register block "definition" as a `struct`. Example below:
5254
//!
5355
//! ``` rust
54-
//! /// Inter-integrated circuit
56+
//! /// Register block
5557
//! #[repr(C)]
5658
//! pub struct I2c1 {
5759
//! /// 0x00 - Control register 1
@@ -80,14 +82,15 @@
8082
//! ```
8183
//!
8284
//! The user has to "instantiate" this definition for each peripheral the
83-
//! microcontroller has. They have two choices:
85+
//! microcontroller has. There are two alternatives:
8486
//!
8587
//! - `static` variables. Example below:
8688
//!
8789
//! ``` rust
8890
//! extern "C" {
8991
//! // I2C1 can be accessed in read-write mode
9092
//! pub static mut I2C1: I2c;
93+
//!
9194
//! // whereas I2C2 can only be accessed in "read-only" mode
9295
//! pub static I2C1: I2c;
9396
//! }
@@ -136,38 +139,42 @@
136139
//!
137140
//! This is signature of each of these methods:
138141
//!
139-
//! (using the `CR2` register as an example)
142+
//! (using `I2C`'s `CR2` register as an example)
140143
//!
141144
//! ``` rust
142145
//! impl Cr2 {
146+
//! /// Modifies the contents of the register
143147
//! pub fn modify<F>(&mut self, f: F)
144-
//! where for<'w> F: FnOnce(&Cr2R, &'w mut Cr2W) -> &'w mut Cr2W
148+
//! where for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W
145149
//! {
146150
//! ..
147151
//! }
148152
//!
149-
//! pub fn read(&self) -> Cr2R { .. }
153+
//! /// Reads the contents of the register
154+
//! pub fn read(&self) -> R { .. }
150155
//!
156+
//! /// Writes to the register
151157
//! pub fn write<F>(&mut self, f: F)
152-
//! where F: FnOnce(&mut Cr2W) -> &mut Cr2W,
158+
//! where F: FnOnce(&mut W) -> &mut W,
153159
//! {
154160
//! ..
155161
//! }
156162
//! }
157163
//! ```
158164
//!
159165
//! The `read` method "reads" the register using a **single**, volatile `LDR`
160-
//! instruction and returns a proxy `Cr2R` struct that allows access to only the
166+
//! instruction and returns a proxy `R` struct that allows access to only the
161167
//! readable bits (i.e. not to the reserved or write-only bits) of the `CR2`
162168
//! register:
163169
//!
164170
//! ``` rust
165-
//! impl Cr2R {
171+
//! /// Value read from the register
172+
//! impl R {
166173
//! /// Bit 0 - Slave address bit 0 (master mode)
167-
//! pub fn sadd0(&self) -> bool { .. }
174+
//! pub fn sadd0(&self) -> Sadd0R { .. }
168175
//!
169176
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
170-
//! pub fn sadd1(&self) -> u8 { .. }
177+
//! pub fn sadd1(&self) -> Sadd1R { .. }
171178
//!
172179
//! (..)
173180
//! }
@@ -177,20 +184,20 @@
177184
//!
178185
//! ``` rust
179186
//! // is the SADD0 bit of the CR2 register set?
180-
//! if i2c1.c2r.read().sadd0() {
181-
//! // something
187+
//! if i2c1.c2r.read().sadd0().bits() == 1 {
188+
//! // yes
182189
//! } else {
183-
//! // something else
190+
//! // no
184191
//! }
185192
//! ```
186193
//!
187-
//! The `write` method writes some value to the register using a **single**,
188-
//! volatile `STR` instruction. This method involves a `Cr2W` struct that only
189-
//! allows constructing valid states of the `CR2` register.
194+
//! On the other hand, the `write` method writes some value to the register
195+
//! using a **single**, volatile `STR` instruction. This method involves a `W`
196+
//! struct that only allows constructing valid states of the `CR2` register.
190197
//!
191-
//! The only constructor that `Cr2W` provides is `reset_value` which returns the
192-
//! value of the `CR2` register after a reset. The rest of `Cr2W` methods are
193-
//! "builder-like" and can be used to set or reset the writable bits of the
198+
//! The only constructor that `W` provides is `reset_value` which returns the
199+
//! value of the `CR2` register after a reset. The rest of `W` methods are
200+
//! "builder-like" and can be used to modify the writable bitfields of the
194201
//! `CR2` register.
195202
//!
196203
//! ``` rust
@@ -201,41 +208,119 @@
201208
//! }
202209
//!
203210
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
204-
//! pub fn sadd1(&mut self, value: u8) -> &mut Self { .. }
211+
//! pub fn sadd1(&mut self) -> _Sadd1W { .. }
205212
//!
206213
//! /// Bit 0 - Slave address bit 0 (master mode)
207-
//! pub fn sadd0(&mut self, value: bool) -> &mut Self { .. }
214+
//! pub fn sadd0(&mut self) -> _Sadd0 { .. }
208215
//! }
209216
//! ```
210217
//!
211-
//! The `write` method takes a closure with signature `&mut Cr2W -> &mut Cr2W`.
212-
//! If the "identity closure", `|w| w`, is passed then `write` method will set
218+
//! The `write` method takes a closure with signature `(&mut W) -> &mut W`. If
219+
//! the "identity closure", `|w| w`, is passed then the `write` method will set
213220
//! the `CR2` register to its reset value. Otherwise, the closure specifies how
214-
//! that reset value will be modified *before* it's written to `CR2`.
221+
//! the reset value will be modified *before* it's written to `CR2`.
215222
//!
216223
//! Usage looks like this:
217224
//!
218225
//! ``` rust
219-
//! // Write to CR2, its reset value (`0x0000_0000`) but with its SADD0 and
220-
//! // SADD1 fields set to `true` and `0b0011110` respectively
221-
//! i2c1.cr2.write(|w| w.sadd0(true).sadd1(0b0011110));
226+
//! // Starting from the reset value, `0x0000_0000`, change the bitfields SADD0
227+
//! // and SADD1 to `1` and `0b0011110` respectively and write that to the
228+
//! // register CR2.
229+
//! i2c1.cr2.write(|w| unsafe { w.sadd0().bits(1).sadd1().bits(0b0011110) });
230+
//! // NOTE ^ unsafe because you could be writing a reserved bit pattern into
231+
//! // the register. The SVD doesn't provide enough information to check that's
232+
//! // not the case.
233+
//!
234+
//! // NOTE The argument to `bits` will be *masked* before writing it to the
235+
//! // bitfield. This makes it impossible to write, for example, `6` to a 2-bit
236+
//! // field; instead, `6 & 3` (i.e. `2`) will be written to the bitfield.
222237
//! ```
223238
//!
224239
//! Finally, the `modify` method performs a **single** read-modify-write
225-
//! operation that involves reading (`LDR`) the register, modifying the fetched
226-
//! value and then writing (`STR`) the modified value to the register. This
227-
//! method accepts a closure that specifies how the `CR2` register will be
228-
//! modified (the `w` argument) and also provides access to the state of the
229-
//! register before it's modified (the `r` argument).
240+
//! operation that involves **one** read (`LDR`) to the register, modifying the
241+
//! value and then a **single** write (`STR`) of the modified value to the
242+
//! register. This method accepts a closure that specifies how the CR2 register
243+
//! will be modified (the `w` argument) and also provides access to the state of
244+
//! the register before it's modified (the `r` argument).
230245
//!
231246
//! Usage looks like this:
232247
//!
233248
//! ``` rust
234249
//! // Set the START bit to 1 while KEEPING the state of the other bits intact
235-
//! i2c1.cr2.modify(|_, w| w.start(true));
250+
//! i2c1.cr2.modify(|_, w| unsafe { w.start().bits(1) });
251+
//!
252+
//! // TOGGLE the STOP bit, all the other bits will remain untouched
253+
//! i2c1.cr2.modify(|r, w| w.stop().bits(r.stop().bits() ^ 1));
254+
//! ```
255+
//!
256+
//! # enumeratedValues
257+
//!
258+
//! If your SVD uses the `<enumeratedValues>` feature, then the API will be
259+
//! *extended* to provide even more type safety. This extension is backward
260+
//! compatible with the original version so you could "upgrade" your SVD by
261+
//! adding, yourself, `<enumeratedValues>` to it and then use `svd2rust` to
262+
//! re-generate a better API that doesn't break the existing code that uses
263+
//! that API.
264+
//!
265+
//! The new `read` API returns an enum that you can match:
266+
//!
267+
//! ```
268+
//! match gpioa.dir.read().pin0() {
269+
//! gpio::dir::DirR::Input => { .. },
270+
//! gpio::dir::DirR::Output => { .. },
271+
//! }
272+
//! ```
273+
//!
274+
//! or test for equality
275+
//!
276+
//! ```
277+
//! if gpioa.dir.read().pin0() == gpio::dir::DirR::Input {
278+
//! ..
279+
//! }
280+
//! ```
281+
//!
282+
//! It also provides convenience methods to check for a specific variant without
283+
//! having to import the enum:
284+
//!
285+
//! ```
286+
//! if gpioa.dir.read().pin0().is_input() {
287+
//! ..
288+
//! }
289+
//!
290+
//! if gpioa.dir.read().pin0().is_output() {
291+
//! ..
292+
//! }
293+
//! ```
294+
//!
295+
//! The original `bits` method is available as well:
296+
//!
297+
//! ```
298+
//! if gpioa.dir.read().pin0().bits() == 0 {
299+
//! ..
300+
//! }
301+
//! ```
236302
//!
237-
//! // TOGGLE the STOP bit
238-
//! i2c1.cr2.modify(|r, w| w.stop(!r.stop()));
303+
//! And the new `write` API provides similar additions as well: `variant` lets
304+
//! you pick the value to write from an `enum`eration of the possible ones:
305+
//!
306+
//! ```
307+
//! // enum DirW { Input, Output }
308+
//! gpioa.dir.write(|w| w.pin0().variant(gpio::dir::DirW::Output));
309+
//! ```
310+
//!
311+
//! There are convenience methods to pick one of the variants without having to
312+
//! import the enum:
313+
//!
314+
//! ```
315+
//! gpioa.dir.write(|w| w.pin0().output());
316+
//! ```
317+
//!
318+
//! The `bits` method is still available but will become safe if it's impossible to
319+
//! write a reserved bit pattern into the register
320+
//!
321+
//! ```
322+
//! // safe because there are only two options: `0` or `1`
323+
//! gpioa.dir.write(|w| w.pin0().bits(1));
239324
//! ```
240325
241326
#![recursion_limit = "128"]

0 commit comments

Comments
 (0)