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<const MAX_EP_COUNT: usize>(r: Otg, state: &State<MAX_EP_COUNT>, ep_count: usize) {
33 trace!("irq");
34
35 let ints = r.gintsts().read();
36 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
37 r.gintmsk().write(|w| {
39 w.set_iepint(true);
40 w.set_oepint(true);
41 w.set_rxflvlm(true);
42 });
43 state.bus_waker.wake();
44 }
45
46 while r.gintsts().read().rxflvl() {
48 let status = r.grxstsp().read();
49 trace!("=== status {:08x}", status.0);
50 let ep_num = status.epnum() as usize;
51 let len = status.bcnt() as usize;
52
53 assert!(ep_num < ep_count);
54
55 match status.pktstsd() {
56 vals::Pktstsd::SETUP_DATA_RX => {
57 trace!("SETUP_DATA_RX");
58 assert!(len == 8, "invalid SETUP packet length={}", len);
59 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
60
61 if r.dieptsiz(ep_num).read().pktcnt() != 0 {
63 r.grstctl().modify(|w| {
64 w.set_txfnum(ep_num as _);
65 w.set_txfflsh(true);
66 });
67 while r.grstctl().read().txfflsh() {}
68 }
69
70 let data = &state.cp_state.setup_data;
71 data[0].store(r.fifo(0).read().data(), Ordering::Relaxed);
72 data[1].store(r.fifo(0).read().data(), Ordering::Relaxed);
73 }
74 vals::Pktstsd::OUT_DATA_RX => {
75 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
76
77 if state.ep_states[ep_num].out_size.load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
78 let buf =
81 unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) };
82
83 let mut chunks = buf.chunks_exact_mut(4);
84 for chunk in &mut chunks {
85 let data = r.fifo(0).read().0;
87 chunk.copy_from_slice(&data.to_ne_bytes());
88 }
89 let rem = chunks.into_remainder();
90 if !rem.is_empty() {
91 let data = r.fifo(0).read().0;
92 rem.copy_from_slice(&data.to_ne_bytes()[0..rem.len()]);
93 }
94
95 state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release);
96 state.ep_states[ep_num].out_waker.wake();
97 } else {
98 error!("ep_out buffer overflow index={}", ep_num);
99
100 let len_words = (len + 3) / 4;
102 for _ in 0..len_words {
103 r.fifo(0).read().data();
104 }
105 }
106 }
107 vals::Pktstsd::OUT_DATA_DONE => {
108 trace!("OUT_DATA_DONE ep={}", ep_num);
109 }
110 vals::Pktstsd::SETUP_DATA_DONE => {
111 trace!("SETUP_DATA_DONE ep={}", ep_num);
112 }
113 x => trace!("unknown PKTSTS: {}", x.to_bits()),
114 }
115 }
116
117 if ints.iepint() {
119 let mut ep_mask = r.daint().read().iepint();
120 let mut ep_num = 0;
121
122 while ep_mask != 0 {
124 if ep_mask & 1 != 0 {
125 let ep_ints = r.diepint(ep_num).read();
126
127 r.diepint(ep_num).write_value(ep_ints);
129
130 if ep_ints.txfe() {
132 critical_section::with(|_| {
133 r.diepempmsk().modify(|w| {
134 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
135 });
136 });
137 }
138
139 state.ep_states[ep_num].in_waker.wake();
140 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0);
141 }
142
143 ep_mask >>= 1;
144 ep_num += 1;
145 }
146 }
147
148 if ints.oepint() {
150 trace!("oepint");
151 let mut ep_mask = r.daint().read().oepint();
152 let mut ep_num = 0;
153
154 while ep_mask != 0 {
156 if ep_mask & 1 != 0 {
157 let ep_ints = r.doepint(ep_num).read();
158 r.doepint(ep_num).write_value(ep_ints);
160
161 if ep_ints.stup() {
162 state.cp_state.setup_ready.store(true, Ordering::Release);
163 }
164 state.ep_states[ep_num].out_waker.wake();
165 trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
166 }
167
168 ep_mask >>= 1;
169 ep_num += 1;
170 }
171 }
172
173 if ints.eopf() {
174 let frame_number = r.dsts().read().fnsof();
175 let frame_is_odd = frame_number & 0x01 == 1;
176
177 for ep_num in (0..ep_count).into_iter().filter(|ep_num| {
180 let diepctl = r.diepctl(*ep_num).read();
181 diepctl.eptyp() == vals::Eptyp::ISOCHRONOUS
183 && diepctl.epena()
185 && diepctl.eonum_dpid() == frame_is_odd
187 }) {
188 trace!("Unsent message at EOF for ep: {}, frame: {}", ep_num, frame_number);
189
190 let ep_diepctl = r.diepctl(ep_num);
191 let ep_diepint = r.diepint(ep_num);
192
193 ep_diepctl.modify(|m| m.set_snak(true));
195 while !ep_diepint.read().inepne() {}
196
197 ep_diepctl.modify(|m| {
199 m.set_snak(true);
200 m.set_epdis(true);
201 });
202 while !ep_diepint.read().epdisd() {}
203 ep_diepint.modify(|m| m.set_epdisd(true));
204
205 ep_diepctl.modify(|r| {
207 if frame_is_odd {
208 r.set_sd0pid_sevnfrm(true);
209 } else {
210 r.set_soddfrm_sd1pid(true);
211 }
212 });
213
214 ep_diepctl.modify(|w| {
216 w.set_cnak(true);
217 w.set_epena(true);
218 });
219 }
220 }
221}
222
223#[derive(Copy, Clone, Debug, Eq, PartialEq)]
225pub enum PhyType {
226 InternalFullSpeed,
230 InternalHighSpeed,
234 ExternalFullSpeed,
236 ExternalHighSpeed,
238}
239
240impl PhyType {
241 pub fn internal(&self) -> bool {
243 match self {
244 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
245 PhyType::ExternalHighSpeed | PhyType::ExternalFullSpeed => false,
246 }
247 }
248
249 pub fn high_speed(&self) -> bool {
251 match self {
252 PhyType::InternalFullSpeed | PhyType::ExternalFullSpeed => false,
253 PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
254 }
255 }
256
257 fn to_dspd(&self) -> vals::Dspd {
258 match self {
259 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
260 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
261 PhyType::ExternalFullSpeed => vals::Dspd::FULL_SPEED_EXTERNAL,
262 PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
263 }
264 }
265}
266
267const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
269
270struct EpState {
271 in_waker: AtomicWaker,
272 out_waker: AtomicWaker,
273 out_buffer: UnsafeCell<*mut u8>,
276 out_size: AtomicU16,
277}
278
279unsafe impl Send for EpState {}
283unsafe impl Sync for EpState {}
284
285struct ControlPipeSetupState {
286 setup_data: [AtomicU32; 2],
288 setup_ready: AtomicBool,
289}
290
291pub struct State<const EP_COUNT: usize> {
293 cp_state: ControlPipeSetupState,
294 ep_states: [EpState; EP_COUNT],
295 bus_waker: AtomicWaker,
296}
297
298unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
299unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
300
301impl<const EP_COUNT: usize> State<EP_COUNT> {
302 pub const fn new() -> Self {
304 Self {
305 cp_state: ControlPipeSetupState {
306 setup_data: [const { AtomicU32::new(0) }; 2],
307 setup_ready: AtomicBool::new(false),
308 },
309 ep_states: [const {
310 EpState {
311 in_waker: AtomicWaker::new(),
312 out_waker: AtomicWaker::new(),
313 out_buffer: UnsafeCell::new(0 as _),
314 out_size: AtomicU16::new(EP_OUT_BUFFER_EMPTY),
315 }
316 }; EP_COUNT],
317 bus_waker: AtomicWaker::new(),
318 }
319 }
320}
321
322#[derive(Debug, Clone, Copy)]
323struct EndpointData {
324 ep_type: EndpointType,
325 max_packet_size: u16,
326 fifo_size_words: u16,
327}
328
329#[non_exhaustive]
331#[derive(Clone, Copy, PartialEq, Eq, Debug)]
332pub struct Config {
333 pub vbus_detection: bool,
348
349 pub xcvrdly: bool,
356}
357
358impl Default for Config {
359 fn default() -> Self {
360 Self {
361 vbus_detection: false,
362 xcvrdly: false,
363 }
364 }
365}
366
367pub struct Driver<'d, const MAX_EP_COUNT: usize> {
369 config: Config,
370 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
371 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
372 ep_out_buffer: &'d mut [u8],
373 ep_out_buffer_offset: usize,
374 instance: OtgInstance<'d, MAX_EP_COUNT>,
375}
376
377impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
378 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d, MAX_EP_COUNT>, config: Config) -> Self {
388 Self {
389 config,
390 ep_in: [None; MAX_EP_COUNT],
391 ep_out: [None; MAX_EP_COUNT],
392 ep_out_buffer,
393 ep_out_buffer_offset: 0,
394 instance,
395 }
396 }
397
398 fn allocated_fifo_words(&self) -> u16 {
400 self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
401 }
402
403 fn alloc_endpoint<D: Dir>(
405 &mut self,
406 ep_type: EndpointType,
407 ep_addr: Option<EndpointAddress>,
408 max_packet_size: u16,
409 interval_ms: u8,
410 ) -> Result<Endpoint<'d, D>, EndpointAllocError> {
411 trace!(
412 "allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
413 ep_type,
414 max_packet_size,
415 interval_ms,
416 D::dir()
417 );
418
419 if D::dir() == Direction::Out {
420 if self.ep_out_buffer_offset + max_packet_size as usize > self.ep_out_buffer.len() {
421 error!("Not enough endpoint out buffer capacity");
422 return Err(EndpointAllocError);
423 }
424 };
425
426 let fifo_size_words = match D::dir() {
427 Direction::Out => (max_packet_size + 3) / 4,
428 Direction::In => u16::max((max_packet_size + 3) / 4, 16),
430 };
431
432 if fifo_size_words + self.allocated_fifo_words() > self.instance.fifo_depth_words {
433 error!("Not enough FIFO capacity");
434 return Err(EndpointAllocError);
435 }
436
437 let eps = match D::dir() {
438 Direction::Out => &mut self.ep_out[..self.instance.endpoint_count],
439 Direction::In => &mut self.ep_in[..self.instance.endpoint_count],
440 };
441
442 let slot = if let Some(addr) = ep_addr {
444 let requested_index = addr.index();
446 if requested_index >= self.instance.endpoint_count {
447 return Err(EndpointAllocError);
448 }
449 if requested_index == 0 && ep_type != EndpointType::Control {
450 return Err(EndpointAllocError); }
452 if eps[requested_index].is_some() {
453 return Err(EndpointAllocError); }
455 Some((requested_index, &mut eps[requested_index]))
456 } else {
457 eps.iter_mut().enumerate().find(|(i, ep)| {
459 if *i == 0 && ep_type != EndpointType::Control {
460 false
462 } else {
463 ep.is_none()
464 }
465 })
466 };
467
468 let index = match slot {
469 Some((index, ep)) => {
470 *ep = Some(EndpointData {
471 ep_type,
472 max_packet_size,
473 fifo_size_words,
474 });
475 index
476 }
477 None => {
478 error!("No free endpoints available");
479 return Err(EndpointAllocError);
480 }
481 };
482
483 trace!(" index={}", index);
484
485 let state = &self.instance.state.ep_states[index];
486 if D::dir() == Direction::Out {
487 unsafe {
489 *state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
490 }
491 self.ep_out_buffer_offset += max_packet_size as usize;
492 }
493
494 Ok(Endpoint {
495 _phantom: PhantomData,
496 regs: self.instance.regs,
497 state,
498 info: EndpointInfo {
499 addr: EndpointAddress::from_parts(index, D::dir()),
500 ep_type,
501 max_packet_size,
502 interval_ms,
503 },
504 })
505 }
506}
507
508impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d, MAX_EP_COUNT> {
509 type EndpointOut = Endpoint<'d, Out>;
510 type EndpointIn = Endpoint<'d, In>;
511 type ControlPipe = ControlPipe<'d>;
512 type Bus = Bus<'d, MAX_EP_COUNT>;
513
514 fn alloc_endpoint_in(
515 &mut self,
516 ep_type: EndpointType,
517 ep_addr: Option<EndpointAddress>,
518 max_packet_size: u16,
519 interval_ms: u8,
520 ) -> Result<Self::EndpointIn, EndpointAllocError> {
521 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
522 }
523
524 fn alloc_endpoint_out(
525 &mut self,
526 ep_type: EndpointType,
527 ep_addr: Option<EndpointAddress>,
528 max_packet_size: u16,
529 interval_ms: u8,
530 ) -> Result<Self::EndpointOut, EndpointAllocError> {
531 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
532 }
533
534 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
535 let ep_out = self
536 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
537 .unwrap();
538 let ep_in = self
539 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
540 .unwrap();
541 assert_eq!(ep_out.info.addr.index(), 0);
542 assert_eq!(ep_in.info.addr.index(), 0);
543
544 trace!("start");
545
546 let regs = self.instance.regs;
547 let cp_setup_state = &self.instance.state.cp_state;
548 (
549 Bus {
550 config: self.config,
551 ep_in: self.ep_in,
552 ep_out: self.ep_out,
553 inited: false,
554 instance: self.instance,
555 },
556 ControlPipe {
557 max_packet_size: control_max_packet_size,
558 setup_state: cp_setup_state,
559 ep_out,
560 ep_in,
561 regs,
562 },
563 )
564 }
565}
566
567pub struct Bus<'d, const MAX_EP_COUNT: usize> {
569 config: Config,
570 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
571 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
572 instance: OtgInstance<'d, MAX_EP_COUNT>,
573 inited: bool,
574}
575
576impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
577 fn restore_irqs(&mut self) {
578 self.instance.regs.gintmsk().write(|w| {
579 w.set_usbrst(true);
580 w.set_enumdnem(true);
581 w.set_usbsuspm(true);
582 w.set_wuim(true);
583 w.set_iepint(true);
584 w.set_oepint(true);
585 w.set_rxflvlm(true);
586 w.set_srqim(true);
587 w.set_otgint(true);
588 });
589 }
590
591 pub fn phy_type(&self) -> PhyType {
593 self.instance.phy_type
594 }
595
596 pub fn core_soft_reset(&mut self) {
598 let r = self.instance.regs;
599
600 while !r.grstctl().read().ahbidl() {}
602
603 r.grstctl().write(|w| {
604 w.set_csrst(true);
605 });
606
607 loop {
609 let grstctl = r.grstctl().read();
610 if !grstctl.csrst() || grstctl.csrstdone() {
611 break;
612 }
613 }
614
615 r.grstctl().modify(|w| {
617 w.set_csrst(false);
618 });
619 }
620
621 pub fn configure_as_device(&mut self) {
623 let r = self.instance.regs;
624 let phy_type = self.instance.phy_type;
625
626 let hw_width = r.hwcfg4().read().utmi_phy_data_width();
629 r.gusbcfg().write(|w| {
630 w.set_fdmod(true);
632
633 match phy_type {
634 PhyType::InternalFullSpeed => {
635 w.set_physel(true);
637 w.set_ulpi_utmi_sel(false);
638 w.set_phyif(false);
639 }
640 PhyType::InternalHighSpeed => {
641 w.set_physel(false);
643 w.set_ulpi_utmi_sel(false);
644 w.set_phyif(hw_width == 1);
645 w.set_ulpievbusd(false);
647 w.set_ulpievbusi(false);
648 w.set_ulpifsls(false);
649 w.set_ulpicsm(false);
650 }
651 PhyType::ExternalFullSpeed | PhyType::ExternalHighSpeed => {
652 w.set_physel(false);
654 w.set_ulpi_utmi_sel(true);
655 w.set_phyif(false);
656 w.set_ddr_sel(false);
657 w.set_ulpievbusd(false);
659 w.set_ulpievbusi(false);
660 w.set_ulpifsls(false);
662 w.set_ulpicsm(false);
663 }
664 }
665 });
666
667 while r.gintsts().read().cmod() {}
669 }
670
671 pub fn config_v1(&mut self) {
674 let r = self.instance.regs;
675 let phy_type = self.instance.phy_type;
676 assert!(phy_type != PhyType::InternalHighSpeed);
677
678 r.gccfg_v1().modify(|w| {
679 w.set_pwrdwn(phy_type.internal());
681 });
682
683 r.gccfg_v1().modify(|w| {
685 w.set_novbussens(!self.config.vbus_detection);
686 w.set_vbusasen(false);
687 w.set_vbusbsen(self.config.vbus_detection);
688 w.set_sofouten(false);
689 });
690 }
691
692 pub fn config_v2v3(&mut self) {
695 let r = self.instance.regs;
696 let phy_type = self.instance.phy_type;
697
698 r.gccfg_v2().modify(|w| {
700 w.set_pwrdwn(phy_type.internal() && !phy_type.high_speed());
702 w.set_phyhsen(phy_type.internal() && phy_type.high_speed());
703 });
704
705 r.gccfg_v2().modify(|w| {
706 w.set_vbden(self.config.vbus_detection);
707 });
708
709 r.gotgctl().modify(|w| {
711 w.set_bvaloen(!self.config.vbus_detection);
712 w.set_bvaloval(true);
713 });
714 }
715
716 pub fn config_v5(&mut self) {
719 let r = self.instance.regs;
720 let phy_type = self.instance.phy_type;
721
722 if phy_type == PhyType::InternalHighSpeed {
723 r.gccfg_v3().modify(|w| {
724 w.set_vbvaloven(!self.config.vbus_detection);
725 w.set_vbvaloval(!self.config.vbus_detection);
726 w.set_vbden(self.config.vbus_detection);
727 });
728 } else {
729 r.gotgctl().modify(|w| {
730 w.set_bvaloen(!self.config.vbus_detection);
731 w.set_bvaloval(!self.config.vbus_detection);
732 });
733 r.gccfg_v3().modify(|w| {
734 w.set_vbden(self.config.vbus_detection);
735 });
736 }
737 }
738
739 fn init(&mut self) {
740 let r = self.instance.regs;
741 let phy_type = self.instance.phy_type;
742
743 r.dctl().write(|w| w.set_sdis(true));
745
746 r.dcfg().write(|w| {
748 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
749 w.set_dspd(phy_type.to_dspd());
750 if self.config.xcvrdly {
751 w.set_xcvrdly(true);
752 }
753 });
754
755 r.diepmsk().write(|w| {
757 w.set_xfrcm(true);
758 });
759
760 r.doepmsk().write(|w| {
762 w.set_stupm(true);
763 });
764
765 self.restore_irqs();
767 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
768
769 r.gahbcfg().write(|w| {
771 w.set_gint(true); });
773
774 r.dctl().write(|w| w.set_sdis(false));
776 }
777
778 fn init_fifo(&mut self) {
779 trace!("init_fifo");
780
781 let regs = self.instance.regs;
782 critical_section::with(|_| {
786 let rx_fifo_size_words = self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out);
788 trace!("configuring rx fifo size={}", rx_fifo_size_words);
789
790 regs.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
791
792 let mut fifo_top = rx_fifo_size_words;
794 for i in 0..self.instance.endpoint_count {
795 if let Some(ep) = self.ep_in[i] {
796 trace!(
797 "configuring tx fifo ep={}, offset={}, size={}",
798 i, fifo_top, ep.fifo_size_words
799 );
800
801 let dieptxf = if i == 0 { regs.dieptxf0() } else { regs.dieptxf(i - 1) };
802
803 dieptxf.write(|w| {
804 w.set_fd(ep.fifo_size_words);
805 w.set_sa(fifo_top);
806 });
807
808 fifo_top += ep.fifo_size_words;
809 }
810 }
811
812 assert!(
813 fifo_top <= self.instance.fifo_depth_words,
814 "FIFO allocations exceeded maximum capacity"
815 );
816
817 regs.grstctl().write(|w| {
819 w.set_rxfflsh(true);
820 w.set_txfflsh(true);
821 w.set_txfnum(0x10);
822 });
823 });
824
825 loop {
826 let x = regs.grstctl().read();
827 if !x.rxfflsh() && !x.txfflsh() {
828 break;
829 }
830 }
831 }
832
833 fn configure_endpoints(&mut self) {
834 trace!("configure_endpoints");
835
836 let regs = self.instance.regs;
837
838 for (index, ep) in self.ep_in.iter().enumerate() {
840 if let Some(ep) = ep {
841 critical_section::with(|_| {
842 regs.diepctl(index).write(|w| {
843 if index == 0 {
844 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
845 } else {
846 w.set_mpsiz(ep.max_packet_size);
847 w.set_eptyp(to_eptyp(ep.ep_type));
848 w.set_sd0pid_sevnfrm(true);
849 w.set_txfnum(index as _);
850 w.set_snak(true);
851 }
852 });
853 });
854 }
855 }
856
857 for (index, ep) in self.ep_out.iter().enumerate() {
859 if let Some(ep) = ep {
860 critical_section::with(|_| {
861 regs.doepctl(index).write(|w| {
862 if index == 0 {
863 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
864 } else {
865 w.set_mpsiz(ep.max_packet_size);
866 w.set_eptyp(to_eptyp(ep.ep_type));
867 w.set_sd0pid_sevnfrm(true);
868 }
869 });
870
871 regs.doeptsiz(index).modify(|w| {
872 w.set_xfrsiz(ep.max_packet_size as _);
873 if index == 0 {
874 w.set_rxdpid_stupcnt(3);
875 } else {
876 w.set_pktcnt(1);
877 }
878 });
879 });
880 }
881 }
882
883 regs.daintmsk().modify(|w| {
885 w.set_iepm(ep_irq_mask(&self.ep_in));
886 w.set_oepm(ep_irq_mask(&self.ep_out));
887 });
888 }
889
890 fn disable_all_endpoints(&mut self) {
891 for i in 0..self.instance.endpoint_count {
892 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
893 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
894 }
895 }
896
897 pub fn init_device(&mut self) {
899 if !self.inited {
900 self.init();
901 self.inited = true;
902 }
903 }
904
905 pub fn deinit_device(&mut self) {
907 if self.inited {
908 self.inited = false;
909 }
910 }
911}
912
913impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Bus for Bus<'d, MAX_EP_COUNT> {
914 async fn poll(&mut self) -> Event {
915 poll_fn(move |cx| {
916 if !self.inited {
917 self.init_device();
918 if !self.config.vbus_detection {
920 return Poll::Ready(Event::PowerDetected);
921 }
922 }
923
924 let regs = self.instance.regs;
925 self.instance.state.bus_waker.register(cx.waker());
926
927 let ints = regs.gintsts().read();
928
929 if ints.srqint() {
930 trace!("vbus detected");
931
932 regs.gintsts().write(|w| w.set_srqint(true)); self.restore_irqs();
934
935 if self.config.vbus_detection {
936 return Poll::Ready(Event::PowerDetected);
937 }
938 }
939
940 if ints.otgint() {
941 let otgints = regs.gotgint().read();
942 regs.gotgint().write_value(otgints); self.restore_irqs();
944
945 if otgints.sedet() {
946 trace!("vbus removed");
947 if self.config.vbus_detection {
948 self.disable_all_endpoints();
949 return Poll::Ready(Event::PowerRemoved);
950 }
951 }
952 }
953
954 if ints.usbrst() {
955 trace!("reset");
956
957 self.init_fifo();
958 self.configure_endpoints();
959
960 critical_section::with(|_| {
962 regs.dcfg().modify(|w| {
963 w.set_dad(0);
964 });
965 });
966
967 regs.gintsts().write(|w| w.set_usbrst(true)); self.restore_irqs();
969 }
970
971 if ints.enumdne() {
972 trace!("enumdne");
973
974 let speed = regs.dsts().read().enumspd();
975 let trdt = (self.instance.calculate_trdt_fn)(speed);
976 trace!(" speed={} trdt={}", speed.to_bits(), trdt);
977 regs.gusbcfg().modify(|w| w.set_trdt(trdt));
978
979 regs.gintsts().write(|w| w.set_enumdne(true)); self.restore_irqs();
981
982 return Poll::Ready(Event::Reset);
983 }
984
985 if ints.usbsusp() {
986 trace!("suspend");
987 regs.gintsts().write(|w| w.set_usbsusp(true)); self.restore_irqs();
989 return Poll::Ready(Event::Suspend);
990 }
991
992 if ints.wkupint() {
993 trace!("resume");
994 regs.gintsts().write(|w| w.set_wkupint(true)); self.restore_irqs();
996 return Poll::Ready(Event::Resume);
997 }
998
999 Poll::Pending
1000 })
1001 .await
1002 }
1003
1004 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
1005 trace!("endpoint_set_stalled ep={:?} en={}", ep_addr, stalled);
1006
1007 assert!(
1008 ep_addr.index() < self.instance.endpoint_count,
1009 "endpoint_set_stalled index {} out of range",
1010 ep_addr.index()
1011 );
1012
1013 let regs = self.instance.regs;
1014 let state = self.instance.state;
1015 match ep_addr.direction() {
1016 Direction::Out => {
1017 critical_section::with(|_| {
1018 regs.doepctl(ep_addr.index()).modify(|w| {
1019 w.set_stall(stalled);
1020 });
1021 });
1022
1023 state.ep_states[ep_addr.index()].out_waker.wake();
1024 }
1025 Direction::In => {
1026 critical_section::with(|_| {
1027 regs.diepctl(ep_addr.index()).modify(|w| {
1028 w.set_stall(stalled);
1029 });
1030 });
1031
1032 state.ep_states[ep_addr.index()].in_waker.wake();
1033 }
1034 }
1035 }
1036
1037 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
1038 assert!(
1039 ep_addr.index() < self.instance.endpoint_count,
1040 "endpoint_is_stalled index {} out of range",
1041 ep_addr.index()
1042 );
1043
1044 let regs = self.instance.regs;
1045 match ep_addr.direction() {
1046 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
1047 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
1048 }
1049 }
1050
1051 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
1052 trace!("endpoint_set_enabled ep={:?} en={}", ep_addr, enabled);
1053
1054 assert!(
1055 ep_addr.index() < self.instance.endpoint_count,
1056 "endpoint_set_enabled index {} out of range",
1057 ep_addr.index()
1058 );
1059
1060 let regs = self.instance.regs;
1061 let state = self.instance.state;
1062 match ep_addr.direction() {
1063 Direction::Out => {
1064 critical_section::with(|_| {
1065 if !enabled && regs.doepctl(ep_addr.index()).read().epena() {
1067 regs.doepctl(ep_addr.index()).modify(|w| {
1068 w.set_snak(true);
1069 w.set_epdis(true);
1070 })
1071 }
1072
1073 regs.doepctl(ep_addr.index()).modify(|w| {
1074 w.set_usbaep(enabled);
1075 });
1076
1077 if enabled && ep_addr.index() != 0 {
1080 if let Some(ep) = &self.ep_out[ep_addr.index()] {
1081 regs.doeptsiz(ep_addr.index()).modify(|w| {
1082 w.set_xfrsiz(ep.max_packet_size as _);
1083 w.set_pktcnt(1);
1084 });
1085 regs.doepctl(ep_addr.index()).modify(|w| {
1086 w.set_cnak(true);
1087 w.set_epena(true);
1088 });
1089 }
1090 }
1091 });
1092
1093 state.ep_states[ep_addr.index()].out_waker.wake();
1095 }
1096 Direction::In => {
1097 critical_section::with(|_| {
1098 if !enabled && regs.diepctl(ep_addr.index()).read().epena() {
1100 regs.diepctl(ep_addr.index()).modify(|w| {
1101 w.set_snak(true); w.set_epdis(true);
1103 })
1104 }
1105
1106 regs.diepctl(ep_addr.index()).modify(|w| {
1107 w.set_usbaep(enabled);
1108 if enabled {
1112 w.set_snak(true);
1113 }
1114 });
1115
1116 regs.grstctl().write(|w| {
1118 w.set_txfflsh(true);
1119 w.set_txfnum(ep_addr.index() as _);
1120 });
1121 loop {
1122 let x = regs.grstctl().read();
1123 if !x.txfflsh() {
1124 break;
1125 }
1126 }
1127 });
1128
1129 state.ep_states[ep_addr.index()].in_waker.wake();
1131 }
1132 }
1133 }
1134
1135 async fn enable(&mut self) {
1136 trace!("enable");
1137 }
1139
1140 async fn disable(&mut self) {
1141 trace!("disable");
1142
1143 }
1146
1147 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
1148 let r = self.instance.regs;
1149
1150 r.pcgcctl().modify(|w| {
1153 w.set_stppclk(false);
1154 if self.instance.phy_type.high_speed() {
1156 w.set_gatehclk(false);
1157 }
1158 });
1159
1160 r.dctl().modify(|w| w.set_rwusig(true));
1163 embassy_time::Timer::after_millis(10).await;
1164 r.dctl().modify(|w| w.set_rwusig(false));
1165
1166 Ok(())
1167 }
1168}
1169
1170trait Dir {
1172 fn dir() -> Direction;
1174}
1175
1176pub enum In {}
1178impl Dir for In {
1179 fn dir() -> Direction {
1180 Direction::In
1181 }
1182}
1183
1184pub enum Out {}
1186impl Dir for Out {
1187 fn dir() -> Direction {
1188 Direction::Out
1189 }
1190}
1191
1192pub struct Endpoint<'d, D> {
1194 _phantom: PhantomData<D>,
1195 regs: Otg,
1196 info: EndpointInfo,
1197 state: &'d EpState,
1198}
1199
1200impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
1201 fn info(&self) -> &EndpointInfo {
1202 &self.info
1203 }
1204
1205 async fn wait_enabled(&mut self) {
1206 poll_fn(|cx| {
1207 let ep_index = self.info.addr.index();
1208
1209 self.state.in_waker.register(cx.waker());
1210
1211 if self.regs.diepctl(ep_index).read().usbaep() {
1212 Poll::Ready(())
1213 } else {
1214 Poll::Pending
1215 }
1216 })
1217 .await
1218 }
1219}
1220
1221impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> {
1222 fn info(&self) -> &EndpointInfo {
1223 &self.info
1224 }
1225
1226 async fn wait_enabled(&mut self) {
1227 poll_fn(|cx| {
1228 let ep_index = self.info.addr.index();
1229
1230 self.state.out_waker.register(cx.waker());
1231
1232 if self.regs.doepctl(ep_index).read().usbaep() {
1233 Poll::Ready(())
1234 } else {
1235 Poll::Pending
1236 }
1237 })
1238 .await
1239 }
1240}
1241
1242impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1243 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
1244 trace!("read start len={}", buf.len());
1245
1246 poll_fn(|cx| {
1247 let index = self.info.addr.index();
1248 self.state.out_waker.register(cx.waker());
1249
1250 let doepctl = self.regs.doepctl(index).read();
1251 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
1252 if !doepctl.usbaep() {
1253 trace!("read ep={:?} error disabled", self.info.addr);
1254 return Poll::Ready(Err(EndpointError::Disabled));
1255 }
1256
1257 let len = self.state.out_size.load(Ordering::Relaxed);
1258 if len != EP_OUT_BUFFER_EMPTY {
1259 trace!("read ep={:?} done len={}", self.info.addr, len);
1260
1261 if len as usize > buf.len() {
1262 return Poll::Ready(Err(EndpointError::BufferOverflow));
1263 }
1264
1265 let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) };
1267 buf[..len as usize].copy_from_slice(data);
1268
1269 self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1271
1272 critical_section::with(|_| {
1273 self.regs.doeptsiz(index).modify(|w| {
1275 w.set_xfrsiz(self.info.max_packet_size as _);
1276 w.set_pktcnt(1);
1277 });
1278
1279 if self.info.ep_type == EndpointType::Isochronous {
1280 let frame_number = self.regs.dsts().read().fnsof();
1283 let frame_is_odd = frame_number & 0x01 == 1;
1284
1285 self.regs.doepctl(index).modify(|r| {
1286 if frame_is_odd {
1287 r.set_sd0pid_sevnfrm(true);
1288 } else {
1289 r.set_soddfrm(true);
1290 }
1291 });
1292 }
1293
1294 self.regs.doepctl(index).modify(|w| {
1296 w.set_cnak(true);
1297 });
1298 });
1299
1300 Poll::Ready(Ok(len as usize))
1301 } else {
1302 Poll::Pending
1303 }
1304 })
1305 .await
1306 }
1307}
1308
1309impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1310 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
1311 trace!("write ep={:?} data={:?}", self.info.addr, Bytes(buf));
1312
1313 if buf.len() > self.info.max_packet_size as usize {
1314 return Err(EndpointError::BufferOverflow);
1315 }
1316
1317 let index = self.info.addr.index();
1318 poll_fn(|cx| {
1320 self.state.in_waker.register(cx.waker());
1321
1322 let diepctl = self.regs.diepctl(index).read();
1323 let dtxfsts = self.regs.dtxfsts(index).read();
1324 trace!(
1325 "write ep={:?}: diepctl {:08x} ftxfsts {:08x}",
1326 self.info.addr, diepctl.0, dtxfsts.0
1327 );
1328 if !diepctl.usbaep() {
1329 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1330 Poll::Ready(Err(EndpointError::Disabled))
1331 } else if !diepctl.epena() {
1332 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1333 Poll::Ready(Ok(()))
1334 } else {
1335 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1336 Poll::Pending
1337 }
1338 })
1339 .await?;
1340
1341 if buf.len() > 0 {
1342 poll_fn(|cx| {
1343 self.state.in_waker.register(cx.waker());
1344
1345 let size_words = (buf.len() + 3) / 4;
1346
1347 let fifo_space = self.regs.dtxfsts(index).read().ineptfsav() as usize;
1348 if size_words > fifo_space {
1349 critical_section::with(|_| {
1351 self.regs.diepempmsk().modify(|w| {
1352 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1353 });
1354 });
1355
1356 trace!("tx fifo for ep={} full, waiting for txfe", index);
1357
1358 Poll::Pending
1359 } else {
1360 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1361 Poll::Ready(())
1362 }
1363 })
1364 .await
1365 }
1366
1367 critical_section::with(|_| {
1372 self.regs.dieptsiz(index).write(|w| {
1374 w.set_mcnt(1);
1375 w.set_pktcnt(1);
1376 w.set_xfrsiz(buf.len() as _);
1377 });
1378
1379 if self.info.ep_type == EndpointType::Isochronous {
1380 let frame_number = self.regs.dsts().read().fnsof();
1383 let frame_is_odd = frame_number & 0x01 == 1;
1384
1385 self.regs.diepctl(index).modify(|r| {
1386 if frame_is_odd {
1387 r.set_sd0pid_sevnfrm(true);
1388 } else {
1389 r.set_soddfrm_sd1pid(true);
1390 }
1391 });
1392 }
1393
1394 self.regs.diepctl(index).modify(|w| {
1396 w.set_cnak(true);
1397 w.set_epena(true);
1398 });
1399
1400 let fifo = self.regs.fifo(index);
1402 let mut chunks = buf.chunks_exact(4);
1403 for chunk in &mut chunks {
1404 let val = u32::from_ne_bytes(chunk.try_into().unwrap());
1405 fifo.write_value(regs::Fifo(val));
1406 }
1407 let rem = chunks.remainder();
1409 if !rem.is_empty() {
1410 let mut tmp = [0u8; 4];
1411 tmp[0..rem.len()].copy_from_slice(rem);
1412 let tmp = u32::from_ne_bytes(tmp);
1413 fifo.write_value(regs::Fifo(tmp));
1414 }
1415 });
1416
1417 trace!("write done ep={:?}", self.info.addr);
1418
1419 Ok(())
1420 }
1421}
1422
1423pub struct ControlPipe<'d> {
1425 max_packet_size: u16,
1426 regs: Otg,
1427 setup_state: &'d ControlPipeSetupState,
1428 ep_in: Endpoint<'d, In>,
1429 ep_out: Endpoint<'d, Out>,
1430}
1431
1432impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1433 fn max_packet_size(&self) -> usize {
1434 usize::from(self.max_packet_size)
1435 }
1436
1437 async fn setup(&mut self) -> [u8; 8] {
1438 poll_fn(|cx| {
1439 self.ep_out.state.out_waker.register(cx.waker());
1440
1441 if self.setup_state.setup_ready.load(Ordering::Relaxed) {
1442 let mut data = [0; 8];
1443 data[0..4].copy_from_slice(&self.setup_state.setup_data[0].load(Ordering::Relaxed).to_ne_bytes());
1444 data[4..8].copy_from_slice(&self.setup_state.setup_data[1].load(Ordering::Relaxed).to_ne_bytes());
1445 self.setup_state.setup_ready.store(false, Ordering::Release);
1446
1447 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1449 w.set_rxdpid_stupcnt(3);
1450 });
1451
1452 self.regs
1454 .doepctl(self.ep_out.info.addr.index())
1455 .modify(|w| w.set_cnak(true));
1456
1457 trace!("SETUP received: {:?}", Bytes(&data));
1458 Poll::Ready(data)
1459 } else {
1460 trace!("SETUP waiting");
1461 Poll::Pending
1462 }
1463 })
1464 .await
1465 }
1466
1467 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
1468 trace!("control: data_out");
1469 let len = self.ep_out.read(buf).await?;
1470 trace!("control: data_out read: {:?}", Bytes(&buf[..len]));
1471 Ok(len)
1472 }
1473
1474 async fn data_in(&mut self, data: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
1475 trace!("control: data_in write: {:?}", Bytes(data));
1476 self.ep_in.write(data).await?;
1477
1478 if last {
1480 trace!("control: data_in waiting for status");
1481 self.ep_out.read(&mut []).await?;
1482 trace!("control: complete");
1483 }
1484
1485 Ok(())
1486 }
1487
1488 async fn accept(&mut self) {
1489 trace!("control: accept");
1490
1491 self.ep_in.write(&[]).await.ok();
1492
1493 trace!("control: accept OK");
1494 }
1495
1496 async fn reject(&mut self) {
1497 trace!("control: reject");
1498
1499 self.regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1501 w.set_stall(true);
1502 });
1503 self.regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1504 w.set_stall(true);
1505 });
1506 }
1507
1508 async fn accept_set_address(&mut self, addr: u8) {
1509 trace!("setting addr: {}", addr);
1510 critical_section::with(|_| {
1511 self.regs.dcfg().modify(|w| {
1512 w.set_dad(addr);
1513 });
1514 });
1515
1516 self.accept().await
1518 }
1519}
1520
1521fn to_eptyp(ep_type: EndpointType) -> vals::Eptyp {
1523 match ep_type {
1524 EndpointType::Control => vals::Eptyp::CONTROL,
1525 EndpointType::Isochronous => vals::Eptyp::ISOCHRONOUS,
1526 EndpointType::Bulk => vals::Eptyp::BULK,
1527 EndpointType::Interrupt => vals::Eptyp::INTERRUPT,
1528 }
1529}
1530
1531fn ep_fifo_size(eps: &[Option<EndpointData>]) -> u16 {
1533 eps.iter().map(|ep| ep.map(|ep| ep.fifo_size_words).unwrap_or(0)).sum()
1534}
1535
1536fn ep_irq_mask(eps: &[Option<EndpointData>]) -> u16 {
1538 eps.iter().enumerate().fold(
1539 0,
1540 |mask, (index, ep)| {
1541 if ep.is_some() { mask | (1 << index) } else { mask }
1542 },
1543 )
1544}
1545
1546fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1548 match max_packet_size {
1549 8 => 0b11,
1550 16 => 0b10,
1551 32 => 0b01,
1552 64 => 0b00,
1553 other => panic!("Unsupported EP0 size: {}", other),
1554 }
1555}
1556
1557pub struct OtgInstance<'d, const MAX_EP_COUNT: usize> {
1559 pub regs: Otg,
1561 pub state: &'d State<MAX_EP_COUNT>,
1563 pub fifo_depth_words: u16,
1565 pub endpoint_count: usize,
1567 pub phy_type: PhyType,
1569 pub extra_rx_fifo_words: u16,
1571 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8,
1573}