Skip to content

Commit 73f2cc4

Browse files
committed
refactor(usb): migrate code to crate `musb
1 parent 6feab84 commit 73f2cc4

File tree

8 files changed

+133
-933
lines changed

8 files changed

+133
-933
lines changed

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ log = { version = "0.4", optional = true }
4141
critical-section = "1.2"
4242
cfg-if = "1.0.0"
4343
portable-atomic = { version = "1", features = ["unsafe-assume-single-core", "require-cas"], optional = true }
44+
# musb = { version = "0.1.0", optional = true, features = ["prebuild"] }
45+
musb = { git = "https://github.com/decaday/musb.git", optional = true, features = ["prebuild"] }
46+
# musb = { path = "../musb", optional = true , features = ["prebuild"] }
4447

4548
futures-util = { version = "0.3.30", default-features = false }
4649
embassy-hal-internal = { version = "0.2.0", features = [
@@ -87,11 +90,11 @@ exti = []
8790
# PY32F07x: the IN and OUT buffers of the same endpoint being shared
8891
# When this feature is enabled, the In and Out of an endpoint will not be used at the same time, except for ep0.
8992
# PY32F403: IN and OUT do not share FIFO, this feature is invalid
90-
allow-ep-shared-fifo = []
93+
allow-ep-shared-fifo = ["musb/allow-ep-shared-fifo"]
9194

9295
py32f030k28 = ["py32-metapac/py32f030k28"]
9396
py32f030f16 = ["py32-metapac/py32f030f16"]
94-
py32f072c1b = ["py32-metapac/py32f072c1b"]
97+
py32f072c1b = ["py32-metapac/py32f072c1b", "dep:musb", "musb/builtin-py32f07x"]
9598

9699
# As of 2023-12-04, this driver is implemented using CC1 as the halfway rollover interrupt, and any
97100
# additional CC capabilities to provide timer alarms to embassy-time. embassy-time requires AT LEAST

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub mod time_driver;
4747
#[cfg(feature = "time-driver-systick")]
4848
pub mod systick_time_driver;
4949
pub mod gpio;
50-
#[cfg(usb)]
50+
#[cfg(feature = "py32f072c1b")]
5151
pub mod usb;
5252

5353
#[cfg(feature = "exti")]

src/usb.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/// Universal Serial Bus (USB)
2+
///
3+
/// The USB peripheral IP in PY32 is a mini Mentor USB (musb),
4+
/// featuring a fixed FIFO size and with some register functionalities masked.
5+
///
6+
/// See more: https://github.com/decaday/musb
7+
///
8+
/// For the PY32F07x series, IN and OUT endpoints for the same endpoint share a FIFO.
9+
/// By default, we don't use a single endpoint simultaneously for IN and OUT directions.
10+
/// However, you can enable the `allow-ep-shared-fifo` feature to use an endpoint's IN
11+
/// and OUT capabilities concurrently.
12+
13+
use core::marker::PhantomData;
14+
use embassy_usb_driver as driver;
15+
16+
use crate::rcc::{self, RccPeripheral};
17+
use crate::{interrupt, Peripheral};
18+
use crate::interrupt::typelevel::Interrupt;
19+
20+
use embassy_usb_driver::EndpointType;
21+
22+
use musb::{MusbDriver,
23+
Endpoint,
24+
ControlPipe,
25+
UsbInstance,
26+
Bus,
27+
Out,
28+
In,
29+
};
30+
31+
/// Interrupt handler.
32+
pub struct InterruptHandler<T: Instance> {
33+
_phantom: PhantomData<T>,
34+
}
35+
36+
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
37+
unsafe fn on_interrupt() {
38+
musb::on_interrupt::<UsbInstance>();
39+
}
40+
}
41+
42+
/// USB driver.
43+
pub struct Driver<'d, T: Instance> {
44+
phantom: PhantomData<&'d mut T>,
45+
inner: MusbDriver<'d, UsbInstance>,
46+
}
47+
48+
impl<'d, T: Instance> Driver<'d, T> {
49+
/// Create a new USB driver.
50+
pub fn new(
51+
_usb: impl Peripheral<P = T> + 'd,
52+
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
53+
_dp: impl Peripheral<P = impl DpPin<T>> + 'd,
54+
_dm: impl Peripheral<P = impl DmPin<T>> + 'd,
55+
) -> Self {
56+
let freq = T::frequency();
57+
if freq.0 != 48_000_000 {
58+
panic!("USB clock (PLL) must be 48MHz");
59+
}
60+
61+
T::Interrupt::unpend();
62+
unsafe { T::Interrupt::enable() };
63+
rcc::enable_and_reset::<T>();
64+
65+
#[cfg(feature = "time")]
66+
embassy_time::block_for(embassy_time::Duration::from_millis(100));
67+
#[cfg(not(feature = "time"))]
68+
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 10);
69+
70+
Self {
71+
inner: MusbDriver::new(),
72+
phantom: PhantomData,
73+
}
74+
}
75+
}
76+
77+
impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
78+
type EndpointOut = Endpoint<'d, UsbInstance, Out>;
79+
type EndpointIn = Endpoint<'d, UsbInstance, In>;
80+
type ControlPipe = ControlPipe<'d, UsbInstance>;
81+
type Bus = Bus<'d, UsbInstance>;
82+
83+
fn alloc_endpoint_in(
84+
&mut self,
85+
ep_type: EndpointType,
86+
max_packet_size: u16,
87+
interval_ms: u8,
88+
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
89+
self.inner.alloc_endpoint(ep_type, max_packet_size, interval_ms, false)
90+
}
91+
92+
fn alloc_endpoint_out(
93+
&mut self,
94+
ep_type: EndpointType,
95+
max_packet_size: u16,
96+
interval_ms: u8,
97+
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
98+
self.inner.alloc_endpoint(ep_type, max_packet_size, interval_ms, false)
99+
}
100+
101+
fn start(self, control_max_packet_size: u16) -> (Bus<'d, UsbInstance>, ControlPipe<'d, UsbInstance>) {
102+
self.inner.start(control_max_packet_size)
103+
}
104+
}
105+
106+
trait SealedInstance {}
107+
108+
/// USB instance trait.
109+
#[allow(private_bounds)]
110+
pub trait Instance: SealedInstance + RccPeripheral + 'static {
111+
/// Interrupt for this USB instance.
112+
type Interrupt: interrupt::typelevel::Interrupt;
113+
}
114+
115+
// Internal PHY pins
116+
pin_trait!(DpPin, Instance);
117+
pin_trait!(DmPin, Instance);
118+
119+
foreach_interrupt!(
120+
($inst:ident, usb, $block:ident, LP, $irq:ident) => {
121+
impl SealedInstance for crate::peripherals::$inst {}
122+
123+
impl Instance for crate::peripherals::$inst {
124+
type Interrupt = crate::interrupt::typelevel::$irq;
125+
}
126+
};
127+
);

0 commit comments

Comments
 (0)