|
30 | 30 | //!
|
31 | 31 | //! ```
|
32 | 32 | //! $ 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 ) ] |
35 | 37 | //! pub struct Rcc {
|
36 | 38 | //! /// 0x00 - Clock control register
|
37 | 39 | //! pub cr: Cr,
|
|
44 | 46 | //!
|
45 | 47 | //! # API
|
46 | 48 | //!
|
47 |
| -//! The `svd2rust` generates the following API for each peripheral: |
| 49 | +//! `svd2rust` generates the following API for each peripheral: |
48 | 50 | //!
|
49 | 51 | //! ## Register block
|
50 | 52 | //!
|
51 | 53 | //! A register block "definition" as a `struct`. Example below:
|
52 | 54 | //!
|
53 | 55 | //! ``` rust
|
54 |
| -//! /// Inter-integrated circuit |
| 56 | +//! /// Register block |
55 | 57 | //! #[repr(C)]
|
56 | 58 | //! pub struct I2c1 {
|
57 | 59 | //! /// 0x00 - Control register 1
|
|
80 | 82 | //! ```
|
81 | 83 | //!
|
82 | 84 | //! 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: |
84 | 86 | //!
|
85 | 87 | //! - `static` variables. Example below:
|
86 | 88 | //!
|
87 | 89 | //! ``` rust
|
88 | 90 | //! extern "C" {
|
89 | 91 | //! // I2C1 can be accessed in read-write mode
|
90 | 92 | //! pub static mut I2C1: I2c;
|
| 93 | +//! |
91 | 94 | //! // whereas I2C2 can only be accessed in "read-only" mode
|
92 | 95 | //! pub static I2C1: I2c;
|
93 | 96 | //! }
|
|
136 | 139 | //!
|
137 | 140 | //! This is signature of each of these methods:
|
138 | 141 | //!
|
139 |
| -//! (using the `CR2` register as an example) |
| 142 | +//! (using `I2C`'s `CR2` register as an example) |
140 | 143 | //!
|
141 | 144 | //! ``` rust
|
142 | 145 | //! impl Cr2 {
|
| 146 | +//! /// Modifies the contents of the register |
143 | 147 | //! 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 |
145 | 149 | //! {
|
146 | 150 | //! ..
|
147 | 151 | //! }
|
148 | 152 | //!
|
149 |
| -//! pub fn read(&self) -> Cr2R { .. } |
| 153 | +//! /// Reads the contents of the register |
| 154 | +//! pub fn read(&self) -> R { .. } |
150 | 155 | //!
|
| 156 | +//! /// Writes to the register |
151 | 157 | //! pub fn write<F>(&mut self, f: F)
|
152 |
| -//! where F: FnOnce(&mut Cr2W) -> &mut Cr2W, |
| 158 | +//! where F: FnOnce(&mut W) -> &mut W, |
153 | 159 | //! {
|
154 | 160 | //! ..
|
155 | 161 | //! }
|
156 | 162 | //! }
|
157 | 163 | //! ```
|
158 | 164 | //!
|
159 | 165 | //! 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 |
161 | 167 | //! readable bits (i.e. not to the reserved or write-only bits) of the `CR2`
|
162 | 168 | //! register:
|
163 | 169 | //!
|
164 | 170 | //! ``` rust
|
165 |
| -//! impl Cr2R { |
| 171 | +//! /// Value read from the register |
| 172 | +//! impl R { |
166 | 173 | //! /// Bit 0 - Slave address bit 0 (master mode)
|
167 |
| -//! pub fn sadd0(&self) -> bool { .. } |
| 174 | +//! pub fn sadd0(&self) -> Sadd0R { .. } |
168 | 175 | //!
|
169 | 176 | //! /// Bits 1:7 - Slave address bit 7:1 (master mode)
|
170 |
| -//! pub fn sadd1(&self) -> u8 { .. } |
| 177 | +//! pub fn sadd1(&self) -> Sadd1R { .. } |
171 | 178 | //!
|
172 | 179 | //! (..)
|
173 | 180 | //! }
|
|
177 | 184 | //!
|
178 | 185 | //! ``` rust
|
179 | 186 | //! // 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 |
182 | 189 | //! } else {
|
183 |
| -//! // something else |
| 190 | +//! // no |
184 | 191 | //! }
|
185 | 192 | //! ```
|
186 | 193 | //!
|
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. |
190 | 197 | //!
|
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 |
194 | 201 | //! `CR2` register.
|
195 | 202 | //!
|
196 | 203 | //! ``` rust
|
|
201 | 208 | //! }
|
202 | 209 | //!
|
203 | 210 | //! /// 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 { .. } |
205 | 212 | //!
|
206 | 213 | //! /// 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 { .. } |
208 | 215 | //! }
|
209 | 216 | //! ```
|
210 | 217 | //!
|
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 |
213 | 220 | //! 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`. |
215 | 222 | //!
|
216 | 223 | //! Usage looks like this:
|
217 | 224 | //!
|
218 | 225 | //! ``` 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. |
222 | 237 | //! ```
|
223 | 238 | //!
|
224 | 239 | //! 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). |
230 | 245 | //!
|
231 | 246 | //! Usage looks like this:
|
232 | 247 | //!
|
233 | 248 | //! ``` rust
|
234 | 249 | //! // 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 | +//! ``` |
236 | 302 | //!
|
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)); |
239 | 324 | //! ```
|
240 | 325 |
|
241 | 326 | #![recursion_limit = "128"]
|
|
0 commit comments