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
26use otg_v1::{Otg, regs, vals};
27
28pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(r: Otg, state: &State<MAX_EP_COUNT>, ep_count: usize) {
30 trace!("irq");
31
32 let ints = r.gintsts().read();
33 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
34 r.gintmsk().write(|w| {
36 w.set_iepint(true);
37 w.set_oepint(true);
38 w.set_rxflvlm(true);
39 });
40 state.bus_waker.wake();
41 }
42
43 while r.gintsts().read().rxflvl() {
45 let status = r.grxstsp().read();
46 trace!("=== status {:08x}", status.0);
47 let ep_num = status.epnum() as usize;
48 let len = status.bcnt() as usize;
49
50 assert!(ep_num < ep_count);
51
52 match status.pktstsd() {
53 vals::Pktstsd::SETUP_DATA_RX => {
54 trace!("SETUP_DATA_RX");
55 assert!(len == 8, "invalid SETUP packet length={}", len);
56 assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
57
58 if r.dieptsiz(ep_num).read().pktcnt() != 0 {
60 r.grstctl().modify(|w| {
61 w.set_txfnum(ep_num as _);
62 w.set_txfflsh(true);
63 });
64 while r.grstctl().read().txfflsh() {}
65 }
66
67 let data = &state.cp_state.setup_data;
68 data[0].store(r.fifo(0).read().data(), Ordering::Relaxed);
69 data[1].store(r.fifo(0).read().data(), Ordering::Relaxed);
70 }
71 vals::Pktstsd::OUT_DATA_RX => {
72 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
73
74 if state.ep_states[ep_num].out_size.load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
75 let buf =
78 unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) };
79
80 let mut chunks = buf.chunks_exact_mut(4);
81 for chunk in &mut chunks {
82 let data = r.fifo(0).read().0;
84 chunk.copy_from_slice(&data.to_ne_bytes());
85 }
86 let rem = chunks.into_remainder();
87 if !rem.is_empty() {
88 let data = r.fifo(0).read().0;
89 rem.copy_from_slice(&data.to_ne_bytes()[0..rem.len()]);
90 }
91
92 state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release);
93 state.ep_states[ep_num].out_waker.wake();
94 } else {
95 error!("ep_out buffer overflow index={}", ep_num);
96
97 let len_words = (len + 3) / 4;
99 for _ in 0..len_words {
100 r.fifo(0).read().data();
101 }
102 }
103 }
104 vals::Pktstsd::OUT_DATA_DONE => {
105 trace!("OUT_DATA_DONE ep={}", ep_num);
106 }
107 vals::Pktstsd::SETUP_DATA_DONE => {
108 trace!("SETUP_DATA_DONE ep={}", ep_num);
109 }
110 x => trace!("unknown PKTSTS: {}", x.to_bits()),
111 }
112 }
113
114 if ints.iepint() {
116 let mut ep_mask = r.daint().read().iepint();
117 let mut ep_num = 0;
118
119 while ep_mask != 0 {
121 if ep_mask & 1 != 0 {
122 let ep_ints = r.diepint(ep_num).read();
123
124 r.diepint(ep_num).write_value(ep_ints);
126
127 if ep_ints.txfe() {
129 critical_section::with(|_| {
130 r.diepempmsk().modify(|w| {
131 w.set_ineptxfem(w.ineptxfem() & !(1 << ep_num));
132 });
133 });
134 }
135
136 state.ep_states[ep_num].in_waker.wake();
137 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0);
138 }
139
140 ep_mask >>= 1;
141 ep_num += 1;
142 }
143 }
144
145 if ints.oepint() {
147 trace!("oepint");
148 let mut ep_mask = r.daint().read().oepint();
149 let mut ep_num = 0;
150
151 while ep_mask != 0 {
153 if ep_mask & 1 != 0 {
154 let ep_ints = r.doepint(ep_num).read();
155 r.doepint(ep_num).write_value(ep_ints);
157
158 if ep_ints.stup() {
159 state.cp_state.setup_ready.store(true, Ordering::Release);
160 }
161 state.ep_states[ep_num].out_waker.wake();
162 trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
163 }
164
165 ep_mask >>= 1;
166 ep_num += 1;
167 }
168 }
169
170 if ints.eopf() {
171 let frame_number = r.dsts().read().fnsof();
172 let frame_is_odd = frame_number & 0x01 == 1;
173
174 for ep_num in (0..ep_count).into_iter().filter(|ep_num| {
177 let diepctl = r.diepctl(*ep_num).read();
178 diepctl.eptyp() == vals::Eptyp::ISOCHRONOUS
180 && diepctl.epena()
182 && diepctl.eonum_dpid() == frame_is_odd
184 }) {
185 trace!("Unsent message at EOF for ep: {}, frame: {}", ep_num, frame_number);
186
187 let ep_diepctl = r.diepctl(ep_num);
188 let ep_diepint = r.diepint(ep_num);
189
190 ep_diepctl.modify(|m| m.set_snak(true));
192 while !ep_diepint.read().inepne() {}
193
194 ep_diepctl.modify(|m| {
196 m.set_snak(true);
197 m.set_epdis(true);
198 });
199 while !ep_diepint.read().epdisd() {}
200 ep_diepint.modify(|m| m.set_epdisd(true));
201
202 ep_diepctl.modify(|r| {
204 if frame_is_odd {
205 r.set_sd0pid_sevnfrm(true);
206 } else {
207 r.set_sd1pid_soddfrm(true);
208 }
209 });
210
211 ep_diepctl.modify(|w| {
213 w.set_cnak(true);
214 w.set_epena(true);
215 });
216 }
217 }
218}
219
220#[derive(Copy, Clone, Debug, Eq, PartialEq)]
222pub enum PhyType {
223 InternalFullSpeed,
227 InternalHighSpeed,
231 ExternalFullSpeed,
233 ExternalHighSpeed,
235}
236
237impl PhyType {
238 pub fn internal(&self) -> bool {
240 match self {
241 PhyType::InternalFullSpeed | PhyType::InternalHighSpeed => true,
242 PhyType::ExternalHighSpeed | PhyType::ExternalFullSpeed => false,
243 }
244 }
245
246 pub fn high_speed(&self) -> bool {
248 match self {
249 PhyType::InternalFullSpeed | PhyType::ExternalFullSpeed => false,
250 PhyType::ExternalHighSpeed | PhyType::InternalHighSpeed => true,
251 }
252 }
253
254 fn to_dspd(&self) -> vals::Dspd {
255 match self {
256 PhyType::InternalFullSpeed => vals::Dspd::FULL_SPEED_INTERNAL,
257 PhyType::InternalHighSpeed => vals::Dspd::HIGH_SPEED,
258 PhyType::ExternalFullSpeed => vals::Dspd::FULL_SPEED_EXTERNAL,
259 PhyType::ExternalHighSpeed => vals::Dspd::HIGH_SPEED,
260 }
261 }
262}
263
264const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
266
267struct EpState {
268 in_waker: AtomicWaker,
269 out_waker: AtomicWaker,
270 out_buffer: UnsafeCell<*mut u8>,
273 out_size: AtomicU16,
274}
275
276unsafe impl Send for EpState {}
280unsafe impl Sync for EpState {}
281
282struct ControlPipeSetupState {
283 setup_data: [AtomicU32; 2],
285 setup_ready: AtomicBool,
286}
287
288pub struct State<const EP_COUNT: usize> {
290 cp_state: ControlPipeSetupState,
291 ep_states: [EpState; EP_COUNT],
292 bus_waker: AtomicWaker,
293}
294
295unsafe impl<const EP_COUNT: usize> Send for State<EP_COUNT> {}
296unsafe impl<const EP_COUNT: usize> Sync for State<EP_COUNT> {}
297
298impl<const EP_COUNT: usize> State<EP_COUNT> {
299 pub const fn new() -> Self {
301 Self {
302 cp_state: ControlPipeSetupState {
303 setup_data: [const { AtomicU32::new(0) }; 2],
304 setup_ready: AtomicBool::new(false),
305 },
306 ep_states: [const {
307 EpState {
308 in_waker: AtomicWaker::new(),
309 out_waker: AtomicWaker::new(),
310 out_buffer: UnsafeCell::new(0 as _),
311 out_size: AtomicU16::new(EP_OUT_BUFFER_EMPTY),
312 }
313 }; EP_COUNT],
314 bus_waker: AtomicWaker::new(),
315 }
316 }
317}
318
319#[derive(Debug, Clone, Copy)]
320struct EndpointData {
321 ep_type: EndpointType,
322 max_packet_size: u16,
323 fifo_size_words: u16,
324}
325
326#[non_exhaustive]
328#[derive(Clone, Copy, PartialEq, Eq, Debug)]
329pub struct Config {
330 pub vbus_detection: bool,
345
346 pub xcvrdly: bool,
353}
354
355impl Default for Config {
356 fn default() -> Self {
357 Self {
358 vbus_detection: false,
359 xcvrdly: false,
360 }
361 }
362}
363
364pub struct Driver<'d, const MAX_EP_COUNT: usize> {
366 config: Config,
367 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
368 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
369 ep_out_buffer: &'d mut [u8],
370 ep_out_buffer_offset: usize,
371 instance: OtgInstance<'d, MAX_EP_COUNT>,
372}
373
374impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
375 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d, MAX_EP_COUNT>, config: Config) -> Self {
385 Self {
386 config,
387 ep_in: [None; MAX_EP_COUNT],
388 ep_out: [None; MAX_EP_COUNT],
389 ep_out_buffer,
390 ep_out_buffer_offset: 0,
391 instance,
392 }
393 }
394
395 fn allocated_fifo_words(&self) -> u16 {
397 self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out) + ep_fifo_size(&self.ep_in)
398 }
399
400 fn alloc_endpoint<D: Dir>(
402 &mut self,
403 ep_type: EndpointType,
404 ep_addr: Option<EndpointAddress>,
405 max_packet_size: u16,
406 interval_ms: u8,
407 ) -> Result<Endpoint<'d, D>, EndpointAllocError> {
408 trace!(
409 "allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
410 ep_type,
411 max_packet_size,
412 interval_ms,
413 D::dir()
414 );
415
416 if D::dir() == Direction::Out {
417 if self.ep_out_buffer_offset + max_packet_size as usize > self.ep_out_buffer.len() {
418 error!("Not enough endpoint out buffer capacity");
419 return Err(EndpointAllocError);
420 }
421 };
422
423 let fifo_size_words = match D::dir() {
424 Direction::Out => (max_packet_size + 3) / 4,
425 Direction::In => u16::max((max_packet_size + 3) / 4, 16),
427 };
428
429 if fifo_size_words + self.allocated_fifo_words() > self.instance.fifo_depth_words {
430 error!("Not enough FIFO capacity");
431 return Err(EndpointAllocError);
432 }
433
434 let eps = match D::dir() {
435 Direction::Out => &mut self.ep_out[..self.instance.endpoint_count],
436 Direction::In => &mut self.ep_in[..self.instance.endpoint_count],
437 };
438
439 let slot = if let Some(addr) = ep_addr {
441 let requested_index = addr.index();
443 if requested_index >= self.instance.endpoint_count {
444 return Err(EndpointAllocError);
445 }
446 if requested_index == 0 && ep_type != EndpointType::Control {
447 return Err(EndpointAllocError); }
449 if eps[requested_index].is_some() {
450 return Err(EndpointAllocError); }
452 Some((requested_index, &mut eps[requested_index]))
453 } else {
454 eps.iter_mut().enumerate().find(|(i, ep)| {
456 if *i == 0 && ep_type != EndpointType::Control {
457 false
459 } else {
460 ep.is_none()
461 }
462 })
463 };
464
465 let index = match slot {
466 Some((index, ep)) => {
467 *ep = Some(EndpointData {
468 ep_type,
469 max_packet_size,
470 fifo_size_words,
471 });
472 index
473 }
474 None => {
475 error!("No free endpoints available");
476 return Err(EndpointAllocError);
477 }
478 };
479
480 trace!(" index={}", index);
481
482 let state = &self.instance.state.ep_states[index];
483 if D::dir() == Direction::Out {
484 unsafe {
486 *state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
487 }
488 self.ep_out_buffer_offset += max_packet_size as usize;
489 }
490
491 Ok(Endpoint {
492 _phantom: PhantomData,
493 regs: self.instance.regs,
494 state,
495 info: EndpointInfo {
496 addr: EndpointAddress::from_parts(index, D::dir()),
497 ep_type,
498 max_packet_size,
499 interval_ms,
500 },
501 })
502 }
503}
504
505impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d, MAX_EP_COUNT> {
506 type EndpointOut = Endpoint<'d, Out>;
507 type EndpointIn = Endpoint<'d, In>;
508 type ControlPipe = ControlPipe<'d>;
509 type Bus = Bus<'d, MAX_EP_COUNT>;
510
511 fn alloc_endpoint_in(
512 &mut self,
513 ep_type: EndpointType,
514 ep_addr: Option<EndpointAddress>,
515 max_packet_size: u16,
516 interval_ms: u8,
517 ) -> Result<Self::EndpointIn, EndpointAllocError> {
518 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
519 }
520
521 fn alloc_endpoint_out(
522 &mut self,
523 ep_type: EndpointType,
524 ep_addr: Option<EndpointAddress>,
525 max_packet_size: u16,
526 interval_ms: u8,
527 ) -> Result<Self::EndpointOut, EndpointAllocError> {
528 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
529 }
530
531 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
532 let ep_out = self
533 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
534 .unwrap();
535 let ep_in = self
536 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
537 .unwrap();
538 assert_eq!(ep_out.info.addr.index(), 0);
539 assert_eq!(ep_in.info.addr.index(), 0);
540
541 trace!("start");
542
543 let regs = self.instance.regs;
544 let cp_setup_state = &self.instance.state.cp_state;
545 (
546 Bus {
547 config: self.config,
548 ep_in: self.ep_in,
549 ep_out: self.ep_out,
550 inited: false,
551 instance: self.instance,
552 },
553 ControlPipe {
554 max_packet_size: control_max_packet_size,
555 setup_state: cp_setup_state,
556 ep_out,
557 ep_in,
558 regs,
559 },
560 )
561 }
562}
563
564pub struct Bus<'d, const MAX_EP_COUNT: usize> {
566 config: Config,
567 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
568 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
569 instance: OtgInstance<'d, MAX_EP_COUNT>,
570 inited: bool,
571}
572
573impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
574 fn restore_irqs(&mut self) {
575 self.instance.regs.gintmsk().write(|w| {
576 w.set_usbrst(true);
577 w.set_enumdnem(true);
578 w.set_usbsuspm(true);
579 w.set_wuim(true);
580 w.set_iepint(true);
581 w.set_oepint(true);
582 w.set_rxflvlm(true);
583 w.set_srqim(true);
584 w.set_otgint(true);
585 });
586 }
587
588 pub fn phy_type(&self) -> PhyType {
590 self.instance.phy_type
591 }
592
593 pub fn configure_as_device(&mut self) {
595 let r = self.instance.regs;
596 let phy_type = self.instance.phy_type;
597 r.gusbcfg().write(|w| {
598 w.set_fdmod(true);
600 w.set_physel(phy_type.internal() && !phy_type.high_speed());
602 });
603 }
604
605 pub fn config_v1(&mut self) {
608 let r = self.instance.regs;
609 let phy_type = self.instance.phy_type;
610 assert!(phy_type != PhyType::InternalHighSpeed);
611
612 r.gccfg_v1().modify(|w| {
613 w.set_pwrdwn(phy_type.internal());
615 });
616
617 r.gccfg_v1().modify(|w| {
619 w.set_novbussens(!self.config.vbus_detection);
620 w.set_vbusasen(false);
621 w.set_vbusbsen(self.config.vbus_detection);
622 w.set_sofouten(false);
623 });
624 }
625
626 pub fn config_v2v3(&mut self) {
629 let r = self.instance.regs;
630 let phy_type = self.instance.phy_type;
631
632 r.gccfg_v2().modify(|w| {
634 w.set_pwrdwn(phy_type.internal() && !phy_type.high_speed());
636 w.set_phyhsen(phy_type.internal() && phy_type.high_speed());
637 });
638
639 r.gccfg_v2().modify(|w| {
640 w.set_vbden(self.config.vbus_detection);
641 });
642
643 r.gotgctl().modify(|w| {
645 w.set_bvaloen(!self.config.vbus_detection);
646 w.set_bvaloval(true);
647 });
648 }
649
650 pub fn config_v5(&mut self) {
653 let r = self.instance.regs;
654 let phy_type = self.instance.phy_type;
655
656 if phy_type == PhyType::InternalHighSpeed {
657 r.gccfg_v3().modify(|w| {
658 w.set_vbvaloven(!self.config.vbus_detection);
659 w.set_vbvaloval(!self.config.vbus_detection);
660 w.set_vbden(self.config.vbus_detection);
661 });
662 } else {
663 r.gotgctl().modify(|w| {
664 w.set_bvaloen(!self.config.vbus_detection);
665 w.set_bvaloval(!self.config.vbus_detection);
666 });
667 r.gccfg_v3().modify(|w| {
668 w.set_vbden(self.config.vbus_detection);
669 });
670 }
671 }
672
673 fn init(&mut self) {
674 let r = self.instance.regs;
675 let phy_type = self.instance.phy_type;
676
677 r.dctl().write(|w| w.set_sdis(true));
679
680 r.dcfg().write(|w| {
682 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
683 w.set_dspd(phy_type.to_dspd());
684 if self.config.xcvrdly {
685 w.set_xcvrdly(true);
686 }
687 });
688
689 r.diepmsk().write(|w| {
691 w.set_xfrcm(true);
692 });
693
694 r.doepmsk().write(|w| {
696 w.set_stupm(true);
697 });
698
699 self.restore_irqs();
701 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
702
703 r.gahbcfg().write(|w| {
705 w.set_gint(true); });
707
708 r.dctl().write(|w| w.set_sdis(false));
710 }
711
712 fn init_fifo(&mut self) {
713 trace!("init_fifo");
714
715 let regs = self.instance.regs;
716 critical_section::with(|_| {
720 let rx_fifo_size_words = self.instance.extra_rx_fifo_words + ep_fifo_size(&self.ep_out);
722 trace!("configuring rx fifo size={}", rx_fifo_size_words);
723
724 regs.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
725
726 let mut fifo_top = rx_fifo_size_words;
728 for i in 0..self.instance.endpoint_count {
729 if let Some(ep) = self.ep_in[i] {
730 trace!(
731 "configuring tx fifo ep={}, offset={}, size={}",
732 i, fifo_top, ep.fifo_size_words
733 );
734
735 let dieptxf = if i == 0 { regs.dieptxf0() } else { regs.dieptxf(i - 1) };
736
737 dieptxf.write(|w| {
738 w.set_fd(ep.fifo_size_words);
739 w.set_sa(fifo_top);
740 });
741
742 fifo_top += ep.fifo_size_words;
743 }
744 }
745
746 assert!(
747 fifo_top <= self.instance.fifo_depth_words,
748 "FIFO allocations exceeded maximum capacity"
749 );
750
751 regs.grstctl().write(|w| {
753 w.set_rxfflsh(true);
754 w.set_txfflsh(true);
755 w.set_txfnum(0x10);
756 });
757 });
758
759 loop {
760 let x = regs.grstctl().read();
761 if !x.rxfflsh() && !x.txfflsh() {
762 break;
763 }
764 }
765 }
766
767 fn configure_endpoints(&mut self) {
768 trace!("configure_endpoints");
769
770 let regs = self.instance.regs;
771
772 for (index, ep) in self.ep_in.iter().enumerate() {
774 if let Some(ep) = ep {
775 critical_section::with(|_| {
776 regs.diepctl(index).write(|w| {
777 if index == 0 {
778 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
779 } else {
780 w.set_mpsiz(ep.max_packet_size);
781 w.set_eptyp(to_eptyp(ep.ep_type));
782 w.set_sd0pid_sevnfrm(true);
783 w.set_txfnum(index as _);
784 w.set_snak(true);
785 }
786 });
787 });
788 }
789 }
790
791 for (index, ep) in self.ep_out.iter().enumerate() {
793 if let Some(ep) = ep {
794 critical_section::with(|_| {
795 regs.doepctl(index).write(|w| {
796 if index == 0 {
797 w.set_mpsiz(ep0_mpsiz(ep.max_packet_size));
798 } else {
799 w.set_mpsiz(ep.max_packet_size);
800 w.set_eptyp(to_eptyp(ep.ep_type));
801 w.set_sd0pid_sevnfrm(true);
802 }
803 });
804
805 regs.doeptsiz(index).modify(|w| {
806 w.set_xfrsiz(ep.max_packet_size as _);
807 if index == 0 {
808 w.set_rxdpid_stupcnt(3);
809 } else {
810 w.set_pktcnt(1);
811 }
812 });
813 });
814 }
815 }
816
817 regs.daintmsk().modify(|w| {
819 w.set_iepm(ep_irq_mask(&self.ep_in));
820 w.set_oepm(ep_irq_mask(&self.ep_out));
821 });
822 }
823
824 fn disable_all_endpoints(&mut self) {
825 for i in 0..self.instance.endpoint_count {
826 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
827 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
828 }
829 }
830}
831
832impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Bus for Bus<'d, MAX_EP_COUNT> {
833 async fn poll(&mut self) -> Event {
834 poll_fn(move |cx| {
835 if !self.inited {
836 self.init();
837 self.inited = true;
838
839 if !self.config.vbus_detection {
841 return Poll::Ready(Event::PowerDetected);
842 }
843 }
844
845 let regs = self.instance.regs;
846 self.instance.state.bus_waker.register(cx.waker());
847
848 let ints = regs.gintsts().read();
849
850 if ints.srqint() {
851 trace!("vbus detected");
852
853 regs.gintsts().write(|w| w.set_srqint(true)); self.restore_irqs();
855
856 if self.config.vbus_detection {
857 return Poll::Ready(Event::PowerDetected);
858 }
859 }
860
861 if ints.otgint() {
862 let otgints = regs.gotgint().read();
863 regs.gotgint().write_value(otgints); self.restore_irqs();
865
866 if otgints.sedet() {
867 trace!("vbus removed");
868 if self.config.vbus_detection {
869 self.disable_all_endpoints();
870 return Poll::Ready(Event::PowerRemoved);
871 }
872 }
873 }
874
875 if ints.usbrst() {
876 trace!("reset");
877
878 self.init_fifo();
879 self.configure_endpoints();
880
881 critical_section::with(|_| {
883 regs.dcfg().modify(|w| {
884 w.set_dad(0);
885 });
886 });
887
888 regs.gintsts().write(|w| w.set_usbrst(true)); self.restore_irqs();
890 }
891
892 if ints.enumdne() {
893 trace!("enumdne");
894
895 let speed = regs.dsts().read().enumspd();
896 let trdt = (self.instance.calculate_trdt_fn)(speed);
897 trace!(" speed={} trdt={}", speed.to_bits(), trdt);
898 regs.gusbcfg().modify(|w| w.set_trdt(trdt));
899
900 regs.gintsts().write(|w| w.set_enumdne(true)); self.restore_irqs();
902
903 return Poll::Ready(Event::Reset);
904 }
905
906 if ints.usbsusp() {
907 trace!("suspend");
908 regs.gintsts().write(|w| w.set_usbsusp(true)); self.restore_irqs();
910 return Poll::Ready(Event::Suspend);
911 }
912
913 if ints.wkupint() {
914 trace!("resume");
915 regs.gintsts().write(|w| w.set_wkupint(true)); self.restore_irqs();
917 return Poll::Ready(Event::Resume);
918 }
919
920 Poll::Pending
921 })
922 .await
923 }
924
925 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
926 trace!("endpoint_set_stalled ep={:?} en={}", ep_addr, stalled);
927
928 assert!(
929 ep_addr.index() < self.instance.endpoint_count,
930 "endpoint_set_stalled index {} out of range",
931 ep_addr.index()
932 );
933
934 let regs = self.instance.regs;
935 let state = self.instance.state;
936 match ep_addr.direction() {
937 Direction::Out => {
938 critical_section::with(|_| {
939 regs.doepctl(ep_addr.index()).modify(|w| {
940 w.set_stall(stalled);
941 });
942 });
943
944 state.ep_states[ep_addr.index()].out_waker.wake();
945 }
946 Direction::In => {
947 critical_section::with(|_| {
948 regs.diepctl(ep_addr.index()).modify(|w| {
949 w.set_stall(stalled);
950 });
951 });
952
953 state.ep_states[ep_addr.index()].in_waker.wake();
954 }
955 }
956 }
957
958 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
959 assert!(
960 ep_addr.index() < self.instance.endpoint_count,
961 "endpoint_is_stalled index {} out of range",
962 ep_addr.index()
963 );
964
965 let regs = self.instance.regs;
966 match ep_addr.direction() {
967 Direction::Out => regs.doepctl(ep_addr.index()).read().stall(),
968 Direction::In => regs.diepctl(ep_addr.index()).read().stall(),
969 }
970 }
971
972 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
973 trace!("endpoint_set_enabled ep={:?} en={}", ep_addr, enabled);
974
975 assert!(
976 ep_addr.index() < self.instance.endpoint_count,
977 "endpoint_set_enabled index {} out of range",
978 ep_addr.index()
979 );
980
981 let regs = self.instance.regs;
982 let state = self.instance.state;
983 match ep_addr.direction() {
984 Direction::Out => {
985 critical_section::with(|_| {
986 if !enabled && regs.doepctl(ep_addr.index()).read().epena() {
988 regs.doepctl(ep_addr.index()).modify(|w| {
989 w.set_snak(true);
990 w.set_epdis(true);
991 })
992 }
993
994 regs.doepctl(ep_addr.index()).modify(|w| {
995 w.set_usbaep(enabled);
996 });
997 });
998
999 state.ep_states[ep_addr.index()].out_waker.wake();
1001 }
1002 Direction::In => {
1003 critical_section::with(|_| {
1004 if !enabled && regs.diepctl(ep_addr.index()).read().epena() {
1006 regs.diepctl(ep_addr.index()).modify(|w| {
1007 w.set_snak(true); w.set_epdis(true);
1009 })
1010 }
1011
1012 regs.diepctl(ep_addr.index()).modify(|w| {
1013 w.set_usbaep(enabled);
1014 w.set_cnak(enabled); });
1016
1017 regs.grstctl().write(|w| {
1019 w.set_txfflsh(true);
1020 w.set_txfnum(ep_addr.index() as _);
1021 });
1022 loop {
1023 let x = regs.grstctl().read();
1024 if !x.txfflsh() {
1025 break;
1026 }
1027 }
1028 });
1029
1030 state.ep_states[ep_addr.index()].in_waker.wake();
1032 }
1033 }
1034 }
1035
1036 async fn enable(&mut self) {
1037 trace!("enable");
1038 }
1040
1041 async fn disable(&mut self) {
1042 trace!("disable");
1043
1044 }
1047
1048 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
1049 Err(Unsupported)
1050 }
1051}
1052
1053trait Dir {
1055 fn dir() -> Direction;
1057}
1058
1059pub enum In {}
1061impl Dir for In {
1062 fn dir() -> Direction {
1063 Direction::In
1064 }
1065}
1066
1067pub enum Out {}
1069impl Dir for Out {
1070 fn dir() -> Direction {
1071 Direction::Out
1072 }
1073}
1074
1075pub struct Endpoint<'d, D> {
1077 _phantom: PhantomData<D>,
1078 regs: Otg,
1079 info: EndpointInfo,
1080 state: &'d EpState,
1081}
1082
1083impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
1084 fn info(&self) -> &EndpointInfo {
1085 &self.info
1086 }
1087
1088 async fn wait_enabled(&mut self) {
1089 poll_fn(|cx| {
1090 let ep_index = self.info.addr.index();
1091
1092 self.state.in_waker.register(cx.waker());
1093
1094 if self.regs.diepctl(ep_index).read().usbaep() {
1095 Poll::Ready(())
1096 } else {
1097 Poll::Pending
1098 }
1099 })
1100 .await
1101 }
1102}
1103
1104impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> {
1105 fn info(&self) -> &EndpointInfo {
1106 &self.info
1107 }
1108
1109 async fn wait_enabled(&mut self) {
1110 poll_fn(|cx| {
1111 let ep_index = self.info.addr.index();
1112
1113 self.state.out_waker.register(cx.waker());
1114
1115 if self.regs.doepctl(ep_index).read().usbaep() {
1116 Poll::Ready(())
1117 } else {
1118 Poll::Pending
1119 }
1120 })
1121 .await
1122 }
1123}
1124
1125impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1126 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
1127 trace!("read start len={}", buf.len());
1128
1129 poll_fn(|cx| {
1130 let index = self.info.addr.index();
1131 self.state.out_waker.register(cx.waker());
1132
1133 let doepctl = self.regs.doepctl(index).read();
1134 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
1135 if !doepctl.usbaep() {
1136 trace!("read ep={:?} error disabled", self.info.addr);
1137 return Poll::Ready(Err(EndpointError::Disabled));
1138 }
1139
1140 let len = self.state.out_size.load(Ordering::Relaxed);
1141 if len != EP_OUT_BUFFER_EMPTY {
1142 trace!("read ep={:?} done len={}", self.info.addr, len);
1143
1144 if len as usize > buf.len() {
1145 return Poll::Ready(Err(EndpointError::BufferOverflow));
1146 }
1147
1148 let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) };
1150 buf[..len as usize].copy_from_slice(data);
1151
1152 self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1154
1155 critical_section::with(|_| {
1156 self.regs.doeptsiz(index).modify(|w| {
1158 w.set_xfrsiz(self.info.max_packet_size as _);
1159 w.set_pktcnt(1);
1160 });
1161
1162 if self.info.ep_type == EndpointType::Isochronous {
1163 let frame_number = self.regs.dsts().read().fnsof();
1166 let frame_is_odd = frame_number & 0x01 == 1;
1167
1168 self.regs.doepctl(index).modify(|r| {
1169 if frame_is_odd {
1170 r.set_sd0pid_sevnfrm(true);
1171 } else {
1172 r.set_sd1pid_soddfrm(true);
1173 }
1174 });
1175 }
1176
1177 self.regs.doepctl(index).modify(|w| {
1179 w.set_cnak(true);
1180 });
1181 });
1182
1183 Poll::Ready(Ok(len as usize))
1184 } else {
1185 Poll::Pending
1186 }
1187 })
1188 .await
1189 }
1190}
1191
1192impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1193 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
1194 trace!("write ep={:?} data={:?}", self.info.addr, Bytes(buf));
1195
1196 if buf.len() > self.info.max_packet_size as usize {
1197 return Err(EndpointError::BufferOverflow);
1198 }
1199
1200 let index = self.info.addr.index();
1201 poll_fn(|cx| {
1203 self.state.in_waker.register(cx.waker());
1204
1205 let diepctl = self.regs.diepctl(index).read();
1206 let dtxfsts = self.regs.dtxfsts(index).read();
1207 trace!(
1208 "write ep={:?}: diepctl {:08x} ftxfsts {:08x}",
1209 self.info.addr, diepctl.0, dtxfsts.0
1210 );
1211 if !diepctl.usbaep() {
1212 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1213 Poll::Ready(Err(EndpointError::Disabled))
1214 } else if !diepctl.epena() {
1215 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1216 Poll::Ready(Ok(()))
1217 } else {
1218 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1219 Poll::Pending
1220 }
1221 })
1222 .await?;
1223
1224 if buf.len() > 0 {
1225 poll_fn(|cx| {
1226 self.state.in_waker.register(cx.waker());
1227
1228 let size_words = (buf.len() + 3) / 4;
1229
1230 let fifo_space = self.regs.dtxfsts(index).read().ineptfsav() as usize;
1231 if size_words > fifo_space {
1232 critical_section::with(|_| {
1234 self.regs.diepempmsk().modify(|w| {
1235 w.set_ineptxfem(w.ineptxfem() | (1 << index));
1236 });
1237 });
1238
1239 trace!("tx fifo for ep={} full, waiting for txfe", index);
1240
1241 Poll::Pending
1242 } else {
1243 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1244 Poll::Ready(())
1245 }
1246 })
1247 .await
1248 }
1249
1250 critical_section::with(|_| {
1255 self.regs.dieptsiz(index).write(|w| {
1257 w.set_mcnt(1);
1258 w.set_pktcnt(1);
1259 w.set_xfrsiz(buf.len() as _);
1260 });
1261
1262 if self.info.ep_type == EndpointType::Isochronous {
1263 let frame_number = self.regs.dsts().read().fnsof();
1266 let frame_is_odd = frame_number & 0x01 == 1;
1267
1268 self.regs.diepctl(index).modify(|r| {
1269 if frame_is_odd {
1270 r.set_sd0pid_sevnfrm(true);
1271 } else {
1272 r.set_sd1pid_soddfrm(true);
1273 }
1274 });
1275 }
1276
1277 self.regs.diepctl(index).modify(|w| {
1279 w.set_cnak(true);
1280 w.set_epena(true);
1281 });
1282
1283 let fifo = self.regs.fifo(index);
1285 let mut chunks = buf.chunks_exact(4);
1286 for chunk in &mut chunks {
1287 let val = u32::from_ne_bytes(chunk.try_into().unwrap());
1288 fifo.write_value(regs::Fifo(val));
1289 }
1290 let rem = chunks.remainder();
1292 if !rem.is_empty() {
1293 let mut tmp = [0u8; 4];
1294 tmp[0..rem.len()].copy_from_slice(rem);
1295 let tmp = u32::from_ne_bytes(tmp);
1296 fifo.write_value(regs::Fifo(tmp));
1297 }
1298 });
1299
1300 trace!("write done ep={:?}", self.info.addr);
1301
1302 Ok(())
1303 }
1304}
1305
1306pub struct ControlPipe<'d> {
1308 max_packet_size: u16,
1309 regs: Otg,
1310 setup_state: &'d ControlPipeSetupState,
1311 ep_in: Endpoint<'d, In>,
1312 ep_out: Endpoint<'d, Out>,
1313}
1314
1315impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1316 fn max_packet_size(&self) -> usize {
1317 usize::from(self.max_packet_size)
1318 }
1319
1320 async fn setup(&mut self) -> [u8; 8] {
1321 poll_fn(|cx| {
1322 self.ep_out.state.out_waker.register(cx.waker());
1323
1324 if self.setup_state.setup_ready.load(Ordering::Relaxed) {
1325 let mut data = [0; 8];
1326 data[0..4].copy_from_slice(&self.setup_state.setup_data[0].load(Ordering::Relaxed).to_ne_bytes());
1327 data[4..8].copy_from_slice(&self.setup_state.setup_data[1].load(Ordering::Relaxed).to_ne_bytes());
1328 self.setup_state.setup_ready.store(false, Ordering::Release);
1329
1330 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1332 w.set_rxdpid_stupcnt(3);
1333 });
1334
1335 self.regs
1337 .doepctl(self.ep_out.info.addr.index())
1338 .modify(|w| w.set_cnak(true));
1339
1340 trace!("SETUP received: {:?}", Bytes(&data));
1341 Poll::Ready(data)
1342 } else {
1343 trace!("SETUP waiting");
1344 Poll::Pending
1345 }
1346 })
1347 .await
1348 }
1349
1350 async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
1351 trace!("control: data_out");
1352 let len = self.ep_out.read(buf).await?;
1353 trace!("control: data_out read: {:?}", Bytes(&buf[..len]));
1354 Ok(len)
1355 }
1356
1357 async fn data_in(&mut self, data: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
1358 trace!("control: data_in write: {:?}", Bytes(data));
1359 self.ep_in.write(data).await?;
1360
1361 if last {
1363 trace!("control: data_in waiting for status");
1364 self.ep_out.read(&mut []).await?;
1365 trace!("control: complete");
1366 }
1367
1368 Ok(())
1369 }
1370
1371 async fn accept(&mut self) {
1372 trace!("control: accept");
1373
1374 self.ep_in.write(&[]).await.ok();
1375
1376 trace!("control: accept OK");
1377 }
1378
1379 async fn reject(&mut self) {
1380 trace!("control: reject");
1381
1382 self.regs.diepctl(self.ep_in.info.addr.index()).modify(|w| {
1384 w.set_stall(true);
1385 });
1386 self.regs.doepctl(self.ep_out.info.addr.index()).modify(|w| {
1387 w.set_stall(true);
1388 });
1389 }
1390
1391 async fn accept_set_address(&mut self, addr: u8) {
1392 trace!("setting addr: {}", addr);
1393 critical_section::with(|_| {
1394 self.regs.dcfg().modify(|w| {
1395 w.set_dad(addr);
1396 });
1397 });
1398
1399 self.accept().await
1401 }
1402}
1403
1404fn to_eptyp(ep_type: EndpointType) -> vals::Eptyp {
1406 match ep_type {
1407 EndpointType::Control => vals::Eptyp::CONTROL,
1408 EndpointType::Isochronous => vals::Eptyp::ISOCHRONOUS,
1409 EndpointType::Bulk => vals::Eptyp::BULK,
1410 EndpointType::Interrupt => vals::Eptyp::INTERRUPT,
1411 }
1412}
1413
1414fn ep_fifo_size(eps: &[Option<EndpointData>]) -> u16 {
1416 eps.iter().map(|ep| ep.map(|ep| ep.fifo_size_words).unwrap_or(0)).sum()
1417}
1418
1419fn ep_irq_mask(eps: &[Option<EndpointData>]) -> u16 {
1421 eps.iter().enumerate().fold(
1422 0,
1423 |mask, (index, ep)| {
1424 if ep.is_some() { mask | (1 << index) } else { mask }
1425 },
1426 )
1427}
1428
1429fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1431 match max_packet_size {
1432 8 => 0b11,
1433 16 => 0b10,
1434 32 => 0b01,
1435 64 => 0b00,
1436 other => panic!("Unsupported EP0 size: {}", other),
1437 }
1438}
1439
1440pub struct OtgInstance<'d, const MAX_EP_COUNT: usize> {
1442 pub regs: Otg,
1444 pub state: &'d State<MAX_EP_COUNT>,
1446 pub fifo_depth_words: u16,
1448 pub endpoint_count: usize,
1450 pub phy_type: PhyType,
1452 pub extra_rx_fifo_words: u16,
1454 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8,
1456}