diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs
index 98b82bacc..a366fadda 100644
--- a/embassy-stm32/src/ucpd.rs
+++ b/embassy-stm32/src/ucpd.rs
@@ -18,13 +18,14 @@ use core::future::poll_fn;
 use core::marker::PhantomData;
 use core::task::Poll;
 
-use crate::rcc::RccPeripheral;
-use crate::{interrupt, pac};
+use embassy_hal_internal::drop::OnDrop;
 use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
 use embassy_sync::waitqueue::AtomicWaker;
-use pac::ucpd::vals::{Anamode, Ccenable, PscUsbpdclk};
 
-pub use pac::ucpd::vals::TypecVstateCc as CcVState;
+use crate::interrupt;
+pub use crate::pac::ucpd::vals::TypecVstateCc as CcVState;
+use crate::pac::ucpd::vals::{Anamode, Ccenable, PscUsbpdclk};
+use crate::rcc::RccPeripheral;
 
 /// Pull-up or Pull-down resistor state of both CC lines.
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -53,6 +54,16 @@ pub struct Ucpd<'d, T: Instance> {
     _peri: PeripheralRef<'d, T>,
 }
 
+impl<'d, T: Instance> Drop for Ucpd<'d, T> {
+    fn drop(&mut self) {
+        T::REGS.cr().modify(|w| {
+            w.set_ccenable(Ccenable::DISABLED);
+            w.set_cc1tcdis(true);
+            w.set_cc2tcdis(true);
+        });
+    }
+}
+
 impl<'d, T: Instance> Ucpd<'d, T> {
     /// Creates a new UCPD driver instance.
     pub fn new(
@@ -113,13 +124,17 @@ impl<'d, T: Instance> Ucpd<'d, T> {
             } else {
                 Ccenable::DISABLED
             });
+
+            // Make sure detector is enabled on both pins.
+            w.set_cc1tcdis(false);
+            w.set_cc2tcdis(false);
         });
 
         // Disable dead-battery pull-down resistors which are enabled by default on boot.
         critical_section::with(|_| {
             // TODO: other families
             #[cfg(stm32g4)]
-            pac::PWR
+            crate::pac::PWR
                 .cr3()
                 .modify(|w| w.set_ucpd1_dbdis(cc_pull != CcPull::SinkDeadBattery));
         });
@@ -138,26 +153,29 @@ impl<'d, T: Instance> Ucpd<'d, T> {
     }
 
     /// Waits for a change in voltage state on either CC line.
-    pub async fn wait_for_cc_change(&mut self) {
-        let r = T::REGS;
+    pub async fn wait_for_cc_vstate_change(&self) -> (CcVState, CcVState) {
+        let _on_drop = OnDrop::new(|| critical_section::with(|_| self.enable_cc_interrupts(false)));
+        let prev_vstate = self.cc_vstate();
         poll_fn(|cx| {
-            let sr = r.sr().read();
-            if sr.typecevt1() || sr.typecevt2() {
-                r.icr().write(|w| {
-                    w.set_typecevt1cf(true);
-                    w.set_typecevt2cf(true);
-                });
-                Poll::Ready(())
+            let vstate = self.cc_vstate();
+            if vstate != prev_vstate {
+                Poll::Ready(vstate)
             } else {
                 T::waker().register(cx.waker());
-                r.imr().modify(|w| {
-                    w.set_typecevt1ie(true);
-                    w.set_typecevt2ie(true);
-                });
+                self.enable_cc_interrupts(true);
                 Poll::Pending
             }
         })
-        .await;
+        .await
+    }
+
+    fn enable_cc_interrupts(&self, enable: bool) {
+        critical_section::with(|_| {
+            T::REGS.imr().modify(|w| {
+                w.set_typecevt1ie(enable);
+                w.set_typecevt2ie(enable);
+            })
+        });
     }
 }
 
@@ -172,9 +190,9 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
         let sr = r.sr().read();
 
         if sr.typecevt1() || sr.typecevt2() {
-            r.imr().modify(|w| {
-                w.set_typecevt1ie(true);
-                w.set_typecevt2ie(true);
+            r.icr().write(|w| {
+                w.set_typecevt1cf(true);
+                w.set_typecevt2cf(true);
             });
         }
 
diff --git a/examples/stm32g4/src/bin/usb_c_pd.rs b/examples/stm32g4/src/bin/usb_c_pd.rs
index c442ab0a7..7a0065087 100644
--- a/examples/stm32g4/src/bin/usb_c_pd.rs
+++ b/examples/stm32g4/src/bin/usb_c_pd.rs
@@ -3,10 +3,8 @@
 
 use defmt::{info, Format};
 use embassy_executor::Spawner;
-use embassy_stm32::{
-    ucpd::{self, CcPull, CcVState, Ucpd},
-    Config,
-};
+use embassy_stm32::ucpd::{self, CcPull, CcVState, Ucpd};
+use embassy_stm32::Config;
 use embassy_time::{with_timeout, Duration};
 use {defmt_rtt as _, panic_probe as _};
 
@@ -18,17 +16,17 @@ enum CableOrientation {
 }
 
 // Returns true when the cable
-async fn wait_attached<'d, T: ucpd::Instance>(ucpd: &mut Ucpd<'d, T>) -> CableOrientation {
+async fn wait_attached<T: ucpd::Instance>(ucpd: &mut Ucpd<'_, T>) -> CableOrientation {
     loop {
         let (cc1, cc2) = ucpd.cc_vstate();
         if cc1 == CcVState::LOWEST && cc2 == CcVState::LOWEST {
             // Detached, wait until attached by monitoring the CC lines.
-            ucpd.wait_for_cc_change().await;
+            ucpd.wait_for_cc_vstate_change().await;
             continue;
         }
 
         // Attached, wait for CC lines to be stable for tCCDebounce (100..200ms).
-        if with_timeout(Duration::from_millis(100), ucpd.wait_for_cc_change())
+        if with_timeout(Duration::from_millis(100), ucpd.wait_for_cc_vstate_change())
             .await
             .is_ok()
         {