stm32f3xx_hal/lib.rs
1/*!
2 # `stm32f3xx-hal`
3
4 `stm32f3xx-hal` contains a multi device hardware abstraction on top of the
5 peripheral access API for the `STMicro` [STM32F3][stm] series microcontrollers.
6
7 ## Philosophie
8
9 HAL (meaning **H**ardware **A**bstraction **L**ayer) is a generic term used in many contexts,
10 but in the specific context of this crate, it is meant to abstract away the control exposed
11 by the devices "[peripheral access crate](`crate::pac`)" to simplify initialization routines,
12 with a robust interface avoiding miss-configurations while still not abstracting away too much.
13
14 Also, this crate's goal is to integrate well with the rest of the rust embedded ecosystem,
15 for example by implementing the [`embedded_hal`] traits or using crates like [`embedded_time`],
16 or [`rtcc`].
17
18 [stm]: https://www.st.com/en/microcontrollers-microprocessors/stm32f3-series.html
19
20 ## Basic Usage
21
22 ```rust
23 #![no_std]
24 #![no_main]
25
26 use cortex_m::asm;
27 use cortex_m_rt::entry;
28 use panic_halt as _;
29 use stm32f3xx_hal::{self as hal, pac, prelude::*};
30
31 #[entry]
32 fn main() -> ! {
33 let dp = pac::Peripherals::take().unwrap();
34
35 let mut rcc = dp.RCC.constrain();
36 let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);
37
38 let mut led = gpioe
39 .pe13
40 .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
41
42 loop {
43 led.toggle().unwrap();
44 asm::delay(8_000_000);
45 }
46 }
47 ```
48
49 ## Cargo features
50
51 ### Target chip selection
52
53 This crate requires you to specify your target chip as a feature.
54
55 Please select one of the following (`x` denotes any character in [a-z]):
56
57 * stm32f301x6, stm32f301x8, stm32f318x8
58 * stm32f302x6, stm32f302x8, stm32f302xb, stm32f302xc, stm32f302xd, stm32f302xe
59 * stm32f303x6, stm32f303x8, stm32f303xb, stm32f303xc, stm32f303xd, stm32f303xe
60 * stm32f328x8
61 * stm32f358xc
62 * stm32f398xe
63 * stm32f373x8, stm32f373xb, stm32f373xc, stm32f378xc
64 * stm32f334x4, stm32f334x6, stm32f334x8
65
66 Example: The `STM32F3Discovery` board has a STM32F303VCT6 chip.
67 So you need to specify `stm32f303xc` in your `Cargo.toml` (note that VC → xc).
68
69 For more information, see the [README][].
70
71 [README]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/README.md#selecting-the-right-chip
72
73 ### `ld`
74
75 When this feature is enabled the `memory.x` linker script for target chip is automatically
76 provided by this crate. See [`cortex-m-rt` document][memoryx] for more info.
77
78 [memoryx]: https://docs.rs/cortex-m-rt/0.6.13/cortex_m_rt/#memoryx
79
80 ### `rt`
81
82 This feature enables [`stm32f3`][]'s `rt` feature. See [`cortex-m-rt` document][device] for more info.
83
84 [`stm32f3`]: https://crates.io/crates/stm32f3
85 [device]: https://docs.rs/cortex-m-rt/0.6.13/cortex_m_rt/#device
86
87 ### `can`
88
89 Enable CAN peripherals on supported targets.
90 The can implementation of the interface is backed by [`bxcan`](https://crates.io/crates/bxcan)
91
92 ### `usb`
93
94 Enable USB peripherals on supported targets via the [`stm32-usbd`](https://crates.io/crates/stm32-usbd) crate.
95
96 ### `rtc`
97
98 Enables RTC support, build upon [`rtcc`](https://crates.io/crates/rtcc) crate.
99
100 ### `enumset`
101
102 Enable functions, which leverage [`enumset`](https://crates.io/crates/enumset).
103 This is especially usefull to get all set status events at once,
104 see for example [`serial::Serial::triggered_events()`]
105
106 ### `defmt`
107
108 Currently these are only used for panicking calls, like
109 `assert!` `panic!` or `unwrap()`. These are enabled using the [defmt][]
110 [filter][].
111 For now [defmt][] is mostly intended for internal development and testing
112 to further reduce panicking calls in this crate.
113 The support of this feature is _subject to change_ as the development
114 of [defmt][] is advancing.
115
116 To use this feature follow the [Application Setup][] of the `defmt-book`.
117
118 [Application Setup]: https://defmt.ferrous-systems.com/setup-app.html
119 [defmt]: https://github.com/knurling-rs/defmt
120 [filter]: https://defmt.ferrous-systems.com/filtering.html
121 [`serial::Serial::triggered_events`]: `crate::serial::Serial::triggered_events`
122*/
123#![no_std]
124#![allow(clippy::upper_case_acronyms)]
125#![warn(missing_docs)]
126#![warn(clippy::missing_safety_doc)]
127#![warn(clippy::undocumented_unsafe_blocks)]
128#![warn(unsafe_op_in_unsafe_fn)]
129#![deny(macro_use_extern_crate)]
130#![cfg_attr(nightly, deny(rustdoc::broken_intra_doc_links))]
131#![cfg_attr(docsrs, feature(doc_cfg))]
132
133use cfg_if::cfg_if;
134
135pub use embedded_hal as hal;
136
137pub use nb;
138pub use nb::block;
139
140pub use embedded_time as time;
141
142mod private {
143 /// Private sealed trait to seal all GPIO implementations
144 /// which do implement peripheral functionalities.
145 pub trait Sealed {}
146
147 /// Modify specific index of array-like register
148 macro_rules! modify_at {
149 ($reg:expr, $bitwidth:expr, $index:expr, $value:expr) => {
150 $reg.modify(|r, w| {
151 let mask = !(u32::MAX >> (32 - $bitwidth) << ($bitwidth * $index));
152 let value = $value << ($bitwidth * $index);
153 w.bits(r.bits() & mask | value)
154 })
155 };
156 }
157 pub(crate) use modify_at;
158}
159
160pub(crate) use private::{modify_at, Sealed};
161
162/// Peripheral access
163#[cfg(feature = "svd-f301")]
164pub use stm32f3::stm32f301 as pac;
165
166/// Peripheral access
167#[cfg(feature = "svd-f302")]
168pub use stm32f3::stm32f302 as pac;
169
170/// Peripheral access
171#[cfg(feature = "svd-f303")]
172pub use stm32f3::stm32f303 as pac;
173
174/// Peripheral access
175#[cfg(feature = "svd-f373")]
176pub use stm32f3::stm32f373 as pac;
177
178/// Peripheral access
179#[cfg(feature = "svd-f3x4")]
180pub use stm32f3::stm32f3x4 as pac;
181
182/// Enable use of interrupt macro.
183#[cfg(feature = "rt")]
184#[cfg_attr(docsrs, doc(cfg(feature = "rt")))]
185pub use crate::pac::interrupt;
186
187// TODO: Not yet supported for stm32f373 as this does not share a concept of a "shared ADC"
188#[cfg(not(feature = "svd-f373"))]
189pub mod adc;
190#[cfg(all(feature = "can", not(feature = "svd-f301")))]
191#[cfg_attr(docsrs, doc(cfg(feature = "can")))]
192pub mod can;
193pub mod dac;
194pub mod delay;
195pub mod dma;
196pub mod flash;
197pub mod gpio;
198pub mod i2c;
199pub mod interrupts;
200pub mod prelude;
201pub mod pwm;
202pub mod rcc;
203#[cfg(feature = "rtc")]
204#[cfg_attr(docsrs, doc(cfg(feature = "rtc")))]
205pub mod rtc;
206pub mod serial;
207pub mod signature;
208pub mod spi;
209pub mod syscfg;
210pub mod timer;
211#[cfg(all(
212 feature = "usb",
213 any(
214 feature = "stm32f303xb",
215 feature = "stm32f303xc",
216 feature = "stm32f303xd",
217 feature = "stm32f303xe",
218 ),
219))]
220#[cfg_attr(docsrs, doc(cfg(feature = "usb")))]
221pub mod usb;
222pub mod watchdog;
223
224cfg_if! {
225 if #[cfg(feature = "defmt")] {
226 #[allow(unused_imports)]
227 pub(crate) use defmt::{assert, panic, unreachable, unwrap};
228 #[allow(unused_imports)]
229 pub(crate) use macros::expect;
230
231 mod macros {
232 /// Wrapper function for `.expect()`
233 ///
234 /// Uses [`defmt::unwrap!`] instead, because
235 /// it has the same functionality as `expect()`
236 macro_rules! expect_wrapper {
237 ($l:expr, $s:tt) => {
238 defmt::unwrap!($l, $s)
239 };
240 }
241 pub(crate) use expect_wrapper as expect;
242 }
243 } else {
244 #[allow(unused_imports)]
245 pub(crate) use core::{assert, panic, unreachable};
246 #[allow(unused_imports)]
247 pub(crate) use macros::{unwrap, expect};
248
249 mod macros {
250 /// Wrapper macro for `.unwrap()`
251 ///
252 /// Uses core function, when defmt feature is not active
253 macro_rules! unwrap_wrapper {
254 ($l:expr) => {
255 $l.unwrap()
256 };
257 }
258 pub(crate) use unwrap_wrapper as unwrap;
259
260 /// Wrapper macro for `.expect()`
261 ///
262 /// Uses core function, when defmt feature is not active
263 macro_rules! expect_wrapper {
264 ($l:expr, $s:tt) => {
265 $l.expect($s)
266 };
267 }
268 pub(crate) use expect_wrapper as expect;
269 }
270 }
271}
272
273/// Switch something on or off.
274///
275/// Convenience enum and wrapper around a bool, which more explicit about the intention to enable
276/// or disable something, in comparison to `true` or `false`.
277// TODO: Maybe move to some mod like "util"?
278#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
279#[cfg_attr(feature = "defmt", derive(defmt::Format))]
280#[doc(alias = "Toggle")]
281pub enum Switch {
282 /// Switch something on / enable a thing.
283 On,
284 /// Switch something off / disable a thing.
285 Off,
286}
287
288impl From<Switch> for bool {
289 fn from(switch: Switch) -> Self {
290 matches!(switch, Switch::On)
291 }
292}
293
294impl From<bool> for Switch {
295 fn from(b: bool) -> Self {
296 if b {
297 Switch::On
298 } else {
299 Switch::Off
300 }
301 }
302}
303
304/// A generic Error type for failable integer to enum conversions used
305/// in multiple occasions inside this crate.
306#[derive(Debug, Copy, Clone, PartialEq, Eq)]
307#[cfg_attr(feature = "defmt", derive(defmt::Format))]
308pub struct TryFromIntError;