mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-29 02:02:28 +00:00
stm32: doc everything else.
This commit is contained in:
parent
189b15c426
commit
c8c8b89104
@ -16,6 +16,7 @@ use crate::interrupt::Priority;
|
||||
use crate::pac;
|
||||
use crate::pac::gpdma::vals;
|
||||
|
||||
/// GPDMA transfer options.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
@ -113,10 +114,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::gpdma::Gpdma, channel_num: usize, in
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA request type alias. (also known as DMA channel number in some chips)
|
||||
pub type Request = u8;
|
||||
|
||||
/// DMA channel.
|
||||
#[cfg(dmamux)]
|
||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static + super::dmamux::MuxChannel {}
|
||||
/// DMA channel.
|
||||
#[cfg(not(dmamux))]
|
||||
pub trait Channel: sealed::Channel + Peripheral<P = Self> + 'static {}
|
||||
|
||||
@ -131,12 +135,14 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA transfer.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Transfer<'a, C: Channel> {
|
||||
channel: PeripheralRef<'a, C>,
|
||||
}
|
||||
|
||||
impl<'a, C: Channel> Transfer<'a, C> {
|
||||
/// Create a new read DMA transfer (peripheral to memory).
|
||||
pub unsafe fn new_read<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@ -147,6 +153,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
Self::new_read_raw(channel, request, peri_addr, buf, options)
|
||||
}
|
||||
|
||||
/// Create a new read DMA transfer (peripheral to memory), using raw pointers.
|
||||
pub unsafe fn new_read_raw<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@ -172,6 +179,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral).
|
||||
pub unsafe fn new_write<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@ -182,6 +190,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
Self::new_write_raw(channel, request, buf, peri_addr, options)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral), using raw pointers.
|
||||
pub unsafe fn new_write_raw<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@ -207,6 +216,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new write DMA transfer (memory to peripheral), writing the same value repeatedly.
|
||||
pub unsafe fn new_write_repeated<W: Word>(
|
||||
channel: impl Peripheral<P = C> + 'a,
|
||||
request: Request,
|
||||
@ -297,6 +307,9 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
this
|
||||
}
|
||||
|
||||
/// Request the transfer to stop.
|
||||
///
|
||||
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
|
||||
pub fn request_stop(&mut self) {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
ch.cr().modify(|w| {
|
||||
@ -304,6 +317,10 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Return whether this transfer is still running.
|
||||
///
|
||||
/// If this returns `false`, it can be because either the transfer finished, or
|
||||
/// it was requested to stop early with [`request_stop`](Self::request_stop).
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
let ch = self.channel.regs().ch(self.channel.num());
|
||||
let sr = ch.sr().read();
|
||||
@ -317,6 +334,7 @@ impl<'a, C: Channel> Transfer<'a, C> {
|
||||
ch.br1().read().bndt()
|
||||
}
|
||||
|
||||
/// Blocking wait until the transfer finishes.
|
||||
pub fn blocking_wait(mut self) {
|
||||
while self.is_running() {}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
//! Inter-Process Communication Controller (IPCC)
|
||||
|
||||
use core::future::poll_fn;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
@ -41,6 +43,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for Receive
|
||||
}
|
||||
}
|
||||
|
||||
/// TX interrupt handler.
|
||||
pub struct TransmitInterruptHandler {}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// IPCC config.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Config {
|
||||
@ -79,6 +83,8 @@ pub struct Config {
|
||||
// reserved for future use
|
||||
}
|
||||
|
||||
/// Channel.
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub enum IpccChannel {
|
||||
@ -90,9 +96,11 @@ pub enum IpccChannel {
|
||||
Channel6 = 5,
|
||||
}
|
||||
|
||||
/// IPCC driver.
|
||||
pub struct Ipcc;
|
||||
|
||||
impl Ipcc {
|
||||
/// Enable IPCC.
|
||||
pub fn enable(_config: Config) {
|
||||
IPCC::enable_and_reset();
|
||||
IPCC::set_cpu2(true);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
#![allow(async_fn_in_trait)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
//! ## Feature flags
|
||||
#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
|
||||
|
@ -1,50 +1,53 @@
|
||||
/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
|
||||
/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
|
||||
/// can use knowledge of which peripherals are currently blocked upon to transparently and safely
|
||||
/// enter such low-power modes (currently, only `STOP2`) when idle.
|
||||
///
|
||||
/// The executor determines which peripherals are active by their RCC state; consequently,
|
||||
/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few
|
||||
/// exceptions to this rule:
|
||||
///
|
||||
/// * `GPIO`
|
||||
/// * `RCC`
|
||||
///
|
||||
/// Since entering and leaving low-power modes typically incurs a significant latency, the
|
||||
/// low-power executor will only attempt to enter when the next timer event is at least
|
||||
/// [`time_driver::MIN_STOP_PAUSE`] in the future.
|
||||
///
|
||||
/// Currently there is no macro analogous to `embassy_executor::main` for this executor;
|
||||
/// consequently one must define their entrypoint manually. Moveover, you must relinquish control
|
||||
/// of the `RTC` peripheral to the executor. This will typically look like
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use embassy_executor::Spawner;
|
||||
/// use embassy_stm32::low_power::Executor;
|
||||
/// use embassy_stm32::rtc::{Rtc, RtcConfig};
|
||||
/// use static_cell::make_static;
|
||||
///
|
||||
/// #[cortex_m_rt::entry]
|
||||
/// fn main() -> ! {
|
||||
/// Executor::take().run(|spawner| {
|
||||
/// unwrap!(spawner.spawn(async_main(spawner)));
|
||||
/// });
|
||||
/// }
|
||||
///
|
||||
/// #[embassy_executor::task]
|
||||
/// async fn async_main(spawner: Spawner) {
|
||||
/// // initialize the platform...
|
||||
/// let mut config = embassy_stm32::Config::default();
|
||||
/// let p = embassy_stm32::init(config);
|
||||
///
|
||||
/// // give the RTC to the executor...
|
||||
/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
|
||||
/// let rtc = make_static!(rtc);
|
||||
/// embassy_stm32::low_power::stop_with_rtc(rtc);
|
||||
///
|
||||
/// // your application here...
|
||||
/// }
|
||||
/// ```
|
||||
//! Low-power support.
|
||||
//!
|
||||
//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
|
||||
//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
|
||||
//! can use knowledge of which peripherals are currently blocked upon to transparently and safely
|
||||
//! enter such low-power modes (currently, only `STOP2`) when idle.
|
||||
//!
|
||||
//! The executor determines which peripherals are active by their RCC state; consequently,
|
||||
//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few
|
||||
//! exceptions to this rule:
|
||||
//!
|
||||
//! * `GPIO`
|
||||
//! * `RCC`
|
||||
//!
|
||||
//! Since entering and leaving low-power modes typically incurs a significant latency, the
|
||||
//! low-power executor will only attempt to enter when the next timer event is at least
|
||||
//! [`time_driver::MIN_STOP_PAUSE`] in the future.
|
||||
//!
|
||||
//! Currently there is no macro analogous to `embassy_executor::main` for this executor;
|
||||
//! consequently one must define their entrypoint manually. Moveover, you must relinquish control
|
||||
//! of the `RTC` peripheral to the executor. This will typically look like
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use embassy_executor::Spawner;
|
||||
//! use embassy_stm32::low_power::Executor;
|
||||
//! use embassy_stm32::rtc::{Rtc, RtcConfig};
|
||||
//! use static_cell::make_static;
|
||||
//!
|
||||
//! #[cortex_m_rt::entry]
|
||||
//! fn main() -> ! {
|
||||
//! Executor::take().run(|spawner| {
|
||||
//! unwrap!(spawner.spawn(async_main(spawner)));
|
||||
//! });
|
||||
//! }
|
||||
//!
|
||||
//! #[embassy_executor::task]
|
||||
//! async fn async_main(spawner: Spawner) {
|
||||
//! // initialize the platform...
|
||||
//! let mut config = embassy_stm32::Config::default();
|
||||
//! let p = embassy_stm32::init(config);
|
||||
//!
|
||||
//! // give the RTC to the executor...
|
||||
//! let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
|
||||
//! let rtc = make_static!(rtc);
|
||||
//! embassy_stm32::low_power::stop_with_rtc(rtc);
|
||||
//!
|
||||
//! // your application here...
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use core::arch::asm;
|
||||
use core::marker::PhantomData;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
@ -64,6 +67,7 @@ static mut EXECUTOR: Option<Executor> = None;
|
||||
foreach_interrupt! {
|
||||
(RTC, rtc, $block:ident, WKUP, $irq:ident) => {
|
||||
#[interrupt]
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn $irq() {
|
||||
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
||||
}
|
||||
@ -75,10 +79,15 @@ pub(crate) unsafe fn on_wakeup_irq() {
|
||||
EXECUTOR.as_mut().unwrap().on_wakeup_irq();
|
||||
}
|
||||
|
||||
/// Configure STOP mode with RTC.
|
||||
pub fn stop_with_rtc(rtc: &'static Rtc) {
|
||||
unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
|
||||
}
|
||||
|
||||
/// Get whether the core is ready to enter the given stop mode.
|
||||
///
|
||||
/// This will return false if some peripheral driver is in use that
|
||||
/// prevents entering the given stop mode.
|
||||
pub fn stop_ready(stop_mode: StopMode) -> bool {
|
||||
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
|
||||
Some(StopMode::Stop2) => true,
|
||||
@ -87,10 +96,13 @@ pub fn stop_ready(stop_mode: StopMode) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Available stop modes.
|
||||
#[non_exhaustive]
|
||||
#[derive(PartialEq)]
|
||||
pub enum StopMode {
|
||||
/// STOP 1
|
||||
Stop1,
|
||||
/// STOP 2
|
||||
Stop2,
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
//! Operational Amplifier (OPAMP)
|
||||
#![macro_use]
|
||||
|
||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||
|
||||
use crate::Peripheral;
|
||||
|
||||
/// Gain
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum OpAmpGain {
|
||||
Mul1,
|
||||
@ -13,6 +16,8 @@ pub enum OpAmpGain {
|
||||
Mul16,
|
||||
}
|
||||
|
||||
/// Speed
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum OpAmpSpeed {
|
||||
Normal,
|
||||
@ -180,6 +185,7 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Opamp instance trait.
|
||||
pub trait Instance: sealed::Instance + 'static {}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
@ -198,8 +204,11 @@ pub(crate) mod sealed {
|
||||
pub trait OutputPin<T: Instance> {}
|
||||
}
|
||||
|
||||
/// Non-inverting pin trait.
|
||||
pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
|
||||
/// Inverting pin trait.
|
||||
pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
|
||||
/// Output pin trait.
|
||||
pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {}
|
||||
|
||||
macro_rules! impl_opamp_external_output {
|
||||
|
@ -80,6 +80,7 @@ impl<'d, T: Instance> Rng<'d, T> {
|
||||
let _ = self.next_u32();
|
||||
}
|
||||
|
||||
/// Reset the RNG.
|
||||
#[cfg(not(rng_v1))]
|
||||
pub fn reset(&mut self) {
|
||||
T::regs().cr().write(|reg| {
|
||||
|
@ -293,6 +293,7 @@ pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> {
|
||||
|
||||
#[cfg(sdmmc_v1)]
|
||||
impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> {
|
||||
/// Create a new SDMMC driver, with 1 data lane.
|
||||
pub fn new_1bit(
|
||||
sdmmc: impl Peripheral<P = T> + 'd,
|
||||
_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> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new SDMMC driver, with 4 data lanes.
|
||||
pub fn new_4bit(
|
||||
sdmmc: impl Peripheral<P = T> + 'd,
|
||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
|
@ -1,3 +1,5 @@
|
||||
//! Universal Serial Bus (USB)
|
||||
|
||||
use crate::interrupt;
|
||||
use crate::rcc::RccPeripheral;
|
||||
|
||||
@ -10,7 +12,9 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB instance trait.
|
||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||
/// Interrupt for this USB instance.
|
||||
type Interrupt: interrupt::typelevel::Interrupt;
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,7 @@ struct EndpointData {
|
||||
used_out: bool,
|
||||
}
|
||||
|
||||
/// USB driver.
|
||||
pub struct Driver<'d, T: Instance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
alloc: [EndpointData; EP_COUNT],
|
||||
@ -251,6 +252,7 @@ pub struct Driver<'d, T: Instance> {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Driver<'d, T> {
|
||||
/// Create a new USB driver.
|
||||
pub fn new(
|
||||
_usb: impl Peripheral<P = T> + 'd,
|
||||
_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> {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB bus.
|
||||
pub struct Bus<'d, T: Instance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
ep_types: [EpType; EP_COUNT - 1],
|
||||
@ -640,6 +643,7 @@ trait Dir {
|
||||
fn waker(i: usize) -> &'static AtomicWaker;
|
||||
}
|
||||
|
||||
/// Marker type for the "IN" direction.
|
||||
pub enum In {}
|
||||
impl Dir for In {
|
||||
fn dir() -> Direction {
|
||||
@ -652,6 +656,7 @@ impl Dir for In {
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type for the "OUT" direction.
|
||||
pub enum Out {}
|
||||
impl Dir for Out {
|
||||
fn dir() -> Direction {
|
||||
@ -664,6 +669,7 @@ impl Dir for Out {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB endpoint.
|
||||
pub struct Endpoint<'d, T: Instance, D> {
|
||||
_phantom: PhantomData<(&'d mut T, D)>,
|
||||
info: EndpointInfo,
|
||||
@ -813,6 +819,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB control pipe.
|
||||
pub struct ControlPipe<'d, T: Instance> {
|
||||
_phantom: PhantomData<&'d mut T>,
|
||||
max_packet_size: u16,
|
||||
|
@ -20,7 +20,9 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB OTG instance.
|
||||
pub trait Instance: sealed::Instance + RccPeripheral {
|
||||
/// Interrupt for this USB OTG instance.
|
||||
type Interrupt: interrupt::typelevel::Interrupt;
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,7 @@ pub enum PhyType {
|
||||
}
|
||||
|
||||
impl PhyType {
|
||||
/// Get whether this PHY is any of the internal types.
|
||||
pub fn internal(&self) -> bool {
|
||||
match self {
|
||||
PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
|
||||
@ -211,6 +212,7 @@ impl PhyType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get whether this PHY is any of the high-speed types.
|
||||
pub fn high_speed(&self) -> bool {
|
||||
match self {
|
||||
PhyType::InternalFullSpeed => false,
|
||||
@ -218,7 +220,7 @@ impl PhyType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_dspd(&self) -> vals::Dspd {
|
||||
fn to_dspd(&self) -> vals::Dspd {
|
||||
match self {
|
||||
PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
|
||||
PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
|
||||
@ -230,6 +232,7 @@ impl PhyType {
|
||||
/// Indicates that [State::ep_out_buffers] is empty.
|
||||
const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
|
||||
|
||||
/// USB OTG driver state.
|
||||
pub struct State<const EP_COUNT: usize> {
|
||||
/// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
|
||||
ep0_setup_data: UnsafeCell<[u8; 8]>,
|
||||
@ -247,6 +250,7 @@ unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
|
||||
unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
|
||||
|
||||
impl<const EP_COUNT: usize> State<EP_COUNT> {
|
||||
/// Create a new State.
|
||||
pub const fn new() -> Self {
|
||||
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
||||
const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
|
||||
@ -271,6 +275,7 @@ struct EndpointData {
|
||||
fifo_size_words: u16,
|
||||
}
|
||||
|
||||
/// USB driver config.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct Config {
|
||||
@ -297,6 +302,7 @@ impl Default for Config {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB driver.
|
||||
pub struct Driver<'d, T: Instance> {
|
||||
config: Config,
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
@ -527,6 +533,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB bus.
|
||||
pub struct Bus<'d, T: Instance> {
|
||||
config: Config,
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
@ -1092,6 +1099,7 @@ trait Dir {
|
||||
fn dir() -> Direction;
|
||||
}
|
||||
|
||||
/// Marker type for the "IN" direction.
|
||||
pub enum In {}
|
||||
impl Dir for In {
|
||||
fn dir() -> Direction {
|
||||
@ -1099,6 +1107,7 @@ impl Dir for In {
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type for the "OUT" direction.
|
||||
pub enum Out {}
|
||||
impl Dir for Out {
|
||||
fn dir() -> Direction {
|
||||
@ -1106,6 +1115,7 @@ impl Dir for Out {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB endpoint.
|
||||
pub struct Endpoint<'d, T: Instance, D> {
|
||||
_phantom: PhantomData<(&'d mut T, D)>,
|
||||
info: EndpointInfo,
|
||||
@ -1299,6 +1309,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB control pipe.
|
||||
pub struct ControlPipe<'d, T: Instance> {
|
||||
_phantom: PhantomData<&'d mut T>,
|
||||
max_packet_size: u16,
|
||||
|
@ -6,6 +6,7 @@ use stm32_metapac::iwdg::vals::{Key, Pr};
|
||||
|
||||
use crate::rcc::LSI_FREQ;
|
||||
|
||||
/// Independent watchdog (IWDG) driver.
|
||||
pub struct IndependentWatchdog<'d, T: Instance> {
|
||||
wdg: PhantomData<&'d mut T>,
|
||||
}
|
||||
@ -64,10 +65,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
|
||||
IndependentWatchdog { wdg: PhantomData }
|
||||
}
|
||||
|
||||
/// Unleash (start) the watchdog.
|
||||
pub fn unleash(&mut self) {
|
||||
T::regs().kr().write(|w| w.set_key(Key::START));
|
||||
}
|
||||
|
||||
/// Pet (reload, refresh) the watchdog.
|
||||
pub fn pet(&mut self) {
|
||||
T::regs().kr().write(|w| w.set_key(Key::RESET));
|
||||
}
|
||||
@ -79,6 +82,7 @@ mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// IWDG instance trait.
|
||||
pub trait Instance: sealed::Instance {}
|
||||
|
||||
foreach_peripheral!(
|
||||
|
Loading…
Reference in New Issue
Block a user