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