Skip to content

Commit

Permalink
feat(usb): usb-device impl
Browse files Browse the repository at this point in the history
  • Loading branch information
decaday committed Dec 26, 2024
1 parent d43b0b5 commit e9ac3ac
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 30 deletions.
16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ log = { version = "0.4", optional = true }
critical-section = "1.2"
cfg-if = "1.0.0"
portable-atomic = { version = "1", features = ["unsafe-assume-single-core", "require-cas"], optional = true }
# musb = { version = "0.1.0", optional = true, features = ["prebuild"] }
# musb = { version = "0.2.0", optional = true, features = ["prebuild"] }
musb = { git = "https://github.com/decaday/musb.git", optional = true, features = ["prebuild"] }
# musb = { path = "../musb", optional = true , features = ["prebuild"] }

embassy-usb-driver = {version = "0.1.0", optional = true }
usb-device = {version = "0.3.2", optional = true }


futures-util = { version = "0.3.30", default-features = false }
embassy-hal-internal = { version = "0.2.0", features = [
"cortex-m",
Expand All @@ -60,7 +64,7 @@ embassy-executor = { version = "0.6", features = [
"arch-cortex-m",
] }
embassy-embedded-hal = { version = "0.2.0", default-features = false }
embassy-usb-driver = {version = "0.1.0" }


[build-dependencies]
# py32-metapac = { path = "../py32-data/build/py32-metapac", default-features = false, features = [
Expand All @@ -77,7 +81,7 @@ default = ["rt", "memory-x", "defmt", "embassy", "time", "exti"]

rt = ["py32-metapac/rt"]

defmt = ["dep:defmt", "dep:defmt-rtt", "embassy-usb-driver/defmt"]
defmt = ["dep:defmt", "dep:defmt-rtt", "embassy-usb-driver/defmt", "musb?/defmt"]

memory-x = ["py32-metapac/memory-x"]

Expand All @@ -87,10 +91,8 @@ time = ["dep:embassy-time", "embassy-embedded-hal/time"]

exti = []

# PY32F07x: the IN and OUT buffers of the same endpoint being shared
# When this feature is enabled, the In and Out of an endpoint will not be used at the same time, except for ep0.
# PY32F403: IN and OUT do not share FIFO, this feature is invalid
allow-ep-shared-fifo = ["musb/allow-ep-shared-fifo"]
embassy-usb-driver-impl = ["dep:musb","dep:embassy-usb-driver", "musb/embassy-usb-driver-impl"]
usb-device-impl = ["dep:musb","dep:usb-device", "musb/usb-device-impl"]

py32f030k28 = ["py32-metapac/py32f030k28"]
py32f030f16 = ["py32-metapac/py32f030f16"]
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ pub mod usart;
pub mod gpio;
#[cfg(feature = "time-driver-systick")]
pub mod systick_time_driver;
#[cfg(feature = "py32f072c1b")]

#[cfg(any(feature = "embassy-usb-driver-impl", feature = "usb-device-impl"))]
pub mod usb;

#[cfg(feature = "exti")]
Expand Down
67 changes: 45 additions & 22 deletions src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
/// featuring a fixed FIFO size and with some register functionalities masked.
///
/// See more: https://github.com/decaday/musb
///
/// For the PY32F07x series, IN and OUT endpoints for the same endpoint share a FIFO.
/// By default, we don't use a single endpoint simultaneously for IN and OUT directions.
/// However, you can enable the `allow-ep-shared-fifo` feature to use an endpoint's IN
/// and OUT capabilities concurrently.
use core::marker::PhantomData;

#[cfg(feature = "embassy-usb-driver-impl")]
use embassy_usb_driver as driver;
#[cfg(feature = "embassy-usb-driver-impl")]
use embassy_usb_driver::EndpointType;
#[cfg(feature = "embassy-usb-driver-impl")]
use musb::{MusbDriver, In, Out, Bus, ControlPipe, Endpoint};
#[cfg(feature = "usb-device-impl")]
pub use musb::UsbdBus;

use musb::UsbInstance;

use crate::interrupt::typelevel::Interrupt;
use crate::rcc::{self, RccPeripheral};
use crate::{interrupt, Peripheral};

use embassy_usb_driver::EndpointType;

use musb::{Bus, ControlPipe, Endpoint, In, MusbDriver, Out, UsbInstance};

/// Interrupt handler.
pub struct InterruptHandler<T: Instance> {
Expand All @@ -31,12 +35,30 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
}
}

fn init<T: Instance>() {
let freq = T::frequency();
if freq.0 != 48_000_000 {
panic!("USB clock (PLL) must be 48MHz");
}

T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
rcc::enable_and_reset::<T>();

#[cfg(feature = "time")]
embassy_time::block_for(embassy_time::Duration::from_millis(100));
#[cfg(not(feature = "time"))]
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 10);
}

#[cfg(feature = "embassy-usb-driver-impl")]
/// USB driver.
pub struct Driver<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
inner: MusbDriver<'d, UsbInstance>,
}

#[cfg(feature = "embassy-usb-driver-impl")]
impl<'d, T: Instance> Driver<'d, T> {
/// Create a new USB driver.
pub fn new(
Expand All @@ -45,19 +67,7 @@ impl<'d, T: Instance> Driver<'d, T> {
_dp: impl Peripheral<P = impl DpPin<T>> + 'd,
_dm: impl Peripheral<P = impl DmPin<T>> + 'd,
) -> Self {
let freq = T::frequency();
if freq.0 != 48_000_000 {
panic!("USB clock (PLL) must be 48MHz");
}

T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
rcc::enable_and_reset::<T>();

#[cfg(feature = "time")]
embassy_time::block_for(embassy_time::Duration::from_millis(100));
#[cfg(not(feature = "time"))]
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 10);
init::<T>();

Self {
inner: MusbDriver::new(),
Expand All @@ -66,6 +76,7 @@ impl<'d, T: Instance> Driver<'d, T> {
}
}

#[cfg(feature = "embassy-usb-driver-impl")]
impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
type EndpointOut = Endpoint<'d, UsbInstance, Out>;
type EndpointIn = Endpoint<'d, UsbInstance, In>;
Expand All @@ -79,7 +90,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
interval_ms: u8,
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
self.inner
.alloc_endpoint(ep_type, max_packet_size, interval_ms, false)
.alloc_endpoint(ep_type, max_packet_size, interval_ms, None)
}

fn alloc_endpoint_out(
Expand All @@ -89,7 +100,7 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
interval_ms: u8,
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
self.inner
.alloc_endpoint(ep_type, max_packet_size, interval_ms, false)
.alloc_endpoint(ep_type, max_packet_size, interval_ms, None)
}

fn start(
Expand All @@ -100,6 +111,18 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
}
}

#[cfg(feature = "usb-device-impl")]
pub fn new_bus<'d, T: Instance>(
_usb: impl Peripheral<P = T> + 'd,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
_dp: impl Peripheral<P = impl DpPin<T>> + 'd,
_dm: impl Peripheral<P = impl DmPin<T>> + 'd,
) -> UsbdBus<UsbInstance> {
init::<T>();

UsbdBus::new()
}

trait SealedInstance {}

/// USB instance trait.
Expand Down

0 comments on commit e9ac3ac

Please sign in to comment.