|
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