diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-04-27 19:54:27 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-04-27 19:54:27 +0000 |
| commit | 0b0027aac3629447ddcfb98df848645947e52d18 (patch) | |
| tree | 6030c4ca10b5956a035f65ab0b24348a8db7f8fb | |
| parent | 34074e6eb0741e084653b3ef71163393741f558b (diff) | |
| parent | 887d7e143029998e84242a864e26f44b2fccb8a3 (diff) | |
Merge pull request #2881 from bugadani/ep_count
Synopsys: Make max EP count configurable
| -rw-r--r-- | embassy-stm32/src/usb/otg.rs | 8 | ||||
| -rw-r--r-- | embassy-usb-synopsys-otg/src/lib.rs | 144 |
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; | |||
| 7 | pub use embassy_usb_synopsys_otg::Config; | 7 | pub use embassy_usb_synopsys_otg::Config; |
| 8 | use embassy_usb_synopsys_otg::{ | 8 | use 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 | ||
| 13 | use crate::gpio::AFType; | 13 | use crate::gpio::AFType; |
| @@ -15,6 +15,8 @@ use crate::interrupt; | |||
| 15 | use crate::interrupt::typelevel::Interrupt; | 15 | use crate::interrupt::typelevel::Interrupt; |
| 16 | use crate::rcc::{RccPeripheral, SealedRccPeripheral}; | 16 | use crate::rcc::{RccPeripheral, SealedRccPeripheral}; |
| 17 | 17 | ||
| 18 | const MAX_EP_COUNT: usize = 9; | ||
| 19 | |||
| 18 | /// Interrupt handler. | 20 | /// Interrupt handler. |
| 19 | pub struct InterruptHandler<T: Instance> { | 21 | pub 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. |
| 55 | pub struct Driver<'d, T: Instance> { | 57 | pub 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 | ||
| 60 | impl<'d, T: Instance> Driver<'d, T> { | 62 | impl<'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. |
| 191 | pub struct Bus<'d, T: Instance> { | 193 | pub 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; | |||
| 23 | use otg_v1::{regs, vals, Otg}; | 23 | use otg_v1::{regs, vals, Otg}; |
| 24 | 24 | ||
| 25 | /// Handle interrupts. | 25 | /// Handle interrupts. |
| 26 | pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: usize, quirk_setup_late_cnak: bool) { | 26 | pub 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. |
| 207 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; | 213 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; |
| 208 | 214 | ||
| 209 | /// USB OTG driver state. | 215 | struct EpState { |
| 210 | pub 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 | |||
| 224 | struct 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. | ||
| 231 | pub 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. |
| 280 | pub struct Driver<'d> { | 299 | pub 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 | ||
| 289 | impl<'d> Driver<'d> { | 308 | impl<'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 | ||
| 403 | impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> { | 422 | impl<'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. |
| 461 | pub struct Bus<'d> { | 482 | pub 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 | ||
| 469 | impl<'d> Bus<'d> { | 490 | impl<'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 | ||
| 485 | impl<'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 | ||
| 702 | impl<'d> embassy_usb_driver::Bus for Bus<'d> { | 721 | impl<'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 | ||
| 953 | impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { | 972 | impl<'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> { | |||
| 1141 | pub struct ControlPipe<'d> { | 1159 | pub 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 | ||
| 1282 | pub const MAX_EP_COUNT: usize = 9; | ||
| 1283 | |||
| 1284 | /// Hardware-dependent USB IP configuration. | 1298 | /// Hardware-dependent USB IP configuration. |
| 1285 | pub struct OtgInstance<'d> { | 1299 | pub 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. |
