embassy_nrf/usb/
mod.rs

1//! Universal Serial Bus (USB) driver.
2
3#![macro_use]
4
5pub mod vbus_detect;
6
7use core::future::{Future, poll_fn};
8use core::marker::PhantomData;
9use core::mem::MaybeUninit;
10use core::sync::atomic::{AtomicU32, Ordering, compiler_fence};
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 { w.0 |= mask } else { w.0 &= !mask }
334                });
335
336                let ready_mask = In::mask(i);
337                if enabled {
338                    if !was_enabled {
339                        READY_ENDPOINTS.fetch_or(ready_mask, Ordering::AcqRel);
340                    }
341                } else {
342                    READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel);
343                }
344
345                In::waker(i).wake();
346            }
347            Direction::Out => {
348                regs.epouten()
349                    .modify(|w| if enabled { w.0 |= mask } else { w.0 &= !mask });
350
351                let ready_mask = Out::mask(i);
352                if enabled {
353                    // when first enabled, bulk/interrupt OUT endpoints will *not* receive data (the
354                    // peripheral will NAK all incoming packets) until we write a zero to the SIZE
355                    // register (see figure 203 of the 52840 manual). To avoid that we write a 0 to the
356                    // SIZE register
357                    regs.size().epout(i).write(|_| ());
358                } else {
359                    READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel);
360                }
361
362                Out::waker(i).wake();
363            }
364        }
365    }
366
367    #[inline]
368    async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
369        let regs = self.regs;
370
371        if regs.lowpower().read().lowpower() == vals::Lowpower::LOW_POWER {
372            errata::pre_wakeup();
373
374            regs.lowpower().write(|w| w.set_lowpower(vals::Lowpower::FORCE_NORMAL));
375
376            poll_fn(|cx| {
377                BUS_WAKER.register(cx.waker());
378                let regs = self.regs;
379                let r = regs.eventcause().read();
380
381                if regs.events_usbreset().read() != 0 {
382                    Poll::Ready(())
383                } else if r.resume() {
384                    Poll::Ready(())
385                } else if r.usbwuallowed() {
386                    regs.eventcause().write(|w| w.set_usbwuallowed(true));
387                    regs.dpdmvalue().write(|w| w.set_state(vals::State::RESUME));
388                    regs.tasks_dpdmdrive().write_value(1);
389
390                    Poll::Ready(())
391                } else {
392                    Poll::Pending
393                }
394            })
395            .await;
396
397            errata::post_wakeup();
398        }
399
400        Ok(())
401    }
402}
403
404/// Type-level marker for OUT endpoints.
405pub enum Out {}
406
407/// Type-level marker for IN endpoints.
408pub enum In {}
409
410trait EndpointDir {
411    fn waker(i: usize) -> &'static AtomicWaker;
412    fn mask(i: usize) -> u32;
413    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool;
414}
415
416impl EndpointDir for In {
417    #[inline]
418    fn waker(i: usize) -> &'static AtomicWaker {
419        &EP_IN_WAKERS[i - 1]
420    }
421
422    #[inline]
423    fn mask(i: usize) -> u32 {
424        1 << i
425    }
426
427    #[inline]
428    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool {
429        regs.epinen().read().in_(i)
430    }
431}
432
433impl EndpointDir for Out {
434    #[inline]
435    fn waker(i: usize) -> &'static AtomicWaker {
436        &EP_OUT_WAKERS[i - 1]
437    }
438
439    #[inline]
440    fn mask(i: usize) -> u32 {
441        1 << (i + 16)
442    }
443
444    #[inline]
445    fn is_enabled(regs: pac::usbd::Usbd, i: usize) -> bool {
446        regs.epouten().read().out(i)
447    }
448}
449
450/// USB endpoint.
451pub struct Endpoint<'d, Dir> {
452    regs: pac::usbd::Usbd,
453    info: EndpointInfo,
454    _phantom: PhantomData<(&'d (), Dir)>,
455}
456
457impl<'d, Dir> Endpoint<'d, Dir> {
458    fn new(regs: pac::usbd::Usbd, info: EndpointInfo) -> Self {
459        Self {
460            regs,
461            info,
462            _phantom: PhantomData,
463        }
464    }
465}
466
467impl<'d, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, Dir> {
468    fn info(&self) -> &EndpointInfo {
469        &self.info
470    }
471
472    async fn wait_enabled(&mut self) {
473        self.wait_enabled_state(true).await
474    }
475}
476
477#[allow(private_bounds)]
478impl<'d, Dir: EndpointDir> Endpoint<'d, Dir> {
479    fn wait_enabled_state(&mut self, state: bool) -> impl Future<Output = ()> + use<'_, 'd, Dir> {
480        let i = self.info.addr.index();
481        assert!(i != 0);
482
483        poll_fn(move |cx| {
484            Dir::waker(i).register(cx.waker());
485            if Dir::is_enabled(self.regs, i) == state {
486                Poll::Ready(())
487            } else {
488                Poll::Pending
489            }
490        })
491    }
492
493    /// Wait for the endpoint to be disabled
494    pub fn wait_disabled(&mut self) -> impl Future<Output = ()> + use<'_, 'd, Dir> {
495        self.wait_enabled_state(false)
496    }
497}
498
499impl<'d, Dir> Endpoint<'d, Dir> {
500    async fn wait_data_ready(&mut self) -> Result<(), ()>
501    where
502        Dir: EndpointDir,
503    {
504        let i = self.info.addr.index();
505        assert!(i != 0);
506        poll_fn(|cx| {
507            Dir::waker(i).register(cx.waker());
508            let r = READY_ENDPOINTS.load(Ordering::Acquire);
509            if !Dir::is_enabled(self.regs, i) {
510                Poll::Ready(Err(()))
511            } else if r & Dir::mask(i) != 0 {
512                Poll::Ready(Ok(()))
513            } else {
514                Poll::Pending
515            }
516        })
517        .await?;
518
519        // Mark as not ready
520        READY_ENDPOINTS.fetch_and(!Dir::mask(i), Ordering::AcqRel);
521
522        Ok(())
523    }
524}
525
526unsafe fn read_dma(regs: pac::usbd::Usbd, i: usize, buf: &mut [u8]) -> Result<usize, EndpointError> {
527    // Check that the packet fits into the buffer
528    let size = regs.size().epout(i).read().0 as usize;
529    if size > buf.len() {
530        return Err(EndpointError::BufferOverflow);
531    }
532
533    regs.epout(i).ptr().write_value(buf.as_ptr() as u32);
534    // MAXCNT must match SIZE
535    regs.epout(i).maxcnt().write(|w| w.set_maxcnt(size as _));
536
537    dma_start();
538    regs.events_endepout(i).write_value(0);
539    regs.tasks_startepout(i).write_value(1);
540    while regs.events_endepout(i).read() == 0 {}
541    regs.events_endepout(i).write_value(0);
542    dma_end();
543
544    regs.size().epout(i).write(|_| ());
545
546    Ok(size)
547}
548
549unsafe fn write_dma(regs: pac::usbd::Usbd, i: usize, buf: &[u8]) {
550    assert!(buf.len() <= 64);
551
552    let mut ram_buf: MaybeUninit<[u8; 64]> = MaybeUninit::uninit();
553    let ptr = if !slice_in_ram(buf) {
554        // EasyDMA can't read FLASH, so we copy through RAM
555        let ptr = ram_buf.as_mut_ptr() as *mut u8;
556        core::ptr::copy_nonoverlapping(buf.as_ptr(), ptr, buf.len());
557        ptr
558    } else {
559        buf.as_ptr()
560    };
561
562    // Set the buffer length so the right number of bytes are transmitted.
563    // Safety: `buf.len()` has been checked to be <= the max buffer length.
564    regs.epin(i).ptr().write_value(ptr as u32);
565    regs.epin(i).maxcnt().write(|w| w.set_maxcnt(buf.len() as u8));
566
567    regs.events_endepin(i).write_value(0);
568
569    dma_start();
570    regs.tasks_startepin(i).write_value(1);
571    while regs.events_endepin(i).read() == 0 {}
572    dma_end();
573}
574
575impl<'d> driver::EndpointOut for Endpoint<'d, Out> {
576    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
577        let i = self.info.addr.index();
578        assert!(i != 0);
579
580        self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
581
582        unsafe { read_dma(self.regs, i, buf) }
583    }
584}
585
586impl<'d> driver::EndpointIn for Endpoint<'d, In> {
587    async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
588        let i = self.info.addr.index();
589        assert!(i != 0);
590
591        self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
592
593        unsafe { write_dma(self.regs, i, buf) }
594
595        Ok(())
596    }
597}
598
599/// USB control pipe.
600pub struct ControlPipe<'d> {
601    regs: pac::usbd::Usbd,
602    max_packet_size: u16,
603    _phantom: PhantomData<&'d ()>,
604}
605
606impl<'d> driver::ControlPipe for ControlPipe<'d> {
607    fn max_packet_size(&self) -> usize {
608        usize::from(self.max_packet_size)
609    }
610
611    async fn setup(&mut self) -> [u8; 8] {
612        let regs = self.regs;
613
614        // Reset shorts
615        regs.shorts().write(|_| ());
616
617        // Wait for SETUP packet
618        regs.intenset().write(|w| w.set_ep0setup(true));
619        poll_fn(|cx| {
620            EP0_WAKER.register(cx.waker());
621            let regs = self.regs;
622            if regs.events_ep0setup().read() != 0 {
623                Poll::Ready(())
624            } else {
625                Poll::Pending
626            }
627        })
628        .await;
629
630        regs.events_ep0setup().write_value(0);
631
632        let mut buf = [0; 8];
633        buf[0] = regs.bmrequesttype().read().0 as u8;
634        buf[1] = regs.brequest().read().0 as u8;
635        buf[2] = regs.wvaluel().read().0 as u8;
636        buf[3] = regs.wvalueh().read().0 as u8;
637        buf[4] = regs.windexl().read().0 as u8;
638        buf[5] = regs.windexh().read().0 as u8;
639        buf[6] = regs.wlengthl().read().0 as u8;
640        buf[7] = regs.wlengthh().read().0 as u8;
641
642        buf
643    }
644
645    async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
646        let regs = self.regs;
647
648        regs.events_ep0datadone().write_value(0);
649
650        // This starts a RX on EP0. events_ep0datadone notifies when done.
651        regs.tasks_ep0rcvout().write_value(1);
652
653        // Wait until ready
654        regs.intenset().write(|w| {
655            w.set_usbreset(true);
656            w.set_ep0setup(true);
657            w.set_ep0datadone(true);
658        });
659        poll_fn(|cx| {
660            EP0_WAKER.register(cx.waker());
661            let regs = self.regs;
662            if regs.events_ep0datadone().read() != 0 {
663                Poll::Ready(Ok(()))
664            } else if regs.events_usbreset().read() != 0 {
665                trace!("aborted control data_out: usb reset");
666                Poll::Ready(Err(EndpointError::Disabled))
667            } else if regs.events_ep0setup().read() != 0 {
668                trace!("aborted control data_out: received another SETUP");
669                Poll::Ready(Err(EndpointError::Disabled))
670            } else {
671                Poll::Pending
672            }
673        })
674        .await?;
675
676        unsafe { read_dma(self.regs, 0, buf) }
677    }
678
679    async fn data_in(&mut self, buf: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
680        let regs = self.regs;
681        regs.events_ep0datadone().write_value(0);
682
683        regs.shorts().write(|w| w.set_ep0datadone_ep0status(last));
684
685        // This starts a TX on EP0. events_ep0datadone notifies when done.
686        unsafe { write_dma(self.regs, 0, buf) }
687
688        regs.intenset().write(|w| {
689            w.set_usbreset(true);
690            w.set_ep0setup(true);
691            w.set_ep0datadone(true);
692        });
693
694        poll_fn(|cx| {
695            cx.waker().wake_by_ref();
696            EP0_WAKER.register(cx.waker());
697            let regs = self.regs;
698            if regs.events_ep0datadone().read() != 0 {
699                Poll::Ready(Ok(()))
700            } else if regs.events_usbreset().read() != 0 {
701                trace!("aborted control data_in: usb reset");
702                Poll::Ready(Err(EndpointError::Disabled))
703            } else if regs.events_ep0setup().read() != 0 {
704                trace!("aborted control data_in: received another SETUP");
705                Poll::Ready(Err(EndpointError::Disabled))
706            } else {
707                Poll::Pending
708            }
709        })
710        .await
711    }
712
713    async fn accept(&mut self) {
714        let regs = self.regs;
715        regs.tasks_ep0status().write_value(1);
716    }
717
718    async fn reject(&mut self) {
719        let regs = self.regs;
720        regs.tasks_ep0stall().write_value(1);
721    }
722
723    async fn accept_set_address(&mut self, _addr: u8) {
724        self.accept().await;
725        // Nothing to do, the peripheral handles this.
726    }
727}
728
729fn dma_start() {
730    compiler_fence(Ordering::Release);
731}
732
733fn dma_end() {
734    compiler_fence(Ordering::Acquire);
735}
736
737struct Allocator {
738    used: u16,
739}
740
741impl Allocator {
742    fn new() -> Self {
743        Self { used: 0 }
744    }
745
746    fn allocate(
747        &mut self,
748        ep_type: EndpointType,
749        ep_addr: Option<EndpointAddress>,
750    ) -> Result<usize, driver::EndpointAllocError> {
751        // Endpoint addresses are fixed in hardware:
752        // - 0x80 / 0x00 - Control        EP0
753        // - 0x81 / 0x01 - Bulk/Interrupt EP1
754        // - 0x82 / 0x02 - Bulk/Interrupt EP2
755        // - 0x83 / 0x03 - Bulk/Interrupt EP3
756        // - 0x84 / 0x04 - Bulk/Interrupt EP4
757        // - 0x85 / 0x05 - Bulk/Interrupt EP5
758        // - 0x86 / 0x06 - Bulk/Interrupt EP6
759        // - 0x87 / 0x07 - Bulk/Interrupt EP7
760        // - 0x88 / 0x08 - Isochronous
761
762        // Endpoint directions are allocated individually.
763
764        let alloc_index = if let Some(addr) = ep_addr {
765            // Use the specified endpoint address
766            let requested_index = addr.index();
767            // Validate the requested index based on endpoint type
768            match ep_type {
769                EndpointType::Isochronous => {
770                    if requested_index != 8 {
771                        return Err(driver::EndpointAllocError);
772                    }
773                }
774                EndpointType::Control => return Err(driver::EndpointAllocError),
775                EndpointType::Interrupt | EndpointType::Bulk => {
776                    if requested_index < 1 || requested_index > 7 {
777                        return Err(driver::EndpointAllocError);
778                    }
779                }
780            }
781            requested_index
782        } else {
783            // Allocate any available endpoint
784            match ep_type {
785                EndpointType::Isochronous => 8,
786                EndpointType::Control => return Err(driver::EndpointAllocError),
787                EndpointType::Interrupt | EndpointType::Bulk => {
788                    // Find rightmost zero bit in 1..=7
789                    let ones = (self.used >> 1).trailing_ones() as usize;
790                    if ones >= 7 {
791                        return Err(driver::EndpointAllocError);
792                    }
793                    ones + 1
794                }
795            }
796        };
797
798        if self.used & (1 << alloc_index) != 0 {
799            return Err(driver::EndpointAllocError);
800        }
801
802        self.used |= 1 << alloc_index;
803
804        Ok(alloc_index)
805    }
806}
807
808pub(crate) trait SealedInstance {
809    fn regs() -> pac::usbd::Usbd;
810}
811
812/// USB peripheral instance.
813#[allow(private_bounds)]
814pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
815    /// Interrupt for this peripheral.
816    type Interrupt: interrupt::typelevel::Interrupt;
817}
818
819macro_rules! impl_usb {
820    ($type:ident, $pac_type:ident, $irq:ident) => {
821        impl crate::usb::SealedInstance for peripherals::$type {
822            fn regs() -> pac::usbd::Usbd {
823                pac::$pac_type
824            }
825        }
826        impl crate::usb::Instance for peripherals::$type {
827            type Interrupt = crate::interrupt::typelevel::$irq;
828        }
829    };
830}
831
832mod errata {
833
834    /// Writes `val` to `addr`. Used to apply Errata workarounds.
835    #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
836    unsafe fn poke(addr: u32, val: u32) {
837        (addr as *mut u32).write_volatile(val);
838    }
839
840    /// Reads 32 bits from `addr`.
841    #[cfg(feature = "nrf52840")]
842    unsafe fn peek(addr: u32) -> u32 {
843        (addr as *mut u32).read_volatile()
844    }
845
846    pub fn pre_enable() {
847        // Works around Erratum 187 on chip revisions 1 and 2.
848        #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
849        unsafe {
850            poke(0x4006EC00, 0x00009375);
851            poke(0x4006ED14, 0x00000003);
852            poke(0x4006EC00, 0x00009375);
853        }
854
855        pre_wakeup();
856    }
857
858    pub fn post_enable() {
859        post_wakeup();
860
861        // Works around Erratum 187 on chip revisions 1 and 2.
862        #[cfg(any(feature = "nrf52840", feature = "nrf52833", feature = "nrf52820"))]
863        unsafe {
864            poke(0x4006EC00, 0x00009375);
865            poke(0x4006ED14, 0x00000000);
866            poke(0x4006EC00, 0x00009375);
867        }
868    }
869
870    pub fn pre_wakeup() {
871        // Works around Erratum 171 on chip revisions 1 and 2.
872
873        #[cfg(feature = "nrf52840")]
874        unsafe {
875            if peek(0x4006EC00) == 0x00000000 {
876                poke(0x4006EC00, 0x00009375);
877            }
878
879            poke(0x4006EC14, 0x000000C0);
880            poke(0x4006EC00, 0x00009375);
881        }
882    }
883
884    pub fn post_wakeup() {
885        // Works around Erratum 171 on chip revisions 1 and 2.
886
887        #[cfg(feature = "nrf52840")]
888        unsafe {
889            if peek(0x4006EC00) == 0x00000000 {
890                poke(0x4006EC00, 0x00009375);
891            }
892
893            poke(0x4006EC14, 0x00000000);
894            poke(0x4006EC00, 0x00009375);
895        }
896    }
897}