|
31 | 31 | //! ```
|
32 | 32 | //! $ svd2rust -i STM32F30x.svd | rustfmt | tee src/lib.rs
|
33 | 33 | //! //! Peripheral access API for STM32F30X microcontrollers
|
34 |
| -//! //! (generated using svd2rust v0.11.0) |
| 34 | +//! //! (generated using svd2rust v0.12.0) |
35 | 35 | //!
|
36 | 36 | //! #![deny(missing_docs)]
|
37 | 37 | //! #![deny(warnings)]
|
38 | 38 | //! #![no_std]
|
39 | 39 | //!
|
| 40 | +//! extern crate bare_metal; |
40 | 41 | //! extern crate cortex_m;
|
| 42 | +//! #[cfg(feature = "rt")] |
41 | 43 | //! extern crate cortex_m_rt;
|
42 | 44 | //! extern crate vcell;
|
43 | 45 | //!
|
44 | 46 | //! use cortex_m::peripheral::Peripheral;
|
45 | 47 | //!
|
46 | 48 | //! /// Interrupts
|
47 | 49 | //! pub mod interrupt {
|
48 |
| -//! .. |
| 50 | +//! // .. |
49 | 51 | //! }
|
50 | 52 | //!
|
51 | 53 | //! /// General-purpose I/Os
|
52 |
| -//! pub const GPIOA: Peripheral<GPIOA> = unsafe { Peripheral::new(1207959552) }; |
53 |
| -//! |
54 |
| -//! /// General-purpose I/Os |
55 | 54 | //! pub mod gpioa {
|
56 | 55 | //! pub struct RegisterBlock {
|
57 | 56 | //! /// GPIO port mode register
|
|
61 | 60 | //! ..
|
62 | 61 | //! }
|
63 | 62 | //!
|
64 |
| -//! pub struct GPIOA { |
65 |
| -//! register_block: gpioa::RegisterBlock, |
66 |
| -//! } |
67 |
| -//! |
68 | 63 | //! /// General-purpose I/Os
|
69 |
| -//! pub const GPIOB: Peripheral<GPIOB> = unsafe { Peripheral::new(1207960576) }; |
| 64 | +//! pub struct GPIOA { _marker: PhantomData<*const ()> } |
70 | 65 | //!
|
71 |
| -//! /// General-purpose I/Os |
72 |
| -//! pub mod gpiob { |
73 |
| -//! .. |
74 |
| -//! } |
| 66 | +//! unsafe impl Send for GPIOA {} |
75 | 67 | //!
|
76 |
| -//! pub struct GPIOB { |
77 |
| -//! register_block: gpiob::RegisterBlock, |
| 68 | +//! impl GPIOA { |
| 69 | +//! /// Returns a pointer to the register block |
| 70 | +//! pub fn ptr() -> *const gpioa::RegisterBlock { |
| 71 | +//! 0x4800_0000 as *const _ |
| 72 | +//! } |
78 | 73 | //! }
|
79 | 74 | //!
|
80 |
| -//! /// GPIOC |
81 |
| -//! pub const GPIOC: Peripheral<GPIOC> = unsafe { Peripheral::new(1207961600) }; |
| 75 | +//! impl core::ops::Deref for GPIOA { |
| 76 | +//! type Target = gpioa::RegisterBlock; |
82 | 77 | //!
|
83 |
| -//! /// Register block |
84 |
| -//! pub type GPIOC = GPIOB; |
| 78 | +//! fn deref(&self) -> &gpioa::RegisterBlock { |
| 79 | +//! unsafe { &*GPIOA::ptr() } |
| 80 | +//! } |
| 81 | +//! } |
85 | 82 | //!
|
86 | 83 | //! // ..
|
87 | 84 | //! ```
|
|
92 | 89 | //!
|
93 | 90 | //! - [`bare-metal`](https://crates.io/crates/bare-metal) v0.1.x
|
94 | 91 | //! - [`vcell`](https://crates.io/crates/vcell) v0.1.x
|
95 |
| -//! - [`cortex-m-rt`](https://crates.io/crates/cortex-m-rt) v0.3.x if targeting |
| 92 | +//! - [`cortex-m-rt`](https://crates.io/crates/cortex-m-rt) v0.4.x if targeting |
96 | 93 | //! the Cortex-M architecture.
|
97 |
| -//! - [`cortex-m`](https://crates.io/crates/cortex-m) v0.3.x if targeting the |
| 94 | +//! - [`cortex-m`](https://crates.io/crates/cortex-m) v0.4.x if targeting the |
98 | 95 | //! Cortex-M architecture.
|
99 | 96 | //! - [`msp430`](https://crates.io/crates/msp430) v0.1.x if targeting the MSP430
|
100 | 97 | //! architecture.
|
|
103 | 100 | //!
|
104 | 101 | //! # Peripheral API
|
105 | 102 | //!
|
106 |
| -//! In the root of the generated API, you'll find all the device peripherals as |
107 |
| -//! `const`ant `struct`s. You can access the register block behind the |
108 |
| -//! peripheral using either of these two methods: |
| 103 | +//! To use a peripheral first you must get an *instance* of the peripheral. All the device |
| 104 | +//! peripherals are modeled as singletons (there can only ever be, at most, one instance of any |
| 105 | +//! one of them) and the only way to get an instance of them is through the `Peripherals::take` |
| 106 | +//! method. |
| 107 | +//! |
| 108 | +//! ``` |
| 109 | +//! fn main() { |
| 110 | +//! let mut peripherals = stm32f30x::Peripherals::take().unwrap(); |
| 111 | +//! peripherals.GPIOA.odr.write(|w| w.bits(1)); |
| 112 | +//! } |
| 113 | +//! ``` |
109 | 114 | //!
|
110 |
| -//! - `get()` for `unsafe`, unsynchronized access to the peripheral, or |
| 115 | +//! This method can only be successfully called *once* -- that's why the method returns an `Option`. |
| 116 | +//! Subsequent calls to the method will result in a `None` value being returned. |
111 | 117 | //!
|
112 |
| -//! - `borrow()` which grants you exclusive access to the peripheral but can |
113 |
| -//! only be used within a critical section (`interrupt::free`). |
| 118 | +//! ``` |
| 119 | +//! fn main() { |
| 120 | +//! let ok = stm32f30x::Peripherals::take().unwrap(); |
| 121 | +//! let panics = stm32f30x::Peripherals::take().unwrap(); |
| 122 | +//! } |
| 123 | +//! ``` |
| 124 | +//! |
| 125 | +//! The singleton property can be *unsafely* bypassed using the `ptr` static method which is |
| 126 | +//! available on all the peripheral types. This method is a useful for implementing safe higher |
| 127 | +//! level abstractions. |
| 128 | +//! |
| 129 | +//! ``` |
| 130 | +//! struct PA0 { _0: () } |
| 131 | +//! impl PA0 { |
| 132 | +//! fn is_high(&self) -> bool { |
| 133 | +//! // NOTE(unsafe) actually safe because this is an atomic read with no side effects |
| 134 | +//! unsafe { (*GPIOA::ptr()).idr.read().bits() & 1 != 0 } |
| 135 | +//! } |
| 136 | +//! |
| 137 | +//! fn is_low(&self) -> bool { |
| 138 | +//! !self.is_high() |
| 139 | +//! } |
| 140 | +//! } |
| 141 | +//! struct PA1 { _0: () } |
| 142 | +//! // .. |
| 143 | +//! |
| 144 | +//! fn configure(gpioa: GPIOA) -> (PA0, PA1, ..) { |
| 145 | +//! // configure all the PAx pins as inputs |
| 146 | +//! gpioa.moder.reset(); |
| 147 | +//! // the GPIOA proxy is destroyed here now the GPIOA register block can't be modified |
| 148 | +//! // thus the configuration of the PAx pins is now frozen |
| 149 | +//! drop(gpioa); |
| 150 | +//! (PA0 { _0: () }, PA1 { _0: () }, ..) |
| 151 | +//! } |
| 152 | +//! ``` |
114 | 153 | //!
|
115 |
| -//! The register block is basically a `struct` where each field represents a |
116 |
| -//! register. |
| 154 | +//! Each peripheral proxy `deref`s to a `RegisterBlock` struct that represents a piece of device |
| 155 | +//! memory. Each field in this `struct` represents one register in the register block associated to |
| 156 | +//! the peripheral. |
117 | 157 | //!
|
118 | 158 | //! ```
|
119 | 159 | //! /// Inter-integrated circuit
|
|
148 | 188 | //!
|
149 | 189 | //! # `read` / `modify` / `write` API
|
150 | 190 | //!
|
151 |
| -//! Each register in the register block, e.g. the `cr1` field in the `I2C` |
152 |
| -//! struct, exposes a combination of the `read`, `modify` and `write` methods. |
153 |
| -//! Which methods exposes each register depends on whether the register is |
154 |
| -//! read-only, read-write or write-only: |
| 191 | +//! Each register in the register block, e.g. the `cr1` field in the `I2C` struct, exposes a |
| 192 | +//! combination of the `read`, `modify` and `write` methods. Which methods exposes each register |
| 193 | +//! depends on whether the register is read-only, read-write or write-only: |
155 | 194 | //!
|
156 | 195 | //! - read-only registers only expose the `read` method.
|
157 | 196 | //! - write-only registers only expose the `write` method.
|
|
165 | 204 | //! ``` rust
|
166 | 205 | //! impl CR2 {
|
167 | 206 | //! /// Modifies the contents of the register
|
168 |
| -//! pub fn modify<F>(&mut self, f: F) |
| 207 | +//! pub fn modify<F>(&self, f: F) |
169 | 208 | //! where
|
170 | 209 | //! for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W
|
171 | 210 | //! {
|
|
185 | 224 | //! }
|
186 | 225 | //! ```
|
187 | 226 | //!
|
188 |
| -//! The `read` method "reads" the register using a **single**, volatile `LDR` |
189 |
| -//! instruction and returns a proxy `R` struct that allows access to only the |
190 |
| -//! readable bits (i.e. not to the reserved or write-only bits) of the `CR2` |
191 |
| -//! register: |
| 227 | +//! The `read` method "reads" the register using a **single**, volatile `LDR` instruction and |
| 228 | +//! returns a proxy `R` struct that allows access to only the readable bits (i.e. not to the |
| 229 | +//! reserved or write-only bits) of the `CR2` register: |
192 | 230 | //!
|
193 | 231 | //! ``` rust
|
194 | 232 | //! /// Value read from the register
|
|
214 | 252 | //! }
|
215 | 253 | //! ```
|
216 | 254 | //!
|
217 |
| -//! On the other hand, the `write` method writes some value to the register |
218 |
| -//! using a **single**, volatile `STR` instruction. This method involves a `W` |
219 |
| -//! struct that only allows constructing valid states of the `CR2` register. |
| 255 | +//! On the other hand, the `write` method writes some value to the register using a **single**, |
| 256 | +//! volatile `STR` instruction. This method involves a `W` struct that only allows constructing |
| 257 | +//! valid states of the `CR2` register. |
220 | 258 | //!
|
221 |
| -//! The only constructor that `W` provides is `reset_value` which returns the |
222 |
| -//! value of the `CR2` register after a reset. The rest of `W` methods are |
223 |
| -//! "builder-like" and can be used to modify the writable bitfields of the |
224 |
| -//! `CR2` register. |
| 259 | +//! The only constructor that `W` provides is `reset_value` which returns the value of the `CR2` |
| 260 | +//! register after a reset. The rest of `W` methods are "builder-like" and can be used to modify the |
| 261 | +//! writable bitfields of the `CR2` register. |
225 | 262 | //!
|
226 | 263 | //! ``` rust
|
227 | 264 | //! impl CR2W {
|
|
238 | 275 | //! }
|
239 | 276 | //! ```
|
240 | 277 | //!
|
241 |
| -//! The `write` method takes a closure with signature `(&mut W) -> &mut W`. If |
242 |
| -//! the "identity closure", `|w| w`, is passed then the `write` method will set |
243 |
| -//! the `CR2` register to its reset value. Otherwise, the closure specifies how |
244 |
| -//! the reset value will be modified *before* it's written to `CR2`. |
| 278 | +//! The `write` method takes a closure with signature `(&mut W) -> &mut W`. If the "identity |
| 279 | +//! closure", `|w| w`, is passed then the `write` method will set the `CR2` register to its reset |
| 280 | +//! value. Otherwise, the closure specifies how the reset value will be modified *before* it's |
| 281 | +//! written to `CR2`. |
245 | 282 | //!
|
246 | 283 | //! Usage looks like this:
|
247 | 284 | //!
|
|
278 | 315 | //!
|
279 | 316 | //! # enumeratedValues
|
280 | 317 | //!
|
281 |
| -//! If your SVD uses the `<enumeratedValues>` feature, then the API will be |
282 |
| -//! *extended* to provide even more type safety. This extension is backward |
283 |
| -//! compatible with the original version so you could "upgrade" your SVD by |
284 |
| -//! adding, yourself, `<enumeratedValues>` to it and then use `svd2rust` to |
285 |
| -//! re-generate a better API that doesn't break the existing code that uses |
286 |
| -//! that API. |
| 318 | +//! If your SVD uses the `<enumeratedValues>` feature, then the API will be *extended* to provide |
| 319 | +//! even more type safety. This extension is backward compatible with the original version so you |
| 320 | +//! could "upgrade" your SVD by adding, yourself, `<enumeratedValues>` to it and then use `svd2rust` |
| 321 | +//! to re-generate a better API that doesn't break the existing code that uses that API. |
287 | 322 | //!
|
288 | 323 | //! The new `read` API returns an enum that you can match:
|
289 | 324 | //!
|
|
323 | 358 | //! }
|
324 | 359 | //! ```
|
325 | 360 | //!
|
326 |
| -//! And the new `write` API provides similar additions as well: `variant` lets |
327 |
| -//! you pick the value to write from an `enum`eration of the possible ones: |
| 361 | +//! And the new `write` API provides similar additions as well: `variant` lets you pick the value to |
| 362 | +//! write from an `enum`eration of the possible ones: |
328 | 363 | //!
|
329 | 364 | //! ```
|
330 | 365 | //! // enum DIRW { Input, Output }
|
|
348 | 383 | //!
|
349 | 384 | //! # Interrupt API
|
350 | 385 | //!
|
351 |
| -//! SVD files also describe the device interrupts. svd2rust generated crates |
352 |
| -//! expose an enumeration of the device interrupts as an `Interrupt` `enum` in |
353 |
| -//! the root of the crate. This `enum` can be used with the `cortex-m` crate |
354 |
| -//! `NVIC` API. |
| 386 | +//! SVD files also describe the device interrupts. svd2rust generated crates expose an enumeration |
| 387 | +//! of the device interrupts as an `Interrupt` `enum` in the root of the crate. This `enum` can be |
| 388 | +//! used with the `cortex-m` crate `NVIC` API. |
355 | 389 | //!
|
356 | 390 | //! ```
|
357 | 391 | //! extern crate cortex_m;
|
| 392 | +//! extern crate stm32f30x; |
358 | 393 | //!
|
359 | 394 | //! use cortex_m::interrupt;
|
360 |
| -//! use cortex_m::peripheral::NVIC; |
| 395 | +//! use cortex_m::peripheral::Peripherals; |
| 396 | +//! use stm32f30x::Interrupt; |
361 | 397 | //!
|
362 |
| -//! interrupt::free(|cs| { |
363 |
| -//! let nvic = NVIC.borrow(cs); |
| 398 | +//! let p = Peripherals::take().unwrap(); |
| 399 | +//! let mut nvic = p.NVIC; |
364 | 400 | //!
|
365 |
| -//! nvic.enable(Interrupt::TIM2); |
366 |
| -//! nvic.enable(Interrupt::TIM3); |
367 |
| -//! }); |
| 401 | +//! nvic.enable(Interrupt::TIM2); |
| 402 | +//! nvic.enable(Interrupt::TIM3); |
368 | 403 | //! ```
|
369 | 404 | //!
|
370 | 405 | //! ## the "rt" feature
|
371 | 406 | //!
|
372 |
| -//! If the "rt" Cargo feature of the svd2rust generated crate is enabled the |
373 |
| -//! crate will populate the part of the vector table that contains the interrupt |
374 |
| -//! vectors and provide an [`interrupt!`](macro.interrupt.html) macro that can |
375 |
| -//! be used to register interrupt handlers. |
| 407 | +//! If the "rt" Cargo feature of the svd2rust generated crate is enabled the crate will populate the |
| 408 | +//! part of the vector table that contains the interrupt vectors and provide an |
| 409 | +//! [`interrupt!`](macro.interrupt.html) macro that can be used to register interrupt handlers. |
376 | 410 |
|
377 | 411 | // NOTE This file is for documentation only
|
378 | 412 |
|
|
0 commit comments