diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-12-19 18:03:20 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-12-19 18:03:20 +0100 |
| commit | c8c8b89104acb396476b72ff9192d7b14a46752d (patch) | |
| tree | 1367fd299022eb91ddbfd01bf73b55ae58a013ec /embassy-stm32/src | |
| parent | 189b15c426a3a9ef7d4024ba7e5de6a255f88ee7 (diff) | |
stm32: doc everything else.
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/dma/gpdma.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32/src/ipcc.rs | 8 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 106 | ||||
| -rw-r--r-- | embassy-stm32/src/opamp.rs | 9 | ||||
| -rw-r--r-- | embassy-stm32/src/rng.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/usb/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/usb/usb.rs | 7 | ||||
| -rw-r--r-- | embassy-stm32/src/usb_otg/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/usb_otg/usb.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32/src/wdg/mod.rs | 4 |
12 files changed, 127 insertions, 48 deletions
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index b061415eb..34b2426b9 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs | |||
| @@ -16,6 +16,7 @@ use crate::interrupt::Priority; | |||
| 16 | use crate::pac; | 16 | use crate::pac; |
| 17 | use crate::pac::gpdma::vals; | 17 | use crate::pac::gpdma::vals; |
| 18 | 18 | ||
| 19 | /// GPDMA transfer options. | ||
| 19 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 20 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 20 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 21 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 21 | #[non_exhaustive] | 22 | #[non_exhaustive] |
| @@ -113,10 +114,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in | |||
| 113 | } | 114 | } |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 117 | /// DMA request type alias. (also known as DMA channel number in some chips) | ||
| 116 | pub type Request = u8; | 118 | pub type Request = u8; |
| 117 | 119 | ||
| 120 | /// DMA channel. | ||
| 118 | #[cfg(dmamux)] | 121 | #[cfg(dmamux)] |
| 119 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} | 122 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {} |
| 123 | /// DMA channel. | ||
| 120 | #[cfg(not(dmamux))] | 124 | #[cfg(not(dmamux))] |
| 121 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} | 125 | pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {} |
| 122 | 126 | ||
| @@ -131,12 +135,14 @@ pub(crate) mod sealed { | |||
| 131 | } | 135 | } |
| 132 | } | 136 | } |
| 133 | 137 | ||
| 138 | /// DMA transfer. | ||
| 134 | #[must_use = "futures do nothing unless you `.await` or poll them"] | 139 | #[must_use = "futures do nothing unless you `.await` or poll them"] |
| 135 | pub struct Transfer<'a, C: Channel> { | 140 | pub struct Transfer<'a, C: Channel> { |
| 136 | channel: PeripheralRef<'a, C>, | 141 | channel: PeripheralRef<'a, C>, |
| 137 | } | 142 | } |
| 138 | 143 | ||
| 139 | impl<'a, C: Channel> Transfer<'a, C> { | 144 | impl<'a, C: Channel> Transfer<'a, C> { |
| 145 | /// Create a new read DMA transfer (peripheral to memory). | ||
| 140 | pub unsafe fn new_read<W: Word>( | 146 | pub unsafe fn new_read<W: Word>( |
| 141 | channel: impl Peripheral<P = C> + 'a, | 147 | channel: impl Peripheral<P = C> + 'a, |
| 142 | request: Request, | 148 | request: Request, |
| @@ -147,6 +153,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 147 | Self::new_read_raw(channel, request, peri_addr, buf, options) | 153 | Self::new_read_raw(channel, request, peri_addr, buf, options) |
| 148 | } | 154 | } |
| 149 | 155 | ||
| 156 | /// Create a new read DMA transfer (peripheral to memory), using raw pointers. | ||
| 150 | pub unsafe fn new_read_raw<W: Word>( | 157 | pub unsafe fn new_read_raw<W: Word>( |
| 151 | channel: impl Peripheral<P = C> + 'a, | 158 | channel: impl Peripheral<P = C> + 'a, |
| 152 | request: Request, | 159 | request: Request, |
| @@ -172,6 +179,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 172 | ) | 179 | ) |
| 173 | } | 180 | } |
| 174 | 181 | ||
| 182 | /// Create a new write DMA transfer (memory to peripheral). | ||
| 175 | pub unsafe fn new_write<W: Word>( | 183 | pub unsafe fn new_write<W: Word>( |
| 176 | channel: impl Peripheral<P = C> + 'a, | 184 | channel: impl Peripheral<P = C> + 'a, |
| 177 | request: Request, | 185 | request: Request, |
| @@ -182,6 +190,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 182 | Self::new_write_raw(channel, request, buf, peri_addr, options) | 190 | Self::new_write_raw(channel, request, buf, peri_addr, options) |
| 183 | } | 191 | } |
| 184 | 192 | ||
| 193 | /// Create a new write DMA transfer (memory to peripheral), using raw pointers. | ||
| 185 | pub unsafe fn new_write_raw<W: Word>( | 194 | pub unsafe fn new_write_raw<W: Word>( |
| 186 | channel: impl Peripheral<P = C> + 'a, | 195 | channel: impl Peripheral<P = C> + 'a, |
| 187 | request: Request, | 196 | request: Request, |
| @@ -207,6 +216,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 207 | ) | 216 | ) |
| 208 | } | 217 | } |
| 209 | 218 | ||
| 219 | /// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly. | ||
| 210 | pub unsafe fn new_write_repeated<W: Word>( | 220 | pub unsafe fn new_write_repeated<W: Word>( |
| 211 | channel: impl Peripheral<P = C> + 'a, | 221 | channel: impl Peripheral<P = C> + 'a, |
| 212 | request: Request, | 222 | request: Request, |
| @@ -297,6 +307,9 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 297 | this | 307 | this |
| 298 | } | 308 | } |
| 299 | 309 | ||
| 310 | /// Request the transfer to stop. | ||
| 311 | /// | ||
| 312 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | ||
| 300 | pub fn request_stop(&mut self) { | 313 | pub fn request_stop(&mut self) { |
| 301 | let ch = self.channel.regs().ch(self.channel.num()); | 314 | let ch = self.channel.regs().ch(self.channel.num()); |
| 302 | ch.cr().modify(|w| { | 315 | ch.cr().modify(|w| { |
| @@ -304,6 +317,10 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 304 | }) | 317 | }) |
| 305 | } | 318 | } |
| 306 | 319 | ||
| 320 | /// Return whether this transfer is still running. | ||
| 321 | /// | ||
| 322 | /// If this returns `false`, it can be because either the transfer finished, or | ||
| 323 | /// it was requested to stop early with [`request_stop`](Self::request_stop). | ||
| 307 | pub fn is_running(&mut self) -> bool { | 324 | pub fn is_running(&mut self) -> bool { |
| 308 | let ch = self.channel.regs().ch(self.channel.num()); | 325 | let ch = self.channel.regs().ch(self.channel.num()); |
| 309 | let sr = ch.sr().read(); | 326 | let sr = ch.sr().read(); |
| @@ -317,6 +334,7 @@ impl<'a, C: Channel> Transfer<'a, C> { | |||
| 317 | ch.br1().read().bndt() | 334 | ch.br1().read().bndt() |
| 318 | } | 335 | } |
| 319 | 336 | ||
| 337 | /// Blocking wait until the transfer finishes. | ||
| 320 | pub fn blocking_wait(mut self) { | 338 | pub fn blocking_wait(mut self) { |
| 321 | while self.is_running() {} | 339 | while self.is_running() {} |
| 322 | 340 | ||
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 4006dee19..663a7f59d 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! Inter-Process Communication Controller (IPCC) | ||
| 2 | |||
| 1 | use core::future::poll_fn; | 3 | use core::future::poll_fn; |
| 2 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 3 | use core::task::Poll; | 5 | use core::task::Poll; |
| @@ -41,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive | |||
| 41 | } | 43 | } |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 46 | /// TX interrupt handler. | ||
| 44 | pub struct TransmitInterruptHandler {} | 47 | pub struct TransmitInterruptHandler {} |
| 45 | 48 | ||
| 46 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler { | 49 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler { |
| @@ -72,6 +75,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for Transmi | |||
| 72 | } | 75 | } |
| 73 | } | 76 | } |
| 74 | 77 | ||
| 78 | /// IPCC config. | ||
| 75 | #[non_exhaustive] | 79 | #[non_exhaustive] |
| 76 | #[derive(Clone, Copy, Default)] | 80 | #[derive(Clone, Copy, Default)] |
| 77 | pub struct Config { | 81 | pub struct Config { |
| @@ -79,6 +83,8 @@ pub struct Config { | |||
| 79 | // reserved for future use | 83 | // reserved for future use |
| 80 | } | 84 | } |
| 81 | 85 | ||
| 86 | /// Channel. | ||
| 87 | #[allow(missing_docs)] | ||
| 82 | #[derive(Debug, Clone, Copy)] | 88 | #[derive(Debug, Clone, Copy)] |
| 83 | #[repr(C)] | 89 | #[repr(C)] |
| 84 | pub enum IpccChannel { | 90 | pub enum IpccChannel { |
| @@ -90,9 +96,11 @@ pub enum IpccChannel { | |||
| 90 | Channel6 = 5, | 96 | Channel6 = 5, |
| 91 | } | 97 | } |
| 92 | 98 | ||
| 99 | /// IPCC driver. | ||
| 93 | pub struct Ipcc; | 100 | pub struct Ipcc; |
| 94 | 101 | ||
| 95 | impl Ipcc { | 102 | impl Ipcc { |
| 103 | /// Enable IPCC. | ||
| 96 | pub fn enable(_config: Config) { | 104 | pub fn enable(_config: Config) { |
| 97 | IPCC::enable_and_reset(); | 105 | IPCC::enable_and_reset(); |
| 98 | IPCC::set_cpu2(true); | 106 | IPCC::set_cpu2(true); |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 4952d26eb..207f7ed8f 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #![cfg_attr(not(test), no_std)] | 1 | #![cfg_attr(not(test), no_std)] |
| 2 | #![allow(async_fn_in_trait)] | 2 | #![allow(async_fn_in_trait)] |
| 3 | #![warn(missing_docs)] | ||
| 3 | 4 | ||
| 4 | //! ## Feature flags | 5 | //! ## Feature flags |
| 5 | #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] | 6 | #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] |
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 20d8f9045..a41c40eba 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -1,50 +1,53 @@ | |||
| 1 | /// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating | 1 | //! Low-power support. |
| 2 | /// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which | 2 | //! |
| 3 | /// can use knowledge of which peripherals are currently blocked upon to transparently and safely | 3 | //! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating |
| 4 | /// enter such low-power modes (currently, only `STOP2`) when idle. | 4 | //! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which |
| 5 | /// | 5 | //! can use knowledge of which peripherals are currently blocked upon to transparently and safely |
| 6 | /// The executor determines which peripherals are active by their RCC state; consequently, | 6 | //! enter such low-power modes (currently, only `STOP2`) when idle. |
| 7 | /// low-power states can only be entered if all peripherals have been `drop`'d. There are a few | 7 | //! |
| 8 | /// exceptions to this rule: | 8 | //! The executor determines which peripherals are active by their RCC state; consequently, |
| 9 | /// | 9 | //! low-power states can only be entered if all peripherals have been `drop`'d. There are a few |
| 10 | /// * `GPIO` | 10 | //! exceptions to this rule: |
| 11 | /// * `RCC` | 11 | //! |
| 12 | /// | 12 | //! * `GPIO` |
| 13 | /// Since entering and leaving low-power modes typically incurs a significant latency, the | 13 | //! * `RCC` |
| 14 | /// low-power executor will only attempt to enter when the next timer event is at least | 14 | //! |
| 15 | /// [`time_driver::MIN_STOP_PAUSE`] in the future. | 15 | //! Since entering and leaving low-power modes typically incurs a significant latency, the |
| 16 | /// | 16 | //! low-power executor will only attempt to enter when the next timer event is at least |
| 17 | /// Currently there is no macro analogous to `embassy_executor::main` for this executor; | 17 | //! [`time_driver::MIN_STOP_PAUSE`] in the future. |
| 18 | /// consequently one must define their entrypoint manually. Moveover, you must relinquish control | 18 | //! |
| 19 | /// of the `RTC` peripheral to the executor. This will typically look like | 19 | //! Currently there is no macro analogous to `embassy_executor::main` for this executor; |
| 20 | /// | 20 | //! consequently one must define their entrypoint manually. Moveover, you must relinquish control |
| 21 | /// ```rust,no_run | 21 | //! of the `RTC` peripheral to the executor. This will typically look like |
| 22 | /// use embassy_executor::Spawner; | 22 | //! |
| 23 | /// use embassy_stm32::low_power::Executor; | 23 | //! ```rust,no_run |
| 24 | /// use embassy_stm32::rtc::{Rtc, RtcConfig}; | 24 | //! use embassy_executor::Spawner; |
| 25 | /// use static_cell::make_static; | 25 | //! use embassy_stm32::low_power::Executor; |
| 26 | /// | 26 | //! use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 27 | /// #[cortex_m_rt::entry] | 27 | //! use static_cell::make_static; |
| 28 | /// fn main() -> ! { | 28 | //! |
| 29 | /// Executor::take().run(|spawner| { | 29 | //! #[cortex_m_rt::entry] |
| 30 | /// unwrap!(spawner.spawn(async_main(spawner))); | 30 | //! fn main() -> ! { |
| 31 | /// }); | 31 | //! Executor::take().run(|spawner| { |
| 32 | /// } | 32 | //! unwrap!(spawner.spawn(async_main(spawner))); |
| 33 | /// | 33 | //! }); |
| 34 | /// #[embassy_executor::task] | 34 | //! } |
| 35 | /// async fn async_main(spawner: Spawner) { | 35 | //! |
| 36 | /// // initialize the platform... | 36 | //! #[embassy_executor::task] |
| 37 | /// let mut config = embassy_stm32::Config::default(); | 37 | //! async fn async_main(spawner: Spawner) { |
| 38 | /// let p = embassy_stm32::init(config); | 38 | //! // initialize the platform... |
| 39 | /// | 39 | //! let mut config = embassy_stm32::Config::default(); |
| 40 | /// // give the RTC to the executor... | 40 | //! let p = embassy_stm32::init(config); |
| 41 | /// let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | 41 | //! |
| 42 | /// let rtc = make_static!(rtc); | 42 | //! // give the RTC to the executor... |
| 43 | /// embassy_stm32::low_power::stop_with_rtc(rtc); | 43 | //! let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); |
| 44 | /// | 44 | //! let rtc = make_static!(rtc); |
| 45 | /// // your application here... | 45 | //! embassy_stm32::low_power::stop_with_rtc(rtc); |
| 46 | /// } | 46 | //! |
| 47 | /// ``` | 47 | //! // your application here... |
| 48 | //! } | ||
| 49 | //! ``` | ||
| 50 | |||
| 48 | use core::arch::asm; | 51 | use core::arch::asm; |
| 49 | use core::marker::PhantomData; | 52 | use core::marker::PhantomData; |
| 50 | use core::sync::atomic::{compiler_fence, Ordering}; | 53 | use core::sync::atomic::{compiler_fence, Ordering}; |
| @@ -64,6 +67,7 @@ static mut EXECUTOR: Option<Executor> = None; | |||
| 64 | foreach_interrupt! { | 67 | foreach_interrupt! { |
| 65 | (RTC, rtc, $block:ident, WKUP, $irq:ident) => { | 68 | (RTC, rtc, $block:ident, WKUP, $irq:ident) => { |
| 66 | #[interrupt] | 69 | #[interrupt] |
| 70 | #[allow(non_snake_case)] | ||
| 67 | unsafe fn $irq() { | 71 | unsafe fn $irq() { |
| 68 | EXECUTOR.as_mut().unwrap().on_wakeup_irq(); | 72 | EXECUTOR.as_mut().unwrap().on_wakeup_irq(); |
| 69 | } | 73 | } |
| @@ -75,10 +79,15 @@ pub(crate) unsafe fn on_wakeup_irq() { | |||
| 75 | EXECUTOR.as_mut().unwrap().on_wakeup_irq(); | 79 | EXECUTOR.as_mut().unwrap().on_wakeup_irq(); |
| 76 | } | 80 | } |
| 77 | 81 | ||
| 82 | /// Configure STOP mode with RTC. | ||
| 78 | pub fn stop_with_rtc(rtc: &'static Rtc) { | 83 | pub fn stop_with_rtc(rtc: &'static Rtc) { |
| 79 | unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) | 84 | unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc) |
| 80 | } | 85 | } |
| 81 | 86 | ||
| 87 | /// Get whether the core is ready to enter the given stop mode. | ||
| 88 | /// | ||
| 89 | /// This will return false if some peripheral driver is in use that | ||
| 90 | /// prevents entering the given stop mode. | ||
| 82 | pub fn stop_ready(stop_mode: StopMode) -> bool { | 91 | pub fn stop_ready(stop_mode: StopMode) -> bool { |
| 83 | match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() { | 92 | match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() { |
| 84 | Some(StopMode::Stop2) => true, | 93 | Some(StopMode::Stop2) => true, |
| @@ -87,10 +96,13 @@ pub fn stop_ready(stop_mode: StopMode) -> bool { | |||
| 87 | } | 96 | } |
| 88 | } | 97 | } |
| 89 | 98 | ||
| 99 | /// Available stop modes. | ||
| 90 | #[non_exhaustive] | 100 | #[non_exhaustive] |
| 91 | #[derive(PartialEq)] | 101 | #[derive(PartialEq)] |
| 92 | pub enum StopMode { | 102 | pub enum StopMode { |
| 103 | /// STOP 1 | ||
| 93 | Stop1, | 104 | Stop1, |
| 105 | /// STOP 2 | ||
| 94 | Stop2, | 106 | Stop2, |
| 95 | } | 107 | } |
| 96 | 108 | ||
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index e1eb031d1..df8a78bcc 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs | |||
| @@ -1,9 +1,12 @@ | |||
| 1 | //! Operational Amplifier (OPAMP) | ||
| 1 | #![macro_use] | 2 | #![macro_use] |
| 2 | 3 | ||
| 3 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 4 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 4 | 5 | ||
| 5 | use crate::Peripheral; | 6 | use crate::Peripheral; |
| 6 | 7 | ||
| 8 | /// Gain | ||
| 9 | #[allow(missing_docs)] | ||
| 7 | #[derive(Clone, Copy)] | 10 | #[derive(Clone, Copy)] |
| 8 | pub enum OpAmpGain { | 11 | pub enum OpAmpGain { |
| 9 | Mul1, | 12 | Mul1, |
| @@ -13,6 +16,8 @@ pub enum OpAmpGain { | |||
| 13 | Mul16, | 16 | Mul16, |
| 14 | } | 17 | } |
| 15 | 18 | ||
| 19 | /// Speed | ||
| 20 | #[allow(missing_docs)] | ||
| 16 | #[derive(Clone, Copy)] | 21 | #[derive(Clone, Copy)] |
| 17 | pub enum OpAmpSpeed { | 22 | pub enum OpAmpSpeed { |
| 18 | Normal, | 23 | Normal, |
| @@ -180,6 +185,7 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { | |||
| 180 | } | 185 | } |
| 181 | } | 186 | } |
| 182 | 187 | ||
| 188 | /// Opamp instance trait. | ||
| 183 | pub trait Instance: sealed::Instance + 'static {} | 189 | pub trait Instance: sealed::Instance + 'static {} |
| 184 | 190 | ||
| 185 | pub(crate) mod sealed { | 191 | pub(crate) mod sealed { |
| @@ -198,8 +204,11 @@ pub(crate) mod sealed { | |||
| 198 | pub trait OutputPin<T: Instance> {} | 204 | pub trait OutputPin<T: Instance> {} |
| 199 | } | 205 | } |
| 200 | 206 | ||
| 207 | /// Non-inverting pin trait. | ||
| 201 | pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} | 208 | pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {} |
| 209 | /// Inverting pin trait. | ||
| 202 | pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} | 210 | pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {} |
| 211 | /// Output pin trait. | ||
| 203 | pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} | 212 | pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {} |
| 204 | 213 | ||
| 205 | macro_rules! impl_opamp_external_output { | 214 | macro_rules! impl_opamp_external_output { |
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 6ee89a922..ca641f352 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs | |||
| @@ -80,6 +80,7 @@ impl<'d, T: Instance> Rng<'d, T> { | |||
| 80 | let _ = self.next_u32(); | 80 | let _ = self.next_u32(); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /// Reset the RNG. | ||
| 83 | #[cfg(not(rng_v1))] | 84 | #[cfg(not(rng_v1))] |
| 84 | pub fn reset(&mut self) { | 85 | pub fn reset(&mut self) { |
| 85 | T::regs().cr().write(|reg| { | 86 | T::regs().cr().write(|reg| { |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index ab142053a..10006baff 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -293,6 +293,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | |||
| 293 | 293 | ||
| 294 | #[cfg(sdmmc_v1)] | 294 | #[cfg(sdmmc_v1)] |
| 295 | impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | 295 | impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { |
| 296 | /// Create a new SDMMC driver, with 1 data lane. | ||
| 296 | pub fn new_1bit( | 297 | pub fn new_1bit( |
| 297 | sdmmc: impl Peripheral<P = T> + 'd, | 298 | sdmmc: impl Peripheral<P = T> + 'd, |
| 298 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 299 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| @@ -327,6 +328,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 327 | ) | 328 | ) |
| 328 | } | 329 | } |
| 329 | 330 | ||
| 331 | /// Create a new SDMMC driver, with 4 data lanes. | ||
| 330 | pub fn new_4bit( | 332 | pub fn new_4bit( |
| 331 | sdmmc: impl Peripheral<P = T> + 'd, | 333 | sdmmc: impl Peripheral<P = T> + 'd, |
| 332 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 334 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index d0b289462..4debd4e54 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! Universal Serial Bus (USB) | ||
| 2 | |||
| 1 | use crate::interrupt; | 3 | use crate::interrupt; |
| 2 | use crate::rcc::RccPeripheral; | 4 | use crate::rcc::RccPeripheral; |
| 3 | 5 | ||
| @@ -10,7 +12,9 @@ pub(crate) mod sealed { | |||
| 10 | } | 12 | } |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 15 | /// USB instance trait. | ||
| 13 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { | 16 | pub trait Instance: sealed::Instance + RccPeripheral + 'static { |
| 17 | /// Interrupt for this USB instance. | ||
| 14 | type Interrupt: interrupt::typelevel::Interrupt; | 18 | type Interrupt: interrupt::typelevel::Interrupt; |
| 15 | } | 19 | } |
| 16 | 20 | ||
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 295dc9198..a8aebfe1f 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs | |||
| @@ -244,6 +244,7 @@ struct EndpointData { | |||
| 244 | used_out: bool, | 244 | used_out: bool, |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | /// USB driver. | ||
| 247 | pub struct Driver<'d, T: Instance> { | 248 | pub struct Driver<'d, T: Instance> { |
| 248 | phantom: PhantomData<&'d mut T>, | 249 | phantom: PhantomData<&'d mut T>, |
| 249 | alloc: [EndpointData; EP_COUNT], | 250 | alloc: [EndpointData; EP_COUNT], |
| @@ -251,6 +252,7 @@ pub struct Driver<'d, T: Instance> { | |||
| 251 | } | 252 | } |
| 252 | 253 | ||
| 253 | impl<'d, T: Instance> Driver<'d, T> { | 254 | impl<'d, T: Instance> Driver<'d, T> { |
| 255 | /// Create a new USB driver. | ||
| 254 | pub fn new( | 256 | pub fn new( |
| 255 | _usb: impl Peripheral<P = T> + 'd, | 257 | _usb: impl Peripheral<P = T> + 'd, |
| 256 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 258 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| @@ -465,6 +467,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { | |||
| 465 | } | 467 | } |
| 466 | } | 468 | } |
| 467 | 469 | ||
| 470 | /// USB bus. | ||
| 468 | pub struct Bus<'d, T: Instance> { | 471 | pub struct Bus<'d, T: Instance> { |
| 469 | phantom: PhantomData<&'d mut T>, | 472 | phantom: PhantomData<&'d mut T>, |
| 470 | ep_types: [EpType; EP_COUNT - 1], | 473 | ep_types: [EpType; EP_COUNT - 1], |
| @@ -640,6 +643,7 @@ trait Dir { | |||
| 640 | fn waker(i: usize) -> &'static AtomicWaker; | 643 | fn waker(i: usize) -> &'static AtomicWaker; |
| 641 | } | 644 | } |
| 642 | 645 | ||
| 646 | /// Marker type for the "IN" direction. | ||
| 643 | pub enum In {} | 647 | pub enum In {} |
| 644 | impl Dir for In { | 648 | impl Dir for In { |
| 645 | fn dir() -> Direction { | 649 | fn dir() -> Direction { |
| @@ -652,6 +656,7 @@ impl Dir for In { | |||
| 652 | } | 656 | } |
| 653 | } | 657 | } |
| 654 | 658 | ||
| 659 | /// Marker type for the "OUT" direction. | ||
| 655 | pub enum Out {} | 660 | pub enum Out {} |
| 656 | impl Dir for Out { | 661 | impl Dir for Out { |
| 657 | fn dir() -> Direction { | 662 | fn dir() -> Direction { |
| @@ -664,6 +669,7 @@ impl Dir for Out { | |||
| 664 | } | 669 | } |
| 665 | } | 670 | } |
| 666 | 671 | ||
| 672 | /// USB endpoint. | ||
| 667 | pub struct Endpoint<'d, T: Instance, D> { | 673 | pub struct Endpoint<'d, T: Instance, D> { |
| 668 | _phantom: PhantomData<(&'d mut T, D)>, | 674 | _phantom: PhantomData<(&'d mut T, D)>, |
| 669 | info: EndpointInfo, | 675 | info: EndpointInfo, |
| @@ -813,6 +819,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 813 | } | 819 | } |
| 814 | } | 820 | } |
| 815 | 821 | ||
| 822 | /// USB control pipe. | ||
| 816 | pub struct ControlPipe<'d, T: Instance> { | 823 | pub struct ControlPipe<'d, T: Instance> { |
| 817 | _phantom: PhantomData<&'d mut T>, | 824 | _phantom: PhantomData<&'d mut T>, |
| 818 | max_packet_size: u16, | 825 | max_packet_size: u16, |
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs index 1abd031dd..0649e684b 100644 --- a/embassy-stm32/src/usb_otg/mod.rs +++ b/embassy-stm32/src/usb_otg/mod.rs | |||
| @@ -20,7 +20,9 @@ pub(crate) mod sealed { | |||
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | /// USB OTG instance. | ||
| 23 | pub trait Instance: sealed::Instance + RccPeripheral { | 24 | pub trait Instance: sealed::Instance + RccPeripheral { |
| 25 | /// Interrupt for this USB OTG instance. | ||
| 24 | type Interrupt: interrupt::typelevel::Interrupt; | 26 | type Interrupt: interrupt::typelevel::Interrupt; |
| 25 | } | 27 | } |
| 26 | 28 | ||
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index ba77bfb16..190fb274f 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs | |||
| @@ -204,6 +204,7 @@ pub enum PhyType { | |||
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | impl PhyType { | 206 | impl PhyType { |
| 207 | /// Get whether this PHY is any of the internal types. | ||
| 207 | pub fn internal(&self) -> bool { | 208 | pub fn internal(&self) -> bool { |
| 208 | match self { | 209 | match self { |
| 209 | PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true, | 210 | PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true, |
| @@ -211,6 +212,7 @@ impl PhyType { | |||
| 211 | } | 212 | } |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 215 | /// Get whether this PHY is any of the high-speed types. | ||
| 214 | pub fn high_speed(&self) -> bool { | 216 | pub fn high_speed(&self) -> bool { |
| 215 | match self { | 217 | match self { |
| 216 | PhyType::InternalFullSpeed => false, | 218 | PhyType::InternalFullSpeed => false, |
| @@ -218,7 +220,7 @@ impl PhyType { | |||
| 218 | } | 220 | } |
| 219 | } | 221 | } |
| 220 | 222 | ||
| 221 | pub fn to_dspd(&self) -> vals::Dspd { | 223 | fn to_dspd(&self) -> vals::Dspd { |
| 222 | match self { | 224 | match self { |
| 223 | PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL, | 225 | PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL, |
| 224 | PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED, | 226 | PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED, |
| @@ -230,6 +232,7 @@ impl PhyType { | |||
| 230 | /// Indicates that [State::ep_out_buffers] is empty. | 232 | /// Indicates that [State::ep_out_buffers] is empty. |
| 231 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; | 233 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; |
| 232 | 234 | ||
| 235 | /// USB OTG driver state. | ||
| 233 | pub struct State<const EP_COUNT: usize> { | 236 | pub struct State<const EP_COUNT: usize> { |
| 234 | /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. | 237 | /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. |
| 235 | ep0_setup_data: UnsafeCell<[u8; 8]>, | 238 | ep0_setup_data: UnsafeCell<[u8; 8]>, |
| @@ -247,6 +250,7 @@ unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {} | |||
| 247 | unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {} | 250 | unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {} |
| 248 | 251 | ||
| 249 | impl<const EP_COUNT: usize> State<EP_COUNT> { | 252 | impl<const EP_COUNT: usize> State<EP_COUNT> { |
| 253 | /// Create a new State. | ||
| 250 | pub const fn new() -> Self { | 254 | pub const fn new() -> Self { |
| 251 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | 255 | const NEW_AW: AtomicWaker = AtomicWaker::new(); |
| 252 | const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); | 256 | const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); |
| @@ -271,6 +275,7 @@ struct EndpointData { | |||
| 271 | fifo_size_words: u16, | 275 | fifo_size_words: u16, |
| 272 | } | 276 | } |
| 273 | 277 | ||
| 278 | /// USB driver config. | ||
| 274 | #[non_exhaustive] | 279 | #[non_exhaustive] |
| 275 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | 280 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| 276 | pub struct Config { | 281 | pub struct Config { |
| @@ -297,6 +302,7 @@ impl Default for Config { | |||
| 297 | } | 302 | } |
| 298 | } | 303 | } |
| 299 | 304 | ||
| 305 | /// USB driver. | ||
| 300 | pub struct Driver<'d, T: Instance> { | 306 | pub struct Driver<'d, T: Instance> { |
| 301 | config: Config, | 307 | config: Config, |
| 302 | phantom: PhantomData<&'d mut T>, | 308 | phantom: PhantomData<&'d mut T>, |
| @@ -527,6 +533,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> { | |||
| 527 | } | 533 | } |
| 528 | } | 534 | } |
| 529 | 535 | ||
| 536 | /// USB bus. | ||
| 530 | pub struct Bus<'d, T: Instance> { | 537 | pub struct Bus<'d, T: Instance> { |
| 531 | config: Config, | 538 | config: Config, |
| 532 | phantom: PhantomData<&'d mut T>, | 539 | phantom: PhantomData<&'d mut T>, |
| @@ -1092,6 +1099,7 @@ trait Dir { | |||
| 1092 | fn dir() -> Direction; | 1099 | fn dir() -> Direction; |
| 1093 | } | 1100 | } |
| 1094 | 1101 | ||
| 1102 | /// Marker type for the "IN" direction. | ||
| 1095 | pub enum In {} | 1103 | pub enum In {} |
| 1096 | impl Dir for In { | 1104 | impl Dir for In { |
| 1097 | fn dir() -> Direction { | 1105 | fn dir() -> Direction { |
| @@ -1099,6 +1107,7 @@ impl Dir for In { | |||
| 1099 | } | 1107 | } |
| 1100 | } | 1108 | } |
| 1101 | 1109 | ||
| 1110 | /// Marker type for the "OUT" direction. | ||
| 1102 | pub enum Out {} | 1111 | pub enum Out {} |
| 1103 | impl Dir for Out { | 1112 | impl Dir for Out { |
| 1104 | fn dir() -> Direction { | 1113 | fn dir() -> Direction { |
| @@ -1106,6 +1115,7 @@ impl Dir for Out { | |||
| 1106 | } | 1115 | } |
| 1107 | } | 1116 | } |
| 1108 | 1117 | ||
| 1118 | /// USB endpoint. | ||
| 1109 | pub struct Endpoint<'d, T: Instance, D> { | 1119 | pub struct Endpoint<'d, T: Instance, D> { |
| 1110 | _phantom: PhantomData<(&'d mut T, D)>, | 1120 | _phantom: PhantomData<(&'d mut T, D)>, |
| 1111 | info: EndpointInfo, | 1121 | info: EndpointInfo, |
| @@ -1299,6 +1309,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1299 | } | 1309 | } |
| 1300 | } | 1310 | } |
| 1301 | 1311 | ||
| 1312 | /// USB control pipe. | ||
| 1302 | pub struct ControlPipe<'d, T: Instance> { | 1313 | pub struct ControlPipe<'d, T: Instance> { |
| 1303 | _phantom: PhantomData<&'d mut T>, | 1314 | _phantom: PhantomData<&'d mut T>, |
| 1304 | max_packet_size: u16, | 1315 | max_packet_size: u16, |
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 5751a9ff3..dc701ef64 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs | |||
| @@ -6,6 +6,7 @@ use stm32_metapac::iwdg::vals::{Key, Pr}; | |||
| 6 | 6 | ||
| 7 | use crate::rcc::LSI_FREQ; | 7 | use crate::rcc::LSI_FREQ; |
| 8 | 8 | ||
| 9 | /// Independent watchdog (IWDG) driver. | ||
| 9 | pub struct IndependentWatchdog<'d, T: Instance> { | 10 | pub struct IndependentWatchdog<'d, T: Instance> { |
| 10 | wdg: PhantomData<&'d mut T>, | 11 | wdg: PhantomData<&'d mut T>, |
| 11 | } | 12 | } |
| @@ -64,10 +65,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { | |||
| 64 | IndependentWatchdog { wdg: PhantomData } | 65 | IndependentWatchdog { wdg: PhantomData } |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 68 | /// Unleash (start) the watchdog. | ||
| 67 | pub fn unleash(&mut self) { | 69 | pub fn unleash(&mut self) { |
| 68 | T::regs().kr().write(|w| w.set_key(Key::START)); | 70 | T::regs().kr().write(|w| w.set_key(Key::START)); |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 73 | /// Pet (reload, refresh) the watchdog. | ||
| 71 | pub fn pet(&mut self) { | 74 | pub fn pet(&mut self) { |
| 72 | T::regs().kr().write(|w| w.set_key(Key::RESET)); | 75 | T::regs().kr().write(|w| w.set_key(Key::RESET)); |
| 73 | } | 76 | } |
| @@ -79,6 +82,7 @@ mod sealed { | |||
| 79 | } | 82 | } |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 85 | /// IWDG instance trait. | ||
| 82 | pub trait Instance: sealed::Instance {} | 86 | pub trait Instance: sealed::Instance {} |
| 83 | 87 | ||
| 84 | foreach_peripheral!( | 88 | foreach_peripheral!( |
