embassy_nrf/usb/
mod.rs

1//! Universal Serial Bus (USB) driver.
2
3#![macro_use]
4
5pub mod vbus_detect;
6
7use core::future::{poll_fn, Future};
8use core::marker::PhantomData;
9use core::mem::MaybeUninit;
10use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
11use core::task::Poll;
12
13use cortex_m::peripheral::NVIC;
14use embassy_hal_internal::{Peri, PeripheralType};
15use embassy_sync::waitqueue::AtomicWaker;
16use embassy_usb_driver as driver;
17use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
18
19use self::vbus_detect::VbusDetect;
20use crate::interrupt::typelevel::Interrupt;
21use crate::pac::usbd::vals;
22use crate::util::slice_in_ram;
23use crate::{interrupt, pac};
24
25static BUS_WAKER: AtomicWaker = AtomicWaker::new();
26static EP0_WAKER: AtomicWaker = AtomicWaker::new();
27static EP_IN_WAKERS: [AtomicWaker; 8] = [const { AtomicWaker::new() }; 8];
28static EP_OUT_WAKERS: [AtomicWaker; 8] = [const { AtomicWaker::new() }; 8];
29static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
30
31/// Interrupt handler.
32pub struct InterruptHandler<T: Instance> {
33    _phantom: PhantomData<T>,
34}
35
36impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
37    unsafe fn on_interrupt() {
38        let regs = T::regs();
39
40        if regs.events_usbreset().read() != 0 {
41            regs.intenclr().write(|w| w.set_usbreset(true));
42            BUS_WAKER.wake();
43            EP0_WAKER.wake();
44        }
45
46        if regs.events_ep0setup().read() != 0 {
47            regs.intenclr().write(|w| w.set_ep0setup(true));
48            EP0_WAKER.wake();
49        }
50
51        if regs.events_ep0datadone().read() != 0 {
52            regs.intenclr().write(|w| w.set_ep0datadone(true));
53            EP0_WAKER.wake();
54        }
55
56        // USBEVENT and EPDATA events are weird. They're the "aggregate"
57        // of individual bits in EVENTCAUSE and EPDATASTATUS. We handle them
58        // differently than events normally.
59        //
60        // They seem to be edge-triggered, not level-triggered: when an
61        // individual bit goes 0->1, the event fires *just once*.
62        // Therefore, it's fine to clear just the event, and let main thread
63        // check the individual bits in EVENTCAUSE and EPDATASTATUS. It
64        // doesn't cause an infinite irq loop.
65        if regs.events_usbevent().read() != 0 {
66            regs.events_usbevent().write_value(0);
67            BUS_WAKER.wake();
68        }
69
70        if regs.events_epdata().read() != 0 {
71            regs.events_epdata().write_value(0);
72
73            let r = regs.epdatastatus().read();
74            regs.epdatastatus().write_value(r);
75            READY_ENDPOINTS.fetch_or(r.0, Ordering::AcqRel);
76            for i in 1..=7 {
77                if r.0 & In::mask(i) != 0 {
78                    In::waker(i).wake();
79                }
80                if r.0 & Out::mask(i) != 0 {
81                    Out::waker(i).wake();
82                }
83            }
84        }
85    }
86}
87
88/// USB driver.
89pub struct Driver<'d, V: VbusDetect> {
90    regs: pac::usbd::Usbd,
91    alloc_in: Allocator,
92    alloc_out: Allocator,
93    vbus_detect: V,
94    _phantom: PhantomData<&'d ()>,
95}
96
97impl<'d, V: VbusDetect> Driver<'d, V> {
98    /// Create a new USB driver.
99    pub fn new<T: Instance>(
100        _usb: Peri<'d, T>,
101        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
102        vbus_detect: V,
103    ) -> Self {
104        T::Interrupt::unpend();
105        unsafe { T::Interrupt::enable() };
106
107        Self {
108            regs: crate::pac::USBD,
109            alloc_in: Allocator::new(),
110            alloc_out: Allocator::new(),
111            vbus_detect,
112            _phantom: PhantomData,
113        }
114    }
115}
116
117impl<'d, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, V> {
118    type EndpointOut = Endpoint<'d, Out>;
119    type EndpointIn = Endpoint<'d, In>;
120    type ControlPipe = ControlPipe<'d>;
121    type Bus = Bus<'d, V>;
122
123    fn alloc_endpoint_in(
124        &mut self,
125        ep_type: EndpointType,
126        ep_addr: Option<EndpointAddress>,
127        packet_size: u16,
128        interval_ms: u8,
129    ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
130        let index = self.alloc_in.allocate(ep_type, ep_addr)?;
131        let ep_addr = EndpointAddress::from_parts(index, Direction::In);
132        Ok(Endpoint::new(
133            self.regs,
134            EndpointInfo {
135                addr: ep_addr,
136                ep_type,
137                max_packet_size: packet_size,
138                interval_ms,
139            },
140        ))
141    }
142
143    fn alloc_endpoint_out(
144        &mut self,
145        ep_type: EndpointType,
146        ep_addr: Option<EndpointAddress>,
147        packet_size: u16,
148        interval_ms: u8,
149    ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
150        let index = self.alloc_out.allocate(ep_type, ep_addr)?;
151        let ep_addr = EndpointAddress::from_parts(index, Direction::Out);
152        Ok(Endpoint::new(
153            self.regs,
154            EndpointInfo {
155                addr: ep_addr,
156                ep_type,
157                max_packet_size: packet_size,
158                interval_ms,
159            },
160        ))
161    }
162
163    fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
164        (
165            Bus {
166                regs: self.regs,
167                power_available: false,
168                vbus_detect: self.vbus_detect,
169                _phantom: PhantomData,
170            },
171            ControlPipe {
172                regs: self.regs,
173                max_packet_size: control_max_packet_size,
174                _phantom: PhantomData,
175            },
176        )
177    }
178}
179
180/// USB bus.
181pub struct Bus<'d, V: VbusDetect> {
182    regs: pac::usbd::Usbd,
183    power_available: bool,
184    vbus_detect: V,
185    _phantom: PhantomData<&'d ()>,
186}
187
188impl<'d, V: VbusDetect> driver::Bus for Bus<'d, V> {
189    async fn enable(&mut self) {
190        let regs = self.regs;
191
192        errata::pre_enable();
193
194        regs.enable().write(|w| w.set_enable(true));
195
196        // Wait until the peripheral is ready.
197        regs.intenset().write(|w| w.set_usbevent(true));
198        poll_fn(|cx| {
199            BUS_WAKER.register(cx.waker());
200            if regs.eventcause().read().ready() {
201                Poll::Ready(())
202            } else {
203                Poll::Pending
204            }
205        })
206        .await;
207        regs.eventcause().write(|w| w.set_ready(true));
208
209        errata::post_enable();
210
211        unsafe { NVIC::unmask(pac::Interrupt::USBD) };
212
213        regs.intenset().write(|w| {
214            w.set_usbreset(true);
215            w.set_usbevent(true);
216            w.set_epdata(true);
217        });
218
219        if self.vbus_detect.wait_power_ready().await.is_ok() {
220            // Enable the USB pullup, allowing enumeration.
221            regs.usbpullup().write(|w| w.set_connect(true));
222            trace!("enabled");
223        } else {
224            trace!("usb power not ready due to usb removal");
225        }
226    }
227
228    async fn disable(&mut self) {
229        let regs = self.regs;
230        regs.enable().write(|x| x.set_enable(false));
231    }
232
233    fn poll(&mut self) -> impl Future<Output = Event> {
234        poll_fn(|cx| {
235            BUS_WAKER.register(cx.waker());
236            let regs = self.regs;
237
238            if regs.events_usbreset().read() != 0 {
239                regs.events_usbreset().write_value(0);
240                regs.intenset().write(|w| w.set_usbreset(true));
241
242                // Disable all endpoints except EP0
243                regs.epinen().write(|w| w.0 = 0x01);
244                regs.epouten().write(|w| w.0 = 0x01);
245                READY_ENDPOINTS.store(In::mask(0), Ordering::Release);
246                for i in 1..=7 {
247                    In::waker(i).wake();
248                    Out::waker(i).wake();
249                }
250
251                return Poll::Ready(Event::Reset);
252            }
253
254            let r = regs.eventcause().read();
255
256            if r.isooutcrc() {
257                regs.eventcause().write(|w| w.set_isooutcrc(true));
258                trace!("USB event: isooutcrc");
259            }
260            if r.usbwuallowed() {
261                regs.eventcause().write(|w| w.set_usbwuallowed(true));
262                trace!("USB event: usbwuallowed");
263            }
264            if r.suspend() {
265                regs.eventcause().write(|w| w.set_suspend(true));
266                regs.lowpower().write(|w| w.set_lowpower(vals::Lowpower::LOW_POWER));
267                return Poll::Ready(Event::Suspend);
268            }
269            if r.resume() {
270                regs.eventcause().write(|w| w.set_resume(true));
271                return Poll::Ready(Event::Resume);
272            }
273            if r.ready() {
274                regs.eventcause().write(|w| w.set_ready(true));
275                trace!("USB event: ready");
276            }
277
278            if self.vbus_detect.is_usb_detected() != self.power_available {
279                self.power_available = !self.power_available;
280                if self.power_available {
281                    trace!("Power event: available");
282                    return Poll::Ready(Event::PowerDetected);
283                } else {
284                    trace!("Power event: removed");
285                    return Poll::Ready(Event::PowerRemoved);
286                }
287            }
288
289            Poll::Pending
290        })
291    }
292
293    fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) {
294        let regs = self.regs;
295        if ep_addr.index() == 0 {
296            if stalled {
297                regs.tasks_ep0stall().write_value(1);
298            }
299        } else {
300            regs.epstall().write(|w| {
301                w.set_ep(ep_addr.index() as u8 & 0b111);
302                w.set_io(match ep_addr.direction() {
303                    Direction::In => vals::Io::IN,
304                    Direction::Out => vals::Io::OUT,
305                });
306                w.set_stall(stalled);
307            });
308        }
309    }
310
311    fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool {
312        let regs = self.regs;
313        let i = ep_addr.index();
314        match ep_addr.direction() {
315            Direction::Out => regs.halted().epout(i).read().getstatus() == vals::Getstatus::HALTED,
316            Direction::In => regs.halted().epin(i).read().getstatus() == vals::Getstatus::HALTED,
317        }
318    }
319
320    fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
321        let regs = self.regs;
322
323        let i = ep_addr.index();
324        let mask = 1 << i;
325
326        debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled);
327
328        match ep_addr.direction() {
329            Direction::In => {
330                let mut was_enabled = false;
331                regs.epinen().modify(|w| {
332                    was_enabled = (w.0 & mask) != 0;
333                    if enabled {
334                        w.0 |= mask
335                    } else {
336                        w.0 &= !mask
337                    }
338                });
339
340                let ready_mask = In::mask(i);
341                if enabled {
342                    if !was_enabled {
343                        READY_ENDPOINTS.fetch_or(ready_mask, Ordering::AcqRel);
344                    }
345                } else {
346                    READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel);
347                }
348
349                In::waker(i).wake();
350            }
351            Direction::Out => {
352                regs.epouten()
353                    .modify(|w| if enabled { w.0 |= mask } else { w.0 &= !mask });
354
355                let ready_mask = Out::mask(i);
356                if enabled {
357                    // when first enabled, bulk/interrupt OUT endpoints will *not* receive data (the
358                    // peripheral will NAK all incoming packets) until we write a zero to the SIZE
359                    // register (see figure 203 of the 52840 manual). To avoid that we write a 0 to the
360                    // SIZE register
361                    regs.size().epout(i).write(|_| ());
362                } else {
363                    READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel);
364                }
365
366                Out::waker(i).wake();
367            }
368        }
369    }
370
371    #[inline]
372    async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
373        let regs = self.regs;
374
375        if regs.lowpower().read().lowpower() == vals::Lowpower::LOW_POWER {
376            errata::pre_wakeup();
377
378            regs.lowpower().write(|w| w.set_lowpower(vals::Lowpower::FORCE_NORMAL));
379
380            poll_fn(|cx| {
381                BUS_WAKER.register(cx.waker());
382                let regs = self.regs;
383                let r = regs.eventcause().read();
384
385                if regs.events_usbreset().read() != 0 {
386                    Poll::Ready(())
387                } else if r.resume() {
388                    Poll::Ready(())
389                } else if r.usbwuallowed() {
390                    regs.eventcause().write(|w| w.set_usbwuallowed(true));
391                    regs.dpdmvalue().write(|w| w.set_state(vals::State::RESUME));
392                    regs.tasks_dpdmdrive().write_value(1);
393
394                    Poll::Ready(())
395                } else {
396                    Poll::Pending
397                }
398            })
399            .await;
400
401            errata::post_wakeup();
402        }
403
404        Ok(())
405    }
406}
407
408/// Type-level marker for OUT endpoints.
409pub enum Out {}
410
411/// Type-level marker for IN endpoints.
412pub enum In {}
413
414trait EndpointDir {
415    fn waker(i: usize) -> &'static AtomicWaker;
416    fn mask(i: usize) -> u32;
417    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool;
418}
419
420impl EndpointDir for In {
421    #[inline]
422    fn waker(i: usize) -> &'static AtomicWaker {
423        &EP_IN_WAKERS[i - 1]
424    }
425
426    #[inline]
427    fn mask(i: usize) -> u32 {
428        1 << i
429    }
430
431    #[inline]
432    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool {
433        regs.epinen().read().in_(i)
434    }
435}
436
437impl EndpointDir for Out {
438    #[inline]
439    fn waker(i: usize) -> &'static AtomicWaker {
440        &EP_OUT_WAKERS[i - 1]
441    }
442
443    #[inline]
444    fn mask(i: usize) -> u32 {
445        1 << (i + 16)
446    }
447
448    #[inline]
449    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool {
450        regs.epouten().read().out(i)
451    }
452}
453
454/// USB endpoint.
455pub struct Endpoint<'d, Dir> {
456    regs: pac::usbd::Usbd,
457    info: EndpointInfo,
458    _phantom: PhantomData<(&'d (), Dir)>,
459}
460
461impl<'d, Dir> Endpoint<'d, Dir> {
462    fn new(regs: pac::usbd::Usbd, info: EndpointInfo) -> Self {
463        Self {
464            regs,
465            info,
466            _phantom: PhantomData,
467        }
468    }
469}
470
471impl<'d, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, Dir> {
472    fn info(&self) -> &EndpointInfo {
473        &self.info
474    }
475
476    async fn wait_enabled(&mut self) {
477        self.wait_enabled_state(true).await
478    }
479}
480
481#[allow(private_bounds)]
482impl<'d, Dir: EndpointDir> Endpoint<'d, Dir> {
483    fn wait_enabled_state(&mut self, state: bool) -> impl Future<Output = ()> + use<'_, 'd, Dir> {
484        let i = self.info.addr.index();
485        assert!(i != 0);
486
487        poll_fn(move |cx| {
488            Dir::waker(i).register(cx.waker());
489            if Dir::is_enabled(self.regs, i) == state {
490                Poll::Ready(())
491            } else {
492                Poll::Pending
493            }
494        })
495    }
496
497    /// Wait for the endpoint to be disabled
498    pub fn wait_disabled(&mut self) -> impl Future<Output = ()> + use<'_, 'd, Dir> {
499        self.wait_enabled_state(false)
500    }
501}
502
503impl<'d, Dir> Endpoint<'d, Dir> {
504    async fn wait_data_ready(&mut self) -> Result<(), ()>
505    where
506        Dir: EndpointDir,
507    {
508        let i = self.info.addr.index();
509        assert!(i != 0);
510        poll_fn(|cx| {
511            Dir::waker(i).register(cx.waker());
512            let r = READY_ENDPOINTS.load(Ordering::Acquire);
513            if !Dir::is_enabled(self.regs, i) {
514                Poll::Ready(Err(()))
515            } else if r & Dir::mask(i) != 0 {
516                Poll::Ready(Ok(()))
517            } else {
518                Poll::Pending
519            }
520        })
521        .await?;
522
523        // Mark as not ready
524        READY_ENDPOINTS.fetch_and(!Dir::mask(i), Ordering::AcqRel);
525
526        Ok(())
527    }
528}
529
530unsafe fn read_dma(regs: pac::usbd::Usbd, i: usize, buf: &mut [u8]) -> Result<usize, EndpointError> {
531    // Check that the packet fits into the buffer
532    let size = regs.size().epout(i).read().0 as usize;
533    if size > buf.len() {
534        return Err(EndpointError::BufferOverflow);
535    }
536
537    regs.epout(i).ptr().write_value(buf.as_ptr() as u32);
538    // MAXCNT must match SIZE
539    regs.epout(i).maxcnt().write(|w| w.set_maxcnt(size as _));
540
541    dma_start();
542    regs.events_endepout(i).write_value(0);
543    regs.tasks_startepout(i).write_value(1);
544    while regs.events_endepout(i).read() == 0 {}
545    regs.events_endepout(i).write_value(0);
546    dma_end();
547
548    regs.size().epout(i).write(|_| ());
549
550    Ok(size)
551}
552
553unsafe fn write_dma(regs: pac::usbd::Usbd, i: usize, buf: &[u8]) {
554    assert!(buf.len() <= 64);
555
556    let mut ram_buf: MaybeUninit<[u8; 64]> = MaybeUninit::uninit();
557    let ptr = if !slice_in_ram(buf) {
558        // EasyDMA can't read FLASH, so we copy through RAM
559        let ptr = ram_buf.as_mut_ptr() as *mut u8;
560        core::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
561        ptr
562    } else {
563        buf.as_ptr()
564    };
565
566    // Set the buffer length so the right number of bytes are transmitted.
567    // Safety: `buf.len()` has been checked to be <= the max buffer length.
568    regs.epin(i).ptr().write_value(ptr as u32);
569    regs.epin(i).maxcnt().write(|w| w.set_maxcnt(buf.len() as u8));
570
571    regs.events_endepin(i).write_value(0);
572
573    dma_start();
574    regs.tasks_startepin(i).write_value(1);
575    while regs.events_endepin(i).read() == 0 {}
576    dma_end();
577}
578
579impl<'d> driver::EndpointOut for Endpoint<'d, Out> {
580    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
581        let i = self.info.addr.index();
582        assert!(i != 0);
583
584        self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
585
586        unsafe { read_dma(self.regs, i, buf) }
587    }
588}
589
590impl<'d> driver::EndpointIn for Endpoint<'d, In> {
591    async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
592        let i = self.info.addr.index();
593        assert!(i != 0);
594
595        self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
596
597        unsafe { write_dma(self.regs, i, buf) }
598
599        Ok(())
600    }
601}
602
603/// USB control pipe.
604pub struct ControlPipe<'d> {
605    regs: pac::usbd::Usbd,
606    max_packet_size: u16,
607    _phantom: PhantomData<&'d ()>,
608}
609
610impl<'d> driver::ControlPipe for ControlPipe<'d> {
611    fn max_packet_size(&self) -> usize {
612        usize::from(self.max_packet_size)
613    }
614
615    async fn setup(&mut self) -> [u8; 8] {
616        let regs = self.regs;
617
618        // Reset shorts
619        regs.shorts().write(|_| ());
620
621        // Wait for SETUP packet
622        regs.intenset().write(|w| w.set_ep0setup(true));
623        poll_fn(|cx| {
624            EP0_WAKER.register(cx.waker());
625            let regs = self.regs;
626            if regs.events_ep0setup().read() != 0 {
627                Poll::Ready(())
628            } else {
629                Poll::Pending
630            }
631        })
632        .await;
633
634        regs.events_ep0setup().write_value(0);
635
636        let mut buf = [0; 8];
637        buf[0] = regs.bmrequesttype().read().0 as u8;
638        buf[1] = regs.brequest().read().0 as u8;
639        buf[2] = regs.wvaluel().read().0 as u8;
640        buf[3] = regs.wvalueh().read().0 as u8;
641        buf[4] = regs.windexl().read().0 as u8;
642        buf[5] = regs.windexh().read().0 as u8;
643        buf[6] = regs.wlengthl().read().0 as u8;
644        buf[7] = regs.wlengthh().read().0 as u8;
645
646        buf
647    }
648
649    async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
650        let regs = self.regs;
651
652        regs.events_ep0datadone().write_value(0);
653
654        // This starts a RX on EP0. events_ep0datadone notifies when done.
655        regs.tasks_ep0rcvout().write_value(1);
656
657        // Wait until ready
658        regs.intenset().write(|w| {
659            w.set_usbreset(true);
660            w.set_ep0setup(true);
661            w.set_ep0datadone(true);
662        });
663        poll_fn(|cx| {
664            EP0_WAKER.register(cx.waker());
665            let regs = self.regs;
666            if regs.events_ep0datadone().read() != 0 {
667                Poll::Ready(Ok(()))
668            } else if regs.events_usbreset().read() != 0 {
669                trace!("aborted control data_out: usb reset");
670                Poll::Ready(Err(EndpointError::Disabled))
671            } else if regs.events_ep0setup().read() != 0 {
672                trace!("aborted control data_out: received another SETUP");
673                Poll::Ready(Err(EndpointError::Disabled))
674            } else {
675                Poll::Pending
676            }
677        })
678        .await?;
679
680        unsafe { read_dma(self.regs, 0, buf) }
681    }
682
683    async fn data_in(&mut self, buf: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
684        let regs = self.regs;
685        regs.events_ep0datadone().write_value(0);
686
687        regs.shorts().write(|w| w.set_ep0datadone_ep0status(last));
688
689        // This starts a TX on EP0. events_ep0datadone notifies when done.
690        unsafe { write_dma(self.regs, 0, buf) }
691
692        regs.intenset().write(|w| {
693            w.set_usbreset(true);
694            w.set_ep0setup(true);
695            w.set_ep0datadone(true);
696        });
697
698        poll_fn(|cx| {
699            cx.waker().wake_by_ref();
700            EP0_WAKER.register(cx.waker());
701            let regs = self.regs;
702            if regs.events_ep0datadone().read() != 0 {
703                Poll::Ready(Ok(()))
704            } else if regs.events_usbreset().read() != 0 {
705                trace!("aborted control data_in: usb reset");
706                Poll::Ready(Err(EndpointError::Disabled))
707            } else if regs.events_ep0setup().read() != 0 {
708                trace!("aborted control data_in: received another SETUP");
709                Poll::Ready(Err(EndpointError::Disabled))
710            } else {
711                Poll::Pending
712            }
713        })
714        .await
715    }
716
717    async fn accept(&mut self) {
718        let regs = self.regs;
719        regs.tasks_ep0status().write_value(1);
720    }
721
722    async fn reject(&mut self) {
723        let regs = self.regs;
724        regs.tasks_ep0stall().write_value(1);
725    }
726
727    async fn accept_set_address(&mut self, _addr: u8) {
728        self.accept().await;
729        // Nothing to do, the peripheral handles this.
730    }
731}
732
733fn dma_start() {
734    compiler_fence(Ordering::Release);
735}
736
737fn dma_end() {
738    compiler_fence(Ordering::Acquire);
739}
740
741struct Allocator {
742    used: u16,
743}
744
745impl Allocator {
746    fn new() -> Self {
747        Self { used: 0 }
748    }
749
750    fn allocate(
751        &mut self,
752        ep_type: EndpointType,
753        ep_addr: Option<EndpointAddress>,
754    ) -> Result<usize, driver::EndpointAllocError> {
755        // Endpoint addresses are fixed in hardware:
756        // - 0x80 / 0x00 - Control        EP0
757        // - 0x81 / 0x01 - Bulk/Interrupt EP1
758        // - 0x82 / 0x02 - Bulk/Interrupt EP2
759        // - 0x83 / 0x03 - Bulk/Interrupt EP3
760        // - 0x84 / 0x04 - Bulk/Interrupt EP4
761        // - 0x85 / 0x05 - Bulk/Interrupt EP5
762        // - 0x86 / 0x06 - Bulk/Interrupt EP6
763        // - 0x87 / 0x07 - Bulk/Interrupt EP7
764        // - 0x88 / 0x08 - Isochronous
765
766        // Endpoint directions are allocated individually.
767
768        let alloc_index = if let Some(addr) = ep_addr {
769            // Use the specified endpoint address
770            let requested_index = addr.index();
771            // Validate the requested index based on endpoint type
772            match ep_type {
773                EndpointType::Isochronous => {
774                    if requested_index != 8 {
775                        return Err(driver::EndpointAllocError);
776                    }
777                }
778                EndpointType::Control => return Err(driver::EndpointAllocError),
779                EndpointType::Interrupt | EndpointType::Bulk => {
780                    if requested_index < 1 || requested_index > 7 {
781                        return Err(driver::EndpointAllocError);
782                    }
783                }
784            }
785            requested_index
786        } else {
787            // Allocate any available endpoint
788            match ep_type {
789                EndpointType::Isochronous => 8,
790                EndpointType::Control => return Err(driver::EndpointAllocError),
791                EndpointType::Interrupt | EndpointType::Bulk => {
792                    // Find rightmost zero bit in 1..=7
793                    let ones = (self.used >> 1).trailing_ones() as usize;
794                    if ones >= 7 {
795                        return Err(driver::EndpointAllocError);
796                    }
797                    ones + 1
798                }
799            }
800        };
801
802        if self.used & (1 << alloc_index) != 0 {
803            return Err(driver::EndpointAllocError);
804        }
805
806        self.used |= 1 << alloc_index;
807
808        Ok(alloc_index)
809    }
810}
811
812pub(crate) trait SealedInstance {
813    fn regs() -> pac::usbd::Usbd;
814}
815
816/// USB peripheral instance.
817#[allow(private_bounds)]
818pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
819    /// Interrupt for this peripheral.
820    type Interrupt: interrupt::typelevel::Interrupt;
821}
822
823macro_rules! impl_usb {
824    ($type:ident, $pac_type:ident, $irq:ident) => {
825        impl crate::usb::SealedInstance for peripherals::$type {
826            fn regs() -> pac::usbd::Usbd {
827                pac::$pac_type
828            }
829        }
830        impl crate::usb::Instance for peripherals::$type {
831            type Interrupt = crate::interrupt::typelevel::$irq;
832        }
833    };
834}
835
836mod errata {
837
838    /// Writes `val` to `addr`. Used to apply Errata workarounds.
839    #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
840    unsafe fn poke(addr: u32, val: u32) {
841        (addr as *mut u32).write_volatile(val);
842    }
843
844    /// Reads 32 bits from `addr`.
845    #[cfg(feature = "nrf52840")]
846    unsafe fn peek(addr: u32) -> u32 {
847        (addr as *mut u32).read_volatile()
848    }
849
850    pub fn pre_enable() {
851        // Works around Erratum 187 on chip revisions 1 and 2.
852        #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
853        unsafe {
854            poke(0x4006EC00, 0x00009375);
855            poke(0x4006ED14, 0x00000003);
856            poke(0x4006EC00, 0x00009375);
857        }
858
859        pre_wakeup();
860    }
861
862    pub fn post_enable() {
863        post_wakeup();
864
865        // Works around Erratum 187 on chip revisions 1 and 2.
866        #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
867        unsafe {
868            poke(0x4006EC00, 0x00009375);
869            poke(0x4006ED14, 0x00000000);
870            poke(0x4006EC00, 0x00009375);
871        }
872    }
873
874    pub fn pre_wakeup() {
875        // Works around Erratum 171 on chip revisions 1 and 2.
876
877        #[cfg(feature = "nrf52840")]
878        unsafe {
879            if peek(0x4006EC00) == 0x00000000 {
880                poke(0x4006EC00, 0x00009375);
881            }
882
883            poke(0x4006EC14, 0x000000C0);
884            poke(0x4006EC00, 0x00009375);
885        }
886    }
887
888    pub fn post_wakeup() {
889        // Works around Erratum 171 on chip revisions 1 and 2.
890
891        #[cfg(feature = "nrf52840")]
892        unsafe {
893            if peek(0x4006EC00) == 0x00000000 {
894                poke(0x4006EC00, 0x00009375);
895            }
896
897            poke(0x4006EC14, 0x00000000);
898            poke(0x4006EC00, 0x00009375);
899        }
900    }
901}