aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-11-23 00:23:40 +0100
committerDario Nieuwenhuis <[email protected]>2024-11-24 00:32:26 +0100
commit032af9d512140d8464680a444debc76f36222a31 (patch)
treeb72fb1e078bc047d7d36893048bddb09bf0b6493
parent4f459bb91846ed9d72a26c0b751e56cfb0098d21 (diff)
otg: fix corruption in CONTROL OUT transfers in stm32f4.
The RM says we have to process STUP (and therefore clear CNAK to start the data stage) in the DOEPINT STUP interrupt. Seems doing it in RXFLVL when we receive the data is too early. This makes it work consistently on all chips, so the quirk is no longer needed. Fixes #3493 Fixes #3459
-rw-r--r--embassy-stm32/src/usb/otg.rs20
-rw-r--r--embassy-usb-synopsys-otg/src/lib.rs113
2 files changed, 52 insertions, 81 deletions
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 153542fbd..6ca28b156 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -27,9 +27,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
27 let r = T::regs(); 27 let r = T::regs();
28 let state = T::state(); 28 let state = T::state();
29 29
30 let setup_late_cnak = quirk_setup_late_cnak(r); 30 on_interrupt_impl(r, state, T::ENDPOINT_COUNT);
31
32 on_interrupt_impl(r, state, T::ENDPOINT_COUNT, setup_late_cnak);
33 } 31 }
34} 32}
35 33
@@ -86,7 +84,6 @@ impl<'d, T: Instance> Driver<'d, T> {
86 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS, 84 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
87 endpoint_count: T::ENDPOINT_COUNT, 85 endpoint_count: T::ENDPOINT_COUNT,
88 phy_type: PhyType::InternalFullSpeed, 86 phy_type: PhyType::InternalFullSpeed,
89 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
90 calculate_trdt_fn: calculate_trdt::<T>, 87 calculate_trdt_fn: calculate_trdt::<T>,
91 }; 88 };
92 89
@@ -116,16 +113,13 @@ impl<'d, T: Instance> Driver<'d, T> {
116 dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 113 dp.set_as_af(dp.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
117 dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); 114 dm.set_as_af(dm.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
118 115
119 let regs = T::regs();
120
121 let instance = OtgInstance { 116 let instance = OtgInstance {
122 regs, 117 regs: T::regs(),
123 state: T::state(), 118 state: T::state(),
124 fifo_depth_words: T::FIFO_DEPTH_WORDS, 119 fifo_depth_words: T::FIFO_DEPTH_WORDS,
125 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS, 120 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
126 endpoint_count: T::ENDPOINT_COUNT, 121 endpoint_count: T::ENDPOINT_COUNT,
127 phy_type: PhyType::InternalHighSpeed, 122 phy_type: PhyType::InternalHighSpeed,
128 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
129 calculate_trdt_fn: calculate_trdt::<T>, 123 calculate_trdt_fn: calculate_trdt::<T>,
130 }; 124 };
131 125
@@ -165,8 +159,6 @@ impl<'d, T: Instance> Driver<'d, T> {
165 ulpi_d7 159 ulpi_d7
166 ); 160 );
167 161
168 let regs = T::regs();
169
170 let instance = OtgInstance { 162 let instance = OtgInstance {
171 regs: T::regs(), 163 regs: T::regs(),
172 state: T::state(), 164 state: T::state(),
@@ -174,7 +166,6 @@ impl<'d, T: Instance> Driver<'d, T> {
174 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS, 166 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
175 endpoint_count: T::ENDPOINT_COUNT, 167 endpoint_count: T::ENDPOINT_COUNT,
176 phy_type: PhyType::ExternalFullSpeed, 168 phy_type: PhyType::ExternalFullSpeed,
177 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
178 calculate_trdt_fn: calculate_trdt::<T>, 169 calculate_trdt_fn: calculate_trdt::<T>,
179 }; 170 };
180 171
@@ -216,8 +207,6 @@ impl<'d, T: Instance> Driver<'d, T> {
216 ulpi_d7 207 ulpi_d7
217 ); 208 );
218 209
219 let regs = T::regs();
220
221 let instance = OtgInstance { 210 let instance = OtgInstance {
222 regs: T::regs(), 211 regs: T::regs(),
223 state: T::state(), 212 state: T::state(),
@@ -225,7 +214,6 @@ impl<'d, T: Instance> Driver<'d, T> {
225 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS, 214 extra_rx_fifo_words: RX_FIFO_EXTRA_SIZE_WORDS,
226 endpoint_count: T::ENDPOINT_COUNT, 215 endpoint_count: T::ENDPOINT_COUNT,
227 phy_type: PhyType::ExternalHighSpeed, 216 phy_type: PhyType::ExternalHighSpeed,
228 quirk_setup_late_cnak: quirk_setup_late_cnak(regs),
229 calculate_trdt_fn: calculate_trdt::<T>, 217 calculate_trdt_fn: calculate_trdt::<T>,
230 }; 218 };
231 219
@@ -578,7 +566,3 @@ fn calculate_trdt<T: Instance>(speed: Dspd) -> u8 {
578 _ => unimplemented!(), 566 _ => unimplemented!(),
579 } 567 }
580} 568}
581
582fn quirk_setup_late_cnak(r: Otg) -> bool {
583 r.cid().read().0 & 0xf000 == 0x1000
584}
diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs
index bd0ef04b0..615faa2fc 100644
--- a/embassy-usb-synopsys-otg/src/lib.rs
+++ b/embassy-usb-synopsys-otg/src/lib.rs
@@ -9,7 +9,7 @@ mod fmt;
9use core::cell::UnsafeCell; 9use core::cell::UnsafeCell;
10use core::future::poll_fn; 10use core::future::poll_fn;
11use core::marker::PhantomData; 11use core::marker::PhantomData;
12use core::sync::atomic::{AtomicBool, AtomicU16, Ordering}; 12use core::sync::atomic::{AtomicBool, AtomicU16, AtomicU32, Ordering};
13use core::task::Poll; 13use core::task::Poll;
14 14
15use embassy_sync::waitqueue::AtomicWaker; 15use embassy_sync::waitqueue::AtomicWaker;
@@ -25,18 +25,17 @@ pub mod otg_v1;
25use otg_v1::{regs, vals, Otg}; 25use otg_v1::{regs, vals, Otg};
26 26
27/// Handle interrupts. 27/// Handle interrupts.
28pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>( 28pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(r: Otg, state: &State<MAX_EP_COUNT>, ep_count: usize) {
29 r: Otg,
30 state: &State<MAX_EP_COUNT>,
31 ep_count: usize,
32 quirk_setup_late_cnak: bool,
33) {
34 trace!("irq"); 29 trace!("irq");
35 30
36 let ints = r.gintsts().read(); 31 let ints = r.gintsts().read();
37 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() { 32 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
38 // Mask interrupts and notify `Bus` to process them 33 // Mask interrupts and notify `Bus` to process them
39 r.gintmsk().write(|_| {}); 34 r.gintmsk().write(|w| {
35 w.set_iepint(true);
36 w.set_oepint(true);
37 w.set_rxflvlm(true);
38 });
40 state.bus_waker.wake(); 39 state.bus_waker.wake();
41 } 40 }
42 41
@@ -64,19 +63,9 @@ pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(
64 while r.grstctl().read().txfflsh() {} 63 while r.grstctl().read().txfflsh() {}
65 } 64 }
66 65
67 if state.cp_state.setup_ready.load(Ordering::Relaxed) == false { 66 let data = &state.cp_state.setup_data;
68 // SAFETY: exclusive access ensured by atomic bool 67 data[0].store(r.fifo(0).read().data(), Ordering::Relaxed);
69 let data = unsafe { &mut *state.cp_state.setup_data.get() }; 68 data[1].store(r.fifo(0).read().data(), Ordering::Relaxed);
70 data[0..4].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
71 data[4..8].copy_from_slice(&r.fifo(0).read().0.to_ne_bytes());
72 state.cp_state.setup_ready.store(true, Ordering::Release);
73 state.ep_states[0].out_waker.wake();
74 } else {
75 error!("received SETUP before previous finished processing");
76 // discard FIFO
77 r.fifo(0).read();
78 r.fifo(0).read();
79 }
80 } 69 }
81 vals::Pktstsd::OUT_DATA_RX => { 70 vals::Pktstsd::OUT_DATA_RX => {
82 trace!("OUT_DATA_RX ep={} len={}", ep_num, len); 71 trace!("OUT_DATA_RX ep={} len={}", ep_num, len);
@@ -110,11 +99,6 @@ pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(
110 } 99 }
111 vals::Pktstsd::SETUP_DATA_DONE => { 100 vals::Pktstsd::SETUP_DATA_DONE => {
112 trace!("SETUP_DATA_DONE ep={}", ep_num); 101 trace!("SETUP_DATA_DONE ep={}", ep_num);
113
114 if quirk_setup_late_cnak {
115 // Clear NAK to indicate we are ready to receive more data
116 r.doepctl(ep_num).modify(|w| w.set_cnak(true));
117 }
118 } 102 }
119 x => trace!("unknown PKTSTS: {}", x.to_bits()), 103 x => trace!("unknown PKTSTS: {}", x.to_bits()),
120 } 104 }
@@ -151,25 +135,30 @@ pub unsafe fn on_interrupt<const MAX_EP_COUNT: usize>(
151 } 135 }
152 } 136 }
153 137
154 // not needed? reception handled in rxflvl 138 // out endpoint interrupt
155 // OUT endpoint interrupt 139 if ints.oepint() {
156 // if ints.oepint() { 140 trace!("oepint");
157 // let mut ep_mask = r.daint().read().oepint(); 141 let mut ep_mask = r.daint().read().oepint();
158 // let mut ep_num = 0; 142 let mut ep_num = 0;
159 143
160 // while ep_mask != 0 { 144 // Iterate over endpoints while there are non-zero bits in the mask
161 // if ep_mask & 1 != 0 { 145 while ep_mask != 0 {
162 // let ep_ints = r.doepint(ep_num).read(); 146 if ep_mask & 1 != 0 {
163 // // clear all 147 let ep_ints = r.doepint(ep_num).read();
164 // r.doepint(ep_num).write_value(ep_ints); 148 // clear all
165 // state.ep_out_wakers[ep_num].wake(); 149 r.doepint(ep_num).write_value(ep_ints);
166 // trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0); 150
167 // } 151 if ep_ints.stup() {
168 152 state.cp_state.setup_ready.store(true, Ordering::Release);
169 // ep_mask >>= 1; 153 }
170 // ep_num += 1; 154 state.ep_states[ep_num].out_waker.wake();
171 // } 155 trace!("out ep={} irq val={:08x}", ep_num, ep_ints.0);
172 // } 156 }
157
158 ep_mask >>= 1;
159 ep_num += 1;
160 }
161 }
173} 162}
174 163
175/// USB PHY type 164/// USB PHY type
@@ -236,7 +225,7 @@ unsafe impl Sync for EpState {}
236 225
237struct ControlPipeSetupState { 226struct ControlPipeSetupState {
238 /// Holds received SETUP packets. Available if [Ep0State::setup_ready] is true. 227 /// Holds received SETUP packets. Available if [Ep0State::setup_ready] is true.
239 setup_data: UnsafeCell<[u8; 8]>, 228 setup_data: [AtomicU32; 2],
240 setup_ready: AtomicBool, 229 setup_ready: AtomicBool,
241} 230}
242 231
@@ -265,7 +254,7 @@ impl<const EP_COUNT: usize> State<EP_COUNT> {
265 254
266 Self { 255 Self {
267 cp_state: ControlPipeSetupState { 256 cp_state: ControlPipeSetupState {
268 setup_data: UnsafeCell::new([0u8; 8]), 257 setup_data: [const { AtomicU32::new(0) }; 2],
269 setup_ready: AtomicBool::new(false), 258 setup_ready: AtomicBool::new(false),
270 }, 259 },
271 ep_states: [NEW_EP_STATE; EP_COUNT], 260 ep_states: [NEW_EP_STATE; EP_COUNT],
@@ -480,7 +469,6 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d
480 trace!("start"); 469 trace!("start");
481 470
482 let regs = self.instance.regs; 471 let regs = self.instance.regs;
483 let quirk_setup_late_cnak = self.instance.quirk_setup_late_cnak;
484 let cp_setup_state = &self.instance.state.cp_state; 472 let cp_setup_state = &self.instance.state.cp_state;
485 ( 473 (
486 Bus { 474 Bus {
@@ -496,7 +484,6 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d
496 ep_out, 484 ep_out,
497 ep_in, 485 ep_in,
498 regs, 486 regs,
499 quirk_setup_late_cnak,
500 }, 487 },
501 ) 488 )
502 } 489 }
@@ -632,6 +619,11 @@ impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
632 w.set_xfrcm(true); 619 w.set_xfrcm(true);
633 }); 620 });
634 621
622 // Unmask SETUP received EP interrupt
623 r.doepmsk().write(|w| {
624 w.set_stupm(true);
625 });
626
635 // Unmask and clear core interrupts 627 // Unmask and clear core interrupts
636 self.restore_irqs(); 628 self.restore_irqs();
637 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF)); 629 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
@@ -743,7 +735,7 @@ impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
743 regs.doeptsiz(index).modify(|w| { 735 regs.doeptsiz(index).modify(|w| {
744 w.set_xfrsiz(ep.max_packet_size as _); 736 w.set_xfrsiz(ep.max_packet_size as _);
745 if index == 0 { 737 if index == 0 {
746 w.set_rxdpid_stupcnt(1); 738 w.set_rxdpid_stupcnt(3);
747 } else { 739 } else {
748 w.set_pktcnt(1); 740 w.set_pktcnt(1);
749 } 741 }
@@ -755,8 +747,7 @@ impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> {
755 // Enable IRQs for allocated endpoints 747 // Enable IRQs for allocated endpoints
756 regs.daintmsk().modify(|w| { 748 regs.daintmsk().modify(|w| {
757 w.set_iepm(ep_irq_mask(&self.ep_in)); 749 w.set_iepm(ep_irq_mask(&self.ep_in));
758 // OUT interrupts not used, handled in RXFLVL 750 w.set_oepm(ep_irq_mask(&self.ep_out));
759 // w.set_oepm(ep_irq_mask(&self.ep_out));
760 }); 751 });
761 } 752 }
762 753
@@ -1242,7 +1233,6 @@ pub struct ControlPipe<'d> {
1242 setup_state: &'d ControlPipeSetupState, 1233 setup_state: &'d ControlPipeSetupState,
1243 ep_in: Endpoint<'d, In>, 1234 ep_in: Endpoint<'d, In>,
1244 ep_out: Endpoint<'d, Out>, 1235 ep_out: Endpoint<'d, Out>,
1245 quirk_setup_late_cnak: bool,
1246} 1236}
1247 1237
1248impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> { 1238impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
@@ -1255,21 +1245,20 @@ impl<'d> embassy_usb_driver::ControlPipe for ControlPipe<'d> {
1255 self.ep_out.state.out_waker.register(cx.waker()); 1245 self.ep_out.state.out_waker.register(cx.waker());
1256 1246
1257 if self.setup_state.setup_ready.load(Ordering::Relaxed) { 1247 if self.setup_state.setup_ready.load(Ordering::Relaxed) {
1258 let data = unsafe { *self.setup_state.setup_data.get() }; 1248 let mut data = [0; 8];
1249 data[0..4].copy_from_slice(&self.setup_state.setup_data[0].load(Ordering::Relaxed).to_ne_bytes());
1250 data[4..8].copy_from_slice(&self.setup_state.setup_data[1].load(Ordering::Relaxed).to_ne_bytes());
1259 self.setup_state.setup_ready.store(false, Ordering::Release); 1251 self.setup_state.setup_ready.store(false, Ordering::Release);
1260 1252
1261 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section 1253 // EP0 should not be controlled by `Bus` so this RMW does not need a critical section
1262 // Receive 1 SETUP packet
1263 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| { 1254 self.regs.doeptsiz(self.ep_out.info.addr.index()).modify(|w| {
1264 w.set_rxdpid_stupcnt(1); 1255 w.set_rxdpid_stupcnt(3);
1265 }); 1256 });
1266 1257
1267 // Clear NAK to indicate we are ready to receive more data 1258 // Clear NAK to indicate we are ready to receive more data
1268 if !self.quirk_setup_late_cnak { 1259 self.regs
1269 self.regs 1260 .doepctl(self.ep_out.info.addr.index())
1270 .doepctl(self.ep_out.info.addr.index()) 1261 .modify(|w| w.set_cnak(true));
1271 .modify(|w| w.set_cnak(true));
1272 }
1273 1262
1274 trace!("SETUP received: {:?}", Bytes(&data)); 1263 trace!("SETUP received: {:?}", Bytes(&data));
1275 Poll::Ready(data) 1264 Poll::Ready(data)
@@ -1389,8 +1378,6 @@ pub struct OtgInstance<'d, const MAX_EP_COUNT: usize> {
1389 pub phy_type: PhyType, 1378 pub phy_type: PhyType,
1390 /// Extra RX FIFO words needed by some implementations. 1379 /// Extra RX FIFO words needed by some implementations.
1391 pub extra_rx_fifo_words: u16, 1380 pub extra_rx_fifo_words: u16,
1392 /// Whether to set up late cnak
1393 pub quirk_setup_late_cnak: bool,
1394 /// Function to calculate TRDT value based on some internal clock speed. 1381 /// Function to calculate TRDT value based on some internal clock speed.
1395 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8, 1382 pub calculate_trdt_fn: fn(speed: vals::Dspd) -> u8,
1396} 1383}