aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb-synopsys-otg/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-usb-synopsys-otg/src/lib.rs')
-rw-r--r--embassy-usb-synopsys-otg/src/lib.rs113
1 files changed, 50 insertions, 63 deletions
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}