aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-04-27 17:18:40 +0200
committerDániel Buga <[email protected]>2024-04-27 17:18:40 +0200
commit7b4d2ab1bec554a4e4d8bf6950e424155fa61f19 (patch)
treec94bc610b5e6bc2b2189b1cc1234ae95b7bb7887
parent34074e6eb0741e084653b3ef71163393741f558b (diff)
Group endpoint states into a per-endpoint struct
-rw-r--r--embassy-usb-synopsys-otg/src/lib.rs70
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.
207const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX; 208const EP_OUT_BUFFER_EMPTY: u16 = u16::MAX;
208 209
210struct 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.
210pub struct State<const EP_COUNT: usize> { 220pub 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() };