diff options
Diffstat (limited to 'embassy-usb-synopsys-otg')
| -rw-r--r-- | embassy-usb-synopsys-otg/src/lib.rs | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index 402347017..59be2c0be 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs | |||
| @@ -55,12 +55,12 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us | |||
| 55 | while r.grstctl().read().txfflsh() {} | 55 | while r.grstctl().read().txfflsh() {} |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | if state.ep0_setup_ready.load(Ordering::Relaxed) == false { | 58 | if state.cp_state.setup_ready.load(Ordering::Relaxed) == false { |
| 59 | // SAFETY: exclusive access ensured by atomic bool | 59 | // SAFETY: exclusive access ensured by atomic bool |
| 60 | let data = unsafe { &mut *state.ep0_setup_data.get() }; | 60 | 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()); | 61 | 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()); | 62 | data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes()); |
| 63 | state.ep0_setup_ready.store(true, Ordering::Release); | 63 | state.cp_state.setup_ready.store(true, Ordering::Release); |
| 64 | state.ep_states[0].out_waker.wake(); | 64 | state.ep_states[0].out_waker.wake(); |
| 65 | } else { | 65 | } else { |
| 66 | error!("received SETUP before previous finished processing"); | 66 | error!("received SETUP before previous finished processing"); |
| @@ -216,11 +216,15 @@ struct EpState { | |||
| 216 | out_size: AtomicU16, | 216 | out_size: AtomicU16, |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | struct ControlPipeSetupState { | ||
| 220 | /// Holds received SETUP packets. Available if [Ep0State::setup_ready] is true. | ||
| 221 | setup_data: UnsafeCell<[u8; 8]>, | ||
| 222 | setup_ready: AtomicBool, | ||
| 223 | } | ||
| 224 | |||
| 219 | /// USB OTG driver state. | 225 | /// USB OTG driver state. |
| 220 | pub struct State<const EP_COUNT: usize> { | 226 | pub struct State<const EP_COUNT: usize> { |
| 221 | /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. | 227 | cp_state: ControlPipeSetupState, |
| 222 | ep0_setup_data: UnsafeCell<[u8; 8]>, | ||
| 223 | ep0_setup_ready: AtomicBool, | ||
| 224 | ep_states: [EpState; EP_COUNT], | 228 | ep_states: [EpState; EP_COUNT], |
| 225 | bus_waker: AtomicWaker, | 229 | bus_waker: AtomicWaker, |
| 226 | } | 230 | } |
| @@ -242,8 +246,10 @@ impl<const EP_COUNT: usize> State<EP_COUNT> { | |||
| 242 | }; | 246 | }; |
| 243 | 247 | ||
| 244 | Self { | 248 | Self { |
| 245 | ep0_setup_data: UnsafeCell::new([0u8; 8]), | 249 | cp_state: ControlPipeSetupState { |
| 246 | ep0_setup_ready: AtomicBool::new(false), | 250 | setup_data: UnsafeCell::new([0u8; 8]), |
| 251 | setup_ready: AtomicBool::new(false), | ||
| 252 | }, | ||
| 247 | ep_states: [NEW_EP_STATE; EP_COUNT], | 253 | ep_states: [NEW_EP_STATE; EP_COUNT], |
| 248 | bus_waker: NEW_AW, | 254 | bus_waker: NEW_AW, |
| 249 | } | 255 | } |
| @@ -385,11 +391,11 @@ impl<'d> Driver<'d> { | |||
| 385 | 391 | ||
| 386 | trace!(" index={}", index); | 392 | trace!(" index={}", index); |
| 387 | 393 | ||
| 394 | let state = &self.instance.state.ep_states[index]; | ||
| 388 | if D::dir() == Direction::Out { | 395 | if D::dir() == Direction::Out { |
| 389 | // Buffer capacity check was done above, now allocation cannot fail | 396 | // Buffer capacity check was done above, now allocation cannot fail |
| 390 | unsafe { | 397 | unsafe { |
| 391 | *self.instance.state.ep_states[index].out_buffer.get() = | 398 | *state.out_buffer.get() = self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _); |
| 392 | self.ep_out_buffer.as_mut_ptr().offset(self.ep_out_buffer_offset as _); | ||
| 393 | } | 399 | } |
| 394 | self.ep_out_buffer_offset += max_packet_size as usize; | 400 | self.ep_out_buffer_offset += max_packet_size as usize; |
| 395 | } | 401 | } |
| @@ -397,7 +403,7 @@ impl<'d> Driver<'d> { | |||
| 397 | Ok(Endpoint { | 403 | Ok(Endpoint { |
| 398 | _phantom: PhantomData, | 404 | _phantom: PhantomData, |
| 399 | regs: self.instance.regs, | 405 | regs: self.instance.regs, |
| 400 | state: self.instance.state, | 406 | state, |
| 401 | info: EndpointInfo { | 407 | info: EndpointInfo { |
| 402 | addr: EndpointAddress::from_parts(index, D::dir()), | 408 | addr: EndpointAddress::from_parts(index, D::dir()), |
| 403 | ep_type, | 409 | ep_type, |
| @@ -446,6 +452,7 @@ impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> { | |||
| 446 | 452 | ||
| 447 | let regs = self.instance.regs; | 453 | let regs = self.instance.regs; |
| 448 | let quirk_setup_late_cnak = self.instance.quirk_setup_late_cnak; | 454 | let quirk_setup_late_cnak = self.instance.quirk_setup_late_cnak; |
| 455 | let cp_setup_state = &self.instance.state.cp_state; | ||
| 449 | ( | 456 | ( |
| 450 | Bus { | 457 | Bus { |
| 451 | config: self.config, | 458 | config: self.config, |
| @@ -456,6 +463,7 @@ impl<'d> embassy_usb_driver::Driver<'d> for Driver<'d> { | |||
| 456 | }, | 463 | }, |
| 457 | ControlPipe { | 464 | ControlPipe { |
| 458 | max_packet_size: control_max_packet_size, | 465 | max_packet_size: control_max_packet_size, |
| 466 | setup_state: cp_setup_state, | ||
| 459 | ep_out, | 467 | ep_out, |
| 460 | ep_in, | 468 | ep_in, |
| 461 | regs, | 469 | regs, |
| @@ -955,7 +963,7 @@ pub struct Endpoint<'d, D> { | |||
| 955 | _phantom: PhantomData<D>, | 963 | _phantom: PhantomData<D>, |
| 956 | regs: Otg, | 964 | regs: Otg, |
| 957 | info: EndpointInfo, | 965 | info: EndpointInfo, |
| 958 | state: &'d State<{ MAX_EP_COUNT }>, | 966 | state: &'d EpState, |
| 959 | } | 967 | } |
| 960 | 968 | ||
| 961 | impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { | 969 | impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { |
| @@ -967,7 +975,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { | |||
| 967 | poll_fn(|cx| { | 975 | poll_fn(|cx| { |
| 968 | let ep_index = self.info.addr.index(); | 976 | let ep_index = self.info.addr.index(); |
| 969 | 977 | ||
| 970 | self.state.ep_states[ep_index].in_waker.register(cx.waker()); | 978 | self.state.in_waker.register(cx.waker()); |
| 971 | 979 | ||
| 972 | if self.regs.diepctl(ep_index).read().usbaep() { | 980 | if self.regs.diepctl(ep_index).read().usbaep() { |
| 973 | Poll::Ready(()) | 981 | Poll::Ready(()) |
| @@ -988,7 +996,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> { | |||
| 988 | poll_fn(|cx| { | 996 | poll_fn(|cx| { |
| 989 | let ep_index = self.info.addr.index(); | 997 | let ep_index = self.info.addr.index(); |
| 990 | 998 | ||
| 991 | self.state.ep_states[ep_index].out_waker.register(cx.waker()); | 999 | self.state.out_waker.register(cx.waker()); |
| 992 | 1000 | ||
| 993 | if self.regs.doepctl(ep_index).read().usbaep() { | 1001 | if self.regs.doepctl(ep_index).read().usbaep() { |
| 994 | Poll::Ready(()) | 1002 | Poll::Ready(()) |
| @@ -1006,7 +1014,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 1006 | 1014 | ||
| 1007 | poll_fn(|cx| { | 1015 | poll_fn(|cx| { |
| 1008 | let index = self.info.addr.index(); | 1016 | let index = self.info.addr.index(); |
| 1009 | self.state.ep_states[index].out_waker.register(cx.waker()); | 1017 | self.state.out_waker.register(cx.waker()); |
| 1010 | 1018 | ||
| 1011 | let doepctl = self.regs.doepctl(index).read(); | 1019 | let doepctl = self.regs.doepctl(index).read(); |
| 1012 | trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); | 1020 | trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); |
| @@ -1015,7 +1023,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 1015 | return Poll::Ready(Err(EndpointError::Disabled)); | 1023 | return Poll::Ready(Err(EndpointError::Disabled)); |
| 1016 | } | 1024 | } |
| 1017 | 1025 | ||
| 1018 | let len = self.state.ep_states[index].out_size.load(Ordering::Relaxed); | 1026 | let len = self.state.out_size.load(Ordering::Relaxed); |
| 1019 | if len != EP_OUT_BUFFER_EMPTY { | 1027 | if len != EP_OUT_BUFFER_EMPTY { |
| 1020 | trace!("read ep={:?} done len={}", self.info.addr, len); | 1028 | trace!("read ep={:?} done len={}", self.info.addr, len); |
| 1021 | 1029 | ||
| @@ -1024,14 +1032,11 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 1024 | } | 1032 | } |
| 1025 | 1033 | ||
| 1026 | // SAFETY: exclusive access ensured by `ep_out_size` atomic variable | 1034 | // SAFETY: exclusive access ensured by `ep_out_size` atomic variable |
| 1027 | let data = | 1035 | let data = unsafe { core::slice::from_raw_parts(*self.state.out_buffer.get(), len as usize) }; |
| 1028 | unsafe { core::slice::from_raw_parts(*self.state.ep_states[index].out_buffer.get(), len as usize) }; | ||
| 1029 | buf[..len as usize].copy_from_slice(data); | 1036 | buf[..len as usize].copy_from_slice(data); |
| 1030 | 1037 | ||
| 1031 | // Release buffer | 1038 | // Release buffer |
| 1032 | self.state.ep_states[index] | 1039 | self.state.out_size.store(EP_OUT_BUFFER_EMPTY, Ordering::Release); |
| 1033 | .out_size | ||
| 1034 | .store(EP_OUT_BUFFER_EMPTY, Ordering::Release); | ||
| 1035 | 1040 | ||
| 1036 | critical_section::with(|_| { | 1041 | critical_section::with(|_| { |
| 1037 | // Receive 1 packet | 1042 | // Receive 1 packet |
| @@ -1066,7 +1071,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { | |||
| 1066 | let index = self.info.addr.index(); | 1071 | let index = self.info.addr.index(); |
| 1067 | // Wait for previous transfer to complete and check if endpoint is disabled | 1072 | // Wait for previous transfer to complete and check if endpoint is disabled |
| 1068 | poll_fn(|cx| { | 1073 | poll_fn(|cx| { |
| 1069 | self.state.ep_states[index].in_waker.register(cx.waker()); | 1074 | self.state.in_waker.register(cx.waker()); |
| 1070 | 1075 | ||
| 1071 | let diepctl = self.regs.diepctl(index).read(); | 1076 | let diepctl = self.regs.diepctl(index).read(); |
| 1072 | let dtxfsts = self.regs.dtxfsts(index).read(); | 1077 | let dtxfsts = self.regs.dtxfsts(index).read(); |
| @@ -1091,7 +1096,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { | |||
| 1091 | 1096 | ||
| 1092 | if buf.len() > 0 { | 1097 | if buf.len() > 0 { |
| 1093 | poll_fn(|cx| { | 1098 | poll_fn(|cx| { |
| 1094 | self.state.ep_states[index].in_waker.register(cx.waker()); | 1099 | self.state.in_waker.register(cx.waker()); |
| 1095 | 1100 | ||
| 1096 | let size_words = (buf.len() + 3) / 4; | 1101 | let size_words = (buf.len() + 3) / 4; |
| 1097 | 1102 | ||
| @@ -1151,6 +1156,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { | |||
| 1151 | pub struct ControlPipe<'d> { | 1156 | pub struct ControlPipe<'d> { |
| 1152 | max_packet_size: u16, | 1157 | max_packet_size: u16, |
| 1153 | regs: Otg, | 1158 | regs: Otg, |
| 1159 | setup_state: &'d ControlPipeSetupState, | ||
| 1154 | ep_in: Endpoint<'d, In>, | 1160 | ep_in: Endpoint<'d, In>, |
| 1155 | ep_out: Endpoint<'d, Out>, | 1161 | ep_out: Endpoint<'d, Out>, |
| 1156 | quirk_setup_late_cnak: bool, | 1162 | quirk_setup_late_cnak: bool, |
| @@ -1163,11 +1169,11 @@ impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> { | |||
| 1163 | 1169 | ||
| 1164 | async fn setup(&mut self) -> [u8; 8] { | 1170 | async fn setup(&mut self) -> [u8; 8] { |
| 1165 | poll_fn(|cx| { | 1171 | poll_fn(|cx| { |
| 1166 | self.ep_out.state.ep_states[0].out_waker.register(cx.waker()); | 1172 | self.ep_out.state.out_waker.register(cx.waker()); |
| 1167 | 1173 | ||
| 1168 | if self.ep_out.state.ep0_setup_ready.load(Ordering::Relaxed) { | 1174 | if self.setup_state.setup_ready.load(Ordering::Relaxed) { |
| 1169 | let data = unsafe { *self.ep_out.state.ep0_setup_data.get() }; | 1175 | let data = unsafe { *self.setup_state.setup_data.get() }; |
| 1170 | self.ep_out.state.ep0_setup_ready.store(false, Ordering::Release); | 1176 | self.setup_state.setup_ready.store(false, Ordering::Release); |
| 1171 | 1177 | ||
| 1172 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section | 1178 | // EP0 should not be controlled by `Bus` so this RMW does not need a critical section |
| 1173 | // Receive 1 SETUP packet | 1179 | // Receive 1 SETUP packet |
