aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-27 19:54:27 +0000
committerGitHub <[email protected]>2024-04-27 19:54:27 +0000
commit0b0027aac3629447ddcfb98df848645947e52d18 (patch)
tree6030c4ca10b5956a035f65ab0b24348a8db7f8fb
parent34074e6eb0741e084653b3ef71163393741f558b (diff)
parent887d7e143029998e84242a864e26f44b2fccb8a3 (diff)
Merge pull request #2881 from bugadani/ep_count
Synopsys: Make max EP count configurable
-rw-r--r--embassy-stm32/src/usb/otg.rs8
-rw-r--r--embassy-usb-synopsys-otg/src/lib.rs144
2 files changed, 84 insertions, 68 deletions
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 9551af99b..5d0e1116e 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -7,7 +7,7 @@ use embassy_usb_synopsys_otg::otg_v1::Otg;
7pub use embassy_usb_synopsys_otg::Config; 7pub use embassy_usb_synopsys_otg::Config;
8use embassy_usb_synopsys_otg::{ 8use embassy_usb_synopsys_otg::{
9 on_interrupt as on_interrupt_impl, Bus as OtgBus, ControlPipe, Driver as OtgDriver, Endpoint, In, OtgInstance, Out, 9 on_interrupt as on_interrupt_impl, Bus as OtgBus, ControlPipe, Driver as OtgDriver, Endpoint, In, OtgInstance, Out,
10 PhyType, State, MAX_EP_COUNT, 10 PhyType, State,
11}; 11};
12 12
13use crate::gpio::AFType; 13use crate::gpio::AFType;
@@ -15,6 +15,8 @@ use crate::interrupt;
15use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
16use crate::rcc::{RccPeripheral, SealedRccPeripheral}; 16use crate::rcc::{RccPeripheral, SealedRccPeripheral};
17 17
18const MAX_EP_COUNT: usize = 9;
19
18/// Interrupt handler. 20/// Interrupt handler.
19pub struct InterruptHandler<T: Instance> { 21pub struct InterruptHandler<T: Instance> {
20 _phantom: PhantomData<T>, 22 _phantom: PhantomData<T>,
@@ -54,7 +56,7 @@ const RX_FIFO_EXTRA_SIZE_WORDS: u16 = 30;
54/// USB driver. 56/// USB driver.
55pub struct Driver<'d, T: Instance> { 57pub struct Driver<'d, T: Instance> {
56 phantom: PhantomData<&'d mut T>, 58 phantom: PhantomData<&'d mut T>,
57 inner: OtgDriver<'d>, 59 inner: OtgDriver<'d, MAX_EP_COUNT>,
58} 60}
59 61
60impl<'d, T: Instance> Driver<'d, T> { 62impl<'d, T: Instance> Driver<'d, T> {
@@ -190,7 +192,7 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
190/// USB bus. 192/// USB bus.
191pub struct Bus<'d, T: Instance> { 193pub struct Bus<'d, T: Instance> {
192 phantom: PhantomData<&'d mut T>, 194 phantom: PhantomData<&'d mut T>,
193 inner: OtgBus<'d>, 195 inner: OtgBus<'d, MAX_EP_COUNT>,
194 inited: bool, 196 inited: bool,
195} 197}
196 198
diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs
index af82de2c1..a84f50e5a 100644
--- a/embassy-usb-synopsys-otg/src/lib.rs
+++ b/embassy-usb-synopsys-otg/src/lib.rs
@@ -23,7 +23,12 @@ pub mod otg_v1;
23use otg_v1::{regs, vals, Otg}; 23use otg_v1::{regs, vals, Otg};
24 24
25/// Handle interrupts. 25/// Handle interrupts.
26pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: usize, quirk_setup_late_cnak: bool) { 26pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(
27 r: Otg,
28 state: &State<MAX_EP_COUNT>,
29 ep_count: usize,
30 quirk_setup_late_cnak: bool,
31) {
27 let ints = r.gintsts().read(); 32 let ints = r.gintsts().read();
28 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() { 33 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
29 // Mask interrupts and notify `Bus` to process them 34 // Mask interrupts and notify `Bus` to process them
@@ -55,13 +60,13 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us
55 while r.grstctl().read().txfflsh() {} 60 while r.grstctl().read().txfflsh() {}
56 } 61 }
57 62
58 if state.ep0_setup_ready.load(Ordering::Relaxed) == false { 63 if state.cp_state.setup_ready.load(Ordering::Relaxed) == false {
59 // SAFETY: exclusive access ensured by atomic bool 64 // SAFETY: exclusive access ensured by atomic bool
60 let data = unsafe { &mut *state.ep0_setup_data.get() }; 65 let data = unsafe { &mut *state.cp_state.setup_data.get() };
61 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); 66 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
62 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); 67 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
63 state.ep0_setup_ready.store(true, Ordering::Release); 68 state.cp_state.setup_ready.store(true, Ordering::Release);
64 state.ep_out_wakers[0].wake(); 69 state.ep_states[0].out_waker.wake();
65 } else { 70 } else {
66 error!("received SETUP before previous finished processing"); 71 error!("received SETUP before previous finished processing");
67 // discard FIFO 72 // discard FIFO
@@ -72,10 +77,11 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us
72 vals::Pktstsd::OUT_DATA_RX => { 77 vals::Pktstsd::OUT_DATA_RX => {
73 trace!("OUT_DATA_RX ep={} len={}", ep_num, len); 78 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
74 79
75 if state.ep_out_size[ep_num].load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY { 80 if state.ep_states[ep_num].out_size.load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY {
76 // SAFETY: Buffer size is allocated to be equal to endpoint's maximum packet size 81 // SAFETY: Buffer size is allocated to be equal to endpoint's maximum packet size
77 // We trust the peripheral to not exceed its configured MPSIZ 82 // We trust the peripheral to not exceed its configured MPSIZ
78 let buf = unsafe { core::slice::from_raw_parts_mut(*state.ep_out_buffers[ep_num].get(), len) }; 83 let buf =
84 unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) };
79 85
80 for chunk in buf.chunks_mut(4) { 86 for chunk in buf.chunks_mut(4) {
81 // RX FIFO is shared so always read from fifo(0) 87 // RX FIFO is shared so always read from fifo(0)
@@ -83,8 +89,8 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us
83 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); 89 chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]);
84 } 90 }
85 91
86 state.ep_out_size[ep_num].store(len as u16, Ordering::Release); 92 state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release);
87 state.ep_out_wakers[ep_num].wake(); 93 state.ep_states[ep_num].out_waker.wake();
88 } else { 94 } else {
89 error!("ep_out buffer overflow index={}", ep_num); 95 error!("ep_out buffer overflow index={}", ep_num);
90 96
@@ -132,7 +138,7 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us
132 }); 138 });
133 } 139 }
134 140
135 state.ep_in_wakers[ep_num].wake(); 141 state.ep_states[ep_num].in_waker.wake();
136 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0); 142 trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0);
137 } 143 }
138 144
@@ -206,17 +212,25 @@ impl PhyType {
206/// Indicates that [State::ep_out_buffers] is empty. 212/// Indicates that [State::ep_out_buffers] is empty.
207const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; 213const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
208 214
209/// USB OTG driver state. 215struct EpState {
210pub struct State<const EP_COUNT: usize> { 216 in_waker: AtomicWaker,
211 /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. 217 out_waker: AtomicWaker,
212 ep0_setup_data: UnsafeCell<[u8; 8]>,
213 ep0_setup_ready: AtomicBool,
214 ep_in_wakers: [AtomicWaker; EP_COUNT],
215 ep_out_wakers: [AtomicWaker; EP_COUNT],
216 /// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint. 218 /// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint.
217 /// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY]. 219 /// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY].
218 ep_out_buffers: [UnsafeCell<*mut u8>; EP_COUNT], 220 out_buffer: UnsafeCell<*mut u8>,
219 ep_out_size: [AtomicU16; EP_COUNT], 221 out_size: AtomicU16,
222}
223
224struct ControlPipeSetupState {
225 /// Holds received SETUP packets. Available if [Ep0State::setup_ready] is true.
226 setup_data: UnsafeCell<[u8; 8]>,
227 setup_ready: AtomicBool,
228}
229
230/// USB OTG driver state.
231pub struct State<const EP_COUNT: usize> {
232 cp_state: ControlPipeSetupState,
233 ep_states: [EpState; EP_COUNT],
220 bus_waker: AtomicWaker, 234 bus_waker: AtomicWaker,
221} 235}
222 236
@@ -229,14 +243,19 @@ impl<const EP_COUNT: usize> State<EP_COUNT> {
229 const NEW_AW: AtomicWaker = AtomicWaker::new(); 243 const NEW_AW: AtomicWaker = AtomicWaker::new();
230 const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); 244 const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _);
231 const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY); 245 const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY);
246 const NEW_EP_STATE: EpState = EpState {
247 in_waker: NEW_AW,
248 out_waker: NEW_AW,
249 out_buffer: NEW_BUF,
250 out_size: NEW_SIZE,
251 };
232 252
233 Self { 253 Self {
234 ep0_setup_data: UnsafeCell::new([0u8; 8]), 254 cp_state: ControlPipeSetupState {
235 ep0_setup_ready: AtomicBool::new(false), 255 setup_data: UnsafeCell::new([0u8; 8]),
236 ep_in_wakers: [NEW_AW; EP_COUNT], 256 setup_ready: AtomicBool::new(false),
237 ep_out_wakers: [NEW_AW; EP_COUNT], 257 },
238 ep_out_buffers: [NEW_BUF; EP_COUNT], 258 ep_states: [NEW_EP_STATE; EP_COUNT],
239 ep_out_size: [NEW_SIZE; EP_COUNT],
240 bus_waker: NEW_AW, 259 bus_waker: NEW_AW,
241 } 260 }
242 } 261 }
@@ -277,16 +296,16 @@ impl Default for Config {
277} 296}
278 297
279/// USB OTG driver. 298/// USB OTG driver.
280pub struct Driver<'d> { 299pub struct Driver<'d, const MAX_EP_COUNT: usize> {
281 config: Config, 300 config: Config,
282 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 301 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
283 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 302 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
284 ep_out_buffer: &'d mut [u8], 303 ep_out_buffer: &'d mut [u8],
285 ep_out_buffer_offset: usize, 304 ep_out_buffer_offset: usize,
286 instance: OtgInstance<'d>, 305 instance: OtgInstance<'d, MAX_EP_COUNT>,
287} 306}
288 307
289impl<'d> Driver<'d> { 308impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
290 /// Initializes the USB OTG peripheral. 309 /// Initializes the USB OTG peripheral.
291 /// 310 ///
292 /// # Arguments 311 /// # Arguments
@@ -296,7 +315,7 @@ impl<'d> Driver<'d> {
296 /// Endpoint allocation will fail if it is too small. 315 /// Endpoint allocation will fail if it is too small.
297 /// * `instance` - The USB OTG peripheral instance and its configuration. 316 /// * `instance` - The USB OTG peripheral instance and its configuration.
298 /// * `config` - The USB driver configuration. 317 /// * `config` - The USB driver configuration.
299 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d>, config: Config) -> Self { 318 pub fn new(ep_out_buffer: &'d mut [u8], instance: OtgInstance<'d, MAX_EP_COUNT>, config: Config) -> Self {
300 Self { 319 Self {
301 config, 320 config,
302 ep_in: [None; MAX_EP_COUNT], 321 ep_in: [None; MAX_EP_COUNT],
@@ -377,11 +396,11 @@ impl<'d> Driver<'d> {
377 396
378 trace!(" index={}", index); 397 trace!(" index={}", index);
379 398
399 let state = &self.instance.state.ep_states[index];
380 if D::dir() == Direction::Out { 400 if D::dir() == Direction::Out {
381 // Buffer capacity check was done above, now allocation cannot fail 401 // Buffer capacity check was done above, now allocation cannot fail
382 unsafe { 402 unsafe {
383 *self.instance.state.ep_out_buffers[index].get() = 403 *state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
384 self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _);
385 } 404 }
386 self.ep_out_buffer_offset += max_packet_size as usize; 405 self.ep_out_buffer_offset += max_packet_size as usize;
387 } 406 }
@@ -389,7 +408,7 @@ impl<'d> Driver<'d> {
389 Ok(Endpoint { 408 Ok(Endpoint {
390 _phantom: PhantomData, 409 _phantom: PhantomData,
391 regs: self.instance.regs, 410 regs: self.instance.regs,
392 state: self.instance.state, 411 state,
393 info: EndpointInfo { 412 info: EndpointInfo {
394 addr: EndpointAddress::from_parts(index, D::dir()), 413 addr: EndpointAddress::from_parts(index, D::dir()),
395 ep_type, 414 ep_type,
@@ -400,11 +419,11 @@ impl<'d> Driver<'d> {
400 } 419 }
401} 420}
402 421
403impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> { 422impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d, MAX_EP_COUNT> {
404 type EndpointOut = Endpoint<'d, Out>; 423 type EndpointOut = Endpoint<'d, Out>;
405 type EndpointIn = Endpoint<'d, In>; 424 type EndpointIn = Endpoint<'d, In>;
406 type ControlPipe = ControlPipe<'d>; 425 type ControlPipe = ControlPipe<'d>;
407 type Bus = Bus<'d>; 426 type Bus = Bus<'d, MAX_EP_COUNT>;
408 427
409 fn alloc_endpoint_in( 428 fn alloc_endpoint_in(
410 &mut self, 429 &mut self,
@@ -438,6 +457,7 @@ impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
438 457
439 let regs = self.instance.regs; 458 let regs = self.instance.regs;
440 let quirk_setup_late_cnak = self.instance.quirk_setup_late_cnak; 459 let quirk_setup_late_cnak = self.instance.quirk_setup_late_cnak;
460 let cp_setup_state = &self.instance.state.cp_state;
441 ( 461 (
442 Bus { 462 Bus {
443 config: self.config, 463 config: self.config,
@@ -448,6 +468,7 @@ impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
448 }, 468 },
449 ControlPipe { 469 ControlPipe {
450 max_packet_size: control_max_packet_size, 470 max_packet_size: control_max_packet_size,
471 setup_state: cp_setup_state,
451 ep_out, 472 ep_out,
452 ep_in, 473 ep_in,
453 regs, 474 regs,
@@ -458,15 +479,15 @@ impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> {
458} 479}
459 480
460/// USB bus. 481/// USB bus.
461pub struct Bus<'d> { 482pub struct Bus<'d, const MAX_EP_COUNT: usize> {
462 config: Config, 483 config: Config,
463 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 484 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
464 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 485 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
465 instance: OtgInstance<'d>, 486 instance: OtgInstance<'d, MAX_EP_COUNT>,
466 inited: bool, 487 inited: bool,
467} 488}
468 489
469impl<'d> Bus<'d> { 490impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
470 fn restore_irqs(&mut self) { 491 fn restore_irqs(&mut self) {
471 self.instance.regs.gintmsk().write(|w| { 492 self.instance.regs.gintmsk().write(|w| {
472 w.set_usbrst(true); 493 w.set_usbrst(true);
@@ -480,9 +501,7 @@ impl<'d> Bus<'d> {
480 w.set_otgint(true); 501 w.set_otgint(true);
481 }); 502 });
482 } 503 }
483}
484 504
485impl<'d> Bus<'d> {
486 /// Returns the PHY type. 505 /// Returns the PHY type.
487 pub fn phy_type(&self) -> PhyType { 506 pub fn phy_type(&self) -> PhyType {
488 self.instance.phy_type 507 self.instance.phy_type
@@ -699,7 +718,7 @@ impl<'d> Bus<'d> {
699 } 718 }
700} 719}
701 720
702impl<'d> embassy_usb_driver::Bus for Bus<'d> { 721impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Bus for Bus<'d, MAX_EP_COUNT> {
703 async fn poll(&mut self) -> Event { 722 async fn poll(&mut self) -> Event {
704 poll_fn(move |cx| { 723 poll_fn(move |cx| {
705 if !self.inited { 724 if !self.inited {
@@ -811,7 +830,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> {
811 }); 830 });
812 }); 831 });
813 832
814 state.ep_out_wakers[ep_addr.index()].wake(); 833 state.ep_states[ep_addr.index()].out_waker.wake();
815 } 834 }
816 Direction::In => { 835 Direction::In => {
817 critical_section::with(|_| { 836 critical_section::with(|_| {
@@ -820,7 +839,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> {
820 }); 839 });
821 }); 840 });
822 841
823 state.ep_in_wakers[ep_addr.index()].wake(); 842 state.ep_states[ep_addr.index()].in_waker.wake();
824 } 843 }
825 } 844 }
826 } 845 }
@@ -879,7 +898,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> {
879 }); 898 });
880 899
881 // Wake `Endpoint::wait_enabled()` 900 // Wake `Endpoint::wait_enabled()`
882 state.ep_out_wakers[ep_addr.index()].wake(); 901 state.ep_states[ep_addr.index()].out_waker.wake();
883 } 902 }
884 Direction::In => { 903 Direction::In => {
885 critical_section::with(|_| { 904 critical_section::with(|_| {
@@ -898,7 +917,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> {
898 }); 917 });
899 918
900 // Wake `Endpoint::wait_enabled()` 919 // Wake `Endpoint::wait_enabled()`
901 state.ep_in_wakers[ep_addr.index()].wake(); 920 state.ep_states[ep_addr.index()].in_waker.wake();
902 } 921 }
903 } 922 }
904 } 923 }
@@ -947,7 +966,7 @@ pub struct Endpoint<'d, D> {
947 _phantom: PhantomData<D>, 966 _phantom: PhantomData<D>,
948 regs: Otg, 967 regs: Otg,
949 info: EndpointInfo, 968 info: EndpointInfo,
950 state: &'d State<{ MAX_EP_COUNT }>, 969 state: &'d EpState,
951} 970}
952 971
953impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { 972impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
@@ -959,7 +978,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> {
959 poll_fn(|cx| { 978 poll_fn(|cx| {
960 let ep_index = self.info.addr.index(); 979 let ep_index = self.info.addr.index();
961 980
962 self.state.ep_in_wakers[ep_index].register(cx.waker()); 981 self.state.in_waker.register(cx.waker());
963 982
964 if self.regs.diepctl(ep_index).read().usbaep() { 983 if self.regs.diepctl(ep_index).read().usbaep() {
965 Poll::Ready(()) 984 Poll::Ready(())
@@ -980,7 +999,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> {
980 poll_fn(|cx| { 999 poll_fn(|cx| {
981 let ep_index = self.info.addr.index(); 1000 let ep_index = self.info.addr.index();
982 1001
983 self.state.ep_out_wakers[ep_index].register(cx.waker()); 1002 self.state.out_waker.register(cx.waker());
984 1003
985 if self.regs.doepctl(ep_index).read().usbaep() { 1004 if self.regs.doepctl(ep_index).read().usbaep() {
986 Poll::Ready(()) 1005 Poll::Ready(())
@@ -998,7 +1017,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
998 1017
999 poll_fn(|cx| { 1018 poll_fn(|cx| {
1000 let index = self.info.addr.index(); 1019 let index = self.info.addr.index();
1001 self.state.ep_out_wakers[index].register(cx.waker()); 1020 self.state.out_waker.register(cx.waker());
1002 1021
1003 let doepctl = self.regs.doepctl(index).read(); 1022 let doepctl = self.regs.doepctl(index).read();
1004 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); 1023 trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,);
@@ -1007,7 +1026,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1007 return Poll::Ready(Err(EndpointError::Disabled)); 1026 return Poll::Ready(Err(EndpointError::Disabled));
1008 } 1027 }
1009 1028
1010 let len = self.state.ep_out_size[index].load(Ordering::Relaxed); 1029 let len = self.state.out_size.load(Ordering::Relaxed);
1011 if len != EP_OUT_BUFFER_EMPTY { 1030 if len != EP_OUT_BUFFER_EMPTY {
1012 trace!("read ep={:?} done len={}", self.info.addr, len); 1031 trace!("read ep={:?} done len={}", self.info.addr, len);
1013 1032
@@ -1016,12 +1035,11 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> {
1016 } 1035 }
1017 1036
1018 // SAFETY: exclusive access ensured by `ep_out_size` atomic variable 1037 // SAFETY: exclusive access ensured by `ep_out_size` atomic variable
1019 let data = 1038 let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) };
1020 unsafe { core::slice::from_raw_parts(*self.state.ep_out_buffers[index].get(), len as usize) };
1021 buf[..len as usize].copy_from_slice(data); 1039 buf[..len as usize].copy_from_slice(data);
1022 1040
1023 // Release buffer 1041 // Release buffer
1024 self.state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); 1042 self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release);
1025 1043
1026 critical_section::with(|_| { 1044 critical_section::with(|_| {
1027 // Receive 1 packet 1045 // Receive 1 packet
@@ -1056,7 +1074,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1056 let index = self.info.addr.index(); 1074 let index = self.info.addr.index();
1057 // Wait for previous transfer to complete and check if endpoint is disabled 1075 // Wait for previous transfer to complete and check if endpoint is disabled
1058 poll_fn(|cx| { 1076 poll_fn(|cx| {
1059 self.state.ep_in_wakers[index].register(cx.waker()); 1077 self.state.in_waker.register(cx.waker());
1060 1078
1061 let diepctl = self.regs.diepctl(index).read(); 1079 let diepctl = self.regs.diepctl(index).read();
1062 let dtxfsts = self.regs.dtxfsts(index).read(); 1080 let dtxfsts = self.regs.dtxfsts(index).read();
@@ -1081,7 +1099,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1081 1099
1082 if buf.len() > 0 { 1100 if buf.len() > 0 {
1083 poll_fn(|cx| { 1101 poll_fn(|cx| {
1084 self.state.ep_in_wakers[index].register(cx.waker()); 1102 self.state.in_waker.register(cx.waker());
1085 1103
1086 let size_words = (buf.len() + 3) / 4; 1104 let size_words = (buf.len() + 3) / 4;
1087 1105
@@ -1141,6 +1159,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> {
1141pub struct ControlPipe<'d> { 1159pub struct ControlPipe<'d> {
1142 max_packet_size: u16, 1160 max_packet_size: u16,
1143 regs: Otg, 1161 regs: Otg,
1162 setup_state: &'d ControlPipeSetupState,
1144 ep_in: Endpoint<'d, In>, 1163 ep_in: Endpoint<'d, In>,
1145 ep_out: Endpoint<'d, Out>, 1164 ep_out: Endpoint<'d, Out>,
1146 quirk_setup_late_cnak: bool, 1165 quirk_setup_late_cnak: bool,
@@ -1153,11 +1172,11 @@ impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1153 1172
1154 async fn setup(&mut self) -> [u8; 8] { 1173 async fn setup(&mut self) -> [u8; 8] {
1155 poll_fn(|cx| { 1174 poll_fn(|cx| {
1156 self.ep_out.state.ep_out_wakers[0].register(cx.waker()); 1175 self.ep_out.state.out_waker.register(cx.waker());
1157 1176
1158 if self.ep_out.state.ep0_setup_ready.load(Ordering::Relaxed) { 1177 if self.setup_state.setup_ready.load(Ordering::Relaxed) {
1159 let data = unsafe { *self.ep_out.state.ep0_setup_data.get() }; 1178 let data = unsafe { *self.setup_state.setup_data.get() };
1160 self.ep_out.state.ep0_setup_ready.store(false, Ordering::Release); 1179 self.setup_state.setup_ready.store(false, Ordering::Release);
1161 1180
1162 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section 1181 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1163 // Receive 1 SETUP packet 1182 // Receive 1 SETUP packet
@@ -1276,17 +1295,12 @@ fn ep0_mpsiz(max_packet_size: u16) -> u16 {
1276 } 1295 }
1277} 1296}
1278 1297
1279/// The number of maximum configurable EPs.
1280// TODO: this should at least be configurable, but ideally not a constant.
1281// Using OtgInstance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps
1282pub const MAX_EP_COUNT: usize = 9;
1283
1284/// Hardware-dependent USB IP configuration. 1298/// Hardware-dependent USB IP configuration.
1285pub struct OtgInstance<'d> { 1299pub struct OtgInstance<'d, const MAX_EP_COUNT: usize> {
1286 /// The USB peripheral. 1300 /// The USB peripheral.
1287 pub regs: Otg, 1301 pub regs: Otg,
1288 /// The USB state. 1302 /// The USB state.
1289 pub state: &'d State<{ MAX_EP_COUNT }>, 1303 pub state: &'d State<MAX_EP_COUNT>,
1290 /// FIFO depth in words. 1304 /// FIFO depth in words.
1291 pub fifo_depth_words: u16, 1305 pub fifo_depth_words: u16,
1292 /// Number of used endpoints. 1306 /// Number of used endpoints.