aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-04-26 17:35:28 +0200
committerDániel Buga <[email protected]>2024-04-26 17:58:23 +0200
commit91c42e0b9e118d88a51fecf07dc3f41b61c0762c (patch)
tree8614303f101e8fc86263c9d7cf1a6812aa01d9f1 /embassy-stm32/src
parent4d4cbc0dd3e84dfd7d29d1ecdd2b388568be081f (diff)
Extract synopsys otg driver
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/usb/otg.rs1310
1 files changed, 107 insertions, 1203 deletions
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 29572d3c6..c59aae87f 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -1,22 +1,19 @@
1use core::cell::UnsafeCell;
2use core::marker::PhantomData; 1use core::marker::PhantomData;
3use core::sync::atomic::{AtomicBool, AtomicU16, Ordering};
4use core::task::Poll;
5 2
6use embassy_hal_internal::{into_ref, Peripheral}; 3use embassy_hal_internal::{into_ref, Peripheral};
7use embassy_sync::waitqueue::AtomicWaker; 4use embassy_usb_driver::{EndpointAddress, EndpointAllocError, EndpointType, Event, Unsupported};
8use embassy_usb_driver::{ 5use embassy_usb_synopsys_otg::otg_v1::vals::Dspd;
9 Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut, 6use embassy_usb_synopsys_otg::otg_v1::Otg;
10 EndpointType, Event, Unsupported, 7pub use embassy_usb_synopsys_otg::Config;
8use embassy_usb_synopsys_otg::{
9 on_interrupt as on_interrupt_impl, Bus as OtgBus, ControlPipe, Driver as OtgDriver, Endpoint, In, OtgInstance, Out,
10 PhyType, State, MAX_EP_COUNT,
11}; 11};
12use futures::future::poll_fn;
13 12
14use crate::gpio::AFType; 13use crate::gpio::AFType;
15use crate::interrupt; 14use crate::interrupt;
16use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
17use crate::pac::otg::{regs, vals};
18use crate::rcc::{RccPeripheral, SealedRccPeripheral}; 16use crate::rcc::{RccPeripheral, SealedRccPeripheral};
19use crate::time::Hertz;
20 17
21/// Interrupt handler. 18/// Interrupt handler.
22pub struct InterruptHandler<T: Instance> { 19pub struct InterruptHandler<T: Instance> {
@@ -29,142 +26,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
29 let r = T::regs(); 26 let r = T::regs();
30 let state = T::state(); 27 let state = T::state();
31 28
32 let ints = r.gintsts().read(); 29 let setup_late_cnak = quirk_setup_late_cnak(r);
33 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
34 // Mask interrupts and notify `Bus` to process them
35 r.gintmsk().write(|_| {});
36 T::state().bus_waker.wake();
37 }
38
39 // Handle RX
40 while r.gintsts().read().rxflvl() {
41 let status = r.grxstsp().read();
42 trace!("=== status {:08x}", status.0);
43 let ep_num = status.epnum() as usize;
44 let len = status.bcnt() as usize;
45
46 assert!(ep_num < T::ENDPOINT_COUNT);
47
48 match status.pktstsd() {
49 vals::Pktstsd::SETUP_DATA_RX => {
50 trace!("SETUP_DATA_RX");
51 assert!(len == 8, "invalid SETUP packet length={}", len);
52 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
53
54 // flushing TX if something stuck in control endpoint
55 if r.dieptsiz(ep_num).read().pktcnt() != 0 {
56 r.grstctl().modify(|w| {
57 w.set_txfnum(ep_num as _);
58 w.set_txfflsh(true);
59 });
60 while r.grstctl().read().txfflsh() {}
61 }
62
63 if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
64 // SAFETY: exclusive access ensured by atomic bool
65 let data = unsafe { &mut *state.ep0_setup_data.get() };
66 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
67 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
68 state.ep0_setup_ready.store(true, Ordering::Release);
69 state.ep_out_wakers[0].wake();
70 } else {
71 error!("received SETUP before previous finished processing");
72 // discard FIFO
73 r.fifo(0).read();
74 r.fifo(0).read();
75 }
76 }
77 vals::Pktstsd::OUT_DATA_RX => {
78 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
79
80 if state.ep_out_size[ep_num].load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
81 // SAFETY: Buffer size is allocated to be equal to endpoint's maximum packet size
82 // We trust the peripheral to not exceed its configured MPSIZ
83 let buf = unsafe { core::slice::from_raw_parts_mut(*state.ep_out_buffers[ep_num].get(), len) };
84
85 for chunk in buf.chunks_mut(4) {
86 // RX FIFO is shared so always read from fifo(0)
87 let data = r.fifo(0).read().0;
88 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
89 }
90
91 state.ep_out_size[ep_num].store(len as u16, Ordering::Release);
92 state.ep_out_wakers[ep_num].wake();
93 } else {
94 error!("ep_out buffer overflow index={}", ep_num);
95
96 // discard FIFO data
97 let len_words = (len + 3) / 4;
98 for _ in 0..len_words {
99 r.fifo(0).read().data();
100 }
101 }
102 }
103 vals::Pktstsd::OUT_DATA_DONE => {
104 trace!("OUT_DATA_DONE ep={}", ep_num);
105 }
106 vals::Pktstsd::SETUP_DATA_DONE => {
107 trace!("SETUP_DATA_DONE ep={}", ep_num);
108
109 if quirk_setup_late_cnak(r) {
110 // Clear NAK to indicate we are ready to receive more data
111 r.doepctl(ep_num).modify(|w| w.set_cnak(true));
112 }
113 }
114 x => trace!("unknown PKTSTS: {}", x.to_bits()),
115 }
116 }
117
118 // IN endpoint interrupt
119 if ints.iepint() {
120 let mut ep_mask = r.daint().read().iepint();
121 let mut ep_num = 0;
122
123 // Iterate over endpoints while there are non-zero bits in the mask
124 while ep_mask != 0 {
125 if ep_mask & 1 != 0 {
126 let ep_ints = r.diepint(ep_num).read();
127
128 // clear all
129 r.diepint(ep_num).write_value(ep_ints);
130
131 // TXFE is cleared in DIEPEMPMSK
132 if ep_ints.txfe() {
133 critical_section::with(|_| {
134 r.diepempmsk().modify(|w| {
135 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
136 });
137 });
138 }
139
140 state.ep_in_wakers[ep_num].wake();
141 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0);
142 }
143
144 ep_mask >>= 1;
145 ep_num += 1;
146 }
147 }
148 30
149 // not needed? reception handled in rxflvl 31 on_interrupt_impl(r, state, T::ENDPOINT_COUNT, setup_late_cnak);
150 // OUT endpoint interrupt
151 // if ints.oepint() {
152 // let mut ep_mask = r.daint().read().oepint();
153 // let mut ep_num = 0;
154
155 // while ep_mask != 0 {
156 // if ep_mask & 1 != 0 {
157 // let ep_ints = r.doepint(ep_num).read();
158 // // clear all
159 // r.doepint(ep_num).write_value(ep_ints);
160 // state.ep_out_wakers[ep_num].wake();
161 // trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
162 // }
163
164 // ep_mask >>= 1;
165 // ep_num += 1;
166 // }
167 // }
168 } 32 }
169} 33}
170 34
@@ -187,129 +51,10 @@ macro_rules! config_ulpi_pins {
187// The following numbers are pessimistic and were figured out empirically. 51// The following numbers are pessimistic and were figured out empirically.
188const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30; 52const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30;
189 53
190/// USB PHY type
191#[derive(Copy, Clone, Debug, Eq, PartialEq)]
192pub enum PhyType {
193 /// Internal Full-Speed PHY
194 ///
195 /// Available on most High-Speed peripherals.
196 InternalFullSpeed,
197 /// Internal High-Speed PHY
198 ///
199 /// Available on a few STM32 chips.
200 InternalHighSpeed,
201 /// External ULPI High-Speed PHY
202 ExternalHighSpeed,
203}
204
205impl PhyType {
206 /// Get whether this PHY is any of the internal types.
207 pub fn internal(&self) -> bool {
208 match self {
209 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
210 PhyType::ExternalHighSpeed => false,
211 }
212 }
213
214 /// Get whether this PHY is any of the high-speed types.
215 pub fn high_speed(&self) -> bool {
216 match self {
217 PhyType::InternalFullSpeed => false,
218 PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
219 }
220 }
221
222 fn to_dspd(&self) -> vals::Dspd {
223 match self {
224 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
225 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
226 PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
227 }
228 }
229}
230
231/// Indicates that [State::ep_out_buffers] is empty.
232const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
233
234/// USB OTG driver state.
235pub struct State<const EP_COUNT: usize> {
236 /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true.
237 ep0_setup_data: UnsafeCell<[u8; 8]>,
238 ep0_setup_ready: AtomicBool,
239 ep_in_wakers: [AtomicWaker; EP_COUNT],
240 ep_out_wakers: [AtomicWaker; EP_COUNT],
241 /// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint.
242 /// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY].
243 ep_out_buffers: [UnsafeCell<*mut u8>; EP_COUNT],
244 ep_out_size: [AtomicU16; EP_COUNT],
245 bus_waker: AtomicWaker,
246}
247
248unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
249unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
250
251impl<const EP_COUNT: usize> State<EP_COUNT> {
252 /// Create a new State.
253 pub const fn new() -> Self {
254 const NEW_AW: AtomicWaker = AtomicWaker::new();
255 const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
256 const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY);
257
258 Self {
259 ep0_setup_data: UnsafeCell::new([0u8; 8]),
260 ep0_setup_ready: AtomicBool::new(false),
261 ep_in_wakers: [NEW_AW; EP_COUNT],
262 ep_out_wakers: [NEW_AW; EP_COUNT],
263 ep_out_buffers: [NEW_BUF; EP_COUNT],
264 ep_out_size: [NEW_SIZE; EP_COUNT],
265 bus_waker: NEW_AW,
266 }
267 }
268}
269
270#[derive(Debug, Clone, Copy)]
271struct EndpointData {
272 ep_type: EndpointType,
273 max_packet_size: u16,
274 fifo_size_words: u16,
275}
276
277/// USB driver config.
278#[non_exhaustive]
279#[derive(Clone, Copy, PartialEq, Eq, Debug)]
280pub struct Config {
281 /// Enable VBUS detection.
282 ///
283 /// The USB spec requires USB devices monitor for USB cable plug/unplug and react accordingly.
284 /// This is done by checking whether there is 5V on the VBUS pin or not.
285 ///
286 /// If your device is bus-powered (powers itself from the USB host via VBUS), then this is optional.
287 /// (If there's no power in VBUS your device would be off anyway, so it's fine to always assume
288 /// there's power in VBUS, i.e. the USB cable is always plugged in.)
289 ///
290 /// If your device is self-powered (i.e. it gets power from a source other than the USB cable, and
291 /// therefore can stay powered through USB cable plug/unplug) then you MUST set this to true.
292 ///
293 /// If you set this to true, you must connect VBUS to PA9 for FS, PB13 for HS, possibly with a
294 /// voltage divider. See ST application note AN4879 and the reference manual for more details.
295 pub vbus_detection: bool,
296}
297
298impl Default for Config {
299 fn default() -> Self {
300 Self { vbus_detection: true }
301 }
302}
303
304/// USB driver. 54/// USB driver.
305pub struct Driver<'d, T: Instance> { 55pub struct Driver<'d, T: Instance> {
306 config: Config,
307 phantom: PhantomData<&'d mut T>, 56 phantom: PhantomData<&'d mut T>,
308 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 57 inner: OtgDriver<'d>,
309 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
310 ep_out_buffer: &'d mut [u8],
311 ep_out_buffer_offset: usize,
312 phy_type: PhyType,
313} 58}
314 59
315impl<'d, T: Instance> Driver<'d, T> { 60impl<'d, T: Instance> Driver<'d, T> {
@@ -333,14 +78,22 @@ impl<'d, T: Instance> Driver<'d, T> {
333 dp.set_as_af(dp.af_num(), AFType::OutputPushPull); 78 dp.set_as_af(dp.af_num(), AFType::OutputPushPull);
334 dm.set_as_af(dm.af_num(), AFType::OutputPushPull); 79 dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
335 80
81 let regs = T::regs();
82
83 let instance = OtgInstance {
84 regs,
85 state: T::state(),
86 fifo_depth_words: T::FIFO_DEPTH_WORDS,
87 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
88 endpoint_count: T::ENDPOINT_COUNT,
89 phy_type: PhyType::InternalFullSpeed,
90 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
91 calculate_trdt_fn: calculate_trdt::<T>,
92 };
93
336 Self { 94 Self {
337 config, 95 inner: OtgDriver::new(ep_out_buffer, instance, config),
338 phantom: PhantomData, 96 phantom: PhantomData,
339 ep_in: [None; MAX_EP_COUNT],
340 ep_out: [None; MAX_EP_COUNT],
341 ep_out_buffer,
342 ep_out_buffer_offset: 0,
343 phy_type: PhyType::InternalFullSpeed,
344 } 97 }
345 } 98 }
346 99
@@ -376,111 +129,30 @@ impl<'d, T: Instance> Driver<'d, T> {
376 ulpi_d7 129 ulpi_d7
377 ); 130 );
378 131
379 Self { 132 let regs = T::regs();
380 config,
381 phantom: PhantomData,
382 ep_in: [None; MAX_EP_COUNT],
383 ep_out: [None; MAX_EP_COUNT],
384 ep_out_buffer,
385 ep_out_buffer_offset: 0,
386 phy_type: PhyType::ExternalHighSpeed,
387 }
388 }
389
390 // Returns total amount of words (u32) allocated in dedicated FIFO
391 fn allocated_fifo_words(&self) -> u16 {
392 RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
393 }
394
395 fn alloc_endpoint<D: Dir>(
396 &mut self,
397 ep_type: EndpointType,
398 max_packet_size: u16,
399 interval_ms: u8,
400 ) -> Result<Endpoint<'d, T, D>, EndpointAllocError> {
401 trace!(
402 "allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
403 ep_type,
404 max_packet_size,
405 interval_ms,
406 D::dir()
407 );
408
409 if D::dir() == Direction::Out {
410 if self.ep_out_buffer_offset + max_packet_size as usize >= self.ep_out_buffer.len() {
411 error!("Not enough endpoint out buffer capacity");
412 return Err(EndpointAllocError);
413 }
414 };
415
416 let fifo_size_words = match D::dir() {
417 Direction::Out => (max_packet_size + 3) / 4,
418 // INEPTXFD requires minimum size of 16 words
419 Direction::In => u16::max((max_packet_size + 3) / 4, 16),
420 };
421
422 if fifo_size_words + self.allocated_fifo_words() > T::FIFO_DEPTH_WORDS {
423 error!("Not enough FIFO capacity");
424 return Err(EndpointAllocError);
425 }
426
427 let eps = match D::dir() {
428 Direction::Out => &mut self.ep_out,
429 Direction::In => &mut self.ep_in,
430 };
431
432 // Find free endpoint slot
433 let slot = eps.iter_mut().enumerate().find(|(i, ep)| {
434 if *i == 0 && ep_type != EndpointType::Control {
435 // reserved for control pipe
436 false
437 } else {
438 ep.is_none()
439 }
440 });
441 133
442 let index = match slot { 134 let instance = OtgInstance {
443 Some((index, ep)) => { 135 regs: T::regs(),
444 *ep = Some(EndpointData { 136 state: T::state(),
445 ep_type, 137 fifo_depth_words: T::FIFO_DEPTH_WORDS,
446 max_packet_size, 138 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
447 fifo_size_words, 139 endpoint_count: T::ENDPOINT_COUNT,
448 }); 140 phy_type: PhyType::ExternalHighSpeed,
449 index 141 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
450 } 142 calculate_trdt_fn: calculate_trdt::<T>,
451 None => {
452 error!("No free endpoints available");
453 return Err(EndpointAllocError);
454 }
455 }; 143 };
456 144
457 trace!(" index={}", index); 145 Self {
458 146 inner: OtgDriver::new(ep_out_buffer, instance, config),
459 if D::dir() == Direction::Out { 147 phantom: PhantomData,
460 // Buffer capacity check was done above, now allocation cannot fail
461 unsafe {
462 *T::state().ep_out_buffers[index].get() =
463 self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
464 }
465 self.ep_out_buffer_offset += max_packet_size as usize;
466 } 148 }
467
468 Ok(Endpoint {
469 _phantom: PhantomData,
470 info: EndpointInfo {
471 addr: EndpointAddress::from_parts(index, D::dir()),
472 ep_type,
473 max_packet_size,
474 interval_ms,
475 },
476 })
477 } 149 }
478} 150}
479 151
480impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> { 152impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
481 type EndpointOut = Endpoint<'d, T, Out>; 153 type EndpointOut = Endpoint<'d, Out>;
482 type EndpointIn = Endpoint<'d, T, In>; 154 type EndpointIn = Endpoint<'d, In>;
483 type ControlPipe = ControlPipe<'d, T>; 155 type ControlPipe = ControlPipe<'d>;
484 type Bus = Bus<'d, T>; 156 type Bus = Bus<'d, T>;
485 157
486 fn alloc_endpoint_in( 158 fn alloc_endpoint_in(
@@ -489,7 +161,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
489 max_packet_size: u16, 161 max_packet_size: u16,
490 interval_ms: u8, 162 interval_ms: u8,
491 ) -> Result<Self::EndpointIn, EndpointAllocError> { 163 ) -> Result<Self::EndpointIn, EndpointAllocError> {
492 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 164 self.inner.alloc_endpoint(ep_type, max_packet_size, interval_ms)
493 } 165 }
494 166
495 fn alloc_endpoint_out( 167 fn alloc_endpoint_out(
@@ -498,72 +170,37 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
498 max_packet_size: u16, 170 max_packet_size: u16,
499 interval_ms: u8, 171 interval_ms: u8,
500 ) -> Result<Self::EndpointOut, EndpointAllocError> { 172 ) -> Result<Self::EndpointOut, EndpointAllocError> {
501 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 173 self.inner.alloc_endpoint(ep_type, max_packet_size, interval_ms)
502 } 174 }
503 175
504 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 176 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
505 let ep_out = self 177 let (bus, cp) = self.inner.start(control_max_packet_size);
506 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
507 .unwrap();
508 let ep_in = self
509 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
510 .unwrap();
511 assert_eq!(ep_out.info.addr.index(), 0);
512 assert_eq!(ep_in.info.addr.index(), 0);
513
514 trace!("start");
515 178
516 ( 179 (
517 Bus { 180 Bus {
518 config: self.config,
519 phantom: PhantomData, 181 phantom: PhantomData,
520 ep_in: self.ep_in, 182 inner: bus,
521 ep_out: self.ep_out,
522 phy_type: self.phy_type,
523 inited: false, 183 inited: false,
524 }, 184 },
525 ControlPipe { 185 cp,
526 _phantom: PhantomData,
527 max_packet_size: control_max_packet_size,
528 ep_out,
529 ep_in,
530 },
531 ) 186 )
532 } 187 }
533} 188}
534 189
535/// USB bus. 190/// USB bus.
536pub struct Bus<'d, T: Instance> { 191pub struct Bus<'d, T: Instance> {
537 config: Config,
538 phantom: PhantomData<&'d mut T>, 192 phantom: PhantomData<&'d mut T>,
539 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 193 inner: OtgBus<'d>,
540 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
541 phy_type: PhyType,
542 inited: bool, 194 inited: bool,
543} 195}
544 196
545impl<'d, T: Instance> Bus<'d, T> { 197impl<'d, T: Instance> Bus<'d, T> {
546 fn restore_irqs() {
547 T::regs().gintmsk().write(|w| {
548 w.set_usbrst(true);
549 w.set_enumdnem(true);
550 w.set_usbsuspm(true);
551 w.set_wuim(true);
552 w.set_iepint(true);
553 w.set_oepint(true);
554 w.set_rxflvlm(true);
555 w.set_srqim(true);
556 w.set_otgint(true);
557 });
558 }
559}
560
561impl<'d, T: Instance> Bus<'d, T> {
562 fn init(&mut self) { 198 fn init(&mut self) {
563 super::common_init::<T>(); 199 super::common_init::<T>();
564 200
565 // Enable ULPI clock if external PHY is used 201 // Enable ULPI clock if external PHY is used
566 let _ulpien = !self.phy_type.internal(); 202 let phy_type = self.inner.phy_type();
203 let _ulpien = !phy_type.internal();
567 204
568 #[cfg(any(stm32f2, stm32f4, stm32f7))] 205 #[cfg(any(stm32f2, stm32f4, stm32f7))]
569 if T::HIGH_SPEED { 206 if T::HIGH_SPEED {
@@ -594,200 +231,14 @@ impl<'d, T: Instance> Bus<'d, T> {
594 while !r.grstctl().read().ahbidl() {} 231 while !r.grstctl().read().ahbidl() {}
595 232
596 // Configure as device. 233 // Configure as device.
597 r.gusbcfg().write(|w| { 234 self.inner.configure_as_device();
598 // Force device mode
599 w.set_fdmod(true);
600 // Enable internal full-speed PHY
601 w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed());
602 });
603 235
604 // Configuring Vbus sense and SOF output 236 // Configuring Vbus sense and SOF output
605 match core_id { 237 match core_id {
606 0x0000_1200 | 0x0000_1100 => { 238 0x0000_1200 | 0x0000_1100 => self.inner.config_v1(),
607 assert!(self.phy_type != PhyType::InternalHighSpeed); 239 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => self.inner.config_v2v3(),
608
609 r.gccfg_v1().modify(|w| {
610 // Enable internal full-speed PHY, logic is inverted
611 w.set_pwrdwn(self.phy_type.internal());
612 });
613
614 // F429-like chips have the GCCFG.NOVBUSSENS bit
615 r.gccfg_v1().modify(|w| {
616 w.set_novbussens(!self.config.vbus_detection);
617 w.set_vbusasen(false);
618 w.set_vbusbsen(self.config.vbus_detection);
619 w.set_sofouten(false);
620 });
621 }
622 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => {
623 // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning
624 r.gccfg_v2().modify(|w| {
625 // Enable internal full-speed PHY, logic is inverted
626 w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed());
627 w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed());
628 });
629
630 r.gccfg_v2().modify(|w| {
631 w.set_vbden(self.config.vbus_detection);
632 });
633
634 // Force B-peripheral session
635 r.gotgctl().modify(|w| {
636 w.set_bvaloen(!self.config.vbus_detection);
637 w.set_bvaloval(true);
638 });
639 }
640 _ => unimplemented!("Unknown USB core id {:X}", core_id), 240 _ => unimplemented!("Unknown USB core id {:X}", core_id),
641 } 241 }
642
643 // Soft disconnect.
644 r.dctl().write(|w| w.set_sdis(true));
645
646 // Set speed.
647 r.dcfg().write(|w| {
648 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
649 w.set_dspd(self.phy_type.to_dspd());
650 });
651
652 // Unmask transfer complete EP interrupt
653 r.diepmsk().write(|w| {
654 w.set_xfrcm(true);
655 });
656
657 // Unmask and clear core interrupts
658 Bus::<T>::restore_irqs();
659 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
660
661 // Unmask global interrupt
662 r.gahbcfg().write(|w| {
663 w.set_gint(true); // unmask global interrupt
664 });
665
666 // Connect
667 r.dctl().write(|w| w.set_sdis(false));
668 }
669
670 fn init_fifo(&mut self) {
671 trace!("init_fifo");
672
673 let r = T::regs();
674
675 // ERRATA NOTE: Don't interrupt FIFOs being written to. The interrupt
676 // handler COULD interrupt us here and do FIFO operations, so ensure
677 // the interrupt does not occur.
678 critical_section::with(|_| {
679 // Configure RX fifo size. All endpoints share the same FIFO area.
680 let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
681 trace!("configuring rx fifo size={}", rx_fifo_size_words);
682
683 r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
684
685 // Configure TX (USB in direction) fifo size for each endpoint
686 let mut fifo_top = rx_fifo_size_words;
687 for i in 0..T::ENDPOINT_COUNT {
688 if let Some(ep) = self.ep_in[i] {
689 trace!(
690 "configuring tx fifo ep={}, offset={}, size={}",
691 i,
692 fifo_top,
693 ep.fifo_size_words
694 );
695
696 let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
697
698 dieptxf.write(|w| {
699 w.set_fd(ep.fifo_size_words);
700 w.set_sa(fifo_top);
701 });
702
703 fifo_top += ep.fifo_size_words;
704 }
705 }
706
707 assert!(
708 fifo_top <= T::FIFO_DEPTH_WORDS,
709 "FIFO allocations exceeded maximum capacity"
710 );
711
712 // Flush fifos
713 r.grstctl().write(|w| {
714 w.set_rxfflsh(true);
715 w.set_txfflsh(true);
716 w.set_txfnum(0x10);
717 });
718 });
719
720 loop {
721 let x = r.grstctl().read();
722 if !x.rxfflsh() && !x.txfflsh() {
723 break;
724 }
725 }
726 }
727
728 fn configure_endpoints(&mut self) {
729 trace!("configure_endpoints");
730
731 let r = T::regs();
732
733 // Configure IN endpoints
734 for (index, ep) in self.ep_in.iter().enumerate() {
735 if let Some(ep) = ep {
736 critical_section::with(|_| {
737 r.diepctl(index).write(|w| {
738 if index == 0 {
739 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
740 } else {
741 w.set_mpsiz(ep.max_packet_size);
742 w.set_eptyp(to_eptyp(ep.ep_type));
743 w.set_sd0pid_sevnfrm(true);
744 w.set_txfnum(index as _);
745 w.set_snak(true);
746 }
747 });
748 });
749 }
750 }
751
752 // Configure OUT endpoints
753 for (index, ep) in self.ep_out.iter().enumerate() {
754 if let Some(ep) = ep {
755 critical_section::with(|_| {
756 r.doepctl(index).write(|w| {
757 if index == 0 {
758 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
759 } else {
760 w.set_mpsiz(ep.max_packet_size);
761 w.set_eptyp(to_eptyp(ep.ep_type));
762 w.set_sd0pid_sevnfrm(true);
763 }
764 });
765
766 r.doeptsiz(index).modify(|w| {
767 w.set_xfrsiz(ep.max_packet_size as _);
768 if index == 0 {
769 w.set_rxdpid_stupcnt(1);
770 } else {
771 w.set_pktcnt(1);
772 }
773 });
774 });
775 }
776 }
777
778 // Enable IRQs for allocated endpoints
779 r.daintmsk().modify(|w| {
780 w.set_iepm(ep_irq_mask(&self.ep_in));
781 // OUT interrupts not used, handled in RXFLVL
782 // w.set_oepm(ep_irq_mask(&self.ep_out));
783 });
784 }
785
786 fn disable_all_endpoints(&mut self) {
787 for i in 0..T::ENDPOINT_COUNT {
788 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
789 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
790 }
791 } 242 }
792 243
793 fn disable(&mut self) { 244 fn disable(&mut self) {
@@ -803,634 +254,52 @@ impl<'d, T: Instance> Bus<'d, T> {
803 254
804impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { 255impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
805 async fn poll(&mut self) -> Event { 256 async fn poll(&mut self) -> Event {
806 poll_fn(move |cx| { 257 if !self.inited {
807 if !self.inited { 258 self.init();
808 self.init(); 259 self.inited = true;
809 self.inited = true; 260 }
810
811 // If no vbus detection, just return a single PowerDetected event at startup.
812 if !self.config.vbus_detection {
813 return Poll::Ready(Event::PowerDetected);
814 }
815 }
816
817 let r = T::regs();
818
819 T::state().bus_waker.register(cx.waker());
820
821 let ints = r.gintsts().read();
822
823 if ints.srqint() {
824 trace!("vbus detected");
825
826 r.gintsts().write(|w| w.set_srqint(true)); // clear
827 Self::restore_irqs();
828
829 if self.config.vbus_detection {
830 return Poll::Ready(Event::PowerDetected);
831 }
832 }
833
834 if ints.otgint() {
835 let otgints = r.gotgint().read();
836 r.gotgint().write_value(otgints); // clear all
837 Self::restore_irqs();
838
839 if otgints.sedet() {
840 trace!("vbus removed");
841 if self.config.vbus_detection {
842 self.disable_all_endpoints();
843 return Poll::Ready(Event::PowerRemoved);
844 }
845 }
846 }
847
848 if ints.usbrst() {
849 trace!("reset");
850
851 self.init_fifo();
852 self.configure_endpoints();
853
854 // Reset address
855 critical_section::with(|_| {
856 r.dcfg().modify(|w| {
857 w.set_dad(0);
858 });
859 });
860
861 r.gintsts().write(|w| w.set_usbrst(true)); // clear
862 Self::restore_irqs();
863 }
864
865 if ints.enumdne() {
866 trace!("enumdne");
867
868 let speed = r.dsts().read().enumspd();
869 let trdt = calculate_trdt(speed, T::frequency());
870 trace!(" speed={} trdt={}", speed.to_bits(), trdt);
871 r.gusbcfg().modify(|w| w.set_trdt(trdt));
872
873 r.gintsts().write(|w| w.set_enumdne(true)); // clear
874 Self::restore_irqs();
875
876 return Poll::Ready(Event::Reset);
877 }
878
879 if ints.usbsusp() {
880 trace!("suspend");
881 r.gintsts().write(|w| w.set_usbsusp(true)); // clear
882 Self::restore_irqs();
883 return Poll::Ready(Event::Suspend);
884 }
885
886 if ints.wkupint() {
887 trace!("resume");
888 r.gintsts().write(|w| w.set_wkupint(true)); // clear
889 Self::restore_irqs();
890 return Poll::Ready(Event::Resume);
891 }
892 261
893 Poll::Pending 262 self.inner.poll().await
894 })
895 .await
896 } 263 }
897 264
898 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) { 265 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
899 trace!("endpoint_set_stalled ep={:?} en={}", ep_addr, stalled); 266 self.inner.endpoint_set_stalled(ep_addr, stalled)
900
901 assert!(
902 ep_addr.index() < T::ENDPOINT_COUNT,
903 "endpoint_set_stalled index {} out of range",
904 ep_addr.index()
905 );
906
907 let regs = T::regs();
908 match ep_addr.direction() {
909 Direction::Out => {
910 critical_section::with(|_| {
911 regs.doepctl(ep_addr.index()).modify(|w| {
912 w.set_stall(stalled);
913 });
914 });
915
916 T::state().ep_out_wakers[ep_addr.index()].wake();
917 }
918 Direction::In => {
919 critical_section::with(|_| {
920 regs.diepctl(ep_addr.index()).modify(|w| {
921 w.set_stall(stalled);
922 });
923 });
924
925 T::state().ep_in_wakers[ep_addr.index()].wake();
926 }
927 }
928 } 267 }
929 268
930 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { 269 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
931 assert!( 270 self.inner.endpoint_is_stalled(ep_addr)
932 ep_addr.index() < T::ENDPOINT_COUNT,
933 "endpoint_is_stalled index {} out of range",
934 ep_addr.index()
935 );
936
937 let regs = T::regs();
938
939 match ep_addr.direction() {
940 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
941 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
942 }
943 } 271 }
944 272
945 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) { 273 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
946 trace!("endpoint_set_enabled ep={:?} en={}", ep_addr, enabled); 274 self.inner.endpoint_set_enabled(ep_addr, enabled)
947
948 assert!(
949 ep_addr.index() < T::ENDPOINT_COUNT,
950 "endpoint_set_enabled index {} out of range",
951 ep_addr.index()
952 );
953
954 let r = T::regs();
955 match ep_addr.direction() {
956 Direction::Out => {
957 critical_section::with(|_| {
958 // cancel transfer if active
959 if !enabled && r.doepctl(ep_addr.index()).read().epena() {
960 r.doepctl(ep_addr.index()).modify(|w| {
961 w.set_snak(true);
962 w.set_epdis(true);
963 })
964 }
965
966 r.doepctl(ep_addr.index()).modify(|w| {
967 w.set_usbaep(enabled);
968 });
969
970 // Flush tx fifo
971 r.grstctl().write(|w| {
972 w.set_txfflsh(true);
973 w.set_txfnum(ep_addr.index() as _);
974 });
975 loop {
976 let x = r.grstctl().read();
977 if !x.txfflsh() {
978 break;
979 }
980 }
981 });
982
983 // Wake `Endpoint::wait_enabled()`
984 T::state().ep_out_wakers[ep_addr.index()].wake();
985 }
986 Direction::In => {
987 critical_section::with(|_| {
988 // cancel transfer if active
989 if !enabled && r.diepctl(ep_addr.index()).read().epena() {
990 r.diepctl(ep_addr.index()).modify(|w| {
991 w.set_snak(true); // set NAK
992 w.set_epdis(true);
993 })
994 }
995
996 r.diepctl(ep_addr.index()).modify(|w| {
997 w.set_usbaep(enabled);
998 w.set_cnak(enabled); // clear NAK that might've been set by SNAK above.
999 })
1000 });
1001
1002 // Wake `Endpoint::wait_enabled()`
1003 T::state().ep_in_wakers[ep_addr.index()].wake();
1004 }
1005 }
1006 } 275 }
1007 276
1008 async fn enable(&mut self) { 277 async fn enable(&mut self) {
1009 trace!("enable"); 278 self.inner.enable().await
1010 // TODO: enable the peripheral once enable/disable semantics are cleared up in embassy-usb
1011 } 279 }
1012 280
1013 async fn disable(&mut self) { 281 async fn disable(&mut self) {
1014 trace!("disable"); 282 Bus::disable(self);
1015 283 // NOTE: inner call is a no-op
1016 // TODO: disable the peripheral once enable/disable semantics are cleared up in embassy-usb 284 self.inner.disable().await
1017 //Bus::disable(self);
1018 } 285 }
1019 286
1020 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> { 287 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
1021 Err(Unsupported) 288 self.inner.remote_wakeup().await
1022 } 289 }
1023} 290}
1024 291
1025impl<'d, T: Instance> Drop for Bus<'d, T> { 292impl<'d, T: Instance> Drop for Bus<'d, T> {
1026 fn drop(&mut self) { 293 fn drop(&mut self) {}
1027 Bus::disable(self);
1028 }
1029}
1030
1031trait Dir {
1032 fn dir() -> Direction;
1033}
1034
1035/// Marker type for the "IN" direction.
1036pub enum In {}
1037impl Dir for In {
1038 fn dir() -> Direction {
1039 Direction::In
1040 }
1041}
1042
1043/// Marker type for the "OUT" direction.
1044pub enum Out {}
1045impl Dir for Out {
1046 fn dir() -> Direction {
1047 Direction::Out
1048 }
1049}
1050
1051/// USB endpoint.
1052pub struct Endpoint<'d, T: Instance, D> {
1053 _phantom: PhantomData<(&'d mut T, D)>,
1054 info: EndpointInfo,
1055}
1056
1057impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, In> {
1058 fn info(&self) -> &EndpointInfo {
1059 &self.info
1060 }
1061
1062 async fn wait_enabled(&mut self) {
1063 poll_fn(|cx| {
1064 let ep_index = self.info.addr.index();
1065
1066 T::state().ep_in_wakers[ep_index].register(cx.waker());
1067
1068 if T::regs().diepctl(ep_index).read().usbaep() {
1069 Poll::Ready(())
1070 } else {
1071 Poll::Pending
1072 }
1073 })
1074 .await
1075 }
1076}
1077
1078impl<'d, T: Instance> embassy_usb_driver::Endpoint for Endpoint<'d, T, Out> {
1079 fn info(&self) -> &EndpointInfo {
1080 &self.info
1081 }
1082
1083 async fn wait_enabled(&mut self) {
1084 poll_fn(|cx| {
1085 let ep_index = self.info.addr.index();
1086
1087 T::state().ep_out_wakers[ep_index].register(cx.waker());
1088
1089 if T::regs().doepctl(ep_index).read().usbaep() {
1090 Poll::Ready(())
1091 } else {
1092 Poll::Pending
1093 }
1094 })
1095 .await
1096 }
1097}
1098
1099impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> {
1100 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
1101 trace!("read start len={}", buf.len());
1102
1103 poll_fn(|cx| {
1104 let r = T::regs();
1105 let index = self.info.addr.index();
1106 let state = T::state();
1107
1108 state.ep_out_wakers[index].register(cx.waker());
1109
1110 let doepctl = r.doepctl(index).read();
1111 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
1112 if !doepctl.usbaep() {
1113 trace!("read ep={:?} error disabled", self.info.addr);
1114 return Poll::Ready(Err(EndpointError::Disabled));
1115 }
1116
1117 let len = state.ep_out_size[index].load(Ordering::Relaxed);
1118 if len != EP_OUT_BUFFER_EMPTY {
1119 trace!("read ep={:?} done len={}", self.info.addr, len);
1120
1121 if len as usize > buf.len() {
1122 return Poll::Ready(Err(EndpointError::BufferOverflow));
1123 }
1124
1125 // SAFETY: exclusive access ensured by `ep_out_size` atomic variable
1126 let data = unsafe { core::slice::from_raw_parts(*state.ep_out_buffers[index].get(), len as usize) };
1127 buf[..len as usize].copy_from_slice(data);
1128
1129 // Release buffer
1130 state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1131
1132 critical_section::with(|_| {
1133 // Receive 1 packet
1134 T::regs().doeptsiz(index).modify(|w| {
1135 w.set_xfrsiz(self.info.max_packet_size as _);
1136 w.set_pktcnt(1);
1137 });
1138
1139 // Clear NAK to indicate we are ready to receive more data
1140 T::regs().doepctl(index).modify(|w| {
1141 w.set_cnak(true);
1142 });
1143 });
1144
1145 Poll::Ready(Ok(len as usize))
1146 } else {
1147 Poll::Pending
1148 }
1149 })
1150 .await
1151 }
1152}
1153
1154impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1155 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
1156 trace!("write ep={:?} data={:?}", self.info.addr, buf);
1157
1158 if buf.len() > self.info.max_packet_size as usize {
1159 return Err(EndpointError::BufferOverflow);
1160 }
1161
1162 let r = T::regs();
1163 let index = self.info.addr.index();
1164 let state = T::state();
1165
1166 // Wait for previous transfer to complete and check if endpoint is disabled
1167 poll_fn(|cx| {
1168 state.ep_in_wakers[index].register(cx.waker());
1169
1170 let diepctl = r.diepctl(index).read();
1171 let dtxfsts = r.dtxfsts(index).read();
1172 trace!(
1173 "write ep={:?}: diepctl {:08x} ftxfsts {:08x}",
1174 self.info.addr,
1175 diepctl.0,
1176 dtxfsts.0
1177 );
1178 if !diepctl.usbaep() {
1179 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1180 Poll::Ready(Err(EndpointError::Disabled))
1181 } else if !diepctl.epena() {
1182 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1183 Poll::Ready(Ok(()))
1184 } else {
1185 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1186 Poll::Pending
1187 }
1188 })
1189 .await?;
1190
1191 if buf.len() > 0 {
1192 poll_fn(|cx| {
1193 state.ep_in_wakers[index].register(cx.waker());
1194
1195 let size_words = (buf.len() + 3) / 4;
1196
1197 let fifo_space = r.dtxfsts(index).read().ineptfsav() as usize;
1198 if size_words > fifo_space {
1199 // Not enough space in fifo, enable tx fifo empty interrupt
1200 critical_section::with(|_| {
1201 r.diepempmsk().modify(|w| {
1202 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1203 });
1204 });
1205
1206 trace!("tx fifo for ep={} full, waiting for txfe", index);
1207
1208 Poll::Pending
1209 } else {
1210 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1211 Poll::Ready(())
1212 }
1213 })
1214 .await
1215 }
1216
1217 // ERRATA: Transmit data FIFO is corrupted when a write sequence to the FIFO is interrupted with
1218 // accesses to certain OTG_FS registers.
1219 //
1220 // Prevent the interrupt (which might poke FIFOs) from executing while copying data to FIFOs.
1221 critical_section::with(|_| {
1222 // Setup transfer size
1223 r.dieptsiz(index).write(|w| {
1224 w.set_mcnt(1);
1225 w.set_pktcnt(1);
1226 w.set_xfrsiz(buf.len() as _);
1227 });
1228
1229 // Enable endpoint
1230 r.diepctl(index).modify(|w| {
1231 w.set_cnak(true);
1232 w.set_epena(true);
1233 });
1234
1235 // Write data to FIFO
1236 for chunk in buf.chunks(4) {
1237 let mut tmp = [0u8; 4];
1238 tmp[0..chunk.len()].copy_from_slice(chunk);
1239 r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp)));
1240 }
1241 });
1242
1243 trace!("write done ep={:?}", self.info.addr);
1244
1245 Ok(())
1246 }
1247} 294}
1248 295
1249/// USB control pipe.
1250pub struct ControlPipe<'d, T: Instance> {
1251 _phantom: PhantomData<&'d mut T>,
1252 max_packet_size: u16,
1253 ep_in: Endpoint<'d, T, In>,
1254 ep_out: Endpoint<'d, T, Out>,
1255}
1256
1257impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
1258 fn max_packet_size(&self) -> usize {
1259 usize::from(self.max_packet_size)
1260 }
1261
1262 async fn setup(&mut self) -> [u8; 8] {
1263 poll_fn(|cx| {
1264 let state = T::state();
1265
1266 state.ep_out_wakers[0].register(cx.waker());
1267
1268 let r = T::regs();
1269
1270 if state.ep0_setup_ready.load(Ordering::Relaxed) {
1271 let data = unsafe { *state.ep0_setup_data.get() };
1272 state.ep0_setup_ready.store(false, Ordering::Release);
1273
1274 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1275 // Receive 1 SETUP packet
1276 r.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1277 w.set_rxdpid_stupcnt(1);
1278 });
1279
1280 // Clear NAK to indicate we are ready to receive more data
1281 if !quirk_setup_late_cnak(r) {
1282 r.doepctl(self.ep_out.info.addr.index()).modify(|w| w.set_cnak(true));
1283 }
1284
1285 trace!("SETUP received: {:?}", data);
1286 Poll::Ready(data)
1287 } else {
1288 trace!("SETUP waiting");
1289 Poll::Pending
1290 }
1291 })
1292 .await
1293 }
1294
1295 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
1296 trace!("control: data_out");
1297 let len = self.ep_out.read(buf).await?;
1298 trace!("control: data_out read: {:?}", &buf[..len]);
1299 Ok(len)
1300 }
1301
1302 async fn data_in(&mut self, data: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
1303 trace!("control: data_in write: {:?}", data);
1304 self.ep_in.write(data).await?;
1305
1306 // wait for status response from host after sending the last packet
1307 if last {
1308 trace!("control: data_in waiting for status");
1309 self.ep_out.read(&mut []).await?;
1310 trace!("control: complete");
1311 }
1312
1313 Ok(())
1314 }
1315
1316 async fn accept(&mut self) {
1317 trace!("control: accept");
1318
1319 self.ep_in.write(&[]).await.ok();
1320
1321 trace!("control: accept OK");
1322 }
1323
1324 async fn reject(&mut self) {
1325 trace!("control: reject");
1326
1327 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1328 let regs = T::regs();
1329 regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1330 w.set_stall(true);
1331 });
1332 regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1333 w.set_stall(true);
1334 });
1335 }
1336
1337 async fn accept_set_address(&mut self, addr: u8) {
1338 trace!("setting addr: {}", addr);
1339 critical_section::with(|_| {
1340 T::regs().dcfg().modify(|w| {
1341 w.set_dad(addr);
1342 });
1343 });
1344
1345 // synopsys driver requires accept to be sent after changing address
1346 self.accept().await
1347 }
1348}
1349
1350/// Translates HAL [EndpointType] into PAC [vals::Eptyp]
1351fn to_eptyp(ep_type: EndpointType) -> vals::Eptyp {
1352 match ep_type {
1353 EndpointType::Control => vals::Eptyp::CONTROL,
1354 EndpointType::Isochronous => vals::Eptyp::ISOCHRONOUS,
1355 EndpointType::Bulk => vals::Eptyp::BULK,
1356 EndpointType::Interrupt => vals::Eptyp::INTERRUPT,
1357 }
1358}
1359
1360/// Calculates total allocated FIFO size in words
1361fn ep_fifo_size(eps: &[Option<EndpointData>]) -> u16 {
1362 eps.iter().map(|ep| ep.map(|ep| ep.fifo_size_words).unwrap_or(0)).sum()
1363}
1364
1365/// Generates IRQ mask for enabled endpoints
1366fn ep_irq_mask(eps: &[Option<EndpointData>]) -> u16 {
1367 eps.iter().enumerate().fold(
1368 0,
1369 |mask, (index, ep)| {
1370 if ep.is_some() {
1371 mask | (1 << index)
1372 } else {
1373 mask
1374 }
1375 },
1376 )
1377}
1378
1379/// Calculates MPSIZ value for EP0, which uses special values.
1380fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1381 match max_packet_size {
1382 8 => 0b11,
1383 16 => 0b10,
1384 32 => 0b01,
1385 64 => 0b00,
1386 other => panic!("Unsupported EP0 size: {}", other),
1387 }
1388}
1389
1390fn calculate_trdt(speed: vals::Dspd, ahb_freq: Hertz) -> u8 {
1391 match speed {
1392 vals::Dspd::HIGH_SPEED => {
1393 // From RM0431 (F72xx), RM0090 (F429), RM0390 (F446)
1394 if ahb_freq.0 >= 30_000_000 {
1395 0x9
1396 } else {
1397 panic!("AHB frequency is too low")
1398 }
1399 }
1400 vals::Dspd::FULL_SPEED_EXTERNAL | vals::Dspd::FULL_SPEED_INTERNAL => {
1401 // From RM0431 (F72xx), RM0090 (F429)
1402 match ahb_freq.0 {
1403 0..=14_199_999 => panic!("AHB frequency is too low"),
1404 14_200_000..=14_999_999 => 0xF,
1405 15_000_000..=15_999_999 => 0xE,
1406 16_000_000..=17_199_999 => 0xD,
1407 17_200_000..=18_499_999 => 0xC,
1408 18_500_000..=19_999_999 => 0xB,
1409 20_000_000..=21_799_999 => 0xA,
1410 21_800_000..=23_999_999 => 0x9,
1411 24_000_000..=27_499_999 => 0x8,
1412 27_500_000..=31_999_999 => 0x7, // 27.7..32 in code from CubeIDE
1413 32_000_000..=u32::MAX => 0x6,
1414 }
1415 }
1416 _ => unimplemented!(),
1417 }
1418}
1419
1420fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool {
1421 r.cid().read().0 & 0xf000 == 0x1000
1422}
1423
1424// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
1425const MAX_EP_COUNT: usize = 9;
1426
1427trait SealedInstance { 296trait SealedInstance {
1428 const HIGH_SPEED: bool; 297 const HIGH_SPEED: bool;
1429 const FIFO_DEPTH_WORDS: u16; 298 const FIFO_DEPTH_WORDS: u16;
1430 const ENDPOINT_COUNT: usize; 299 const ENDPOINT_COUNT: usize;
1431 300
1432 fn regs() -> crate::pac::otg::Otg; 301 fn regs() -> Otg;
1433 fn state() -> &'static super::State<{ MAX_EP_COUNT }>; 302 fn state() -> &'static State<{ MAX_EP_COUNT }>;
1434} 303}
1435 304
1436/// USB instance trait. 305/// USB instance trait.
@@ -1509,8 +378,8 @@ foreach_interrupt!(
1509 } 378 }
1510 } 379 }
1511 380
1512 fn regs() -> crate::pac::otg::Otg { 381 fn regs() -> Otg {
1513 crate::pac::USB_OTG_FS 382 unsafe { Otg::from_ptr(crate::pac::USB_OTG_FS.as_ptr()) }
1514 } 383 }
1515 384
1516 fn state() -> &'static State<MAX_EP_COUNT> { 385 fn state() -> &'static State<MAX_EP_COUNT> {
@@ -1559,9 +428,9 @@ foreach_interrupt!(
1559 } 428 }
1560 } 429 }
1561 430
1562 fn regs() -> crate::pac::otg::Otg { 431 fn regs() -> Otg {
1563 // OTG HS registers are a superset of FS registers 432 // OTG HS registers are a superset of FS registers
1564 unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } 433 unsafe { Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) }
1565 } 434 }
1566 435
1567 fn state() -> &'static State<MAX_EP_COUNT> { 436 fn state() -> &'static State<MAX_EP_COUNT> {
@@ -1575,3 +444,38 @@ foreach_interrupt!(
1575 } 444 }
1576 }; 445 };
1577); 446);
447
448fn calculate_trdt<T: Instance>(speed: Dspd) -> u8 {
449 let ahb_freq = T::frequency().0;
450 match speed {
451 Dspd::HIGH_SPEED => {
452 // From RM0431 (F72xx), RM0090 (F429), RM0390 (F446)
453 if ahb_freq >= 30_000_000 {
454 0x9
455 } else {
456 panic!("AHB frequency is too low")
457 }
458 }
459 Dspd::FULL_SPEED_EXTERNAL | Dspd::FULL_SPEED_INTERNAL => {
460 // From RM0431 (F72xx), RM0090 (F429)
461 match ahb_freq {
462 0..=14_199_999 => panic!("AHB frequency is too low"),
463 14_200_000..=14_999_999 => 0xF,
464 15_000_000..=15_999_999 => 0xE,
465 16_000_000..=17_199_999 => 0xD,
466 17_200_000..=18_499_999 => 0xC,
467 18_500_000..=19_999_999 => 0xB,
468 20_000_000..=21_799_999 => 0xA,
469 21_800_000..=23_999_999 => 0x9,
470 24_000_000..=27_499_999 => 0x8,
471 27_500_000..=31_999_999 => 0x7, // 27.7..32 in code from CubeIDE
472 32_000_000..=u32::MAX => 0x6,
473 }
474 }
475 _ => unimplemented!(),
476 }
477}
478
479fn quirk_setup_late_cnak(r: Otg) -> bool {
480 r.cid().read().0 & 0xf000 == 0x1000
481}