mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 20:30:29 +00:00
Merge pull request #2711 from embassy-rs/stm32-usb-clock-check
stm32/usb: assert correct clock on init, set mux in all examples.
This commit is contained in:
commit
7bf4710f3f
@ -826,20 +826,20 @@ fn main() {
|
|||||||
(("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)),
|
(("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)),
|
||||||
(("usb", "DP"), quote!(crate::usb::DpPin)),
|
(("usb", "DP"), quote!(crate::usb::DpPin)),
|
||||||
(("usb", "DM"), quote!(crate::usb::DmPin)),
|
(("usb", "DM"), quote!(crate::usb::DmPin)),
|
||||||
(("otg", "DP"), quote!(crate::usb_otg::DpPin)),
|
(("otg", "DP"), quote!(crate::usb::DpPin)),
|
||||||
(("otg", "DM"), quote!(crate::usb_otg::DmPin)),
|
(("otg", "DM"), quote!(crate::usb::DmPin)),
|
||||||
(("otg", "ULPI_CK"), quote!(crate::usb_otg::UlpiClkPin)),
|
(("otg", "ULPI_CK"), quote!(crate::usb::UlpiClkPin)),
|
||||||
(("otg", "ULPI_DIR"), quote!(crate::usb_otg::UlpiDirPin)),
|
(("otg", "ULPI_DIR"), quote!(crate::usb::UlpiDirPin)),
|
||||||
(("otg", "ULPI_NXT"), quote!(crate::usb_otg::UlpiNxtPin)),
|
(("otg", "ULPI_NXT"), quote!(crate::usb::UlpiNxtPin)),
|
||||||
(("otg", "ULPI_STP"), quote!(crate::usb_otg::UlpiStpPin)),
|
(("otg", "ULPI_STP"), quote!(crate::usb::UlpiStpPin)),
|
||||||
(("otg", "ULPI_D0"), quote!(crate::usb_otg::UlpiD0Pin)),
|
(("otg", "ULPI_D0"), quote!(crate::usb::UlpiD0Pin)),
|
||||||
(("otg", "ULPI_D1"), quote!(crate::usb_otg::UlpiD1Pin)),
|
(("otg", "ULPI_D1"), quote!(crate::usb::UlpiD1Pin)),
|
||||||
(("otg", "ULPI_D2"), quote!(crate::usb_otg::UlpiD2Pin)),
|
(("otg", "ULPI_D2"), quote!(crate::usb::UlpiD2Pin)),
|
||||||
(("otg", "ULPI_D3"), quote!(crate::usb_otg::UlpiD3Pin)),
|
(("otg", "ULPI_D3"), quote!(crate::usb::UlpiD3Pin)),
|
||||||
(("otg", "ULPI_D4"), quote!(crate::usb_otg::UlpiD4Pin)),
|
(("otg", "ULPI_D4"), quote!(crate::usb::UlpiD4Pin)),
|
||||||
(("otg", "ULPI_D5"), quote!(crate::usb_otg::UlpiD5Pin)),
|
(("otg", "ULPI_D5"), quote!(crate::usb::UlpiD5Pin)),
|
||||||
(("otg", "ULPI_D6"), quote!(crate::usb_otg::UlpiD6Pin)),
|
(("otg", "ULPI_D6"), quote!(crate::usb::UlpiD6Pin)),
|
||||||
(("otg", "ULPI_D7"), quote!(crate::usb_otg::UlpiD7Pin)),
|
(("otg", "ULPI_D7"), quote!(crate::usb::UlpiD7Pin)),
|
||||||
(("can", "TX"), quote!(crate::can::TxPin)),
|
(("can", "TX"), quote!(crate::can::TxPin)),
|
||||||
(("can", "RX"), quote!(crate::can::RxPin)),
|
(("can", "RX"), quote!(crate::can::RxPin)),
|
||||||
(("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)),
|
(("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)),
|
||||||
|
@ -79,10 +79,8 @@ pub mod ucpd;
|
|||||||
pub mod uid;
|
pub mod uid;
|
||||||
#[cfg(usart)]
|
#[cfg(usart)]
|
||||||
pub mod usart;
|
pub mod usart;
|
||||||
#[cfg(usb)]
|
#[cfg(any(usb, otg))]
|
||||||
pub mod usb;
|
pub mod usb;
|
||||||
#[cfg(otg)]
|
|
||||||
pub mod usb_otg;
|
|
||||||
#[cfg(iwdg)]
|
#[cfg(iwdg)]
|
||||||
pub mod wdg;
|
pub mod wdg;
|
||||||
|
|
||||||
@ -107,10 +105,10 @@ pub use crate::_generated::interrupt;
|
|||||||
/// Example of how to bind one interrupt:
|
/// Example of how to bind one interrupt:
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// use embassy_stm32::{bind_interrupts, usb_otg, peripherals};
|
/// use embassy_stm32::{bind_interrupts, usb, peripherals};
|
||||||
///
|
///
|
||||||
/// bind_interrupts!(struct Irqs {
|
/// bind_interrupts!(struct Irqs {
|
||||||
/// OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
/// OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -1,37 +1,69 @@
|
|||||||
//! Universal Serial Bus (USB)
|
//! Universal Serial Bus (USB)
|
||||||
|
|
||||||
use crate::interrupt;
|
#[cfg_attr(usb, path = "usb.rs")]
|
||||||
use crate::rcc::RccPeripheral;
|
#[cfg_attr(otg, path = "otg.rs")]
|
||||||
|
mod _version;
|
||||||
|
pub use _version::*;
|
||||||
|
|
||||||
mod usb;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
pub use usb::*;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
/// clock, power initialization stuff that's common for USB and OTG.
|
||||||
pub trait Instance {
|
fn common_init<T: Instance>() {
|
||||||
fn regs() -> crate::pac::usb::Usb;
|
// Check the USB clock is enabled and running at exactly 48 MHz.
|
||||||
|
// frequency() will panic if not enabled
|
||||||
|
let freq = T::frequency();
|
||||||
|
// Check frequency is within the 0.25% tolerance allowed by the spec.
|
||||||
|
// Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user
|
||||||
|
// has tight clock restrictions due to something else (like audio).
|
||||||
|
if freq.0.abs_diff(48_000_000) > 120_000 {
|
||||||
|
panic!(
|
||||||
|
"USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.",
|
||||||
|
freq.0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(stm32l4, stm32l5, stm32wb))]
|
||||||
|
critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
|
||||||
|
|
||||||
|
#[cfg(pwr_h5)]
|
||||||
|
critical_section::with(|_| crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)));
|
||||||
|
|
||||||
|
#[cfg(stm32h7)]
|
||||||
|
{
|
||||||
|
// If true, VDD33USB is generated by internal regulator from VDD50USB
|
||||||
|
// If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
|
||||||
|
// TODO: unhardcode
|
||||||
|
let internal_regulator = false;
|
||||||
|
|
||||||
|
// Enable USB power
|
||||||
|
critical_section::with(|_| {
|
||||||
|
crate::pac::PWR.cr3().modify(|w| {
|
||||||
|
w.set_usb33den(true);
|
||||||
|
w.set_usbregen(internal_regulator);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for USB power to stabilize
|
||||||
|
while !crate::pac::PWR.cr3().read().usb33rdy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(stm32u5)]
|
||||||
|
{
|
||||||
|
// Enable USB power
|
||||||
|
critical_section::with(|_| {
|
||||||
|
crate::pac::PWR.svmcr().modify(|w| {
|
||||||
|
w.set_usv(true);
|
||||||
|
w.set_uvmen(true);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for USB power to stabilize
|
||||||
|
while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
T::Interrupt::unpend();
|
||||||
|
unsafe { T::Interrupt::enable() };
|
||||||
|
|
||||||
|
<T as RccPeripheral>::enable_and_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// USB instance trait.
|
|
||||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
|
||||||
/// Interrupt for this USB instance.
|
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal PHY pins
|
|
||||||
pin_trait!(DpPin, Instance);
|
|
||||||
pin_trait!(DmPin, Instance);
|
|
||||||
|
|
||||||
foreach_interrupt!(
|
|
||||||
($inst:ident, usb, $block:ident, LP, $irq:ident) => {
|
|
||||||
impl sealed::Instance for crate::peripherals::$inst {
|
|
||||||
fn regs() -> crate::pac::usb::Usb {
|
|
||||||
crate::pac::$inst
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Instance for crate::peripherals::$inst {
|
|
||||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
);
|
|
||||||
|
@ -11,7 +11,6 @@ use embassy_usb_driver::{
|
|||||||
};
|
};
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
@ -561,8 +560,7 @@ impl<'d, T: Instance> Bus<'d, T> {
|
|||||||
|
|
||||||
impl<'d, T: Instance> Bus<'d, T> {
|
impl<'d, T: Instance> Bus<'d, T> {
|
||||||
fn init(&mut self) {
|
fn init(&mut self) {
|
||||||
#[cfg(stm32l4)]
|
super::common_init::<T>();
|
||||||
critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
|
|
||||||
|
|
||||||
#[cfg(stm32f7)]
|
#[cfg(stm32f7)]
|
||||||
{
|
{
|
||||||
@ -590,22 +588,6 @@ impl<'d, T: Instance> Bus<'d, T> {
|
|||||||
|
|
||||||
#[cfg(stm32h7)]
|
#[cfg(stm32h7)]
|
||||||
{
|
{
|
||||||
// If true, VDD33USB is generated by internal regulator from VDD50USB
|
|
||||||
// If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
|
|
||||||
// TODO: unhardcode
|
|
||||||
let internal_regulator = false;
|
|
||||||
|
|
||||||
// Enable USB power
|
|
||||||
critical_section::with(|_| {
|
|
||||||
crate::pac::PWR.cr3().modify(|w| {
|
|
||||||
w.set_usb33den(true);
|
|
||||||
w.set_usbregen(internal_regulator);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for USB power to stabilize
|
|
||||||
while !crate::pac::PWR.cr3().read().usb33rdy() {}
|
|
||||||
|
|
||||||
// Enable ULPI clock if external PHY is used
|
// Enable ULPI clock if external PHY is used
|
||||||
let ulpien = !self.phy_type.internal();
|
let ulpien = !self.phy_type.internal();
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
@ -626,25 +608,6 @@ impl<'d, T: Instance> Bus<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stm32u5)]
|
|
||||||
{
|
|
||||||
// Enable USB power
|
|
||||||
critical_section::with(|_| {
|
|
||||||
crate::pac::PWR.svmcr().modify(|w| {
|
|
||||||
w.set_usv(true);
|
|
||||||
w.set_uvmen(true);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for USB power to stabilize
|
|
||||||
while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
<T as RccPeripheral>::enable_and_reset();
|
|
||||||
|
|
||||||
T::Interrupt::unpend();
|
|
||||||
unsafe { T::Interrupt::enable() };
|
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
let core_id = r.cid().read().0;
|
let core_id = r.cid().read().0;
|
||||||
trace!("Core id {:08x}", core_id);
|
trace!("Core id {:08x}", core_id);
|
||||||
@ -1469,3 +1432,159 @@ fn calculate_trdt(speed: vals::Dspd, ahb_freq: Hertz) -> u8 {
|
|||||||
fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool {
|
fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool {
|
||||||
r.cid().read().0 & 0xf000 == 0x1000
|
r.cid().read().0 & 0xf000 == 0x1000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
|
||||||
|
const MAX_EP_COUNT: usize = 9;
|
||||||
|
|
||||||
|
pub(crate) mod sealed {
|
||||||
|
pub trait Instance {
|
||||||
|
const HIGH_SPEED: bool;
|
||||||
|
const FIFO_DEPTH_WORDS: u16;
|
||||||
|
const ENDPOINT_COUNT: usize;
|
||||||
|
|
||||||
|
fn regs() -> crate::pac::otg::Otg;
|
||||||
|
fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// USB instance trait.
|
||||||
|
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||||
|
/// Interrupt for this USB instance.
|
||||||
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal PHY pins
|
||||||
|
pin_trait!(DpPin, Instance);
|
||||||
|
pin_trait!(DmPin, Instance);
|
||||||
|
|
||||||
|
// External PHY pins
|
||||||
|
pin_trait!(UlpiClkPin, Instance);
|
||||||
|
pin_trait!(UlpiDirPin, Instance);
|
||||||
|
pin_trait!(UlpiNxtPin, Instance);
|
||||||
|
pin_trait!(UlpiStpPin, Instance);
|
||||||
|
pin_trait!(UlpiD0Pin, Instance);
|
||||||
|
pin_trait!(UlpiD1Pin, Instance);
|
||||||
|
pin_trait!(UlpiD2Pin, Instance);
|
||||||
|
pin_trait!(UlpiD3Pin, Instance);
|
||||||
|
pin_trait!(UlpiD4Pin, Instance);
|
||||||
|
pin_trait!(UlpiD5Pin, Instance);
|
||||||
|
pin_trait!(UlpiD6Pin, Instance);
|
||||||
|
pin_trait!(UlpiD7Pin, Instance);
|
||||||
|
|
||||||
|
foreach_interrupt!(
|
||||||
|
(USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
||||||
|
impl sealed::Instance for crate::peripherals::USB_OTG_FS {
|
||||||
|
const HIGH_SPEED: bool = false;
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(stm32f1)] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 128;
|
||||||
|
const ENDPOINT_COUNT: usize = 8;
|
||||||
|
} else if #[cfg(any(
|
||||||
|
stm32f2,
|
||||||
|
stm32f401,
|
||||||
|
stm32f405,
|
||||||
|
stm32f407,
|
||||||
|
stm32f411,
|
||||||
|
stm32f415,
|
||||||
|
stm32f417,
|
||||||
|
stm32f427,
|
||||||
|
stm32f429,
|
||||||
|
stm32f437,
|
||||||
|
stm32f439,
|
||||||
|
))] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 320;
|
||||||
|
const ENDPOINT_COUNT: usize = 4;
|
||||||
|
} else if #[cfg(any(
|
||||||
|
stm32f412,
|
||||||
|
stm32f413,
|
||||||
|
stm32f423,
|
||||||
|
stm32f446,
|
||||||
|
stm32f469,
|
||||||
|
stm32f479,
|
||||||
|
stm32f7,
|
||||||
|
stm32l4,
|
||||||
|
stm32u5,
|
||||||
|
))] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 320;
|
||||||
|
const ENDPOINT_COUNT: usize = 6;
|
||||||
|
} else if #[cfg(stm32g0x1)] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 512;
|
||||||
|
const ENDPOINT_COUNT: usize = 8;
|
||||||
|
} else if #[cfg(stm32h7)] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||||
|
const ENDPOINT_COUNT: usize = 9;
|
||||||
|
} else if #[cfg(stm32u5)] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 320;
|
||||||
|
const ENDPOINT_COUNT: usize = 6;
|
||||||
|
} else {
|
||||||
|
compile_error!("USB_OTG_FS peripheral is not supported by this chip.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn regs() -> crate::pac::otg::Otg {
|
||||||
|
crate::pac::USB_OTG_FS
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state() -> &'static State<MAX_EP_COUNT> {
|
||||||
|
static STATE: State<MAX_EP_COUNT> = State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for crate::peripherals::USB_OTG_FS {
|
||||||
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
||||||
|
impl sealed::Instance for crate::peripherals::USB_OTG_HS {
|
||||||
|
const HIGH_SPEED: bool = true;
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(any(
|
||||||
|
stm32f2,
|
||||||
|
stm32f405,
|
||||||
|
stm32f407,
|
||||||
|
stm32f415,
|
||||||
|
stm32f417,
|
||||||
|
stm32f427,
|
||||||
|
stm32f429,
|
||||||
|
stm32f437,
|
||||||
|
stm32f439,
|
||||||
|
))] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||||
|
const ENDPOINT_COUNT: usize = 6;
|
||||||
|
} else if #[cfg(any(
|
||||||
|
stm32f446,
|
||||||
|
stm32f469,
|
||||||
|
stm32f479,
|
||||||
|
stm32f7,
|
||||||
|
stm32h7,
|
||||||
|
))] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||||
|
const ENDPOINT_COUNT: usize = 9;
|
||||||
|
} else if #[cfg(stm32u5)] {
|
||||||
|
const FIFO_DEPTH_WORDS: u16 = 1024;
|
||||||
|
const ENDPOINT_COUNT: usize = 9;
|
||||||
|
} else {
|
||||||
|
compile_error!("USB_OTG_HS peripheral is not supported by this chip.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn regs() -> crate::pac::otg::Otg {
|
||||||
|
// OTG HS registers are a superset of FS registers
|
||||||
|
unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state() -> &'static State<MAX_EP_COUNT> {
|
||||||
|
static STATE: State<MAX_EP_COUNT> = State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for crate::peripherals::USB_OTG_HS {
|
||||||
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
);
|
@ -12,8 +12,6 @@ use embassy_usb_driver::{
|
|||||||
Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
|
Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{DmPin, DpPin, Instance};
|
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
|
||||||
use crate::pac::usb::regs;
|
use crate::pac::usb::regs;
|
||||||
use crate::pac::usb::vals::{EpType, Stat};
|
use crate::pac::usb::vals::{EpType, Stat};
|
||||||
use crate::pac::USBRAM;
|
use crate::pac::USBRAM;
|
||||||
@ -259,19 +257,11 @@ impl<'d, T: Instance> Driver<'d, T> {
|
|||||||
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(dp, dm);
|
into_ref!(dp, dm);
|
||||||
T::Interrupt::unpend();
|
|
||||||
unsafe { T::Interrupt::enable() };
|
super::common_init::<T>();
|
||||||
|
|
||||||
let regs = T::regs();
|
let regs = T::regs();
|
||||||
|
|
||||||
#[cfg(any(stm32l4, stm32l5, stm32wb))]
|
|
||||||
crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
|
|
||||||
|
|
||||||
#[cfg(pwr_h5)]
|
|
||||||
crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true));
|
|
||||||
|
|
||||||
<T as RccPeripheral>::enable_and_reset();
|
|
||||||
|
|
||||||
regs.cntr().write(|w| {
|
regs.cntr().write(|w| {
|
||||||
w.set_pdwn(false);
|
w.set_pdwn(false);
|
||||||
w.set_fres(true);
|
w.set_fres(true);
|
||||||
@ -1057,3 +1047,33 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) mod sealed {
|
||||||
|
pub trait Instance {
|
||||||
|
fn regs() -> crate::pac::usb::Usb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// USB instance trait.
|
||||||
|
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||||
|
/// Interrupt for this USB instance.
|
||||||
|
type Interrupt: interrupt::typelevel::Interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal PHY pins
|
||||||
|
pin_trait!(DpPin, Instance);
|
||||||
|
pin_trait!(DmPin, Instance);
|
||||||
|
|
||||||
|
foreach_interrupt!(
|
||||||
|
($inst:ident, usb, $block:ident, LP, $irq:ident) => {
|
||||||
|
impl sealed::Instance for crate::peripherals::$inst {
|
||||||
|
fn regs() -> crate::pac::usb::Usb {
|
||||||
|
crate::pac::$inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for crate::peripherals::$inst {
|
||||||
|
type Interrupt = crate::interrupt::typelevel::$irq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
);
|
||||||
|
@ -1,163 +0,0 @@
|
|||||||
//! USB On The Go (OTG)
|
|
||||||
|
|
||||||
use crate::rcc::RccPeripheral;
|
|
||||||
use crate::{interrupt, peripherals};
|
|
||||||
|
|
||||||
mod usb;
|
|
||||||
pub use usb::*;
|
|
||||||
|
|
||||||
// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
|
|
||||||
const MAX_EP_COUNT: usize = 9;
|
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
|
||||||
pub trait Instance {
|
|
||||||
const HIGH_SPEED: bool;
|
|
||||||
const FIFO_DEPTH_WORDS: u16;
|
|
||||||
const ENDPOINT_COUNT: usize;
|
|
||||||
|
|
||||||
fn regs() -> crate::pac::otg::Otg;
|
|
||||||
fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// USB OTG instance.
|
|
||||||
pub trait Instance: sealed::Instance + RccPeripheral {
|
|
||||||
/// Interrupt for this USB OTG instance.
|
|
||||||
type Interrupt: interrupt::typelevel::Interrupt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal PHY pins
|
|
||||||
pin_trait!(DpPin, Instance);
|
|
||||||
pin_trait!(DmPin, Instance);
|
|
||||||
|
|
||||||
// External PHY pins
|
|
||||||
pin_trait!(UlpiClkPin, Instance);
|
|
||||||
pin_trait!(UlpiDirPin, Instance);
|
|
||||||
pin_trait!(UlpiNxtPin, Instance);
|
|
||||||
pin_trait!(UlpiStpPin, Instance);
|
|
||||||
pin_trait!(UlpiD0Pin, Instance);
|
|
||||||
pin_trait!(UlpiD1Pin, Instance);
|
|
||||||
pin_trait!(UlpiD2Pin, Instance);
|
|
||||||
pin_trait!(UlpiD3Pin, Instance);
|
|
||||||
pin_trait!(UlpiD4Pin, Instance);
|
|
||||||
pin_trait!(UlpiD5Pin, Instance);
|
|
||||||
pin_trait!(UlpiD6Pin, Instance);
|
|
||||||
pin_trait!(UlpiD7Pin, Instance);
|
|
||||||
|
|
||||||
foreach_interrupt!(
|
|
||||||
(USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
|
||||||
impl sealed::Instance for peripherals::USB_OTG_FS {
|
|
||||||
const HIGH_SPEED: bool = false;
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(stm32f1)] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 128;
|
|
||||||
const ENDPOINT_COUNT: usize = 8;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
stm32f2,
|
|
||||||
stm32f401,
|
|
||||||
stm32f405,
|
|
||||||
stm32f407,
|
|
||||||
stm32f411,
|
|
||||||
stm32f415,
|
|
||||||
stm32f417,
|
|
||||||
stm32f427,
|
|
||||||
stm32f429,
|
|
||||||
stm32f437,
|
|
||||||
stm32f439,
|
|
||||||
))] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 320;
|
|
||||||
const ENDPOINT_COUNT: usize = 4;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
stm32f412,
|
|
||||||
stm32f413,
|
|
||||||
stm32f423,
|
|
||||||
stm32f446,
|
|
||||||
stm32f469,
|
|
||||||
stm32f479,
|
|
||||||
stm32f7,
|
|
||||||
stm32l4,
|
|
||||||
stm32u5,
|
|
||||||
))] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 320;
|
|
||||||
const ENDPOINT_COUNT: usize = 6;
|
|
||||||
} else if #[cfg(stm32g0x1)] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 512;
|
|
||||||
const ENDPOINT_COUNT: usize = 8;
|
|
||||||
} else if #[cfg(stm32h7)] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
|
||||||
const ENDPOINT_COUNT: usize = 9;
|
|
||||||
} else if #[cfg(stm32u5)] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 320;
|
|
||||||
const ENDPOINT_COUNT: usize = 6;
|
|
||||||
} else {
|
|
||||||
compile_error!("USB_OTG_FS peripheral is not supported by this chip.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn regs() -> crate::pac::otg::Otg {
|
|
||||||
crate::pac::USB_OTG_FS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn state() -> &'static State<MAX_EP_COUNT> {
|
|
||||||
static STATE: State<MAX_EP_COUNT> = State::new();
|
|
||||||
&STATE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Instance for peripherals::USB_OTG_FS {
|
|
||||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
|
||||||
impl sealed::Instance for peripherals::USB_OTG_HS {
|
|
||||||
const HIGH_SPEED: bool = true;
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(any(
|
|
||||||
stm32f2,
|
|
||||||
stm32f405,
|
|
||||||
stm32f407,
|
|
||||||
stm32f415,
|
|
||||||
stm32f417,
|
|
||||||
stm32f427,
|
|
||||||
stm32f429,
|
|
||||||
stm32f437,
|
|
||||||
stm32f439,
|
|
||||||
))] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
|
||||||
const ENDPOINT_COUNT: usize = 6;
|
|
||||||
} else if #[cfg(any(
|
|
||||||
stm32f446,
|
|
||||||
stm32f469,
|
|
||||||
stm32f479,
|
|
||||||
stm32f7,
|
|
||||||
stm32h7,
|
|
||||||
))] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
|
||||||
const ENDPOINT_COUNT: usize = 9;
|
|
||||||
} else if #[cfg(stm32u5)] {
|
|
||||||
const FIFO_DEPTH_WORDS: u16 = 1024;
|
|
||||||
const ENDPOINT_COUNT: usize = 9;
|
|
||||||
} else {
|
|
||||||
compile_error!("USB_OTG_HS peripheral is not supported by this chip.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn regs() -> crate::pac::otg::Otg {
|
|
||||||
// OTG HS registers are a superset of FS registers
|
|
||||||
unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn state() -> &'static State<MAX_EP_COUNT> {
|
|
||||||
static STATE: State<MAX_EP_COUNT> = State::new();
|
|
||||||
&STATE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Instance for peripherals::USB_OTG_HS {
|
|
||||||
type Interrupt = crate::interrupt::typelevel::$irq;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
);
|
|
@ -7,8 +7,8 @@ use embassy_net::tcp::TcpSocket;
|
|||||||
use embassy_net::{Stack, StackResources};
|
use embassy_net::{Stack, StackResources};
|
||||||
use embassy_stm32::rng::{self, Rng};
|
use embassy_stm32::rng::{self, Rng};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||||
use embassy_usb::{Builder, UsbDevice};
|
use embassy_usb::{Builder, UsbDevice};
|
||||||
@ -36,7 +36,7 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
|
HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -63,13 +63,14 @@ async fn main(spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new();
|
static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new();
|
||||||
let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..];
|
let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_stm32::exti::ExtiInput;
|
use embassy_stm32::exti::ExtiInput;
|
||||||
use embassy_stm32::gpio::Pull;
|
use embassy_stm32::gpio::Pull;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
|
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
|
||||||
use embassy_usb::control::OutResponse;
|
use embassy_usb::control::OutResponse;
|
||||||
use embassy_usb::{Builder, Handler};
|
use embassy_usb::{Builder, Handler};
|
||||||
@ -18,7 +18,7 @@ use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -42,12 +42,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
||||||
use embassy_usb::control::OutResponse;
|
use embassy_usb::control::OutResponse;
|
||||||
@ -15,7 +15,7 @@ use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType};
|
use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType};
|
||||||
use embassy_usb::msos::{self, windows_version};
|
use embassy_usb::msos::{self, windows_version};
|
||||||
use embassy_usb::types::InterfaceNumber;
|
use embassy_usb::types::InterfaceNumber;
|
||||||
@ -66,7 +66,7 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"];
|
const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"];
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -92,12 +92,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
@ -13,7 +13,7 @@ use futures::future::join;
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
@ -13,7 +13,7 @@ use futures::future::join;
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
config.rcc.apb1_pre = APBPrescaler::DIV4;
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
config.rcc.sys = Sysclk::PLL1_P;
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
@ -12,7 +12,7 @@ use futures::future::join;
|
|||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -40,12 +40,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
|
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||||
config.rcc.voltage_scale = VoltageScale::Scale1;
|
config.rcc.voltage_scale = VoltageScale::Scale1;
|
||||||
|
config.rcc.mux.usbsel = mux::Usbsel::HSI48;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use defmt_rtt as _; // global logger
|
use defmt_rtt as _; // global logger
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
@ -14,7 +13,7 @@ use futures::future::join;
|
|||||||
use panic_probe as _;
|
use panic_probe as _;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -22,23 +21,26 @@ async fn main(_spawner: Spawner) {
|
|||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
{
|
||||||
config.rcc.sys = Sysclk::PLL1_R;
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.hsi = true;
|
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
source: PllSource::HSI,
|
config.rcc.hsi = true;
|
||||||
prediv: PllPreDiv::DIV1,
|
config.rcc.pll = Some(Pll {
|
||||||
mul: PllMul::MUL10,
|
source: PllSource::HSI,
|
||||||
divp: None,
|
prediv: PllPreDiv::DIV1,
|
||||||
divq: None,
|
mul: PllMul::MUL10,
|
||||||
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
|
divp: None,
|
||||||
});
|
divq: None,
|
||||||
|
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
|
||||||
|
});
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = true;
|
config.vbus_detection = true;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ use defmt::*;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_net::tcp::TcpSocket;
|
use embassy_net::tcp::TcpSocket;
|
||||||
use embassy_net::{Stack, StackResources};
|
use embassy_net::{Stack, StackResources};
|
||||||
use embassy_stm32::rcc::*;
|
|
||||||
use embassy_stm32::rng::Rng;
|
use embassy_stm32::rng::Rng;
|
||||||
use embassy_stm32::usb::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config};
|
||||||
@ -44,17 +43,22 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
|
|||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.hsi = true;
|
{
|
||||||
config.rcc.sys = Sysclk::PLL1_R;
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.hsi = true;
|
||||||
// 80Mhz clock (16 / 1 * 10 / 2)
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
source: PllSource::HSI,
|
config.rcc.pll = Some(Pll {
|
||||||
prediv: PllPreDiv::DIV1,
|
// 80Mhz clock (16 / 1 * 10 / 2)
|
||||||
mul: PllMul::MUL10,
|
source: PllSource::HSI,
|
||||||
divp: None,
|
prediv: PllPreDiv::DIV1,
|
||||||
divq: None,
|
mul: PllMul::MUL10,
|
||||||
divr: Some(PllRDiv::DIV2),
|
divp: None,
|
||||||
});
|
divq: None,
|
||||||
|
divr: Some(PllRDiv::DIV2),
|
||||||
|
});
|
||||||
|
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::rcc::*;
|
|
||||||
use embassy_stm32::usb::Driver;
|
use embassy_stm32::usb::Driver;
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
@ -21,17 +20,22 @@ bind_interrupts!(struct Irqs {
|
|||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.hsi = true;
|
{
|
||||||
config.rcc.sys = Sysclk::PLL1_R;
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.hsi = true;
|
||||||
// 80Mhz clock (16 / 1 * 10 / 2)
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
source: PllSource::HSI,
|
config.rcc.pll = Some(Pll {
|
||||||
prediv: PllPreDiv::DIV1,
|
// 80Mhz clock (16 / 1 * 10 / 2)
|
||||||
mul: PllMul::MUL10,
|
source: PllSource::HSI,
|
||||||
divp: None,
|
prediv: PllPreDiv::DIV1,
|
||||||
divq: None,
|
mul: PllMul::MUL10,
|
||||||
divr: Some(PllRDiv::DIV2),
|
divp: None,
|
||||||
});
|
divq: None,
|
||||||
|
divr: Some(PllRDiv::DIV2),
|
||||||
|
});
|
||||||
|
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
use embassy_stm32::rcc::*;
|
|
||||||
use embassy_stm32::usb::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
@ -19,17 +18,22 @@ bind_interrupts!(struct Irqs {
|
|||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.hsi = true;
|
{
|
||||||
config.rcc.sys = Sysclk::PLL1_R;
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.hsi = true;
|
||||||
// 80Mhz clock (16 / 1 * 10 / 2)
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
source: PllSource::HSI,
|
config.rcc.pll = Some(Pll {
|
||||||
prediv: PllPreDiv::DIV1,
|
// 80Mhz clock (16 / 1 * 10 / 2)
|
||||||
mul: PllMul::MUL10,
|
source: PllSource::HSI,
|
||||||
divp: None,
|
prediv: PllPreDiv::DIV1,
|
||||||
divq: None,
|
mul: PllMul::MUL10,
|
||||||
divr: Some(PllRDiv::DIV2),
|
divp: None,
|
||||||
});
|
divq: None,
|
||||||
|
divr: Some(PllRDiv::DIV2),
|
||||||
|
});
|
||||||
|
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
||||||
|
config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use defmt_rtt as _; // global logger
|
use defmt_rtt as _; // global logger
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::usb_otg::{Driver, Instance};
|
use embassy_stm32::usb::{Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||||
use embassy_usb::driver::EndpointError;
|
use embassy_usb::driver::EndpointError;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
@ -13,7 +13,7 @@ use futures::future::join;
|
|||||||
use panic_probe as _;
|
use panic_probe as _;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
OTG_FS => usb_otg::InterruptHandler<peripherals::USB_OTG_FS>;
|
OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
|
||||||
});
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
@ -35,13 +35,14 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.rcc.sys = Sysclk::PLL1_R;
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
config.rcc.voltage_range = VoltageScale::RANGE1;
|
config.rcc.voltage_range = VoltageScale::RANGE1;
|
||||||
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB
|
||||||
|
config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let mut ep_out_buffer = [0u8; 256];
|
let mut ep_out_buffer = [0u8; 256];
|
||||||
let mut config = embassy_stm32::usb_otg::Config::default();
|
let mut config = embassy_stm32::usb::Config::default();
|
||||||
config.vbus_detection = false;
|
config.vbus_detection = false;
|
||||||
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user