aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usb
diff options
context:
space:
mode:
authorelagil <[email protected]>2025-03-15 20:16:20 +0100
committerelagil <[email protected]>2025-03-15 20:16:32 +0100
commit0b468ef29cc67e05aae01031604b746b1f21ffcd (patch)
tree923360663c44f4e40c2056e8fb4cbfb130b9ce74 /embassy-stm32/src/usb
parent0b6b0756ed5e6f259cf2fed8bf6de008eab78cb1 (diff)
fix: iso out order
Diffstat (limited to 'embassy-stm32/src/usb')
-rw-r--r--embassy-stm32/src/usb/usb.rs75
1 files changed, 37 insertions, 38 deletions
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 31ab8f76d..cb97169ee 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -83,7 +83,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
83 83
84 let mut epr = regs.epr(index).read(); 84 let mut epr = regs.epr(index).read();
85 if epr.ctr_rx() { 85 if epr.ctr_rx() {
86 CTR_RX_TRIGGERED[index].store(true, Ordering::Relaxed); 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,7 +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 CTR_TX_TRIGGERED[index].store(true, Ordering::Relaxed); 94 TX_PENDING[index].store(false, Ordering::Relaxed);
95 //trace!("EP {} TX", index); 95 //trace!("EP {} TX", index);
96 EP_IN_WAKERS[index].wake(); 96 EP_IN_WAKERS[index].wake();
97 } 97 }
@@ -123,8 +123,8 @@ const USBRAM_ALIGN: usize = 4;
123static BUS_WAKER: AtomicWaker = AtomicWaker::new(); 123static BUS_WAKER: AtomicWaker = AtomicWaker::new();
124static EP0_SETUP: AtomicBool = AtomicBool::new(false); 124static EP0_SETUP: AtomicBool = AtomicBool::new(false);
125 125
126static CTR_TX_TRIGGERED: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT]; 126static TX_PENDING: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT];
127static CTR_RX_TRIGGERED: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT]; 127static RX_COMPLETE: [AtomicBool; EP_COUNT] = [const { AtomicBool::new(false) }; EP_COUNT];
128static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT]; 128static EP_IN_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT];
129static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT]; 129static EP_OUT_WAKERS: [AtomicWaker; EP_COUNT] = [const { AtomicWaker::new() }; EP_COUNT];
130static IRQ_RESET: AtomicBool = AtomicBool::new(false); 130static IRQ_RESET: AtomicBool = AtomicBool::new(false);
@@ -417,10 +417,10 @@ impl<'d, T: Instance> Driver<'d, T> {
417 let addr = self.alloc_ep_mem(len); 417 let addr = self.alloc_ep_mem(len);
418 418
419 // ep_in_len is written when actually TXing packets. 419 // ep_in_len is written when actually TXing packets.
420 btable::write_in_tx::<T>(index, addr); 420 btable::write_in_len_tx::<T>(index, addr, 0);
421 421
422 if ep_type == EndpointType::Isochronous { 422 if ep_type == EndpointType::Isochronous {
423 btable::write_in_rx::<T>(index, addr); 423 btable::write_in_len_rx::<T>(index, addr, 0);
424 } 424 }
425 425
426 EndpointBuffer { 426 EndpointBuffer {
@@ -719,6 +719,7 @@ impl Dir for Out {
719/// For double-buffered endpoints, both the `Rx` and `Tx` buffer from a channel are used for the same 719/// For double-buffered endpoints, both the `Rx` and `Tx` buffer from a channel are used for the same
720/// direction of transfer. This is opposed to single-buffered endpoints, where one channel can serve 720/// direction of transfer. This is opposed to single-buffered endpoints, where one channel can serve
721/// two directions at the same time. 721/// two directions at the same time.
722#[derive(Clone, Copy, Debug)]
722enum PacketBuffer { 723enum PacketBuffer {
723 /// The RX buffer - must be used for single-buffered OUT endpoints 724 /// The RX buffer - must be used for single-buffered OUT endpoints
724 Rx, 725 Rx,
@@ -843,7 +844,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
843 if self.info.ep_type == EndpointType::Isochronous { 844 if self.info.ep_type == EndpointType::Isochronous {
844 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet. 845 // The isochronous endpoint does not change its `STAT_RX` field to `NAK` when receiving a packet.
845 // Therefore, this instead waits until the `CTR` interrupt was triggered. 846 // Therefore, this instead waits until the `CTR` interrupt was triggered.
846 if matches!(stat, Stat::DISABLED) || CTR_RX_TRIGGERED[index].load(Ordering::Relaxed) { 847 if matches!(stat, Stat::DISABLED) || RX_COMPLETE[index].load(Ordering::Relaxed) {
847 assert!(matches!(stat, Stat::VALID | Stat::DISABLED)); 848 assert!(matches!(stat, Stat::VALID | Stat::DISABLED));
848 Poll::Ready(stat) 849 Poll::Ready(stat)
849 } else { 850 } else {
@@ -859,7 +860,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
859 }) 860 })
860 .await; 861 .await;
861 862
862 CTR_RX_TRIGGERED[index].store(false, Ordering::Relaxed); 863 RX_COMPLETE[index].store(false, Ordering::Relaxed);
863 864
864 if stat == Stat::DISABLED { 865 if stat == Stat::DISABLED {
865 return Err(EndpointError::Disabled); 866 return Err(EndpointError::Disabled);
@@ -870,9 +871,9 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
870 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous { 871 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous {
871 // Find the buffer, which is currently in use. Read from the OTHER buffer. 872 // Find the buffer, which is currently in use. Read from the OTHER buffer.
872 if regs.epr(index).read().dtog_rx() { 873 if regs.epr(index).read().dtog_rx() {
873 PacketBuffer::Rx
874 } else {
875 PacketBuffer::Tx 874 PacketBuffer::Tx
875 } else {
876 PacketBuffer::Rx
876 } 877 }
877 } else { 878 } else {
878 PacketBuffer::Rx 879 PacketBuffer::Rx
@@ -904,7 +905,21 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
904 return Err(EndpointError::BufferOverflow); 905 return Err(EndpointError::BufferOverflow);
905 } 906 }
906 trace!("WRITE WAITING, buf.len() = {}", buf.len()); 907 trace!("WRITE WAITING, buf.len() = {}", buf.len());
908
909 let regs = T::regs();
907 let index = self.info.addr.index(); 910 let index = self.info.addr.index();
911
912 if self.info.ep_type == EndpointType::Isochronous {
913 // Find the buffer, which is currently in use. Write to the OTHER buffer.
914 let packet_buffer = if regs.epr(index).read().dtog_tx() {
915 PacketBuffer::Rx
916 } else {
917 PacketBuffer::Tx
918 };
919
920 self.write_data_double_buffered(buf, packet_buffer);
921 }
922
908 let stat = poll_fn(|cx| { 923 let stat = poll_fn(|cx| {
909 EP_IN_WAKERS[index].register(cx.waker()); 924 EP_IN_WAKERS[index].register(cx.waker());
910 let regs = T::regs(); 925 let regs = T::regs();
@@ -912,7 +927,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
912 if self.info.ep_type == EndpointType::Isochronous { 927 if self.info.ep_type == EndpointType::Isochronous {
913 // The isochronous endpoint does not change its `STAT_TX` field to `NAK` after sending a packet. 928 // The isochronous endpoint does not change its `STAT_TX` field to `NAK` after sending a packet.
914 // Therefore, this instead waits until the `CTR` interrupt was triggered. 929 // Therefore, this instead waits until the `CTR` interrupt was triggered.
915 if matches!(stat, Stat::DISABLED) || CTR_TX_TRIGGERED[index].load(Ordering::Relaxed) { 930 if matches!(stat, Stat::DISABLED) || !TX_PENDING[index].load(Ordering::Relaxed) {
916 assert!(matches!(stat, Stat::VALID | Stat::DISABLED)); 931 assert!(matches!(stat, Stat::VALID | Stat::DISABLED));
917 Poll::Ready(stat) 932 Poll::Ready(stat)
918 } else { 933 } else {
@@ -928,39 +943,23 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
928 }) 943 })
929 .await; 944 .await;
930 945
931 CTR_TX_TRIGGERED[index].store(false, Ordering::Relaxed);
932
933 if stat == Stat::DISABLED { 946 if stat == Stat::DISABLED {
934 return Err(EndpointError::Disabled); 947 return Err(EndpointError::Disabled);
935 } 948 }
936 949
937 let regs = T::regs(); 950 if self.info.ep_type != EndpointType::Isochronous {
938 951 self.write_data(buf);
939 let packet_buffer = if self.info.ep_type == EndpointType::Isochronous {
940 // Find the buffer, which is currently in use. Write to the OTHER buffer.
941 if regs.epr(index).read().dtog_tx() {
942 PacketBuffer::Tx
943 } else {
944 PacketBuffer::Rx
945 }
946 } else {
947 PacketBuffer::Tx
948 };
949
950 self.write_data_double_buffered(buf, packet_buffer);
951 952
952 regs.epr(index).write(|w| { 953 regs.epr(index).write(|w| {
953 w.set_ep_type(convert_type(self.info.ep_type)); 954 w.set_ep_type(convert_type(self.info.ep_type));
954 w.set_ea(self.info.addr.index() as _); 955 w.set_ea(self.info.addr.index() as _);
955 if self.info.ep_type == EndpointType::Isochronous {
956 w.set_stat_tx(Stat::from_bits(0)); // STAT_TX remains `VALID`.
957 } else {
958 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits())); 956 w.set_stat_tx(Stat::from_bits(Stat::NAK.to_bits() ^ Stat::VALID.to_bits()));
959 } 957 w.set_stat_rx(Stat::from_bits(0));
960 w.set_stat_rx(Stat::from_bits(0)); 958 w.set_ctr_rx(true); // don't clear
961 w.set_ctr_rx(true); // don't clear 959 w.set_ctr_tx(true); // don't clear
962 w.set_ctr_tx(true); // don't clear 960 });
963 }); 961 }
962 TX_PENDING[index].store(true, Ordering::Relaxed);
964 trace!("WRITE OK"); 963 trace!("WRITE OK");
965 964
966 Ok(()) 965 Ok(())