aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usb/usb.rs211
1 files changed, 186 insertions, 25 deletions
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 9384c8688..0ab2306c8 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -80,6 +80,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
80 80
81 if istr.ctr() { 81 if istr.ctr() {
82 let index = istr.ep_id() as usize; 82 let index = istr.ep_id() as usize;
83 CTR_TRIGGERED[index].store(true, Ordering::Relaxed);
84
83 let mut epr = regs.epr(index).read(); 85 let mut epr = regs.epr(index).read();
84 if epr.ctr_rx() { 86 if epr.ctr_rx() {
85 if index == 0 && epr.setup() { 87 if index == 0 && epr.setup() {
@@ -120,6 +122,10 @@ const USBRAM_ALIGN: usize = 4;
120const NEW_AW: AtomicWaker = AtomicWaker::new(); 122const NEW_AW: AtomicWaker = AtomicWaker::new();
121static BUS_WAKER: AtomicWaker = NEW_AW; 123static BUS_WAKER: AtomicWaker = NEW_AW;
122static EP0_SETUP: AtomicBool = AtomicBool::new(false); 124static EP0_SETUP: AtomicBool = AtomicBool::new(false);
125
126const NEW_CTR_TRIGGERED: AtomicBool = AtomicBool::new(false);
127static CTR_TRIGGERED: [AtomicBool; EP_COUNT] = [NEW_CTR_TRIGGERED; EP_COUNT];
128
123static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [NEW_AW; EP_COUNT]; 129static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [NEW_AW; EP_COUNT];
124static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [NEW_AW; EP_COUNT]; 130static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [NEW_AW; EP_COUNT];
125static IRQ_RESET: AtomicBool = AtomicBool::new(false); 131static IRQ_RESET: AtomicBool = AtomicBool::new(false);
@@ -163,20 +169,37 @@ fn calc_out_len(len: u16) -> (u16, u16) {
163mod btable { 169mod btable {
164 use super::*; 170 use super::*;
165 171
166 pub(super) fn write_in<T: Instance>(index: usize, addr: u16) { 172 pub(super) fn write_in_tx<T: Instance>(index: usize, addr: u16) {
167 USBRAM.mem(index * 4 + 0).write_value(addr); 173 USBRAM.mem(index * 4 + 0).write_value(addr);
168 } 174 }
169 175
170 pub(super) fn write_in_len<T: Instance>(index: usize, _addr: u16, len: u16) { 176 pub(super) fn write_in_rx<T: Instance>(index: usize, addr: u16) {
177 USBRAM.mem(index * 4 + 2).write_value(addr);
178 }
179
180 pub(super) fn write_in_len_rx<T: Instance>(index: usize, _addr: u16, len: u16) {
181 USBRAM.mem(index * 4 + 3).write_value(len);
182 }
183
184 pub(super) fn write_in_len_tx<T: Instance>(index: usize, _addr: u16, len: u16) {
171 USBRAM.mem(index * 4 + 1).write_value(len); 185 USBRAM.mem(index * 4 + 1).write_value(len);
172 } 186 }
173 187
174 pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { 188 pub(super) fn write_out_rx<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
175 USBRAM.mem(index * 4 + 2).write_value(addr); 189 USBRAM.mem(index * 4 + 2).write_value(addr);
176 USBRAM.mem(index * 4 + 3).write_value(max_len_bits); 190 USBRAM.mem(index * 4 + 3).write_value(max_len_bits);
177 } 191 }
178 192
179 pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 { 193 pub(super) fn write_out_tx<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
194 USBRAM.mem(index * 4 + 0).write_value(addr);
195 USBRAM.mem(index * 4 + 1).write_value(max_len_bits);
196 }
197
198 pub(super) fn read_out_len_tx<T: Instance>(index: usize) -> u16 {
199 USBRAM.mem(index * 4 + 1).read()
200 }
201
202 pub(super) fn read_out_len_rx<T: Instance>(index: usize) -> u16 {
180 USBRAM.mem(index * 4 + 3).read() 203 USBRAM.mem(index * 4 + 3).read()
181 } 204 }
182} 205}
@@ -184,19 +207,37 @@ mod btable {
184mod btable { 207mod btable {
185 use super::*; 208 use super::*;
186 209
187 pub(super) fn write_in<T: Instance>(_index: usize, _addr: u16) {} 210 pub(super) fn write_in_tx<T: Instance>(_index: usize, _addr: u16) {}
188 211
189 pub(super) fn write_in_len<T: Instance>(index: usize, addr: u16, len: u16) { 212 pub(super) fn write_in_rx<T: Instance>(_index: usize, _addr: u16) {}
213
214 pub(super) fn write_in_len_tx<T: Instance>(index: usize, addr: u16, len: u16) {
190 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); 215 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16));
191 } 216 }
192 217
193 pub(super) fn write_out<T: Instance>(index: usize, addr: u16, max_len_bits: u16) { 218 pub(super) fn write_in_len_rx<T: Instance>(index: usize, addr: u16, len: u16) {
219 USBRAM
220 .mem(index * 2 + 1)
221 .write_value((addr as u32) | ((len as u32) << 16));
222 }
223
224 pub(super) fn write_out_tx<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
225 USBRAM
226 .mem(index * 2)
227 .write_value((addr as u32) | ((max_len_bits as u32) << 16));
228 }
229
230 pub(super) fn write_out_rx<T: Instance>(index: usize, addr: u16, max_len_bits: u16) {
194 USBRAM 231 USBRAM
195 .mem(index * 2 + 1) 232 .mem(index * 2 + 1)
196 .write_value((addr as u32) | ((max_len_bits as u32) << 16)); 233 .write_value((addr as u32) | ((max_len_bits as u32) << 16));
197 } 234 }
198 235
199 pub(super) fn read_out_len<T: Instance>(index: usize) -> u16 { 236 pub(super) fn read_out_len_tx<T: Instance>(index: usize) -> u16 {
237 (USBRAM.mem(index * 2).read() >> 16) as u16
238 }
239
240 pub(super) fn read_out_len_rx<T: Instance>(index: usize) -> u16 {
200 (USBRAM.mem(index * 2 + 1).read() >> 16) as u16 241 (USBRAM.mem(index * 2 + 1).read() >> 16) as u16
201 } 242 }
202} 243}
@@ -327,6 +368,13 @@ impl<'d, T: Instance> Driver<'d, T> {
327 return false; // reserved for control pipe 368 return false; // reserved for control pipe
328 } 369 }
329 let used = ep.used_out || ep.used_in; 370 let used = ep.used_out || ep.used_in;
371 if used && (ep.ep_type == EndpointType::Isochronous || ep.ep_type == EndpointType::Bulk) {
372 // Isochronous and bulk endpoints are double-buffered.
373 // Their corresponding endpoint/channel registers are forced to be unidirectional.
374 // Do not reuse this index.
375 return false;
376 }
377
330 let used_dir = match D::dir() { 378 let used_dir = match D::dir() {
331 Direction::Out => ep.used_out, 379 Direction::Out => ep.used_out,
332 Direction::In => ep.used_in, 380 Direction::In => ep.used_in,
@@ -350,7 +398,11 @@ impl<'d, T: Instance> Driver<'d, T> {
350 let addr = self.alloc_ep_mem(len); 398 let addr = self.alloc_ep_mem(len);
351 399
352 trace!(" len_bits = {:04x}", len_bits); 400 trace!(" len_bits = {:04x}", len_bits);
353 btable::write_out::<T>(index, addr, len_bits); 401 btable::write_out_rx::<T>(index, addr, len_bits);
402
403 if ep_type == EndpointType::Isochronous {
404 btable::write_out_tx::<T>(index, addr, len_bits);
405 }
354 406
355 EndpointBuffer { 407 EndpointBuffer {
356 addr, 408 addr,
@@ -366,7 +418,11 @@ impl<'d, T: Instance> Driver<'d, T> {
366 let addr = self.alloc_ep_mem(len); 418 let addr = self.alloc_ep_mem(len);
367 419
368 // ep_in_len is written when actually TXing packets. 420 // ep_in_len is written when actually TXing packets.
369 btable::write_in::<T>(index, addr); 421 btable::write_in_tx::<T>(index, addr);
422
423 if ep_type == EndpointType::Isochronous {
424 btable::write_in_rx::<T>(index, addr);
425 }
370 426
371 EndpointBuffer { 427 EndpointBuffer {
372 addr, 428 addr,
@@ -656,6 +712,18 @@ impl Dir for Out {
656 } 712 }
657} 713}
658 714
715/// Selects the packet buffer.
716///
717/// For double-buffered endpoints, both the `Rx` and `Tx` buffer from a channel are used for the same
718/// direction of transfer. This is opposed to single-buffered endpoints, where one channel can serve
719/// two directions at the same time.
720enum PacketBuffer {
721 /// The RX buffer - must be used for single-buffered OUT endpoints
722 Rx,
723 /// The TX buffer - must be used for single-buffered IN endpoints
724 Tx,
725}
726
659/// USB endpoint. 727/// USB endpoint.
660pub struct Endpoint<'d, T: Instance, D> { 728pub struct Endpoint<'d, T: Instance, D> {
661 _phantom: PhantomData<(&'d mut T, D)>, 729 _phantom: PhantomData<(&'d mut T, D)>,
@@ -664,15 +732,46 @@ pub struct Endpoint<'d, T: Instance, D> {
664} 732}
665 733
666impl<'d, T: Instance, D> Endpoint<'d, T, D> { 734impl<'d, T: Instance, D> Endpoint<'d, T, D> {
667 fn write_data(&mut self, buf: &[u8]) { 735 /// Write to a double-buffered endpoint.
736 ///
737 /// For double-buffered endpoints, the data buffers overlap, but we still need to write to the right counter field.
738 /// The DTOG_TX bit indicates the buffer that is currently in use by the USB peripheral, that is, the buffer in
739 /// which the next transmit packet will be stored, so we need to write the counter of the OTHER buffer, which is
740 /// where the last transmitted packet was stored.
741 fn write_data_double_buffered(&mut self, buf: &[u8], packet_buffer: PacketBuffer) {
668 let index = self.info.addr.index(); 742 let index = self.info.addr.index();
669 self.buf.write(buf); 743 self.buf.write(buf);
670 btable::write_in_len::<T>(index, self.buf.addr, buf.len() as _); 744
745 match packet_buffer {
746 PacketBuffer::Rx => btable::write_in_len_rx::<T>(index, self.buf.addr, buf.len() as _),
747 PacketBuffer::Tx => btable::write_in_len_tx::<T>(index, self.buf.addr, buf.len() as _),
748 }
671 } 749 }
672 750
673 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { 751 /// Write to a single-buffered endpoint.
752 fn write_data(&mut self, buf: &[u8]) {
753 self.write_data_double_buffered(buf, PacketBuffer::Tx);
754 }
755
756 /// Read from a double-buffered endpoint.
757 ///
758 /// For double-buffered endpoints, the data buffers overlap, but we still need to read from the right counter field.
759 /// The DTOG_RX bit indicates the buffer that is currently in use by the USB peripheral, that is, the buffer in
760 /// which the next received packet will be stored, so we need to read the counter of the OTHER buffer, which is
761 /// where the last received packet was stored.
762 fn read_data_double_buffered(
763 &mut self,
764 buf: &mut [u8],
765 packet_buffer: PacketBuffer,
766 ) -> Result<usize, EndpointError> {
674 let index = self.info.addr.index(); 767 let index = self.info.addr.index();
675 let rx_len = btable::read_out_len::<T>(index) as usize & 0x3FF; 768
769 let rx_len = match packet_buffer {
770 PacketBuffer::Rx => btable::read_out_len_rx::<T>(index),
771 PacketBuffer::Tx => btable::read_out_len_tx::<T>(index),
772 } as usize
773 & 0x3FF;
774
676 trace!("READ DONE, rx_len = {}", rx_len); 775 trace!("READ DONE, rx_len = {}", rx_len);
677 if rx_len > buf.len() { 776 if rx_len > buf.len() {
678 return Err(EndpointError::BufferOverflow); 777 return Err(EndpointError::BufferOverflow);
@@ -680,6 +779,11 @@ impl<'d, T: Instance, D> Endpoint<'d, T, D> {
680 self.buf.read(&mut buf[..rx_len]); 779 self.buf.read(&mut buf[..rx_len]);
681 Ok(rx_len) 780 Ok(rx_len)
682 } 781 }
782
783 /// Read from a single-buffered endpoint.
784 fn read_data(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
785 self.read_data_double_buffered(buf, PacketBuffer::Rx)
786 }
683} 787}
684 788
685impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { 789impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> {
@@ -734,25 +838,53 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
734 EP_OUT_WAKERS[index].register(cx.waker()); 838 EP_OUT_WAKERS[index].register(cx.waker());
735 let regs = T::regs(); 839 let regs = T::regs();
736 let stat = regs.epr(index).read().stat_rx(); 840 let stat = regs.epr(index).read().stat_rx();
737 if matches!(stat, Stat::NAK | Stat::DISABLED) { 841 if self.info.ep_type == EndpointType::Isochronous {
738 Poll::Ready(stat) 842 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet.
843 // Therefore, this instead waits until the `CTR` interrupt was triggered.
844 if matches!(stat, Stat::DISABLED) || CTR_TRIGGERED[index].load(Ordering::Relaxed) {
845 Poll::Ready(stat)
846 } else {
847 Poll::Pending
848 }
739 } else { 849 } else {
740 Poll::Pending 850 if matches!(stat, Stat::NAK | Stat::DISABLED) {
851 Poll::Ready(stat)
852 } else {
853 Poll::Pending
854 }
741 } 855 }
742 }) 856 })
743 .await; 857 .await;
744 858
859 CTR_TRIGGERED[index].store(false, Ordering::Relaxed);
860
745 if stat == Stat::DISABLED { 861 if stat == Stat::DISABLED {
746 return Err(EndpointError::Disabled); 862 return Err(EndpointError::Disabled);
747 } 863 }
748 864
749 let rx_len = self.read_data(buf)?;
750
751 let regs = T::regs(); 865 let regs = T::regs();
866
867 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous {
868 // Find the buffer, which is currently in use. Read from the OTHER buffer.
869 if regs.epr(index).read().dtog_rx() {
870 PacketBuffer::Rx
871 } else {
872 PacketBuffer::Tx
873 }
874 } else {
875 PacketBuffer::Rx
876 };
877
878 let rx_len = self.read_data_double_buffered(buf, packet_buffer)?;
879
752 regs.epr(index).write(|w| { 880 regs.epr(index).write(|w| {
753 w.set_ep_type(convert_type(self.info.ep_type)); 881 w.set_ep_type(convert_type(self.info.ep_type));
754 w.set_ea(self.info.addr.index() as _); 882 w.set_ea(self.info.addr.index() as _);
755 w.set_stat_rx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits())); 883 if self.info.ep_type == EndpointType::Isochronous {
884 w.set_stat_rx(Stat::from_bits(0)); // STAT_RX remains `VALID`.
885 } else {
886 w.set_stat_rx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits()));
887 }
756 w.set_stat_tx(Stat::from_bits(0)); 888 w.set_stat_tx(Stat::from_bits(0));
757 w.set_ctr_rx(true); // don't clear 889 w.set_ctr_rx(true); // don't clear
758 w.set_ctr_tx(true); // don't clear 890 w.set_ctr_tx(true); // don't clear
@@ -776,25 +908,54 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
776 EP_IN_WAKERS[index].register(cx.waker()); 908 EP_IN_WAKERS[index].register(cx.waker());
777 let regs = T::regs(); 909 let regs = T::regs();
778 let stat = regs.epr(index).read().stat_tx(); 910 let stat = regs.epr(index).read().stat_tx();
779 if matches!(stat, Stat::NAK | Stat::DISABLED) { 911 if self.info.ep_type == EndpointType::Isochronous {
780 Poll::Ready(stat) 912 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet.
913 // Therefore, this instead waits until the `CTR` interrupt was triggered.
914 if matches!(stat, Stat::DISABLED) || CTR_TRIGGERED[index].load(Ordering::Relaxed) {
915 Poll::Ready(stat)
916 } else {
917 Poll::Pending
918 }
781 } else { 919 } else {
782 Poll::Pending 920 if matches!(stat, Stat::NAK | Stat::DISABLED) {
921 Poll::Ready(stat)
922 } else {
923 Poll::Pending
924 }
783 } 925 }
784 }) 926 })
785 .await; 927 .await;
786 928
929 CTR_TRIGGERED[index].store(false, Ordering::Relaxed);
930
787 if stat == Stat::DISABLED { 931 if stat == Stat::DISABLED {
788 return Err(EndpointError::Disabled); 932 return Err(EndpointError::Disabled);
789 } 933 }
790 934
791 self.write_data(buf); 935 let regs = T::regs();
936
937 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous {
938 // Find the buffer, which is currently in use. Write to the OTHER buffer.
939 if regs.epr(index).read().dtog_tx() {
940 PacketBuffer::Tx
941 } else {
942 PacketBuffer::Rx
943 }
944 } else {
945 PacketBuffer::Tx
946 };
947
948 self.write_data_double_buffered(buf, packet_buffer);
792 949
793 let regs = T::regs(); 950 let regs = T::regs();
794 regs.epr(index).write(|w| { 951 regs.epr(index).write(|w| {
795 w.set_ep_type(convert_type(self.info.ep_type)); 952 w.set_ep_type(convert_type(self.info.ep_type));
796 w.set_ea(self.info.addr.index() as _); 953 w.set_ea(self.info.addr.index() as _);
797 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits())); 954 if self.info.ep_type == EndpointType::Isochronous {
955 w.set_stat_tx(Stat::from_bits(0)); // STAT_TX remains `VALID`.
956 } else {
957 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits()));
958 }
798 w.set_stat_rx(Stat::from_bits(0)); 959 w.set_stat_rx(Stat::from_bits(0));
799 w.set_ctr_rx(true); // don't clear 960 w.set_ctr_rx(true); // don't clear
800 w.set_ctr_tx(true); // don't clear 961 w.set_ctr_tx(true); // don't clear