1#![cfg_attr(not(test), no_std)]
2#![allow(async_fn_in_trait)]
3#![allow(unsafe_op_in_unsafe_fn)]
4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)]
6
7mod fmt;
9
10use core::cell::UnsafeCell;
11use core::future::poll_fn;
12use core::marker::PhantomData;
13use core::sync::atomic::{AtomicBool, AtomicU16, AtomicU32, Ordering};
14use core::task::Poll;
15
16use embassy_sync::waitqueue::AtomicWaker;
17use embassy_usb_driver::{
18 Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut,
19 EndpointType, Event, Unsupported,
20};
21
22use crate::fmt::Bytes;
23
24pub mod otg_v1;
25
26#[cfg(feature = "host")]
27pub mod host;
28
29use otg_v1::{Otg, regs, vals};
30
31pub unsafe fn on_interrupt(r: Otg, state: &State<'_>) {
33 trace!("irq");
34 let ep_count = state.endpoint_count();
35
36 let ints = r.gintsts().read();
37 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
38 r.gintmsk().write(|w| {
40 w.set_iepint(true);
41 w.set_oepint(true);
42 w.set_rxflvlm(true);
43 });
44 state.bus_waker.wake();
45 }
46
47 while r.gintsts().read().rxflvl() {
49 let status = r.grxstsp().read();
50 trace!("=== status {:08x}", status.0);
51 let ep_num = status.epnum() as usize;
52 let len = status.bcnt() as usize;
53
54 assert!(ep_num < ep_count);
55
56 match status.pktstsd() {
57 vals::Pktstsd::SETUP_DATA_RX => {
58 trace!("SETUP_DATA_RX");
59 assert!(len == 8, "invalid SETUP packet length={}", len);
60 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
61
62 if r.dieptsiz(ep_num).read().pktcnt() != 0 {
64 r.grstctl().modify(|w| {
65 w.set_txfnum(ep_num as _);
66 w.set_txfflsh(true);
67 });
68 while r.grstctl().read().txfflsh() {}
69 }
70
71 let data = &state.cp_state.setup_data;
72 data[0].store(r.fifo(0).read().data(), Ordering::Relaxed);
73 data[1].store(r.fifo(0).read().data(), Ordering::Relaxed);
74 }
75 vals::Pktstsd::OUT_DATA_RX => {
76 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
77
78 if state.ep_states[ep_num].out_size.load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
79 let buf =
82 unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) };
83
84 let mut chunks = buf.chunks_exact_mut(4);
85 for chunk in &mut chunks {
86 let data = r.fifo(0).read().0;
88 chunk.copy_from_slice(&data.to_ne_bytes());
89 }
90 let rem = chunks.into_remainder();
91 if !rem.is_empty() {
92 let data = r.fifo(0).read().0;
93 rem.copy_from_slice(&data.to_ne_bytes()[0..rem.len()]);
94 }
95
96 state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release);
97 state.ep_states[ep_num].out_waker.wake();
98 } else {
99 error!("ep_out buffer overflow index={}", ep_num);
100
101 let len_words = (len + 3) / 4;
103 for _ in 0..len_words {
104 r.fifo(0).read().data();
105 }
106 }
107 }
108 vals::Pktstsd::OUT_DATA_DONE => {
109 trace!("OUT_DATA_DONE ep={}", ep_num);
110 }
111 vals::Pktstsd::SETUP_DATA_DONE => {
112 trace!("SETUP_DATA_DONE ep={}", ep_num);
113 }
114 x => trace!("unknown PKTSTS: {}", x.to_bits()),
115 }
116 }
117
118 if ints.iepint() {
120 let mut ep_mask = r.daint().read().iepint();
121 let mut ep_num = 0;
122
123 while ep_mask != 0 {
125 if ep_mask & 1 != 0 {
126 let ep_ints = r.diepint(ep_num).read();
127
128 r.diepint(ep_num).write_value(ep_ints);
130
131 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_states[ep_num].in_waker.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
149 if ints.oepint() {
151 trace!("oepint");
152 let mut ep_mask = r.daint().read().oepint();
153 let mut ep_num = 0;
154
155 while ep_mask != 0 {
157 if ep_mask & 1 != 0 {
158 let ep_ints = r.doepint(ep_num).read();
159 r.doepint(ep_num).write_value(ep_ints);
161
162 if ep_ints.stup() {
163 state.cp_state.setup_ready.store(true, Ordering::Release);
164 }
165 state.ep_states[ep_num].out_waker.wake();
166 trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
167 }
168
169 ep_mask >>= 1;
170 ep_num += 1;
171 }
172 }
173
174 if ints.eopf() {
175 let frame_number = r.dsts().read().fnsof();
176 let frame_is_odd = frame_number & 0x01 == 1;
177
178 for ep_num in (0..ep_count).into_iter().filter(|ep_num| {
181 let diepctl = r.diepctl(*ep_num).read();
182 diepctl.eptyp() == vals::Eptyp::ISOCHRONOUS
184 && diepctl.epena()
186 && diepctl.eonum_dpid() == frame_is_odd
188 }) {
189 trace!("Unsent message at EOF for ep: {}, frame: {}", ep_num, frame_number);
190
191 let ep_diepctl = r.diepctl(ep_num);
192 let ep_diepint = r.diepint(ep_num);
193
194 ep_diepctl.modify(|m| m.set_snak(true));
196 while !ep_diepint.read().inepne() {}
197
198 ep_diepctl.modify(|m| {
200 m.set_snak(true);
201 m.set_epdis(true);
202 });
203 while !ep_diepint.read().epdisd() {}
204 ep_diepint.modify(|m| m.set_epdisd(true));
205
206 ep_diepctl.modify(|r| {
208 if frame_is_odd {
209 r.set_sd0pid_sevnfrm(true);
210 } else {
211 r.set_soddfrm_sd1pid(true);
212 }
213 });
214
215 ep_diepctl.modify(|w| {
217 w.set_cnak(true);
218 w.set_epena(true);
219 });
220 }
221 }
222}
223
224#[derive(Copy, Clone, Debug, Eq, PartialEq)]
226pub enum PhyType {
227 InternalFullSpeed,
231 InternalHighSpeed,
235 ExternalFullSpeed,
237 ExternalHighSpeed,
239}
240
241impl PhyType {
242 pub fn internal(&self) -> bool {
244 match self {
245 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
246 PhyType::ExternalHighSpeed | PhyType::ExternalFullSpeed => false,
247 }
248 }
249
250 pub fn high_speed(&self) -> bool {
252 match self {
253 PhyType::InternalFullSpeed | PhyType::ExternalFullSpeed => false,
254 PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
255 }
256 }
257
258 fn to_dspd(&self) -> vals::Dspd {
259 match self {
260 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
261 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
262 PhyType::ExternalFullSpeed => vals::Dspd::FULL_SPEED_EXTERNAL,
263 PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
264 }
265 }
266}
267
268const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
270
271struct EpState {
272 in_waker: AtomicWaker,
273 out_waker: AtomicWaker,
274 out_buffer: UnsafeCell<*mut u8>,
277 out_size: AtomicU16,
278 in_alloc: UnsafeCell<Option<EndpointData>>,
280 out_alloc: UnsafeCell<Option<EndpointData>>,
281}
282
283unsafe impl Send for EpState {}
286unsafe impl Sync for EpState {}
287
288struct ControlPipeSetupState {
289 setup_data: [AtomicU32; 2],
291 setup_ready: AtomicBool,
292}
293
294#[derive(Debug, Clone, Copy)]
295struct EndpointData {
296 ep_type: EndpointType,
297 max_packet_size: u16,
298 fifo_size_words: u16,
299}
300
301#[derive(Clone, Copy)]
306pub struct State<'d> {
307 cp_state: &'d ControlPipeSetupState,
308 ep_states: &'d [EpState],
309 bus_waker: &'d AtomicWaker,
310}
311
312impl State<'_> {
313 pub fn endpoint_count(&self) -> usize {
315 self.ep_states.len()
316 }
317}
318
319impl<'d> State<'d> {
320 pub(crate) fn ep_alloc_get(&self, dir: Direction, index: usize) -> Option<&EndpointData> {
321 unsafe {
322 match dir {
323 Direction::In => (*self.ep_states[index].in_alloc.get()).as_ref(),
324 Direction::Out => (*self.ep_states[index].out_alloc.get()).as_ref(),
325 }
326 }
327 }
328
329 pub(crate) fn ep_fifo_size_in(&self) -> u16 {
330 (0..self.endpoint_count())
331 .filter_map(|i| self.ep_alloc_get(Direction::In, i))
332 .map(|ep| ep.fifo_size_words)
333 .sum()
334 }
335
336 pub(crate) fn ep_fifo_size_out(&self) -> u16 {
337 (0..self.endpoint_count())
338 .filter_map(|i| self.ep_alloc_get(Direction::Out, i))
339 .map(|ep| ep.fifo_size_words)
340 .sum()
341 }
342
343 pub(crate) fn ep_irq_mask_in(&self) -> u16 {
344 (0..self.endpoint_count()).fold(0, |mask, i| {
345 if self.ep_alloc_get(Direction::In, i).is_some() {
346 mask | (1 << i)
347 } else {
348 mask
349 }
350 })
351 }
352
353 pub(crate) fn ep_irq_mask_out(&self) -> u16 {
354 (0..self.endpoint_count()).fold(0, |mask, i| {
355 if self.ep_alloc_get(Direction::Out, i).is_some() {
356 mask | (1 << i)
357 } else {
358 mask
359 }
360 })
361 }
362
363 pub(crate) unsafe fn alloc_slot_write(&self, dir: Direction, index: usize, data: EndpointData) {
367 match dir {
368 Direction::In => *self.ep_states[index].in_alloc.get() = Some(data),
369 Direction::Out => *self.ep_states[index].out_alloc.get() = Some(data),
370 }
371 }
372}
373
374pub struct StateStorage<const EP_COUNT: usize> {
376 cp_state: ControlPipeSetupState,
377 ep_states: [EpState; EP_COUNT],
378 bus_waker: AtomicWaker,
379}
380
381impl<const EP_COUNT: usize> StateStorage<EP_COUNT> {
382 pub const fn new() -> Self {
384 Self {
385 cp_state: ControlPipeSetupState {
386 setup_data: [const { AtomicU32::new(0) }; 2],
387 setup_ready: AtomicBool::new(false),
388 },
389 ep_states: [const {
390 EpState {
391 in_waker: AtomicWaker::new(),
392 out_waker: AtomicWaker::new(),
393 out_buffer: UnsafeCell::new(0 as _),
394 out_size: AtomicU16::new(EP_OUT_BUFFER_EMPTY),
395 in_alloc: UnsafeCell::new(None),
396 out_alloc: UnsafeCell::new(None),
397 }
398 }; EP_COUNT],
399 bus_waker: AtomicWaker::new(),
400 }
401 }
402
403 pub fn as_state(&self) -> State<'_> {
405 State {
406 cp_state: &self.cp_state,
407 ep_states: self.ep_states.as_slice(),
408 bus_waker: &self.bus_waker,
409 }
410 }
411}
412
413#[non_exhaustive]
415#[derive(Clone, Copy, PartialEq, Eq, Debug)]
416pub struct Config {
417 pub vbus_detection: bool,
432
433 pub xcvrdly: bool,
440}
441
442impl Default for Config {
443 fn default() -> Self {
444 Self {
445 vbus_detection: false,
446 xcvrdly: false,
447 }
448 }
449}
450
451pub struct Driver<'d> {
453 config: Config,
454 ep_out_buffer: &'d mut [u8],
455 ep_out_buffer_offset: usize,
456 instance: OtgInstance<'d>,
457}
458
459impl<'d> Driver<'d> {
460 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d>, config: Config) -> Self {
470 Self {
471 config,
472 ep_out_buffer,
473 ep_out_buffer_offset: 0,
474 instance,
475 }
476 }
477
478 fn allocated_fifo_words(&self) -> u16 {
480 let st = self.instance.state;
481 self.instance.extra_rx_fifo_words + st.ep_fifo_size_out() + st.ep_fifo_size_in()
482 }
483
484 fn alloc_endpoint<D: Dir>(
486 &mut self,
487 ep_type: EndpointType,
488 ep_addr: Option<EndpointAddress>,
489 max_packet_size: u16,
490 interval_ms: u8,
491 ) -> Result<Endpoint<'d, D>, EndpointAllocError> {
492 trace!(
493 "allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
494 ep_type,
495 max_packet_size,
496 interval_ms,
497 D::dir()
498 );
499
500 if D::dir() == Direction::Out {
501 if self.ep_out_buffer_offset + max_packet_size as usize > self.ep_out_buffer.len() {
502 error!("Not enough endpoint out buffer capacity");
503 return Err(EndpointAllocError);
504 }
505 };
506
507 let fifo_size_words = match D::dir() {
508 Direction::Out => (max_packet_size + 3) / 4,
509 Direction::In => u16::max((max_packet_size + 3) / 4, 16),
511 };
512
513 if fifo_size_words + self.allocated_fifo_words() > self.instance.fifo_depth_words {
514 error!("Not enough FIFO capacity");
515 return Err(EndpointAllocError);
516 }
517
518 let dir = D::dir();
519 let st = self.instance.state;
520 let endpoint_count = st.endpoint_count();
521
522 let index = if let Some(addr) = ep_addr {
524 let requested_index = addr.index();
526 if requested_index >= endpoint_count {
527 return Err(EndpointAllocError);
528 }
529 if requested_index == 0 && ep_type != EndpointType::Control {
530 return Err(EndpointAllocError); }
532 if st.ep_alloc_get(dir, requested_index).is_some() {
533 return Err(EndpointAllocError); }
535 requested_index
536 } else {
537 let found = (0..endpoint_count).find(|&i| {
539 if i == 0 && ep_type != EndpointType::Control {
540 false
542 } else {
543 st.ep_alloc_get(dir, i).is_none()
544 }
545 });
546 match found {
547 Some(i) => i,
548 None => {
549 error!("No free endpoints available");
550 return Err(EndpointAllocError);
551 }
552 }
553 };
554
555 unsafe {
556 st.alloc_slot_write(
557 dir,
558 index,
559 EndpointData {
560 ep_type,
561 max_packet_size,
562 fifo_size_words,
563 },
564 );
565 };
566
567 trace!(" index={}", index);
568
569 let ep_state = &self.instance.state.ep_states[index];
570 if D::dir() == Direction::Out {
571 unsafe {
573 *ep_state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
574 }
575 self.ep_out_buffer_offset += max_packet_size as usize;
576 }
577
578 Ok(Endpoint {
579 _phantom: PhantomData,
580 regs: self.instance.regs,
581 state: ep_state,
582 info: EndpointInfo {
583 addr: EndpointAddress::from_parts(index, D::dir()),
584 ep_type,
585 max_packet_size,
586 interval_ms,
587 },
588 })
589 }
590}
591
592impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
593 type EndpointOut = Endpoint<'d, Out>;
594 type EndpointIn = Endpoint<'d, In>;
595 type ControlPipe = ControlPipe<'d>;
596 type Bus = Bus<'d>;
597
598 fn alloc_endpoint_in(
599 &mut self,
600 ep_type: EndpointType,
601 ep_addr: Option<EndpointAddress>,
602 max_packet_size: u16,
603 interval_ms: u8,
604 ) -> Result<Self::EndpointIn, EndpointAllocError> {
605 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
606 }
607
608 fn alloc_endpoint_out(
609 &mut self,
610 ep_type: EndpointType,
611 ep_addr: Option<EndpointAddress>,
612 max_packet_size: u16,
613 interval_ms: u8,
614 ) -> Result<Self::EndpointOut, EndpointAllocError> {
615 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
616 }
617
618 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
619 let ep_out = self
620 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
621 .unwrap();
622 let ep_in = self
623 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
624 .unwrap();
625 assert_eq!(ep_out.info.addr.index(), 0);
626 assert_eq!(ep_in.info.addr.index(), 0);
627
628 trace!("start");
629
630 let regs = self.instance.regs;
631 let setup_state = self.instance.state.cp_state;
632 (
633 Bus {
634 config: self.config,
635 inited: false,
636 instance: self.instance,
637 },
638 ControlPipe {
639 max_packet_size: control_max_packet_size,
640 setup_state,
641 ep_out,
642 ep_in,
643 regs,
644 },
645 )
646 }
647}
648
649pub struct Bus<'d> {
651 config: Config,
652 instance: OtgInstance<'d>,
653 inited: bool,
654}
655
656impl<'d> Bus<'d> {
657 fn restore_irqs(&mut self) {
658 self.instance.regs.gintmsk().write(|w| {
659 w.set_usbrst(true);
660 w.set_enumdnem(true);
661 w.set_usbsuspm(true);
662 w.set_wuim(true);
663 w.set_iepint(true);
664 w.set_oepint(true);
665 w.set_rxflvlm(true);
666 w.set_srqim(true);
667 w.set_otgint(true);
668 });
669 }
670
671 pub fn phy_type(&self) -> PhyType {
673 self.instance.phy_type
674 }
675
676 pub fn core_soft_reset(&mut self) {
678 let r = self.instance.regs;
679
680 while !r.grstctl().read().ahbidl() {}
682
683 r.grstctl().write(|w| {
684 w.set_csrst(true);
685 });
686
687 loop {
689 let grstctl = r.grstctl().read();
690 if !grstctl.csrst() || grstctl.csrstdone() {
691 break;
692 }
693 }
694
695 r.grstctl().modify(|w| {
697 w.set_csrst(false);
698 });
699 }
700
701 pub fn configure_as_device(&mut self) {
703 let r = self.instance.regs;
704 let phy_type = self.instance.phy_type;
705
706 let hw_width = r.hwcfg4().read().utmi_phy_data_width();
709 r.gusbcfg().write(|w| {
710 w.set_fdmod(true);
712
713 match phy_type {
714 PhyType::InternalFullSpeed => {
715 w.set_physel(true);
717 w.set_ulpi_utmi_sel(false);
718 w.set_phyif(false);
719 }
720 PhyType::InternalHighSpeed => {
721 w.set_physel(false);
723 w.set_ulpi_utmi_sel(false);
724 w.set_phyif(hw_width == 1);
725 w.set_ulpievbusd(false);
727 w.set_ulpievbusi(false);
728 w.set_ulpifsls(false);
729 w.set_ulpicsm(false);
730 }
731 PhyType::ExternalFullSpeed | PhyType::ExternalHighSpeed => {
732 w.set_physel(false);
734 w.set_ulpi_utmi_sel(true);
735 w.set_phyif(false);
736 w.set_ddr_sel(false);
737 w.set_ulpievbusd(false);
739 w.set_ulpievbusi(false);
740 w.set_ulpifsls(false);
742 w.set_ulpicsm(false);
743 }
744 }
745 });
746
747 while r.gintsts().read().cmod() {}
749 }
750
751 pub fn config_v1(&mut self) {
754 let r = self.instance.regs;
755 let phy_type = self.instance.phy_type;
756 assert!(phy_type != PhyType::InternalHighSpeed);
757
758 r.gccfg_v1().modify(|w| {
759 w.set_pwrdwn(phy_type.internal());
761 });
762
763 r.gccfg_v1().modify(|w| {
765 w.set_novbussens(!self.config.vbus_detection);
766 w.set_vbusasen(false);
767 w.set_vbusbsen(self.config.vbus_detection);
768 w.set_sofouten(false);
769 });
770 }
771
772 pub fn config_v2v3(&mut self) {
775 let r = self.instance.regs;
776 let phy_type = self.instance.phy_type;
777
778 r.gccfg_v2().modify(|w| {
780 w.set_pwrdwn(phy_type.internal() && !phy_type.high_speed());
782 w.set_phyhsen(phy_type.internal() && phy_type.high_speed());
783 });
784
785 r.gccfg_v2().modify(|w| {
786 w.set_vbden(self.config.vbus_detection);
787 });
788
789 r.gotgctl().modify(|w| {
791 w.set_bvaloen(!self.config.vbus_detection);
792 w.set_bvaloval(true);
793 });
794 }
795
796 pub fn config_v5(&mut self) {
799 let r = self.instance.regs;
800 let phy_type = self.instance.phy_type;
801
802 if phy_type == PhyType::InternalHighSpeed {
803 r.gccfg_v3().modify(|w| {
804 w.set_vbvaloven(!self.config.vbus_detection);
805 w.set_vbvaloval(!self.config.vbus_detection);
806 w.set_vbden(self.config.vbus_detection);
807 });
808 } else {
809 r.gotgctl().modify(|w| {
810 w.set_bvaloen(!self.config.vbus_detection);
811 w.set_bvaloval(!self.config.vbus_detection);
812 });
813 r.gccfg_v3().modify(|w| {
814 w.set_vbden(self.config.vbus_detection);
815 });
816 }
817 }
818
819 fn init(&mut self) {
820 let r = self.instance.regs;
821 let phy_type = self.instance.phy_type;
822
823 r.dctl().write(|w| w.set_sdis(true));
825
826 r.dcfg().write(|w| {
828 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
829 w.set_dspd(phy_type.to_dspd());
830 if self.config.xcvrdly {
831 w.set_xcvrdly(true);
832 }
833 });
834
835 r.diepmsk().write(|w| {
837 w.set_xfrcm(true);
838 });
839
840 r.doepmsk().write(|w| {
842 w.set_stupm(true);
843 });
844
845 self.restore_irqs();
847 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
848
849 r.gahbcfg().write(|w| {
851 w.set_gint(true); });
853
854 r.dctl().write(|w| w.set_sdis(false));
856 }
857
858 fn init_fifo(&mut self) {
859 trace!("init_fifo");
860
861 let regs = self.instance.regs;
862 critical_section::with(|_| {
866 let st = self.instance.state;
868 let rx_fifo_size_words = self.instance.extra_rx_fifo_words + st.ep_fifo_size_out();
869 trace!("configuring rx fifo size={}", rx_fifo_size_words);
870
871 regs.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
872
873 let mut fifo_top = rx_fifo_size_words;
875 for i in 0..st.endpoint_count() {
876 if let Some(ep) = st.ep_alloc_get(Direction::In, i) {
877 trace!(
878 "configuring tx fifo ep={}, offset={}, size={}",
879 i, fifo_top, ep.fifo_size_words
880 );
881
882 let dieptxf = if i == 0 { regs.dieptxf0() } else { regs.dieptxf(i - 1) };
883
884 dieptxf.write(|w| {
885 w.set_fd(ep.fifo_size_words);
886 w.set_sa(fifo_top);
887 });
888
889 fifo_top += ep.fifo_size_words;
890 }
891 }
892
893 assert!(
894 fifo_top <= self.instance.fifo_depth_words,
895 "FIFO allocations exceeded maximum capacity"
896 );
897
898 regs.grstctl().write(|w| {
900 w.set_txfflsh(true);
901 w.set_txfnum(0x10);
902 });
903 while regs.grstctl().read().txfflsh() {}
904 regs.grstctl().write(|w| {
905 w.set_rxfflsh(true);
906 });
907 while regs.grstctl().read().rxfflsh() {}
908 });
909 }
910
911 fn configure_endpoints(&mut self) {
912 trace!("configure_endpoints");
913
914 let regs = self.instance.regs;
915 let st = self.instance.state;
916
917 for index in 0..st.endpoint_count() {
919 if let Some(ep) = st.ep_alloc_get(Direction::In, index) {
920 critical_section::with(|_| {
921 regs.diepctl(index).write(|w| {
922 if index == 0 {
923 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
924 } else {
925 w.set_mpsiz(ep.max_packet_size);
926 w.set_eptyp(to_eptyp(ep.ep_type));
927 w.set_sd0pid_sevnfrm(true);
928 w.set_txfnum(index as _);
929 w.set_snak(true);
930 }
931 });
932 });
933 }
934 }
935
936 for index in 0..st.endpoint_count() {
938 if let Some(ep) = st.ep_alloc_get(Direction::Out, index) {
939 critical_section::with(|_| {
940 regs.doepctl(index).write(|w| {
941 if index == 0 {
942 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
943 } else {
944 w.set_mpsiz(ep.max_packet_size);
945 w.set_eptyp(to_eptyp(ep.ep_type));
946 w.set_sd0pid_sevnfrm(true);
947 }
948 });
949
950 regs.doeptsiz(index).modify(|w| {
951 w.set_xfrsiz(ep.max_packet_size as _);
952 if index == 0 {
953 w.set_rxdpid_stupcnt(3);
954 } else {
955 w.set_pktcnt(1);
956 }
957 });
958
959 if index == 0 {
960 regs.doepctl(index).modify(|w| {
961 w.set_epena(true);
962 w.set_cnak(true);
963 });
964 }
965 });
966 }
967 }
968
969 regs.daintmsk().modify(|w| {
971 w.set_iepm(st.ep_irq_mask_in());
972 w.set_oepm(st.ep_irq_mask_out());
973 });
974 }
975
976 fn disable_all_endpoints(&mut self) {
977 let st = self.instance.state;
978 for i in 0..st.endpoint_count() {
979 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
980 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
981 }
982 }
983
984 pub fn init_device(&mut self) {
986 if !self.inited {
987 self.init();
988 self.inited = true;
989 }
990 }
991
992 pub fn deinit_device(&mut self) {
994 if self.inited {
995 self.inited = false;
996 }
997 }
998}
999
1000impl<'d> embassy_usb_driver::Bus for Bus<'d> {
1001 async fn poll(&mut self) -> Event {
1002 poll_fn(move |cx| {
1003 if !self.inited {
1004 self.init_device();
1005 if !self.config.vbus_detection {
1007 return Poll::Ready(Event::PowerDetected);
1008 }
1009 }
1010
1011 let regs = self.instance.regs;
1012 self.instance.state.bus_waker.register(cx.waker());
1013
1014 let ints = regs.gintsts().read();
1015
1016 if ints.srqint() {
1017 trace!("vbus detected");
1018
1019 regs.gintsts().write(|w| w.set_srqint(true)); self.restore_irqs();
1021
1022 if self.config.vbus_detection {
1023 return Poll::Ready(Event::PowerDetected);
1024 }
1025 }
1026
1027 if ints.otgint() {
1028 let otgints = regs.gotgint().read();
1029 regs.gotgint().write_value(otgints); self.restore_irqs();
1031
1032 if otgints.sedet() {
1033 trace!("vbus removed");
1034 if self.config.vbus_detection {
1035 self.disable_all_endpoints();
1036 return Poll::Ready(Event::PowerRemoved);
1037 }
1038 }
1039 }
1040
1041 if ints.usbrst() {
1042 trace!("reset");
1043
1044 self.init_fifo();
1045 self.configure_endpoints();
1046
1047 critical_section::with(|_| {
1049 regs.dcfg().modify(|w| {
1050 w.set_dad(0);
1051 });
1052 });
1053
1054 regs.gintsts().write(|w| w.set_usbrst(true)); self.restore_irqs();
1056 }
1057
1058 if ints.enumdne() {
1059 trace!("enumdne");
1060
1061 let speed = regs.dsts().read().enumspd();
1062 let trdt = (self.instance.calculate_trdt_fn)(speed);
1063 trace!(" speed={} trdt={}", speed.to_bits(), trdt);
1064 regs.gusbcfg().modify(|w| w.set_trdt(trdt));
1065
1066 regs.gintsts().write(|w| w.set_enumdne(true)); self.restore_irqs();
1068
1069 return Poll::Ready(Event::Reset);
1070 }
1071
1072 if ints.usbsusp() {
1073 trace!("suspend");
1074 regs.gintsts().write(|w| w.set_usbsusp(true)); self.restore_irqs();
1076 return Poll::Ready(Event::Suspend);
1077 }
1078
1079 if ints.wkupint() {
1080 trace!("resume");
1081 regs.gintsts().write(|w| w.set_wkupint(true)); self.restore_irqs();
1083 return Poll::Ready(Event::Resume);
1084 }
1085
1086 Poll::Pending
1087 })
1088 .await
1089 }
1090
1091 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
1092 trace!("endpoint_set_stalled ep={:?} en={}", ep_addr, stalled);
1093
1094 let regs = self.instance.regs;
1095 let st = &self.instance.state;
1096
1097 assert!(
1098 ep_addr.index() < st.endpoint_count(),
1099 "endpoint_set_stalled index {} out of range",
1100 ep_addr.index()
1101 );
1102
1103 match ep_addr.direction() {
1104 Direction::Out => {
1105 critical_section::with(|_| {
1106 regs.doepctl(ep_addr.index()).modify(|w| {
1107 w.set_stall(stalled);
1108 });
1109 });
1110
1111 st.ep_states[ep_addr.index()].out_waker.wake();
1112 }
1113 Direction::In => {
1114 critical_section::with(|_| {
1115 regs.diepctl(ep_addr.index()).modify(|w| {
1116 w.set_stall(stalled);
1117 });
1118 });
1119
1120 st.ep_states[ep_addr.index()].in_waker.wake();
1121 }
1122 }
1123 }
1124
1125 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
1126 assert!(
1127 ep_addr.index() < self.instance.state.endpoint_count(),
1128 "endpoint_is_stalled index {} out of range",
1129 ep_addr.index()
1130 );
1131
1132 let regs = self.instance.regs;
1133 match ep_addr.direction() {
1134 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
1135 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
1136 }
1137 }
1138
1139 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
1140 trace!("endpoint_set_enabled ep={:?} en={}", ep_addr, enabled);
1141
1142 assert!(
1143 ep_addr.index() < self.instance.state.endpoint_count(),
1144 "endpoint_set_enabled index {} out of range",
1145 ep_addr.index()
1146 );
1147
1148 let regs = self.instance.regs;
1149 let st = self.instance.state;
1150 match ep_addr.direction() {
1151 Direction::Out => {
1152 critical_section::with(|_| {
1153 if !enabled && regs.doepctl(ep_addr.index()).read().epena() {
1155 regs.doepctl(ep_addr.index()).modify(|w| {
1156 w.set_snak(true);
1157 w.set_epdis(true);
1158 })
1159 }
1160
1161 regs.doepctl(ep_addr.index()).modify(|w| {
1162 w.set_usbaep(enabled);
1163 });
1164
1165 if enabled && ep_addr.index() != 0 {
1168 if let Some(ep) = st.ep_alloc_get(Direction::Out, ep_addr.index()) {
1169 regs.doeptsiz(ep_addr.index()).modify(|w| {
1170 w.set_xfrsiz(ep.max_packet_size as _);
1171 w.set_pktcnt(1);
1172 });
1173 regs.doepctl(ep_addr.index()).modify(|w| {
1174 w.set_cnak(true);
1175 w.set_epena(true);
1176 });
1177 }
1178 }
1179 });
1180
1181 st.ep_states[ep_addr.index()].out_waker.wake();
1183 }
1184 Direction::In => {
1185 critical_section::with(|_| {
1186 if !enabled && regs.diepctl(ep_addr.index()).read().epena() {
1188 regs.diepctl(ep_addr.index()).modify(|w| {
1189 w.set_snak(true); w.set_epdis(true);
1191 })
1192 }
1193
1194 regs.diepctl(ep_addr.index()).modify(|w| {
1195 w.set_usbaep(enabled);
1196 if enabled {
1200 w.set_snak(true);
1201 }
1202 });
1203
1204 regs.grstctl().write(|w| {
1206 w.set_txfflsh(true);
1207 w.set_txfnum(ep_addr.index() as _);
1208 });
1209 loop {
1210 let x = regs.grstctl().read();
1211 if !x.txfflsh() {
1212 break;
1213 }
1214 }
1215 });
1216
1217 st.ep_states[ep_addr.index()].in_waker.wake();
1219 }
1220 }
1221 }
1222
1223 async fn enable(&mut self) {
1224 trace!("enable");
1225 }
1227
1228 async fn disable(&mut self) {
1229 trace!("disable");
1230
1231 }
1234
1235 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
1236 let r = self.instance.regs;
1237
1238 r.pcgcctl().modify(|w| {
1241 w.set_stppclk(false);
1242 if self.instance.phy_type.high_speed() {
1244 w.set_gatehclk(false);
1245 }
1246 });
1247
1248 r.dctl().modify(|w| w.set_rwusig(true));
1251 embassy_time::Timer::after_millis(10).await;
1252 r.dctl().modify(|w| w.set_rwusig(false));
1253
1254 Ok(())
1255 }
1256}
1257
1258trait Dir {
1260 fn dir() -> Direction;
1262}
1263
1264pub enum In {}
1266impl Dir for In {
1267 fn dir() -> Direction {
1268 Direction::In
1269 }
1270}
1271
1272pub enum Out {}
1274impl Dir for Out {
1275 fn dir() -> Direction {
1276 Direction::Out
1277 }
1278}
1279
1280pub struct Endpoint<'d, D> {
1282 _phantom: PhantomData<D>,
1283 regs: Otg,
1284 info: EndpointInfo,
1285 state: &'d EpState,
1286}
1287
1288impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
1289 fn info(&self) -> &EndpointInfo {
1290 &self.info
1291 }
1292
1293 async fn wait_enabled(&mut self) {
1294 poll_fn(|cx| {
1295 let ep_index = self.info.addr.index();
1296
1297 self.state.in_waker.register(cx.waker());
1298
1299 if self.regs.diepctl(ep_index).read().usbaep() {
1300 Poll::Ready(())
1301 } else {
1302 Poll::Pending
1303 }
1304 })
1305 .await
1306 }
1307}
1308
1309impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> {
1310 fn info(&self) -> &EndpointInfo {
1311 &self.info
1312 }
1313
1314 async fn wait_enabled(&mut self) {
1315 poll_fn(|cx| {
1316 let ep_index = self.info.addr.index();
1317
1318 self.state.out_waker.register(cx.waker());
1319
1320 if self.regs.doepctl(ep_index).read().usbaep() {
1321 Poll::Ready(())
1322 } else {
1323 Poll::Pending
1324 }
1325 })
1326 .await
1327 }
1328}
1329
1330impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1331 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
1332 trace!("read start len={}", buf.len());
1333
1334 poll_fn(|cx| {
1335 let index = self.info.addr.index();
1336 self.state.out_waker.register(cx.waker());
1337
1338 let doepctl = self.regs.doepctl(index).read();
1339 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
1340 if !doepctl.usbaep() {
1341 trace!("read ep={:?} error disabled", self.info.addr);
1342 return Poll::Ready(Err(EndpointError::Disabled));
1343 }
1344
1345 let len = self.state.out_size.load(Ordering::Acquire);
1346 if len != EP_OUT_BUFFER_EMPTY {
1347 trace!("read ep={:?} done len={}", self.info.addr, len);
1348
1349 if len as usize > buf.len() {
1350 return Poll::Ready(Err(EndpointError::BufferOverflow));
1351 }
1352
1353 let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) };
1355 buf[..len as usize].copy_from_slice(data);
1356
1357 self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1359
1360 critical_section::with(|_| {
1361 self.regs.doeptsiz(index).modify(|w| {
1363 w.set_xfrsiz(self.info.max_packet_size as _);
1364 w.set_pktcnt(1);
1365 });
1366
1367 if self.info.ep_type == EndpointType::Isochronous {
1368 let frame_number = self.regs.dsts().read().fnsof();
1371 let frame_is_odd = frame_number & 0x01 == 1;
1372
1373 self.regs.doepctl(index).modify(|r| {
1374 if frame_is_odd {
1375 r.set_sd0pid_sevnfrm(true);
1376 } else {
1377 r.set_soddfrm(true);
1378 }
1379 });
1380 }
1381
1382 self.regs.doepctl(index).modify(|w| {
1384 w.set_cnak(true);
1385 });
1386 });
1387
1388 Poll::Ready(Ok(len as usize))
1389 } else {
1390 Poll::Pending
1391 }
1392 })
1393 .await
1394 }
1395}
1396
1397impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1398 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
1399 trace!("write ep={:?} data={:?}", self.info.addr, Bytes(buf));
1400
1401 if buf.len() > self.info.max_packet_size as usize {
1402 return Err(EndpointError::BufferOverflow);
1403 }
1404
1405 let index = self.info.addr.index();
1406 poll_fn(|cx| {
1408 self.state.in_waker.register(cx.waker());
1409
1410 let diepctl = self.regs.diepctl(index).read();
1411 let dtxfsts = self.regs.dtxfsts(index).read();
1412 trace!(
1413 "write ep={:?}: diepctl {:08x} ftxfsts {:08x}",
1414 self.info.addr, diepctl.0, dtxfsts.0
1415 );
1416 if !diepctl.usbaep() {
1417 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1418 Poll::Ready(Err(EndpointError::Disabled))
1419 } else if !diepctl.epena() {
1420 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1421 Poll::Ready(Ok(()))
1422 } else {
1423 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1424 Poll::Pending
1425 }
1426 })
1427 .await?;
1428
1429 if buf.len() > 0 {
1430 poll_fn(|cx| {
1431 self.state.in_waker.register(cx.waker());
1432
1433 let size_words = (buf.len() + 3) / 4;
1434
1435 let fifo_space = self.regs.dtxfsts(index).read().ineptfsav() as usize;
1436 if size_words > fifo_space {
1437 critical_section::with(|_| {
1439 self.regs.diepempmsk().modify(|w| {
1440 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1441 });
1442 });
1443
1444 trace!("tx fifo for ep={} full, waiting for txfe", index);
1445
1446 Poll::Pending
1447 } else {
1448 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1449 Poll::Ready(())
1450 }
1451 })
1452 .await
1453 }
1454
1455 critical_section::with(|_| {
1460 self.regs.dieptsiz(index).write(|w| {
1462 w.set_mcnt(1);
1463 w.set_pktcnt(1);
1464 w.set_xfrsiz(buf.len() as _);
1465 });
1466
1467 if self.info.ep_type == EndpointType::Isochronous {
1468 let frame_number = self.regs.dsts().read().fnsof();
1471 let frame_is_odd = frame_number & 0x01 == 1;
1472
1473 self.regs.diepctl(index).modify(|r| {
1474 if frame_is_odd {
1475 r.set_sd0pid_sevnfrm(true);
1476 } else {
1477 r.set_soddfrm_sd1pid(true);
1478 }
1479 });
1480 }
1481
1482 self.regs.diepctl(index).modify(|w| {
1484 w.set_cnak(true);
1485 w.set_epena(true);
1486 });
1487
1488 let fifo = self.regs.fifo(index);
1490 let mut chunks = buf.chunks_exact(4);
1491 for chunk in &mut chunks {
1492 let val = u32::from_ne_bytes(chunk.try_into().unwrap());
1493 fifo.write_value(regs::Fifo(val));
1494 }
1495 let rem = chunks.remainder();
1497 if !rem.is_empty() {
1498 let mut tmp = [0u8; 4];
1499 tmp[0..rem.len()].copy_from_slice(rem);
1500 let tmp = u32::from_ne_bytes(tmp);
1501 fifo.write_value(regs::Fifo(tmp));
1502 }
1503 });
1504
1505 trace!("write done ep={:?}", self.info.addr);
1506
1507 Ok(())
1508 }
1509}
1510
1511pub struct ControlPipe<'d> {
1513 max_packet_size: u16,
1514 regs: Otg,
1515 setup_state: &'d ControlPipeSetupState,
1516 ep_in: Endpoint<'d, In>,
1517 ep_out: Endpoint<'d, Out>,
1518}
1519
1520impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1521 fn max_packet_size(&self) -> usize {
1522 usize::from(self.max_packet_size)
1523 }
1524
1525 async fn setup(&mut self) -> [u8; 8] {
1526 poll_fn(|cx| {
1527 self.ep_out.state.out_waker.register(cx.waker());
1528
1529 if self.setup_state.setup_ready.load(Ordering::Acquire) {
1530 let mut data = [0; 8];
1531 data[0..4].copy_from_slice(&self.setup_state.setup_data[0].load(Ordering::Relaxed).to_ne_bytes());
1532 data[4..8].copy_from_slice(&self.setup_state.setup_data[1].load(Ordering::Relaxed).to_ne_bytes());
1533 self.setup_state.setup_ready.store(false, Ordering::Release);
1534
1535 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1537 w.set_rxdpid_stupcnt(3);
1538 });
1539
1540 self.regs
1542 .doepctl(self.ep_out.info.addr.index())
1543 .modify(|w| w.set_cnak(true));
1544
1545 trace!("SETUP received: {:?}", Bytes(&data));
1546 Poll::Ready(data)
1547 } else {
1548 trace!("SETUP waiting");
1549 Poll::Pending
1550 }
1551 })
1552 .await
1553 }
1554
1555 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
1556 trace!("control: data_out");
1557 let len = self.ep_out.read(buf).await?;
1558 trace!("control: data_out read: {:?}", Bytes(&buf[..len]));
1559 Ok(len)
1560 }
1561
1562 async fn data_in(&mut self, data: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
1563 trace!("control: data_in write: {:?}", Bytes(data));
1564 self.ep_in.write(data).await?;
1565
1566 if last {
1568 trace!("control: data_in waiting for status");
1569 self.ep_out.read(&mut []).await?;
1570 trace!("control: complete");
1571 }
1572
1573 Ok(())
1574 }
1575
1576 async fn accept(&mut self) {
1577 trace!("control: accept");
1578
1579 self.ep_in.write(&[]).await.ok();
1580
1581 trace!("control: accept OK");
1582 }
1583
1584 async fn reject(&mut self) {
1585 trace!("control: reject");
1586
1587 self.regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1589 w.set_stall(true);
1590 });
1591 self.regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1592 w.set_stall(true);
1593 });
1594 }
1595
1596 async fn accept_set_address(&mut self, addr: u8) {
1597 trace!("setting addr: {}", addr);
1598 critical_section::with(|_| {
1599 self.regs.dcfg().modify(|w| {
1600 w.set_dad(addr);
1601 });
1602 });
1603
1604 self.accept().await
1606 }
1607}
1608
1609fn to_eptyp(ep_type: EndpointType) -> vals::Eptyp {
1611 match ep_type {
1612 EndpointType::Control => vals::Eptyp::CONTROL,
1613 EndpointType::Isochronous => vals::Eptyp::ISOCHRONOUS,
1614 EndpointType::Bulk => vals::Eptyp::BULK,
1615 EndpointType::Interrupt => vals::Eptyp::INTERRUPT,
1616 }
1617}
1618
1619fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1621 match max_packet_size {
1622 8 => 0b11,
1623 16 => 0b10,
1624 32 => 0b01,
1625 64 => 0b00,
1626 other => panic!("Unsupported EP0 size: {}", other),
1627 }
1628}
1629
1630#[derive(Copy, Clone)]
1632pub struct OtgInstance<'d> {
1633 pub regs: Otg,
1635 pub state: State<'d>,
1637 pub fifo_depth_words: u16,
1639 pub phy_type: PhyType,
1641 pub extra_rx_fifo_words: u16,
1643 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8,
1645}