aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-03-16 21:37:24 +0100
committerGitHub <[email protected]>2025-03-16 21:37:24 +0100
commit2e004ccf9ee68d09a70c04c8c62c0558252af575 (patch)
treede80577b46363a4ab14a382f5981019c553c2387
parent38f26137fc67beb874aa73c9a7ab2150d9f3d372 (diff)
parentcecbe082ff5505b69cd4cc7138a4275d7af4aa8a (diff)
Merge pull request #3970 from elagil/fix_usb_iso_in_ep_stat
Fix USB ISO IN EP stat and ISO OUT buffer order
-rw-r--r--embassy-stm32/src/usb/usb.rs158
1 files changed, 83 insertions, 75 deletions
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index b9a16bbf1..8dabfc78f 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -80,10 +80,10 @@ 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
85 let mut epr = regs.epr(index).read(); 84 let mut epr = regs.epr(index).read();
86 if epr.ctr_rx() { 85 if epr.ctr_rx() {
86 RX_COMPLETE[index].store(true, Ordering::Relaxed);
87 if index == 0 && epr.setup() { 87 if index == 0 && epr.setup() {
88 EP0_SETUP.store(true, Ordering::Relaxed); 88 EP0_SETUP.store(true, Ordering::Relaxed);
89 } 89 }
@@ -91,6 +91,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
91 EP_OUT_WAKERS[index].wake(); 91 EP_OUT_WAKERS[index].wake();
92 } 92 }
93 if epr.ctr_tx() { 93 if epr.ctr_tx() {
94 TX_PENDING[index].store(false, Ordering::Relaxed);
94 //trace!("EP {} TX", index); 95 //trace!("EP {} TX", index);
95 EP_IN_WAKERS[index].wake(); 96 EP_IN_WAKERS[index].wake();
96 } 97 }
@@ -122,7 +123,8 @@ const USBRAM_ALIGN: usize = 4;
122static BUS_WAKER: AtomicWaker = AtomicWaker::new(); 123static BUS_WAKER: AtomicWaker = AtomicWaker::new();
123static EP0_SETUP: AtomicBool = AtomicBool::new(false); 124static EP0_SETUP: AtomicBool = AtomicBool::new(false);
124 125
125static CTR_TRIGGERED: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT]; 126static TX_PENDING: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT];
127static RX_COMPLETE: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT];
126static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT]; 128static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT];
127static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT]; 129static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT];
128static IRQ_RESET: AtomicBool = AtomicBool::new(false); 130static IRQ_RESET: AtomicBool = AtomicBool::new(false);
@@ -204,15 +206,13 @@ mod btable {
204mod btable { 206mod btable {
205 use super::*; 207 use super::*;
206 208
207 pub(super) fn write_in_tx<T: Instance>(_index: usize, _addr: u16) {}
208
209 pub(super) fn write_in_rx<T: Instance>(_index: usize, _addr: u16) {}
210
211 pub(super) fn write_in_len_tx<T: Instance>(index: usize, addr: u16, len: u16) { 209 pub(super) fn write_in_len_tx<T: Instance>(index: usize, addr: u16, len: u16) {
210 assert_eq!(addr & 0b11, 0);
212 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); 211 USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16));
213 } 212 }
214 213
215 pub(super) fn write_in_len_rx<T: Instance>(index: usize, addr: u16, len: u16) { 214 pub(super) fn write_in_len_rx<T: Instance>(index: usize, addr: u16, len: u16) {
215 assert_eq!(addr & 0b11, 0);
216 USBRAM 216 USBRAM
217 .mem(index * 2 + 1) 217 .mem(index * 2 + 1)
218 .write_value((addr as u32) | ((len as u32) << 16)); 218 .write_value((addr as u32) | ((len as u32) << 16));
@@ -363,10 +363,11 @@ impl<'d, T: Instance> Driver<'d, T> {
363 return false; // reserved for control pipe 363 return false; // reserved for control pipe
364 } 364 }
365 let used = ep.used_out || ep.used_in; 365 let used = ep.used_out || ep.used_in;
366 if used && (ep.ep_type == EndpointType::Isochronous || ep.ep_type == EndpointType::Bulk) { 366 if used && (ep.ep_type == EndpointType::Isochronous) {
367 // Isochronous and bulk endpoints are double-buffered. 367 // Isochronous endpoints are always double-buffered.
368 // Their corresponding endpoint/channel registers are forced to be unidirectional. 368 // Their corresponding endpoint/channel registers are forced to be unidirectional.
369 // Do not reuse this index. 369 // Do not reuse this index.
370 // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation.
370 return false; 371 return false;
371 } 372 }
372 373
@@ -412,11 +413,23 @@ impl<'d, T: Instance> Driver<'d, T> {
412 let len = align_len_up(max_packet_size); 413 let len = align_len_up(max_packet_size);
413 let addr = self.alloc_ep_mem(len); 414 let addr = self.alloc_ep_mem(len);
414 415
415 // ep_in_len is written when actually TXing packets. 416 #[cfg(not(any(usbram_32_2048, usbram_32_1024)))]
416 btable::write_in_tx::<T>(index, addr); 417 {
418 // ep_in_len is written when actually transmitting packets.
419 btable::write_in_tx::<T>(index, addr);
417 420
418 if ep_type == EndpointType::Isochronous { 421 if ep_type == EndpointType::Isochronous {
419 btable::write_in_rx::<T>(index, addr); 422 btable::write_in_rx::<T>(index, addr);
423 }
424 }
425
426 #[cfg(any(usbram_32_2048, usbram_32_1024))]
427 {
428 btable::write_in_len_tx::<T>(index, addr, 0);
429
430 if ep_type == EndpointType::Isochronous {
431 btable::write_in_len_rx::<T>(index, addr, 0);
432 }
420 } 433 }
421 434
422 EndpointBuffer { 435 EndpointBuffer {
@@ -640,22 +653,25 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
640 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) { 653 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) {
641 trace!("set_enabled {:?} {}", ep_addr, enabled); 654 trace!("set_enabled {:?} {}", ep_addr, enabled);
642 // This can race, so do a retry loop. 655 // This can race, so do a retry loop.
643 let reg = T::regs().epr(ep_addr.index() as _); 656 let epr = T::regs().epr(ep_addr.index() as _);
644 trace!("EPR before: {:04x}", reg.read().0); 657 trace!("EPR before: {:04x}", epr.read().0);
645 match ep_addr.direction() { 658 match ep_addr.direction() {
646 Direction::In => { 659 Direction::In => {
647 loop { 660 loop {
648 let want_stat = match enabled { 661 let want_stat = match enabled {
649 false => Stat::DISABLED, 662 false => Stat::DISABLED,
650 true => Stat::NAK, 663 true => match epr.read().ep_type() {
664 EpType::ISO => Stat::VALID,
665 _ => Stat::NAK,
666 },
651 }; 667 };
652 let r = reg.read(); 668 let r = epr.read();
653 if r.stat_tx() == want_stat { 669 if r.stat_tx() == want_stat {
654 break; 670 break;
655 } 671 }
656 let mut w = invariant(r); 672 let mut w = invariant(r);
657 w.set_stat_tx(Stat::from_bits(r.stat_tx().to_bits() ^ want_stat.to_bits())); 673 w.set_stat_tx(Stat::from_bits(r.stat_tx().to_bits() ^ want_stat.to_bits()));
658 reg.write_value(w); 674 epr.write_value(w);
659 } 675 }
660 EP_IN_WAKERS[ep_addr.index()].wake(); 676 EP_IN_WAKERS[ep_addr.index()].wake();
661 } 677 }
@@ -665,18 +681,18 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
665 false => Stat::DISABLED, 681 false => Stat::DISABLED,
666 true => Stat::VALID, 682 true => Stat::VALID,
667 }; 683 };
668 let r = reg.read(); 684 let r = epr.read();
669 if r.stat_rx() == want_stat { 685 if r.stat_rx() == want_stat {
670 break; 686 break;
671 } 687 }
672 let mut w = invariant(r); 688 let mut w = invariant(r);
673 w.set_stat_rx(Stat::from_bits(r.stat_rx().to_bits() ^ want_stat.to_bits())); 689 w.set_stat_rx(Stat::from_bits(r.stat_rx().to_bits() ^ want_stat.to_bits()));
674 reg.write_value(w); 690 epr.write_value(w);
675 } 691 }
676 EP_OUT_WAKERS[ep_addr.index()].wake(); 692 EP_OUT_WAKERS[ep_addr.index()].wake();
677 } 693 }
678 } 694 }
679 trace!("EPR after: {:04x}", reg.read().0); 695 trace!("EPR after: {:04x}", epr.read().0);
680 } 696 }
681 697
682 async fn enable(&mut self) {} 698 async fn enable(&mut self) {}
@@ -712,6 +728,7 @@ impl Dir for Out {
712/// For double-buffered endpoints, both the `Rx` and `Tx` buffer from a channel are used for the same 728/// For double-buffered endpoints, both the `Rx` and `Tx` buffer from a channel are used for the same
713/// direction of transfer. This is opposed to single-buffered endpoints, where one channel can serve 729/// direction of transfer. This is opposed to single-buffered endpoints, where one channel can serve
714/// two directions at the same time. 730/// two directions at the same time.
731#[derive(Clone, Copy, Debug)]
715enum PacketBuffer { 732enum PacketBuffer {
716 /// The RX buffer - must be used for single-buffered OUT endpoints 733 /// The RX buffer - must be used for single-buffered OUT endpoints
717 Rx, 734 Rx,
@@ -836,7 +853,8 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
836 if self.info.ep_type == EndpointType::Isochronous { 853 if self.info.ep_type == EndpointType::Isochronous {
837 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet. 854 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet.
838 // Therefore, this instead waits until the `CTR` interrupt was triggered. 855 // Therefore, this instead waits until the `CTR` interrupt was triggered.
839 if matches!(stat, Stat::DISABLED) || CTR_TRIGGERED[index].load(Ordering::Relaxed) { 856 if matches!(stat, Stat::DISABLED) || RX_COMPLETE[index].load(Ordering::Relaxed) {
857 assert!(matches!(stat, Stat::VALID | Stat::DISABLED));
840 Poll::Ready(stat) 858 Poll::Ready(stat)
841 } else { 859 } else {
842 Poll::Pending 860 Poll::Pending
@@ -851,7 +869,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
851 }) 869 })
852 .await; 870 .await;
853 871
854 CTR_TRIGGERED[index].store(false, Ordering::Relaxed); 872 RX_COMPLETE[index].store(false, Ordering::Relaxed);
855 873
856 if stat == Stat::DISABLED { 874 if stat == Stat::DISABLED {
857 return Err(EndpointError::Disabled); 875 return Err(EndpointError::Disabled);
@@ -859,31 +877,26 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
859 877
860 let regs = T::regs(); 878 let regs = T::regs();
861 879
862 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous { 880 let rx_len = if self.info.ep_type == EndpointType::Isochronous {
863 // Find the buffer, which is currently in use. Read from the OTHER buffer. 881 // Find the buffer, which is currently in use. Read from the OTHER buffer.
864 if regs.epr(index).read().dtog_rx() { 882 let packet_buffer = if regs.epr(index).read().dtog_rx() {
865 PacketBuffer::Rx
866 } else {
867 PacketBuffer::Tx 883 PacketBuffer::Tx
868 }
869 } else {
870 PacketBuffer::Rx
871 };
872
873 let rx_len = self.read_data_double_buffered(buf, packet_buffer)?;
874
875 regs.epr(index).write(|w| {
876 w.set_ep_type(convert_type(self.info.ep_type));
877 w.set_ea(self.info.addr.index() as _);
878 if self.info.ep_type == EndpointType::Isochronous {
879 w.set_stat_rx(Stat::from_bits(0)); // STAT_RX remains `VALID`.
880 } else { 884 } else {
885 PacketBuffer::Rx
886 };
887 self.read_data_double_buffered(buf, packet_buffer)?
888 } else {
889 regs.epr(index).write(|w| {
890 w.set_ep_type(convert_type(self.info.ep_type));
891 w.set_ea(self.info.addr.index() as _);
881 w.set_stat_rx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits())); 892 w.set_stat_rx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits()));
882 } 893 w.set_stat_tx(Stat::from_bits(0));
883 w.set_stat_tx(Stat::from_bits(0)); 894 w.set_ctr_rx(true); // don't clear
884 w.set_ctr_rx(true); // don't clear 895 w.set_ctr_tx(true); // don't clear
885 w.set_ctr_tx(true); // don't clear 896 });
886 }); 897
898 self.read_data(buf)?
899 };
887 trace!("READ OK, rx_len = {}", rx_len); 900 trace!("READ OK, rx_len = {}", rx_len);
888 901
889 Ok(rx_len) 902 Ok(rx_len)
@@ -895,18 +908,31 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
895 if buf.len() > self.info.max_packet_size as usize { 908 if buf.len() > self.info.max_packet_size as usize {
896 return Err(EndpointError::BufferOverflow); 909 return Err(EndpointError::BufferOverflow);
897 } 910 }
911 trace!("WRITE WAITING, buf.len() = {}", buf.len());
898 912
913 let regs = T::regs();
899 let index = self.info.addr.index(); 914 let index = self.info.addr.index();
900 915
901 trace!("WRITE WAITING"); 916 if self.info.ep_type == EndpointType::Isochronous {
917 // Find the buffer, which is currently in use. Write to the OTHER buffer.
918 let packet_buffer = if regs.epr(index).read().dtog_tx() {
919 PacketBuffer::Rx
920 } else {
921 PacketBuffer::Tx
922 };
923
924 self.write_data_double_buffered(buf, packet_buffer);
925 }
926
902 let stat = poll_fn(|cx| { 927 let stat = poll_fn(|cx| {
903 EP_IN_WAKERS[index].register(cx.waker()); 928 EP_IN_WAKERS[index].register(cx.waker());
904 let regs = T::regs(); 929 let regs = T::regs();
905 let stat = regs.epr(index).read().stat_tx(); 930 let stat = regs.epr(index).read().stat_tx();
906 if self.info.ep_type == EndpointType::Isochronous { 931 if self.info.ep_type == EndpointType::Isochronous {
907 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet. 932 // The isochronous endpoint does not change its `STAT_TX` field to `NAK` after sending a packet.
908 // Therefore, this instead waits until the `CTR` interrupt was triggered. 933 // Therefore, this instead waits until the `CTR` interrupt was triggered.
909 if matches!(stat, Stat::DISABLED) || CTR_TRIGGERED[index].load(Ordering::Relaxed) { 934 if matches!(stat, Stat::DISABLED) || !TX_PENDING[index].load(Ordering::Relaxed) {
935 assert!(matches!(stat, Stat::VALID | Stat::DISABLED));
910 Poll::Ready(stat) 936 Poll::Ready(stat)
911 } else { 937 } else {
912 Poll::Pending 938 Poll::Pending
@@ -921,41 +947,23 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
921 }) 947 })
922 .await; 948 .await;
923 949
924 CTR_TRIGGERED[index].store(false, Ordering::Relaxed);
925
926 if stat == Stat::DISABLED { 950 if stat == Stat::DISABLED {
927 return Err(EndpointError::Disabled); 951 return Err(EndpointError::Disabled);
928 } 952 }
929 953
930 let regs = T::regs(); 954 if self.info.ep_type != EndpointType::Isochronous {
931 955 self.write_data(buf);
932 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous {
933 // Find the buffer, which is currently in use. Write to the OTHER buffer.
934 if regs.epr(index).read().dtog_tx() {
935 PacketBuffer::Tx
936 } else {
937 PacketBuffer::Rx
938 }
939 } else {
940 PacketBuffer::Tx
941 };
942
943 self.write_data_double_buffered(buf, packet_buffer);
944 956
945 let regs = T::regs(); 957 regs.epr(index).write(|w| {
946 regs.epr(index).write(|w| { 958 w.set_ep_type(convert_type(self.info.ep_type));
947 w.set_ep_type(convert_type(self.info.ep_type)); 959 w.set_ea(self.info.addr.index() as _);
948 w.set_ea(self.info.addr.index() as _);
949 if self.info.ep_type == EndpointType::Isochronous {
950 w.set_stat_tx(Stat::from_bits(0)); // STAT_TX remains `VALID`.
951 } else {
952 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits())); 960 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits()));
953 } 961 w.set_stat_rx(Stat::from_bits(0));
954 w.set_stat_rx(Stat::from_bits(0)); 962 w.set_ctr_rx(true); // don't clear
955 w.set_ctr_rx(true); // don't clear 963 w.set_ctr_tx(true); // don't clear
956 w.set_ctr_tx(true); // don't clear 964 });
957 }); 965 }
958 966 TX_PENDING[index].store(true, Ordering::Relaxed);
959 trace!("WRITE OK"); 967 trace!("WRITE OK");
960 968
961 Ok(()) 969 Ok(())