|
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