diff options
| author | Dániel Buga <[email protected]> | 2024-04-27 17:18:40 +0200 |
|---|---|---|
| committer | Dániel Buga <[email protected]> | 2024-04-27 17:18:40 +0200 |
| commit | 7b4d2ab1bec554a4e4d8bf6950e424155fa61f19 (patch) | |
| tree | c94bc610b5e6bc2b2189b1cc1234ae95b7bb7887 /embassy-usb-synopsys-otg | |
| parent | 34074e6eb0741e084653b3ef71163393741f558b (diff) | |
Group endpoint states into a per-endpoint struct
Diffstat (limited to 'embassy-usb-synopsys-otg')
| -rw-r--r-- | embassy-usb-synopsys-otg/src/lib.rs | 70 |
1 files changed, 40 insertions, 30 deletions
diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index af82de2c1..402347017 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs | |||
| @@ -61,7 +61,7 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us | |||
| 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.ep0_setup_ready.store(true, Ordering::Release); |
| 64 | state.ep_out_wakers[0].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"); |
| 67 | // discard FIFO | 67 | // discard FIFO |
| @@ -72,10 +72,11 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us | |||
| 72 | vals::Pktstsd::OUT_DATA_RX => { | 72 | vals::Pktstsd::OUT_DATA_RX => { |
| 73 | trace!("OUT_DATA_RX ep={} len={}", ep_num, len); | 73 | trace!("OUT_DATA_RX ep={} len={}", ep_num, len); |
| 74 | 74 | ||
| 75 | if state.ep_out_size[ep_num].load(Ordering::Acquire) == EP_OUT_BUFFER_EMPTY { | 75 | 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 | 76 | // 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 | 77 | // 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) }; | 78 | let buf = |
| 79 | unsafe { core::slice::from_raw_parts_mut(*state.ep_states[ep_num].out_buffer.get(), len) }; | ||
| 79 | 80 | ||
| 80 | for chunk in buf.chunks_mut(4) { | 81 | for chunk in buf.chunks_mut(4) { |
| 81 | // RX FIFO is shared so always read from fifo(0) | 82 | // RX FIFO is shared so always read from fifo(0) |
| @@ -83,8 +84,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()]); | 84 | chunk.copy_from_slice(&data.to_ne_bytes()[0..chunk.len()]); |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | state.ep_out_size[ep_num].store(len as u16, Ordering::Release); | 87 | state.ep_states[ep_num].out_size.store(len as u16, Ordering::Release); |
| 87 | state.ep_out_wakers[ep_num].wake(); | 88 | state.ep_states[ep_num].out_waker.wake(); |
| 88 | } else { | 89 | } else { |
| 89 | error!("ep_out buffer overflow index={}", ep_num); | 90 | error!("ep_out buffer overflow index={}", ep_num); |
| 90 | 91 | ||
| @@ -132,7 +133,7 @@ pub unsafe fn on_interrupt(r: Otg, state: &State<{ MAX_EP_COUNT }>, ep_count: us | |||
| 132 | }); | 133 | }); |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | state.ep_in_wakers[ep_num].wake(); | 136 | state.ep_states[ep_num].in_waker.wake(); |
| 136 | trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0); | 137 | trace!("in ep={} irq val={:08x}", ep_num, ep_ints.0); |
| 137 | } | 138 | } |
| 138 | 139 | ||
| @@ -206,17 +207,21 @@ impl PhyType { | |||
| 206 | /// Indicates that [State::ep_out_buffers] is empty. | 207 | /// Indicates that [State::ep_out_buffers] is empty. |
| 207 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; | 208 | const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; |
| 208 | 209 | ||
| 210 | struct EpState { | ||
| 211 | in_waker: AtomicWaker, | ||
| 212 | out_waker: AtomicWaker, | ||
| 213 | /// RX FIFO is shared so extra buffers are needed to dequeue all data without waiting on each endpoint. | ||
| 214 | /// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY]. | ||
| 215 | out_buffer: UnsafeCell<*mut u8>, | ||
| 216 | out_size: AtomicU16, | ||
| 217 | } | ||
| 218 | |||
| 209 | /// USB OTG driver state. | 219 | /// USB OTG driver state. |
| 210 | pub struct State<const EP_COUNT: usize> { | 220 | pub struct State<const EP_COUNT: usize> { |
| 211 | /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. | 221 | /// Holds received SETUP packets. Available if [State::ep0_setup_ready] is true. |
| 212 | ep0_setup_data: UnsafeCell<[u8; 8]>, | 222 | ep0_setup_data: UnsafeCell<[u8; 8]>, |
| 213 | ep0_setup_ready: AtomicBool, | 223 | ep0_setup_ready: AtomicBool, |
| 214 | ep_in_wakers: [AtomicWaker; EP_COUNT], | 224 | ep_states: [EpState; 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. | ||
| 217 | /// Buffers are ready when associated [State::ep_out_size] != [EP_OUT_BUFFER_EMPTY]. | ||
| 218 | ep_out_buffers: [UnsafeCell<*mut u8>; EP_COUNT], | ||
| 219 | ep_out_size: [AtomicU16; EP_COUNT], | ||
| 220 | bus_waker: AtomicWaker, | 225 | bus_waker: AtomicWaker, |
| 221 | } | 226 | } |
| 222 | 227 | ||
| @@ -229,14 +234,17 @@ impl<const EP_COUNT: usize> State<EP_COUNT> { | |||
| 229 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | 234 | const NEW_AW: AtomicWaker = AtomicWaker::new(); |
| 230 | const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); | 235 | const NEW_BUF: UnsafeCell<*mut u8> = UnsafeCell::new(0 as _); |
| 231 | const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY); | 236 | const NEW_SIZE: AtomicU16 = AtomicU16::new(EP_OUT_BUFFER_EMPTY); |
| 237 | const NEW_EP_STATE: EpState = EpState { | ||
| 238 | in_waker: NEW_AW, | ||
| 239 | out_waker: NEW_AW, | ||
| 240 | out_buffer: NEW_BUF, | ||
| 241 | out_size: NEW_SIZE, | ||
| 242 | }; | ||
| 232 | 243 | ||
| 233 | Self { | 244 | Self { |
| 234 | ep0_setup_data: UnsafeCell::new([0u8; 8]), | 245 | ep0_setup_data: UnsafeCell::new([0u8; 8]), |
| 235 | ep0_setup_ready: AtomicBool::new(false), | 246 | ep0_setup_ready: AtomicBool::new(false), |
| 236 | ep_in_wakers: [NEW_AW; EP_COUNT], | 247 | ep_states: [NEW_EP_STATE; EP_COUNT], |
| 237 | ep_out_wakers: [NEW_AW; EP_COUNT], | ||
| 238 | ep_out_buffers: [NEW_BUF; EP_COUNT], | ||
| 239 | ep_out_size: [NEW_SIZE; EP_COUNT], | ||
| 240 | bus_waker: NEW_AW, | 248 | bus_waker: NEW_AW, |
| 241 | } | 249 | } |
| 242 | } | 250 | } |
| @@ -380,7 +388,7 @@ impl<'d> Driver<'d> { | |||
| 380 | if D::dir() == Direction::Out { | 388 | if D::dir() == Direction::Out { |
| 381 | // Buffer capacity check was done above, now allocation cannot fail | 389 | // Buffer capacity check was done above, now allocation cannot fail |
| 382 | unsafe { | 390 | unsafe { |
| 383 | *self.instance.state.ep_out_buffers[index].get() = | 391 | *self.instance.state.ep_states[index].out_buffer.get() = |
| 384 | 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 _); |
| 385 | } | 393 | } |
| 386 | self.ep_out_buffer_offset += max_packet_size as usize; | 394 | self.ep_out_buffer_offset += max_packet_size as usize; |
| @@ -811,7 +819,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> { | |||
| 811 | }); | 819 | }); |
| 812 | }); | 820 | }); |
| 813 | 821 | ||
| 814 | state.ep_out_wakers[ep_addr.index()].wake(); | 822 | state.ep_states[ep_addr.index()].out_waker.wake(); |
| 815 | } | 823 | } |
| 816 | Direction::In => { | 824 | Direction::In => { |
| 817 | critical_section::with(|_| { | 825 | critical_section::with(|_| { |
| @@ -820,7 +828,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> { | |||
| 820 | }); | 828 | }); |
| 821 | }); | 829 | }); |
| 822 | 830 | ||
| 823 | state.ep_in_wakers[ep_addr.index()].wake(); | 831 | state.ep_states[ep_addr.index()].in_waker.wake(); |
| 824 | } | 832 | } |
| 825 | } | 833 | } |
| 826 | } | 834 | } |
| @@ -879,7 +887,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> { | |||
| 879 | }); | 887 | }); |
| 880 | 888 | ||
| 881 | // Wake `Endpoint::wait_enabled()` | 889 | // Wake `Endpoint::wait_enabled()` |
| 882 | state.ep_out_wakers[ep_addr.index()].wake(); | 890 | state.ep_states[ep_addr.index()].out_waker.wake(); |
| 883 | } | 891 | } |
| 884 | Direction::In => { | 892 | Direction::In => { |
| 885 | critical_section::with(|_| { | 893 | critical_section::with(|_| { |
| @@ -898,7 +906,7 @@ impl<'d> embassy_usb_driver::Bus for Bus<'d> { | |||
| 898 | }); | 906 | }); |
| 899 | 907 | ||
| 900 | // Wake `Endpoint::wait_enabled()` | 908 | // Wake `Endpoint::wait_enabled()` |
| 901 | state.ep_in_wakers[ep_addr.index()].wake(); | 909 | state.ep_states[ep_addr.index()].in_waker.wake(); |
| 902 | } | 910 | } |
| 903 | } | 911 | } |
| 904 | } | 912 | } |
| @@ -959,7 +967,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, In> { | |||
| 959 | poll_fn(|cx| { | 967 | poll_fn(|cx| { |
| 960 | let ep_index = self.info.addr.index(); | 968 | let ep_index = self.info.addr.index(); |
| 961 | 969 | ||
| 962 | self.state.ep_in_wakers[ep_index].register(cx.waker()); | 970 | self.state.ep_states[ep_index].in_waker.register(cx.waker()); |
| 963 | 971 | ||
| 964 | if self.regs.diepctl(ep_index).read().usbaep() { | 972 | if self.regs.diepctl(ep_index).read().usbaep() { |
| 965 | Poll::Ready(()) | 973 | Poll::Ready(()) |
| @@ -980,7 +988,7 @@ impl<'d> embassy_usb_driver::Endpoint for Endpoint<'d, Out> { | |||
| 980 | poll_fn(|cx| { | 988 | poll_fn(|cx| { |
| 981 | let ep_index = self.info.addr.index(); | 989 | let ep_index = self.info.addr.index(); |
| 982 | 990 | ||
| 983 | self.state.ep_out_wakers[ep_index].register(cx.waker()); | 991 | self.state.ep_states[ep_index].out_waker.register(cx.waker()); |
| 984 | 992 | ||
| 985 | if self.regs.doepctl(ep_index).read().usbaep() { | 993 | if self.regs.doepctl(ep_index).read().usbaep() { |
| 986 | Poll::Ready(()) | 994 | Poll::Ready(()) |
| @@ -998,7 +1006,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 998 | 1006 | ||
| 999 | poll_fn(|cx| { | 1007 | poll_fn(|cx| { |
| 1000 | let index = self.info.addr.index(); | 1008 | let index = self.info.addr.index(); |
| 1001 | self.state.ep_out_wakers[index].register(cx.waker()); | 1009 | self.state.ep_states[index].out_waker.register(cx.waker()); |
| 1002 | 1010 | ||
| 1003 | let doepctl = self.regs.doepctl(index).read(); | 1011 | let doepctl = self.regs.doepctl(index).read(); |
| 1004 | trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); | 1012 | trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); |
| @@ -1007,7 +1015,7 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 1007 | return Poll::Ready(Err(EndpointError::Disabled)); | 1015 | return Poll::Ready(Err(EndpointError::Disabled)); |
| 1008 | } | 1016 | } |
| 1009 | 1017 | ||
| 1010 | let len = self.state.ep_out_size[index].load(Ordering::Relaxed); | 1018 | let len = self.state.ep_states[index].out_size.load(Ordering::Relaxed); |
| 1011 | if len != EP_OUT_BUFFER_EMPTY { | 1019 | if len != EP_OUT_BUFFER_EMPTY { |
| 1012 | trace!("read ep={:?} done len={}", self.info.addr, len); | 1020 | trace!("read ep={:?} done len={}", self.info.addr, len); |
| 1013 | 1021 | ||
| @@ -1017,11 +1025,13 @@ impl<'d> embassy_usb_driver::EndpointOut for Endpoint<'d, Out> { | |||
| 1017 | 1025 | ||
| 1018 | // SAFETY: exclusive access ensured by `ep_out_size` atomic variable | 1026 | // SAFETY: exclusive access ensured by `ep_out_size` atomic variable |
| 1019 | let data = | 1027 | let data = |
| 1020 | unsafe { core::slice::from_raw_parts(*self.state.ep_out_buffers[index].get(), len as usize) }; | 1028 | unsafe { core::slice::from_raw_parts(*self.state.ep_states[index].out_buffer.get(), len as usize) }; |
| 1021 | buf[..len as usize].copy_from_slice(data); | 1029 | buf[..len as usize].copy_from_slice(data); |
| 1022 | 1030 | ||
| 1023 | // Release buffer | 1031 | // Release buffer |
| 1024 | self.state.ep_out_size[index].store(EP_OUT_BUFFER_EMPTY, Ordering::Release); | 1032 | self.state.ep_states[index] |
| 1033 | .out_size | ||
| 1034 | .store(EP_OUT_BUFFER_EMPTY, Ordering::Release); | ||
| 1025 | 1035 | ||
| 1026 | critical_section::with(|_| { | 1036 | critical_section::with(|_| { |
| 1027 | // Receive 1 packet | 1037 | // Receive 1 packet |
| @@ -1056,7 +1066,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { | |||
| 1056 | let index = self.info.addr.index(); | 1066 | let index = self.info.addr.index(); |
| 1057 | // Wait for previous transfer to complete and check if endpoint is disabled | 1067 | // Wait for previous transfer to complete and check if endpoint is disabled |
| 1058 | poll_fn(|cx| { | 1068 | poll_fn(|cx| { |
| 1059 | self.state.ep_in_wakers[index].register(cx.waker()); | 1069 | self.state.ep_states[index].in_waker.register(cx.waker()); |
| 1060 | 1070 | ||
| 1061 | let diepctl = self.regs.diepctl(index).read(); | 1071 | let diepctl = self.regs.diepctl(index).read(); |
| 1062 | let dtxfsts = self.regs.dtxfsts(index).read(); | 1072 | let dtxfsts = self.regs.dtxfsts(index).read(); |
| @@ -1081,7 +1091,7 @@ impl<'d> embassy_usb_driver::EndpointIn for Endpoint<'d, In> { | |||
| 1081 | 1091 | ||
| 1082 | if buf.len() > 0 { | 1092 | if buf.len() > 0 { |
| 1083 | poll_fn(|cx| { | 1093 | poll_fn(|cx| { |
| 1084 | self.state.ep_in_wakers[index].register(cx.waker()); | 1094 | self.state.ep_states[index].in_waker.register(cx.waker()); |
| 1085 | 1095 | ||
| 1086 | let size_words = (buf.len() + 3) / 4; | 1096 | let size_words = (buf.len() + 3) / 4; |
| 1087 | 1097 | ||
| @@ -1153,7 +1163,7 @@ impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> { | |||
| 1153 | 1163 | ||
| 1154 | async fn setup(&mut self) -> [u8; 8] { | 1164 | async fn setup(&mut self) -> [u8; 8] { |
| 1155 | poll_fn(|cx| { | 1165 | poll_fn(|cx| { |
| 1156 | self.ep_out.state.ep_out_wakers[0].register(cx.waker()); | 1166 | self.ep_out.state.ep_states[0].out_waker.register(cx.waker()); |
| 1157 | 1167 | ||
| 1158 | if self.ep_out.state.ep0_setup_ready.load(Ordering::Relaxed) { | 1168 | if self.ep_out.state.ep0_setup_ready.load(Ordering::Relaxed) { |
| 1159 | let data = unsafe { *self.ep_out.state.ep0_setup_data.get() }; | 1169 | let data = unsafe { *self.ep_out.state.ep0_setup_data.get() }; |
