aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-03-09 23:06:27 +0100
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit77ceced036d574c7d67259b85e1d61b96e82d0d3 (patch)
tree4f1a250f92d59922ae7ceda0779aae16cfa767bb /embassy-nrf/src
parent37598a5b3792ec1b763b5c16fe422c9e1347d7d6 (diff)
Working CDC-ACM host->device
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/usb.rs209
1 files changed, 176 insertions, 33 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 0f7d68d8c..163b2c794 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -8,7 +8,7 @@ use embassy::time::{with_timeout, Duration};
8use embassy::util::Unborrow; 8use embassy::util::Unborrow;
9use embassy::waitqueue::AtomicWaker; 9use embassy::waitqueue::AtomicWaker;
10use embassy_hal_common::unborrow; 10use embassy_hal_common::unborrow;
11use embassy_usb::driver::{self, ReadError, WriteError}; 11use embassy_usb::driver::{self, Event, ReadError, WriteError};
12use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 12use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
13use futures::future::poll_fn; 13use futures::future::poll_fn;
14use futures::Future; 14use futures::Future;
@@ -19,7 +19,10 @@ pub use embassy_usb;
19use crate::interrupt::Interrupt; 19use crate::interrupt::Interrupt;
20use crate::pac; 20use crate::pac;
21 21
22static EP0_WAKER: AtomicWaker = AtomicWaker::new(); 22const NEW_AW: AtomicWaker = AtomicWaker::new();
23static BUS_WAKER: AtomicWaker = NEW_AW;
24static EP_IN_WAKERS: [AtomicWaker; 9] = [NEW_AW; 9];
25static EP_OUT_WAKERS: [AtomicWaker; 9] = [NEW_AW; 9];
23 26
24pub struct Driver<'d, T: Instance> { 27pub struct Driver<'d, T: Instance> {
25 phantom: PhantomData<&'d mut T>, 28 phantom: PhantomData<&'d mut T>,
@@ -47,13 +50,48 @@ impl<'d, T: Instance> Driver<'d, T> {
47 fn on_interrupt(_: *mut ()) { 50 fn on_interrupt(_: *mut ()) {
48 let regs = T::regs(); 51 let regs = T::regs();
49 52
53 if regs.events_usbreset.read().bits() != 0 {
54 regs.intenclr.write(|w| w.usbreset().clear());
55 BUS_WAKER.wake();
56 }
57
50 if regs.events_ep0setup.read().bits() != 0 { 58 if regs.events_ep0setup.read().bits() != 0 {
51 regs.intenclr.write(|w| w.ep0setup().clear()); 59 regs.intenclr.write(|w| w.ep0setup().clear());
52 EP0_WAKER.wake(); 60 EP_OUT_WAKERS[0].wake();
53 } 61 }
62
54 if regs.events_ep0datadone.read().bits() != 0 { 63 if regs.events_ep0datadone.read().bits() != 0 {
55 regs.intenclr.write(|w| w.ep0datadone().clear()); 64 regs.intenclr.write(|w| w.ep0datadone().clear());
56 EP0_WAKER.wake(); 65 EP_IN_WAKERS[0].wake();
66 }
67
68 // USBEVENT and EPDATA events are weird. They're the "aggregate"
69 // of individual bits in EVENTCAUSE and EPDATASTATUS. We handle them
70 // differently than events normally.
71 //
72 // They seem to be edge-triggered, not level-triggered: when an
73 // individual bit goes 0->1, the event fires *just once*.
74 // Therefore, it's fine to clear just the event, and let main thread
75 // check the individual bits in EVENTCAUSE and EPDATASTATUS. It
76 // doesn't cause an infinite irq loop.
77 if regs.events_usbevent.read().bits() != 0 {
78 regs.events_usbevent.reset();
79 //regs.intenclr.write(|w| w.usbevent().clear());
80 BUS_WAKER.wake();
81 }
82
83 if regs.events_epdata.read().bits() != 0 {
84 regs.events_epdata.reset();
85
86 let r = regs.epdatastatus.read().bits();
87 for i in 1..=7 {
88 if r & (1 << i) != 0 {
89 EP_IN_WAKERS[i].wake();
90 }
91 if r & (1 << (i + 16)) != 0 {
92 EP_OUT_WAKERS[i].wake();
93 }
94 }
57 } 95 }
58 } 96 }
59 97
@@ -153,6 +191,12 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
153 191
154 unsafe { NVIC::unmask(pac::Interrupt::USBD) }; 192 unsafe { NVIC::unmask(pac::Interrupt::USBD) };
155 193
194 regs.intenset.write(|w| {
195 w.usbreset().set_bit();
196 w.usbevent().set_bit();
197 w.epdata().set_bit();
198 w
199 });
156 // Enable the USB pullup, allowing enumeration. 200 // Enable the USB pullup, allowing enumeration.
157 regs.usbpullup.write(|w| w.connect().enabled()); 201 regs.usbpullup.write(|w| w.connect().enabled());
158 info!("enabled"); 202 info!("enabled");
@@ -172,6 +216,49 @@ pub struct Bus<'d, T: Instance> {
172} 216}
173 217
174impl<'d, T: Instance> driver::Bus for Bus<'d, T> { 218impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
219 type PollFuture<'a>
220 where
221 Self: 'a,
222 = impl Future<Output = Event> + 'a;
223
224 fn poll<'a>(&'a mut self) -> Self::PollFuture<'a> {
225 poll_fn(|cx| {
226 BUS_WAKER.register(cx.waker());
227 let regs = T::regs();
228
229 if regs.events_usbreset.read().bits() != 0 {
230 regs.events_usbreset.reset();
231 regs.intenset.write(|w| w.usbreset().set());
232 return Poll::Ready(Event::Reset);
233 }
234
235 let r = regs.eventcause.read();
236
237 if r.isooutcrc().bit() {
238 regs.eventcause.write(|w| w.isooutcrc().set_bit());
239 info!("USB event: isooutcrc");
240 }
241 if r.usbwuallowed().bit() {
242 regs.eventcause.write(|w| w.usbwuallowed().set_bit());
243 info!("USB event: usbwuallowed");
244 }
245 if r.suspend().bit() {
246 regs.eventcause.write(|w| w.suspend().set_bit());
247 info!("USB event: suspend");
248 }
249 if r.resume().bit() {
250 regs.eventcause.write(|w| w.resume().set_bit());
251 info!("USB event: resume");
252 }
253 if r.ready().bit() {
254 regs.eventcause.write(|w| w.ready().set_bit());
255 info!("USB event: ready");
256 }
257
258 Poll::Pending
259 })
260 }
261
175 #[inline] 262 #[inline]
176 fn reset(&mut self) { 263 fn reset(&mut self) {
177 let regs = T::regs(); 264 let regs = T::regs();
@@ -260,40 +347,95 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
260 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { 347 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
261 async move { 348 async move {
262 let regs = T::regs(); 349 let regs = T::regs();
350 let i = self.info.addr.index();
263 351
264 if buf.len() == 0 { 352 if i == 0 {
265 regs.tasks_ep0status.write(|w| unsafe { w.bits(1) }); 353 if buf.len() == 0 {
266 return Ok(0); 354 regs.tasks_ep0status.write(|w| unsafe { w.bits(1) });
267 } 355 return Ok(0);
356 }
357
358 // Wait for SETUP packet
359 regs.events_ep0setup.reset();
360 regs.intenset.write(|w| w.ep0setup().set());
361 poll_fn(|cx| {
362 EP_OUT_WAKERS[0].register(cx.waker());
363 let regs = T::regs();
364 if regs.events_ep0setup.read().bits() != 0 {
365 Poll::Ready(())
366 } else {
367 Poll::Pending
368 }
369 })
370 .await;
371 info!("got SETUP");
268 372
269 // Wait for SETUP packet 373 if buf.len() < 8 {
270 regs.events_ep0setup.reset(); 374 return Err(ReadError::BufferOverflow);
271 regs.intenset.write(|w| w.ep0setup().set());
272 poll_fn(|cx| {
273 EP0_WAKER.register(cx.waker());
274 if regs.events_ep0setup.read().bits() != 0 {
275 Poll::Ready(())
276 } else {
277 Poll::Pending
278 } 375 }
279 })
280 .await;
281 info!("got SETUP");
282 376
283 if buf.len() < 8 { 377 buf[0] = regs.bmrequesttype.read().bits() as u8;
284 return Err(ReadError::BufferOverflow); 378 buf[1] = regs.brequest.read().brequest().bits();
285 } 379 buf[2] = regs.wvaluel.read().wvaluel().bits();
380 buf[3] = regs.wvalueh.read().wvalueh().bits();
381 buf[4] = regs.windexl.read().windexl().bits();
382 buf[5] = regs.windexh.read().windexh().bits();
383 buf[6] = regs.wlengthl.read().wlengthl().bits();
384 buf[7] = regs.wlengthh.read().wlengthh().bits();
385
386 Ok(8)
387 } else {
388 poll_fn(|cx| {
389 EP_OUT_WAKERS[i].register(cx.waker());
390 let regs = T::regs();
391 let r = regs.epdatastatus.read().bits();
392 if r & (1 << (i + 16)) != 0 {
393 Poll::Ready(())
394 } else {
395 Poll::Pending
396 }
397 })
398 .await;
286 399
287 buf[0] = regs.bmrequesttype.read().bits() as u8; 400 // Clear status
288 buf[1] = regs.brequest.read().brequest().bits(); 401 regs.epdatastatus
289 buf[2] = regs.wvaluel.read().wvaluel().bits(); 402 .write(|w| unsafe { w.bits(1 << (i + 16)) });
290 buf[3] = regs.wvalueh.read().wvalueh().bits();
291 buf[4] = regs.windexl.read().windexl().bits();
292 buf[5] = regs.windexh.read().windexh().bits();
293 buf[6] = regs.wlengthl.read().wlengthl().bits();
294 buf[7] = regs.wlengthh.read().wlengthh().bits();
295 403
296 Ok(8) 404 // Check that the packet fits into the buffer
405 let size = regs.size.epout[i].read().bits();
406 if size as usize > buf.len() {
407 return Err(ReadError::BufferOverflow);
408 }
409
410 let epout = [
411 &regs.epout0,
412 &regs.epout1,
413 &regs.epout2,
414 &regs.epout3,
415 &regs.epout4,
416 &regs.epout5,
417 &regs.epout6,
418 &regs.epout7,
419 ];
420 epout[i]
421 .ptr
422 .write(|w| unsafe { w.bits(buf.as_ptr() as u32) });
423 // MAXCNT must match SIZE
424 epout[i].maxcnt.write(|w| unsafe { w.bits(size) });
425
426 dma_start();
427 regs.events_endepout[i].reset();
428 regs.tasks_startepout[i].write(|w| w.tasks_startepout().set_bit());
429 while regs.events_endepout[i]
430 .read()
431 .events_endepout()
432 .bit_is_clear()
433 {}
434 regs.events_endepout[i].reset();
435 dma_end();
436
437 Ok(size as usize)
438 }
297 } 439 }
298 } 440 }
299} 441}
@@ -331,7 +473,8 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
331 let res = with_timeout( 473 let res = with_timeout(
332 Duration::from_millis(10), 474 Duration::from_millis(10),
333 poll_fn(|cx| { 475 poll_fn(|cx| {
334 EP0_WAKER.register(cx.waker()); 476 EP_IN_WAKERS[0].register(cx.waker());
477 let regs = T::regs();
335 if regs.events_ep0datadone.read().bits() != 0 { 478 if regs.events_ep0datadone.read().bits() != 0 {
336 Poll::Ready(()) 479 Poll::Ready(())
337 } else { 480 } else {