diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs
index 2d119c973..9c37d2c04 100644
--- a/embassy-stm32/src/ucpd.rs
+++ b/embassy-stm32/src/ucpd.rs
@@ -42,8 +42,8 @@ pub(crate) fn init(
         // strobe will apply the CC pin configuration from the control register
         // (which is why we need to be careful about when we call this)
         crate::pac::SYSCFG.cfgr1().modify(|w| {
-            w.set_ucpd1_strobe(ucpd1_db_enable);
-            w.set_ucpd2_strobe(ucpd2_db_enable);
+            w.set_ucpd1_strobe(!ucpd1_db_enable);
+            w.set_ucpd2_strobe(!ucpd2_db_enable);
         });
     }
 
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bfe003a11..e42470004 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -13,7 +13,7 @@ stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"]
 stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac", "rng"]
 stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma", "dac", "sdmmc"]
 stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"]
-stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac"]
+stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"]
 stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan"]
 stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "hash"]
 stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"]
@@ -47,6 +47,7 @@ mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"]
 embassy-stm32-wpan = []
 not-gpdma = []
 dac = []
+ucpd = []
 
 cm0 = ["portable-atomic/unsafe-assume-single-core"]
 
@@ -160,6 +161,11 @@ name = "timer"
 path = "src/bin/timer.rs"
 required-features = []
 
+[[bin]]
+name = "ucpd"
+path = "src/bin/ucpd.rs"
+required-features = [ "ucpd",]
+
 [[bin]]
 name = "usart"
 path = "src/bin/usart.rs"
diff --git a/tests/stm32/src/bin/ucpd.rs b/tests/stm32/src/bin/ucpd.rs
new file mode 100644
index 000000000..c09334ec8
--- /dev/null
+++ b/tests/stm32/src/bin/ucpd.rs
@@ -0,0 +1,120 @@
+// required-features: ucpd
+#![no_std]
+#![no_main]
+#[path = "../common.rs"]
+mod common;
+
+use common::*;
+use defmt::{assert, assert_eq};
+use embassy_executor::Spawner;
+use embassy_futures::join::join;
+use embassy_stm32::ucpd::{self, CcPhy, CcPull, CcSel, CcVState, RxError, Ucpd};
+use embassy_stm32::{bind_interrupts, peripherals};
+use embassy_time::Timer;
+
+bind_interrupts!(struct Irqs {
+    UCPD1_2 => ucpd::InterruptHandler<peripherals::UCPD1>, ucpd::InterruptHandler<peripherals::UCPD2>;
+});
+
+static SRC_TO_SNK: [u8; 6] = [0, 1, 2, 3, 4, 5];
+static SNK_TO_SRC: [u8; 4] = [9, 8, 7, 6];
+
+async fn wait_for_vstate<T: ucpd::Instance>(cc_phy: &mut CcPhy<'_, T>, vstate: CcVState) {
+    let (mut cc1, mut _cc2) = cc_phy.vstate();
+    while cc1 != vstate {
+        (cc1, _cc2) = cc_phy.wait_for_vstate_change().await;
+    }
+}
+
+async fn source(
+    mut ucpd: Ucpd<'static, peripherals::UCPD1>,
+    rx_dma: peripherals::DMA1_CH1,
+    tx_dma: peripherals::DMA1_CH2,
+) {
+    debug!("source: setting default current pull-up");
+    ucpd.cc_phy().set_pull(CcPull::SourceDefaultUsb);
+
+    // Wait for default sink.
+    debug!("source: wait for sink");
+    wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await;
+
+    // Advertise a higher current by changing the pull-up resistor.
+    debug!("source: sink detected, setting 3.0A current pull-up");
+    ucpd.cc_phy().set_pull(CcPull::Source3_0A);
+
+    let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1);
+
+    // Listen for an incoming message
+    debug!("source: wait for message from sink");
+    let mut snk_to_src_buf = [0_u8; 30];
+    let n = unwrap!(pd_phy.receive(snk_to_src_buf.as_mut()).await);
+    assert_eq!(n, SNK_TO_SRC.len());
+    assert_eq!(&snk_to_src_buf[..n], SNK_TO_SRC.as_slice());
+
+    // Send message
+    debug!("source: message received, sending message");
+    unwrap!(pd_phy.transmit(SRC_TO_SNK.as_slice()).await);
+
+    // Wait for hard-reset
+    debug!("source: message sent, waiting for hard-reset");
+    assert!(matches!(
+        pd_phy.receive(snk_to_src_buf.as_mut()).await,
+        Err(RxError::HardReset)
+    ));
+}
+
+async fn sink(
+    mut ucpd: Ucpd<'static, peripherals::UCPD2>,
+    rx_dma: peripherals::DMA1_CH3,
+    tx_dma: peripherals::DMA1_CH4,
+) {
+    debug!("sink: setting pull down");
+    ucpd.cc_phy().set_pull(CcPull::Sink);
+
+    // Wait for default source.
+    debug!("sink: waiting for default vstate");
+    wait_for_vstate(ucpd.cc_phy(), CcVState::LOW).await;
+
+    // Wait higher current pull-up.
+    //debug!("sink: source default vstate detected, waiting for 3.0A vstate");
+    //wait_for_vstate(ucpd.cc_phy(), CcVState::HIGHEST).await;
+    //debug!("sink: source 3.0A vstate detected");
+    // TODO: not working yet, why? no idea, replace with timer for now
+    Timer::after_millis(100).await;
+
+    let (_, mut pd_phy) = ucpd.split_pd_phy(rx_dma, tx_dma, CcSel::CC1);
+
+    // Send message
+    debug!("sink: sending message");
+    unwrap!(pd_phy.transmit(SNK_TO_SRC.as_slice()).await);
+
+    // Listen for an incoming message
+    debug!("sink: message sent, waiting for message from source");
+    let mut src_to_snk_buf = [0_u8; 30];
+    let n = unwrap!(pd_phy.receive(src_to_snk_buf.as_mut()).await);
+    assert_eq!(n, SRC_TO_SNK.len());
+    assert_eq!(&src_to_snk_buf[..n], SRC_TO_SNK.as_slice());
+
+    // Send hard reset
+    debug!("sink: message received, sending hard-reset");
+    unwrap!(pd_phy.transmit_hardreset().await);
+}
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+    let p = embassy_stm32::init(config());
+    info!("Hello World!");
+
+    // Wire between PD0 and PA8
+    let ucpd1 = Ucpd::new(p.UCPD1, Irqs {}, p.PA8, p.PB15);
+    let ucpd2 = Ucpd::new(p.UCPD2, Irqs {}, p.PD0, p.PD2);
+
+    join(
+        source(ucpd1, p.DMA1_CH1, p.DMA1_CH2),
+        sink(ucpd2, p.DMA1_CH3, p.DMA1_CH4),
+    )
+    .await;
+
+    info!("Test OK");
+    cortex_m::asm::bkpt();
+}