-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathusb.rs
More file actions
192 lines (161 loc) · 5.11 KB
/
usb.rs
File metadata and controls
192 lines (161 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/// Universal Serial Bus (USB)
///
/// See more: https://github.com/decaday/musb
use core::marker::PhantomData;
use embassy_usb_driver::{self as driver, EndpointAddress, EndpointType};
use musb::MusbInstance;
use musb::{Bus, ControlPipe, Endpoint, In, MusbDriver, Out, UsbInstance};
use crate::gpio::hpsys::HpsysPin;
use crate::interrupt::typelevel::Interrupt;
use crate::pac::HPSYS_CFG;
use crate::rcc::{RccEnableReset, RccGetFreq, get_clk_usb_div, get_clk_usb_source};
use crate::{Peripheral, interrupt};
fn init<T: Instance>() {
let freq = T::frequency();
if let Some(f) = freq {
if f.0 != 60_000_000 {
panic!(
"USB clock must be 60MHz, clock is {:?}, clock source:{:?}, div:{}",
freq,
get_clk_usb_source(),
get_clk_usb_div()
);
}
} else {
panic!(
"USB clock is not configured, clock source:{:?}",
get_clk_usb_source()
);
}
// rcc::enable_and_reset::<T>();
T::rcc_enable();
// 58: TODO
// 52 & 56
HPSYS_CFG.usbcr().modify(|w| {
w.set_dm_pd(true);
w.set_dp_en(true);
w.set_usb_en(true);
});
// Enable USB PHY
UsbInstance::regs().usbcfg().modify(|w| {
w.set_avalid(true);
w.set_avalid_dr(true);
// w.set_usb_en(true);
});
musb::common_impl::endpoints_set_rx_dualpacket_enabled::<UsbInstance>(0x00);
musb::common_impl::endpoints_set_tx_dualpacket_enabled::<UsbInstance>(0x00);
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
HPSYS_CFG.usbcr().modify(|w| {
w.set_usb_en(true);
});
// info!("USB power {:b}", UsbInstance::regs().power().read().0);
UsbInstance::regs().power().modify(|w| {
w.set_hs_enab(false);
});
UsbInstance::regs().power().modify(|w| {
w.set_soft_conn(true);
});
// UsbInstance::regs().devctl().modify(|w| {
// w.set_session(true);
// });
UsbInstance::regs().index().write(|w| w.set_index(0));
// TODO: Should this?
// crate::blocking_delay_us(1000);
}
/// USB driver.
pub struct Driver<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
inner: MusbDriver<'d, UsbInstance>,
}
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,
dp: impl Peripheral<P = impl DpPin<T>> + 'd,
dm: impl Peripheral<P = impl DmPin<T>> + 'd,
) -> Self {
let mut dm = HpsysPin::new(dm.into_ref().pin_bank());
dm.disable_interrupt();
dm.set_as_analog();
let mut dp = HpsysPin::new(dp.into_ref().pin_bank());
dp.disable_interrupt();
dp.set_as_analog();
init::<T>();
Self {
inner: MusbDriver::new(),
phantom: PhantomData,
}
}
}
impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
type EndpointOut = Endpoint<'d, UsbInstance, Out>;
type EndpointIn = Endpoint<'d, UsbInstance, In>;
type ControlPipe = ControlPipe<'d, UsbInstance>;
type Bus = Bus<'d, UsbInstance>;
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
self.inner
.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
self.inner
.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(
self,
control_max_packet_size: u16,
) -> (Bus<'d, UsbInstance>, ControlPipe<'d, UsbInstance>) {
self.inner.start(control_max_packet_size)
}
}
/// Interrupt handler.
pub struct InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
unsafe {
musb::on_interrupt::<UsbInstance>();
}
}
}
trait SealedInstance: RccEnableReset + RccGetFreq {}
/// USB instance trait.
#[allow(private_bounds)]
pub trait Instance: SealedInstance + 'static {
/// Interrupt for this USB instance.
type Interrupt: interrupt::typelevel::Interrupt;
}
impl SealedInstance for crate::peripherals::USBC {}
impl Instance for crate::peripherals::USBC {
type Interrupt = crate::interrupt::typelevel::USBC;
}
// Internal PHY pins
pin_trait!(DpPin, Instance);
pin_trait!(DmPin, Instance);
// SDK set them to analog.
// Datasheet shows: PA35 AF2 #USB11_DP
impl DpPin<crate::peripherals::USBC> for crate::peripherals::PA35 {
fn fsel(&self) -> u8 {
0x2
}
}
impl DmPin<crate::peripherals::USBC> for crate::peripherals::PA36 {
fn fsel(&self) -> u8 {
0x2
}
}
// impl SealedInstance for {}