Merge pull request #2148 from embassy-rs/usb-fixes3
stm32/otg: fix CONTROL OUT transfers on F4.
This commit is contained in:
		@@ -113,6 +113,14 @@ pub(crate) unsafe fn init(config: Config) {
 | 
				
			|||||||
        while !PWR.csr1().read().odswrdy() {}
 | 
					        while !PWR.csr1().read().odswrdy() {}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[cfg(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423))]
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        use crate::pac::pwr::vals::Vos;
 | 
				
			||||||
 | 
					        use crate::pac::PWR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PWR.cr1().modify(|w| w.set_vos(Vos::SCALE1));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Configure HSI
 | 
					    // Configure HSI
 | 
				
			||||||
    let hsi = match config.hsi {
 | 
					    let hsi = match config.hsi {
 | 
				
			||||||
        false => {
 | 
					        false => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
				
			|||||||
        // Handle RX
 | 
					        // Handle RX
 | 
				
			||||||
        while r.gintsts().read().rxflvl() {
 | 
					        while r.gintsts().read().rxflvl() {
 | 
				
			||||||
            let status = r.grxstsp().read();
 | 
					            let status = r.grxstsp().read();
 | 
				
			||||||
 | 
					            trace!("=== status {:08x}", status.0);
 | 
				
			||||||
            let ep_num = status.epnum() as usize;
 | 
					            let ep_num = status.epnum() as usize;
 | 
				
			||||||
            let len = status.bcnt() as usize;
 | 
					            let len = status.bcnt() as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,6 +52,15 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
				
			|||||||
                    assert!(len == 8, "invalid SETUP packet length={}", len);
 | 
					                    assert!(len == 8, "invalid SETUP packet length={}", len);
 | 
				
			||||||
                    assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
 | 
					                    assert!(ep_num == 0, "invalid SETUP packet endpoint={}", ep_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // flushing TX if something stuck in control endpoint
 | 
				
			||||||
 | 
					                    if r.dieptsiz(ep_num).read().pktcnt() != 0 {
 | 
				
			||||||
 | 
					                        r.grstctl().modify(|w| {
 | 
				
			||||||
 | 
					                            w.set_txfnum(ep_num as _);
 | 
				
			||||||
 | 
					                            w.set_txfflsh(true);
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                        while r.grstctl().read().txfflsh() {}
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
 | 
					                    if state.ep0_setup_ready.load(Ordering::Relaxed) == false {
 | 
				
			||||||
                        // SAFETY: exclusive access ensured by atomic bool
 | 
					                        // SAFETY: exclusive access ensured by atomic bool
 | 
				
			||||||
                        let data = unsafe { &mut *state.ep0_setup_data.get() };
 | 
					                        let data = unsafe { &mut *state.ep0_setup_data.get() };
 | 
				
			||||||
@@ -96,6 +106,11 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                vals::Pktstsd::SETUP_DATA_DONE => {
 | 
					                vals::Pktstsd::SETUP_DATA_DONE => {
 | 
				
			||||||
                    trace!("SETUP_DATA_DONE ep={}", ep_num);
 | 
					                    trace!("SETUP_DATA_DONE ep={}", ep_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Clear NAK to indicate we are ready to receive more data
 | 
				
			||||||
 | 
					                    T::regs().doepctl(ep_num).modify(|w| {
 | 
				
			||||||
 | 
					                        w.set_cnak(true);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                x => trace!("unknown PKTSTS: {}", x.to_bits()),
 | 
					                x => trace!("unknown PKTSTS: {}", x.to_bits()),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -911,11 +926,9 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
 | 
				
			|||||||
                trace!("enumdne");
 | 
					                trace!("enumdne");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let speed = r.dsts().read().enumspd();
 | 
					                let speed = r.dsts().read().enumspd();
 | 
				
			||||||
                trace!("  speed={}", speed.to_bits());
 | 
					                let trdt = calculate_trdt(speed, T::frequency());
 | 
				
			||||||
 | 
					                trace!("  speed={} trdt={}", speed.to_bits(), trdt);
 | 
				
			||||||
                r.gusbcfg().modify(|w| {
 | 
					                r.gusbcfg().modify(|w| w.set_trdt(trdt));
 | 
				
			||||||
                    w.set_trdt(calculate_trdt(speed, T::frequency()));
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                r.gintsts().write(|w| w.set_enumdne(true)); // clear
 | 
					                r.gintsts().write(|w| w.set_enumdne(true)); // clear
 | 
				
			||||||
                Self::restore_irqs();
 | 
					                Self::restore_irqs();
 | 
				
			||||||
@@ -1314,11 +1327,6 @@ impl<'d, T: Instance> embassy_usb_driver::ControlPipe for ControlPipe<'d, T> {
 | 
				
			|||||||
                    w.set_rxdpid_stupcnt(1);
 | 
					                    w.set_rxdpid_stupcnt(1);
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Clear NAK to indicate we are ready to receive more data
 | 
					 | 
				
			||||||
                T::regs().doepctl(self.ep_out.info.addr.index()).modify(|w| {
 | 
					 | 
				
			||||||
                    w.set_cnak(true);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                trace!("SETUP received: {:?}", data);
 | 
					                trace!("SETUP received: {:?}", data);
 | 
				
			||||||
                Poll::Ready(data)
 | 
					                Poll::Ready(data)
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -406,6 +406,16 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 | 
				
			|||||||
        let max_packet_size = self.control.max_packet_size();
 | 
					        let max_packet_size = self.control.max_packet_size();
 | 
				
			||||||
        let mut total = 0;
 | 
					        let mut total = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if req_length > self.control_buf.len() {
 | 
				
			||||||
 | 
					            warn!(
 | 
				
			||||||
 | 
					                "got CONTROL OUT with length {} higher than the control_buf len {}, rejecting.",
 | 
				
			||||||
 | 
					                req_length,
 | 
				
			||||||
 | 
					                self.control_buf.len()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            self.control.reject().await;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let chunks = self.control_buf[..req_length].chunks_mut(max_packet_size);
 | 
					        let chunks = self.control_buf[..req_length].chunks_mut(max_packet_size);
 | 
				
			||||||
        for (first, last, chunk) in first_last(chunks) {
 | 
					        for (first, last, chunk) in first_last(chunks) {
 | 
				
			||||||
            let size = match self.control.data_out(chunk, first, last).await {
 | 
					            let size = match self.control.data_out(chunk, first, last).await {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user