aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-06-27 08:42:51 +0200
committerDario Nieuwenhuis <[email protected]>2023-06-27 12:52:37 +0200
commit219ef5b37a1dff5f6e770da252ec010d55c43257 (patch)
treed90597e01633865ea810a55266c90a5d56d555ea
parenta2d1e7f02ca8d94c755ced56f1db11646ac2aa72 (diff)
stm32/otg: add VBUS detection.
Fixes #1442.
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs479
-rw-r--r--examples/stm32f4/src/bin/usb_ethernet.rs4
-rw-r--r--examples/stm32f4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32f7/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32l4/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs4
7 files changed, 297 insertions, 206 deletions
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index b2f7eb852..6c00c93d6 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -6,8 +6,8 @@ use atomic_polyfill::{AtomicBool, AtomicU16, Ordering};
6use embassy_hal_common::{into_ref, Peripheral}; 6use embassy_hal_common::{into_ref, Peripheral};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embassy_usb_driver::{ 8use embassy_usb_driver::{
9 self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut, 9 self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo,
10 EndpointType, Event, Unsupported, 10 EndpointOut, EndpointType, Event, Unsupported,
11}; 11};
12use futures::future::poll_fn; 12use futures::future::poll_fn;
13 13
@@ -31,7 +31,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
31 let state = T::state(); 31 let state = T::state();
32 32
33 let ints = r.gintsts().read(); 33 let ints = r.gintsts().read();
34 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() { 34 if ints.wkupint() || ints.usbsusp() || ints.usbrst() || ints.enumdne() || ints.otgint() || ints.srqint() {
35 // Mask interrupts and notify `Bus` to process them 35 // Mask interrupts and notify `Bus` to process them
36 r.gintmsk().write(|_| {}); 36 r.gintmsk().write(|_| {});
37 T::state().bus_waker.wake(); 37 T::state().bus_waker.wake();
@@ -256,7 +256,34 @@ struct EndpointData {
256 fifo_size_words: u16, 256 fifo_size_words: u16,
257} 257}
258 258
259#[non_exhaustive]
260#[derive(Clone, Copy, PartialEq, Eq, Debug)]
261pub struct Config {
262 /// Enable VBUS detection.
263 ///
264 /// The USB spec requires USB devices monitor for USB cable plug/unplug and react accordingly.
265 /// This is done by checkihg whether there is 5V on the VBUS pin or not.
266 ///
267 /// If your device is bus-powered (powers itself from the USB host via VBUS), then this is optional.
268 /// (if there's no power in VBUS your device would be off anyway, so it's fine to always assume
269 /// there's power in VBUS, i.e. the USB cable is always plugged in.)
270 ///
271 /// If your device is self-powered (i.e. it gets power from a source other than the USB cable, and
272 /// therefore can stay powered through USB cable plug/unplug) then you MUST set this to true.
273 ///
274 /// If you set this to true, you must connect VBUS to PA9 for FS, PB13 for HS, possibly with a
275 /// voltage divider. See ST application note AN4879 and the reference manual for more details.
276 pub vbus_detection: bool,
277}
278
279impl Default for Config {
280 fn default() -> Self {
281 Self { vbus_detection: true }
282 }
283}
284
259pub struct Driver<'d, T: Instance> { 285pub struct Driver<'d, T: Instance> {
286 config: Config,
260 phantom: PhantomData<&'d mut T>, 287 phantom: PhantomData<&'d mut T>,
261 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 288 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
262 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 289 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
@@ -279,6 +306,7 @@ impl<'d, T: Instance> Driver<'d, T> {
279 dp: impl Peripheral<P = impl DpPin<T>> + 'd, 306 dp: impl Peripheral<P = impl DpPin<T>> + 'd,
280 dm: impl Peripheral<P = impl DmPin<T>> + 'd, 307 dm: impl Peripheral<P = impl DmPin<T>> + 'd,
281 ep_out_buffer: &'d mut [u8], 308 ep_out_buffer: &'d mut [u8],
309 config: Config,
282 ) -> Self { 310 ) -> Self {
283 into_ref!(dp, dm); 311 into_ref!(dp, dm);
284 312
@@ -286,6 +314,7 @@ impl<'d, T: Instance> Driver<'d, T> {
286 dm.set_as_af(dm.af_num(), AFType::OutputPushPull); 314 dm.set_as_af(dm.af_num(), AFType::OutputPushPull);
287 315
288 Self { 316 Self {
317 config,
289 phantom: PhantomData, 318 phantom: PhantomData,
290 ep_in: [None; MAX_EP_COUNT], 319 ep_in: [None; MAX_EP_COUNT],
291 ep_out: [None; MAX_EP_COUNT], 320 ep_out: [None; MAX_EP_COUNT],
@@ -318,6 +347,7 @@ impl<'d, T: Instance> Driver<'d, T> {
318 ulpi_d6: impl Peripheral<P = impl UlpiD6Pin<T>> + 'd, 347 ulpi_d6: impl Peripheral<P = impl UlpiD6Pin<T>> + 'd,
319 ulpi_d7: impl Peripheral<P = impl UlpiD7Pin<T>> + 'd, 348 ulpi_d7: impl Peripheral<P = impl UlpiD7Pin<T>> + 'd,
320 ep_out_buffer: &'d mut [u8], 349 ep_out_buffer: &'d mut [u8],
350 config: Config,
321 ) -> Self { 351 ) -> Self {
322 assert!(T::HIGH_SPEED == true, "Peripheral is not capable of high-speed USB"); 352 assert!(T::HIGH_SPEED == true, "Peripheral is not capable of high-speed USB");
323 353
@@ -327,6 +357,7 @@ impl<'d, T: Instance> Driver<'d, T> {
327 ); 357 );
328 358
329 Self { 359 Self {
360 config,
330 phantom: PhantomData, 361 phantom: PhantomData,
331 ep_in: [None; MAX_EP_COUNT], 362 ep_in: [None; MAX_EP_COUNT],
332 ep_out: [None; MAX_EP_COUNT], 363 ep_out: [None; MAX_EP_COUNT],
@@ -464,11 +495,12 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
464 495
465 ( 496 (
466 Bus { 497 Bus {
498 config: self.config,
467 phantom: PhantomData, 499 phantom: PhantomData,
468 ep_in: self.ep_in, 500 ep_in: self.ep_in,
469 ep_out: self.ep_out, 501 ep_out: self.ep_out,
470 phy_type: self.phy_type, 502 phy_type: self.phy_type,
471 enabled: false, 503 inited: false,
472 }, 504 },
473 ControlPipe { 505 ControlPipe {
474 _phantom: PhantomData, 506 _phantom: PhantomData,
@@ -481,11 +513,12 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
481} 513}
482 514
483pub struct Bus<'d, T: Instance> { 515pub struct Bus<'d, T: Instance> {
516 config: Config,
484 phantom: PhantomData<&'d mut T>, 517 phantom: PhantomData<&'d mut T>,
485 ep_in: [Option<EndpointData>; MAX_EP_COUNT], 518 ep_in: [Option<EndpointData>; MAX_EP_COUNT],
486 ep_out: [Option<EndpointData>; MAX_EP_COUNT], 519 ep_out: [Option<EndpointData>; MAX_EP_COUNT],
487 phy_type: PhyType, 520 phy_type: PhyType,
488 enabled: bool, 521 inited: bool,
489} 522}
490 523
491impl<'d, T: Instance> Bus<'d, T> { 524impl<'d, T: Instance> Bus<'d, T> {
@@ -498,11 +531,202 @@ impl<'d, T: Instance> Bus<'d, T> {
498 w.set_iepint(true); 531 w.set_iepint(true);
499 w.set_oepint(true); 532 w.set_oepint(true);
500 w.set_rxflvlm(true); 533 w.set_rxflvlm(true);
534 w.set_srqim(true);
535 w.set_otgint(true);
501 }); 536 });
502 } 537 }
503} 538}
504 539
505impl<'d, T: Instance> Bus<'d, T> { 540impl<'d, T: Instance> Bus<'d, T> {
541 fn init(&mut self) {
542 #[cfg(stm32l4)]
543 {
544 crate::peripherals::PWR::enable();
545 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
546 }
547
548 #[cfg(stm32f7)]
549 {
550 // Enable ULPI clock if external PHY is used
551 let ulpien = !self.phy_type.internal();
552 critical_section::with(|_| {
553 crate::pac::RCC.ahb1enr().modify(|w| {
554 if T::HIGH_SPEED {
555 w.set_usb_otg_hsulpien(ulpien);
556 } else {
557 w.set_usb_otg_hsen(ulpien);
558 }
559 });
560
561 // Low power mode
562 crate::pac::RCC.ahb1lpenr().modify(|w| {
563 if T::HIGH_SPEED {
564 w.set_usb_otg_hsulpilpen(ulpien);
565 } else {
566 w.set_usb_otg_hslpen(ulpien);
567 }
568 });
569 });
570 }
571
572 #[cfg(stm32h7)]
573 {
574 // If true, VDD33USB is generated by internal regulator from VDD50USB
575 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
576 // TODO: unhardcode
577 let internal_regulator = false;
578
579 // Enable USB power
580 critical_section::with(|_| {
581 crate::pac::PWR.cr3().modify(|w| {
582 w.set_usb33den(true);
583 w.set_usbregen(internal_regulator);
584 })
585 });
586
587 // Wait for USB power to stabilize
588 while !crate::pac::PWR.cr3().read().usb33rdy() {}
589
590 // Use internal 48MHz HSI clock. Should be enabled in RCC by default.
591 critical_section::with(|_| {
592 crate::pac::RCC
593 .d2ccip2r()
594 .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48))
595 });
596
597 // Enable ULPI clock if external PHY is used
598 let ulpien = !self.phy_type.internal();
599 critical_section::with(|_| {
600 crate::pac::RCC.ahb1enr().modify(|w| {
601 if T::HIGH_SPEED {
602 w.set_usb_otg_hs_ulpien(ulpien);
603 } else {
604 w.set_usb_otg_fs_ulpien(ulpien);
605 }
606 });
607 crate::pac::RCC.ahb1lpenr().modify(|w| {
608 if T::HIGH_SPEED {
609 w.set_usb_otg_hs_ulpilpen(ulpien);
610 } else {
611 w.set_usb_otg_fs_ulpilpen(ulpien);
612 }
613 });
614 });
615 }
616
617 #[cfg(stm32u5)]
618 {
619 // Enable USB power
620 critical_section::with(|_| {
621 crate::pac::RCC.ahb3enr().modify(|w| {
622 w.set_pwren(true);
623 });
624 cortex_m::asm::delay(2);
625
626 crate::pac::PWR.svmcr().modify(|w| {
627 w.set_usv(true);
628 w.set_uvmen(true);
629 });
630 });
631
632 // Wait for USB power to stabilize
633 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
634
635 // Select HSI48 as USB clock source.
636 critical_section::with(|_| {
637 crate::pac::RCC.ccipr1().modify(|w| {
638 w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48);
639 })
640 });
641 }
642
643 <T as RccPeripheral>::enable();
644 <T as RccPeripheral>::reset();
645
646 T::Interrupt::unpend();
647 unsafe { T::Interrupt::enable() };
648
649 let r = T::regs();
650 let core_id = r.cid().read().0;
651 info!("Core id {:08x}", core_id);
652
653 // Wait for AHB ready.
654 while !r.grstctl().read().ahbidl() {}
655
656 // Configure as device.
657 r.gusbcfg().write(|w| {
658 // Force device mode
659 w.set_fdmod(true);
660 // Enable internal full-speed PHY
661 w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed());
662 });
663
664 // Configuring Vbus sense and SOF output
665 match core_id {
666 0x0000_1200 | 0x0000_1100 => {
667 assert!(self.phy_type != PhyType::InternalHighSpeed);
668
669 r.gccfg_v1().modify(|w| {
670 // Enable internal full-speed PHY, logic is inverted
671 w.set_pwrdwn(self.phy_type.internal());
672 });
673
674 // F429-like chips have the GCCFG.NOVBUSSENS bit
675 r.gccfg_v1().modify(|w| {
676 w.set_novbussens(!self.config.vbus_detection);
677 w.set_vbusasen(false);
678 w.set_vbusbsen(self.config.vbus_detection);
679 w.set_sofouten(false);
680 });
681 }
682 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => {
683 // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning
684 r.gccfg_v2().modify(|w| {
685 // Enable internal full-speed PHY, logic is inverted
686 w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed());
687 w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed());
688 });
689
690 r.gccfg_v2().modify(|w| {
691 w.set_vbden(self.config.vbus_detection);
692 });
693
694 // Force B-peripheral session
695 r.gotgctl().modify(|w| {
696 w.set_bvaloen(!self.config.vbus_detection);
697 w.set_bvaloval(true);
698 });
699 }
700 _ => unimplemented!("Unknown USB core id {:X}", core_id),
701 }
702
703 // Soft disconnect.
704 r.dctl().write(|w| w.set_sdis(true));
705
706 // Set speed.
707 r.dcfg().write(|w| {
708 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
709 w.set_dspd(self.phy_type.to_dspd());
710 });
711
712 // Unmask transfer complete EP interrupt
713 r.diepmsk().write(|w| {
714 w.set_xfrcm(true);
715 });
716
717 // Unmask and clear core interrupts
718 Bus::<T>::restore_irqs();
719 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
720
721 // Unmask global interrupt
722 r.gahbcfg().write(|w| {
723 w.set_gint(true); // unmask global interrupt
724 });
725
726 // Connect
727 r.dctl().write(|w| w.set_sdis(false));
728 }
729
506 fn init_fifo(&mut self) { 730 fn init_fifo(&mut self) {
507 trace!("init_fifo"); 731 trace!("init_fifo");
508 732
@@ -613,6 +837,13 @@ impl<'d, T: Instance> Bus<'d, T> {
613 }); 837 });
614 } 838 }
615 839
840 fn disable_all_endpoints(&mut self) {
841 for i in 0..T::ENDPOINT_COUNT {
842 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::In), false);
843 self.endpoint_set_enabled(EndpointAddress::from_parts(i, Direction::Out), false);
844 }
845 }
846
616 fn disable(&mut self) { 847 fn disable(&mut self) {
617 T::Interrupt::disable(); 848 T::Interrupt::disable();
618 849
@@ -627,9 +858,14 @@ impl<'d, T: Instance> Bus<'d, T> {
627impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> { 858impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
628 async fn poll(&mut self) -> Event { 859 async fn poll(&mut self) -> Event {
629 poll_fn(move |cx| { 860 poll_fn(move |cx| {
630 // TODO: implement VBUS detection 861 if !self.inited {
631 if !self.enabled { 862 self.init();
632 return Poll::Ready(Event::PowerDetected); 863 self.inited = true;
864
865 // If no vbus detection, just return a single PowerDetected event at startup.
866 if !self.config.vbus_detection {
867 return Poll::Ready(Event::PowerDetected);
868 }
633 } 869 }
634 870
635 let r = T::regs(); 871 let r = T::regs();
@@ -637,6 +873,32 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
637 T::state().bus_waker.register(cx.waker()); 873 T::state().bus_waker.register(cx.waker());
638 874
639 let ints = r.gintsts().read(); 875 let ints = r.gintsts().read();
876
877 if ints.srqint() {
878 trace!("vbus detected");
879
880 r.gintsts().write(|w| w.set_srqint(true)); // clear
881 Self::restore_irqs();
882
883 if self.config.vbus_detection {
884 return Poll::Ready(Event::PowerDetected);
885 }
886 }
887
888 if ints.otgint() {
889 let otgints = r.gotgint().read();
890 r.gotgint().write_value(otgints); // clear all
891 Self::restore_irqs();
892
893 if otgints.sedet() {
894 trace!("vbus removed");
895 if self.config.vbus_detection {
896 self.disable_all_endpoints();
897 return Poll::Ready(Event::PowerRemoved);
898 }
899 }
900 }
901
640 if ints.usbrst() { 902 if ints.usbrst() {
641 trace!("reset"); 903 trace!("reset");
642 904
@@ -801,203 +1063,14 @@ impl<'d, T: Instance> embassy_usb_driver::Bus for Bus<'d, T> {
801 1063
802 async fn enable(&mut self) { 1064 async fn enable(&mut self) {
803 trace!("enable"); 1065 trace!("enable");
804 1066 // TODO: enable the peripheral once enable/disable semantics are cleared up in embassy-usb
805 #[cfg(stm32l4)]
806 {
807 crate::peripherals::PWR::enable();
808 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
809 }
810
811 #[cfg(stm32f7)]
812 {
813 // Enable ULPI clock if external PHY is used
814 let ulpien = !self.phy_type.internal();
815 critical_section::with(|_| {
816 crate::pac::RCC.ahb1enr().modify(|w| {
817 if T::HIGH_SPEED {
818 w.set_usb_otg_hsulpien(ulpien);
819 } else {
820 w.set_usb_otg_hsen(ulpien);
821 }
822 });
823
824 // Low power mode
825 crate::pac::RCC.ahb1lpenr().modify(|w| {
826 if T::HIGH_SPEED {
827 w.set_usb_otg_hsulpilpen(ulpien);
828 } else {
829 w.set_usb_otg_hslpen(ulpien);
830 }
831 });
832 });
833 }
834
835 #[cfg(stm32h7)]
836 {
837 // If true, VDD33USB is generated by internal regulator from VDD50USB
838 // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo)
839 // TODO: unhardcode
840 let internal_regulator = false;
841
842 // Enable USB power
843 critical_section::with(|_| {
844 crate::pac::PWR.cr3().modify(|w| {
845 w.set_usb33den(true);
846 w.set_usbregen(internal_regulator);
847 })
848 });
849
850 // Wait for USB power to stabilize
851 while !crate::pac::PWR.cr3().read().usb33rdy() {}
852
853 // Use internal 48MHz HSI clock. Should be enabled in RCC by default.
854 critical_section::with(|_| {
855 crate::pac::RCC
856 .d2ccip2r()
857 .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48))
858 });
859
860 // Enable ULPI clock if external PHY is used
861 let ulpien = !self.phy_type.internal();
862 critical_section::with(|_| {
863 crate::pac::RCC.ahb1enr().modify(|w| {
864 if T::HIGH_SPEED {
865 w.set_usb_otg_hs_ulpien(ulpien);
866 } else {
867 w.set_usb_otg_fs_ulpien(ulpien);
868 }
869 });
870 crate::pac::RCC.ahb1lpenr().modify(|w| {
871 if T::HIGH_SPEED {
872 w.set_usb_otg_hs_ulpilpen(ulpien);
873 } else {
874 w.set_usb_otg_fs_ulpilpen(ulpien);
875 }
876 });
877 });
878 }
879
880 #[cfg(stm32u5)]
881 {
882 // Enable USB power
883 critical_section::with(|_| {
884 crate::pac::RCC.ahb3enr().modify(|w| {
885 w.set_pwren(true);
886 });
887 cortex_m::asm::delay(2);
888
889 crate::pac::PWR.svmcr().modify(|w| {
890 w.set_usv(true);
891 w.set_uvmen(true);
892 });
893 });
894
895 // Wait for USB power to stabilize
896 while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
897
898 // Select HSI48 as USB clock source.
899 critical_section::with(|_| {
900 crate::pac::RCC.ccipr1().modify(|w| {
901 w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48);
902 })
903 });
904 }
905
906 <T as RccPeripheral>::enable();
907 <T as RccPeripheral>::reset();
908
909 T::Interrupt::unpend();
910 unsafe { T::Interrupt::enable() };
911
912 let r = T::regs();
913 let core_id = r.cid().read().0;
914 info!("Core id {:08x}", core_id);
915
916 // Wait for AHB ready.
917 while !r.grstctl().read().ahbidl() {}
918
919 // Configure as device.
920 r.gusbcfg().write(|w| {
921 // Force device mode
922 w.set_fdmod(true);
923 // Enable internal full-speed PHY
924 w.set_physel(self.phy_type.internal() && !self.phy_type.high_speed());
925 });
926
927 // Configuring Vbus sense and SOF output
928 match core_id {
929 0x0000_1200 | 0x0000_1100 => {
930 assert!(self.phy_type != PhyType::InternalHighSpeed);
931
932 r.gccfg_v1().modify(|w| {
933 // Enable internal full-speed PHY, logic is inverted
934 w.set_pwrdwn(self.phy_type.internal());
935 });
936
937 // F429-like chips have the GCCFG.NOVBUSSENS bit
938 r.gccfg_v1().modify(|w| {
939 w.set_novbussens(true);
940 w.set_vbusasen(false);
941 w.set_vbusbsen(false);
942 w.set_sofouten(false);
943 });
944 }
945 0x0000_2000 | 0x0000_2100 | 0x0000_2300 | 0x0000_3000 | 0x0000_3100 => {
946 // F446-like chips have the GCCFG.VBDEN bit with the opposite meaning
947 r.gccfg_v2().modify(|w| {
948 // Enable internal full-speed PHY, logic is inverted
949 w.set_pwrdwn(self.phy_type.internal() && !self.phy_type.high_speed());
950 w.set_phyhsen(self.phy_type.internal() && self.phy_type.high_speed());
951 });
952
953 r.gccfg_v2().modify(|w| {
954 w.set_vbden(false);
955 });
956
957 // Force B-peripheral session
958 r.gotgctl().modify(|w| {
959 w.set_bvaloen(true);
960 w.set_bvaloval(true);
961 });
962 }
963 _ => unimplemented!("Unknown USB core id {:X}", core_id),
964 }
965
966 // Soft disconnect.
967 r.dctl().write(|w| w.set_sdis(true));
968
969 // Set speed.
970 r.dcfg().write(|w| {
971 w.set_pfivl(vals::Pfivl::FRAME_INTERVAL_80);
972 w.set_dspd(self.phy_type.to_dspd());
973 });
974
975 // Unmask transfer complete EP interrupt
976 r.diepmsk().write(|w| {
977 w.set_xfrcm(true);
978 });
979
980 // Unmask and clear core interrupts
981 Bus::<T>::restore_irqs();
982 r.gintsts().write_value(regs::Gintsts(0xFFFF_FFFF));
983
984 // Unmask global interrupt
985 r.gahbcfg().write(|w| {
986 w.set_gint(true); // unmask global interrupt
987 });
988
989 // Connect
990 r.dctl().write(|w| w.set_sdis(false));
991
992 self.enabled = true;
993 } 1067 }
994 1068
995 async fn disable(&mut self) { 1069 async fn disable(&mut self) {
996 trace!("disable"); 1070 trace!("disable");
997 1071
998 Bus::disable(self); 1072 // TODO: disable the peripheral once enable/disable semantics are cleared up in embassy-usb
999 1073 //Bus::disable(self);
1000 self.enabled = false;
1001 } 1074 }
1002 1075
1003 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> { 1076 async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
@@ -1140,11 +1213,16 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1140 state.ep_in_wakers[index].register(cx.waker()); 1213 state.ep_in_wakers[index].register(cx.waker());
1141 1214
1142 let diepctl = r.diepctl(index).read(); 1215 let diepctl = r.diepctl(index).read();
1216 let dtxfsts = r.dtxfsts(index).read();
1217 info!("diepctl {:08x} ftxfsts {:08x}", diepctl.0, dtxfsts.0);
1143 if !diepctl.usbaep() { 1218 if !diepctl.usbaep() {
1219 trace!("write ep={:?} wait for prev: error disabled", self.info.addr);
1144 Poll::Ready(Err(EndpointError::Disabled)) 1220 Poll::Ready(Err(EndpointError::Disabled))
1145 } else if !diepctl.epena() { 1221 } else if !diepctl.epena() {
1222 trace!("write ep={:?} wait for prev: ready", self.info.addr);
1146 Poll::Ready(Ok(())) 1223 Poll::Ready(Ok(()))
1147 } else { 1224 } else {
1225 trace!("write ep={:?} wait for prev: pending", self.info.addr);
1148 Poll::Pending 1226 Poll::Pending
1149 } 1227 }
1150 }) 1228 })
@@ -1169,6 +1247,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1169 1247
1170 Poll::Pending 1248 Poll::Pending
1171 } else { 1249 } else {
1250 trace!("write ep={:?} wait for fifo: ready", self.info.addr);
1172 Poll::Ready(()) 1251 Poll::Ready(())
1173 } 1252 }
1174 }) 1253 })
diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs
index 953d99a45..b1f01417c 100644
--- a/examples/stm32f4/src/bin/usb_ethernet.rs
+++ b/examples/stm32f4/src/bin/usb_ethernet.rs
@@ -52,7 +52,9 @@ async fn main(spawner: Spawner) {
52 52
53 // Create the driver, from the HAL. 53 // Create the driver, from the HAL.
54 let ep_out_buffer = &mut make_static!([0; 256])[..]; 54 let ep_out_buffer = &mut make_static!([0; 256])[..];
55 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer); 55 let mut config = embassy_stm32::usb_otg::Config::default();
56 config.vbus_detection = true;
57 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config);
56 58
57 // Create embassy-usb Config 59 // Create embassy-usb Config
58 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 60 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs
index f8f5940a7..4ff6452ef 100644
--- a/examples/stm32f4/src/bin/usb_serial.rs
+++ b/examples/stm32f4/src/bin/usb_serial.rs
@@ -29,7 +29,9 @@ async fn main(_spawner: Spawner) {
29 29
30 // Create the driver, from the HAL. 30 // Create the driver, from the HAL.
31 let mut ep_out_buffer = [0u8; 256]; 31 let mut ep_out_buffer = [0u8; 256];
32 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer); 32 let mut config = embassy_stm32::usb_otg::Config::default();
33 config.vbus_detection = true;
34 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
33 35
34 // Create embassy-usb Config 36 // Create embassy-usb Config
35 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 37 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs
index 763309ce2..a2c76178b 100644
--- a/examples/stm32f7/src/bin/usb_serial.rs
+++ b/examples/stm32f7/src/bin/usb_serial.rs
@@ -30,7 +30,9 @@ async fn main(_spawner: Spawner) {
30 30
31 // Create the driver, from the HAL. 31 // Create the driver, from the HAL.
32 let mut ep_out_buffer = [0u8; 256]; 32 let mut ep_out_buffer = [0u8; 256];
33 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer); 33 let mut config = embassy_stm32::usb_otg::Config::default();
34 config.vbus_detection = true;
35 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
34 36
35 // Create embassy-usb Config 37 // Create embassy-usb Config
36 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 38 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index c622f19f7..97291f60c 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -29,7 +29,9 @@ async fn main(_spawner: Spawner) {
29 29
30 // Create the driver, from the HAL. 30 // Create the driver, from the HAL.
31 let mut ep_out_buffer = [0u8; 256]; 31 let mut ep_out_buffer = [0u8; 256];
32 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer); 32 let mut config = embassy_stm32::usb_otg::Config::default();
33 config.vbus_detection = true;
34 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
33 35
34 // Create embassy-usb Config 36 // Create embassy-usb Config
35 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 37 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs
index 80811a43e..410d6891b 100644
--- a/examples/stm32l4/src/bin/usb_serial.rs
+++ b/examples/stm32l4/src/bin/usb_serial.rs
@@ -30,7 +30,9 @@ async fn main(_spawner: Spawner) {
30 30
31 // Create the driver, from the HAL. 31 // Create the driver, from the HAL.
32 let mut ep_out_buffer = [0u8; 256]; 32 let mut ep_out_buffer = [0u8; 256];
33 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer); 33 let mut config = embassy_stm32::usb_otg::Config::default();
34 config.vbus_detection = true;
35 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
34 36
35 // Create embassy-usb Config 37 // Create embassy-usb Config
36 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 38 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index f36daf91b..9e47fb18a 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -31,7 +31,9 @@ async fn main(_spawner: Spawner) {
31 31
32 // Create the driver, from the HAL. 32 // Create the driver, from the HAL.
33 let mut ep_out_buffer = [0u8; 256]; 33 let mut ep_out_buffer = [0u8; 256];
34 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer); 34 let mut config = embassy_stm32::usb_otg::Config::default();
35 config.vbus_detection = true;
36 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
35 37
36 // Create embassy-usb Config 38 // Create embassy-usb Config
37 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); 39 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);