diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 63997c99f..885a4746d 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -33,6 +33,7 @@ unstable-traits = ["embedded-hal-1"]
 embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
 embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
 embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] }
+embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
 embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]}
 embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
 embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 3cf823573..03293e064 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -1,9 +1,9 @@
 use core::marker::PhantomData;
 
 use embassy_embedded_hal::SetConfig;
+use embassy_futures::join::join;
 use embassy_hal_common::{into_ref, PeripheralRef};
 pub use embedded_hal_02::spi::{Phase, Polarity};
-use futures::future::join;
 
 use crate::dma::{AnyChannel, Channel};
 use crate::gpio::sealed::Pin as _;
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index b4c19f32e..484496f24 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -34,6 +34,7 @@ flavors = [
 embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
 embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
 embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
+embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
 embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]}
 embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
 embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index ff9157d51..20e1a4070 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -429,7 +429,7 @@ where
             }
         });
 
-        let (_, result) = futures::future::join(dma_read, result).await;
+        let (_, result) = embassy_futures::join::join(dma_read, result).await;
 
         unsafe { Self::toggle(false) };
 
@@ -537,7 +537,7 @@ where
 
         unsafe { Self::toggle(true) };
 
-        let (_, result) = futures::future::join(dma_result, result).await;
+        let (_, result) = embassy_futures::join::join(dma_result, result).await;
 
         unsafe { Self::toggle(false) };
 
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 02e6020b0..556d12305 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -3,9 +3,9 @@
 use core::ptr;
 
 use embassy_embedded_hal::SetConfig;
+use embassy_futures::join::join;
 use embassy_hal_common::{into_ref, PeripheralRef};
 pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
-use futures::future::join;
 
 use self::sealed::WordSize;
 use crate::dma::{slice_ptr_parts, NoDma, Transfer};
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs
index 4761fcf66..70318b78f 100644
--- a/examples/nrf/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf/src/bin/usb_hid_keyboard.rs
@@ -7,6 +7,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
 
 use defmt::*;
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_futures::select::{select, Either};
 use embassy_nrf::gpio::{Input, Pin, Pull};
 use embassy_nrf::usb::{Driver, PowerUsb};
@@ -15,7 +16,6 @@ use embassy_sync::signal::Signal;
 use embassy_usb::control::OutResponse;
 use embassy_usb::{Builder, Config, DeviceStateHandler};
 use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State};
-use futures::future::join;
 use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 use {defmt_rtt as _, panic_probe as _};
 
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs
index f1b57a17f..65fbda1cf 100644
--- a/examples/nrf/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf/src/bin/usb_hid_mouse.rs
@@ -6,13 +6,13 @@ use core::mem;
 
 use defmt::*;
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_nrf::usb::{Driver, PowerUsb};
 use embassy_nrf::{interrupt, pac};
 use embassy_time::{Duration, Timer};
 use embassy_usb::control::OutResponse;
 use embassy_usb::{Builder, Config};
 use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State};
-use futures::future::join;
 use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
 use {defmt_rtt as _, panic_probe as _};
 
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs
index f9526cbc4..a740b4e0a 100644
--- a/examples/nrf/src/bin/usb_serial.rs
+++ b/examples/nrf/src/bin/usb_serial.rs
@@ -6,12 +6,12 @@ use core::mem;
 
 use defmt::{info, panic};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply};
 use embassy_nrf::{interrupt, pac};
 use embassy_usb::driver::EndpointError;
 use embassy_usb::{Builder, Config};
 use embassy_usb_serial::{CdcAcmClass, State};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 17393322c..24c3cdd67 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -13,6 +13,7 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm
 embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
 embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
 embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] }
+embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 
 defmt = "0.3"
 defmt-rtt = "0.3"
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 00cf3e93f..bf92a1636 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -4,12 +4,12 @@
 
 use defmt::{info, panic};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_rp::interrupt;
 use embassy_rp::usb::{Driver, Instance};
 use embassy_usb::driver::EndpointError;
 use embassy_usb::{Builder, Config};
 use embassy_usb_serial::{CdcAcmClass, State};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index 33ac63db1..895e043dd 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -10,6 +10,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de
 embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"]  }
 embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
 embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
+embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 
 defmt = "0.3"
 defmt-rtt = "0.3"
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs
index a9c46068f..a14e728ba 100644
--- a/examples/stm32f1/src/bin/usb_serial.rs
+++ b/examples/stm32f1/src/bin/usb_serial.rs
@@ -4,6 +4,7 @@
 
 use defmt::{panic, *};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_stm32::gpio::{Level, Output, Speed};
 use embassy_stm32::time::Hertz;
 use embassy_stm32::usb::{Driver, Instance};
@@ -12,7 +13,6 @@ use embassy_time::{Duration, Timer};
 use embassy_usb::driver::EndpointError;
 use embassy_usb::Builder;
 use embassy_usb_serial::{CdcAcmClass, State};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 208f39080..27f5c260a 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -11,6 +11,7 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["
 embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
 embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] }
 embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] }
+embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 
 defmt = "0.3"
 defmt-rtt = "0.3"
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index d3702fc35..b9fd20e2b 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -4,6 +4,7 @@
 
 use defmt::{panic, *};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_stm32::gpio::{Level, Output, Speed};
 use embassy_stm32::time::mhz;
 use embassy_stm32::usb::{Driver, Instance};
@@ -12,7 +13,6 @@ use embassy_time::{Duration, Timer};
 use embassy_usb::driver::EndpointError;
 use embassy_usb::Builder;
 use embassy_usb_serial::{CdcAcmClass, State};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index c451bd221..05945f6bf 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -15,6 +15,7 @@ embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", fea
 embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] }
 embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] }
 embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
+embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 usbd-hid = "0.6.0"
 
 defmt = "0.3"
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs
index 0aca6f1cd..fa92ceae3 100644
--- a/examples/stm32l5/src/bin/usb_hid_mouse.rs
+++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs
@@ -4,6 +4,7 @@
 
 use defmt::*;
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_stm32::rcc::*;
 use embassy_stm32::usb::Driver;
 use embassy_stm32::{interrupt, Config};
@@ -11,7 +12,6 @@ use embassy_time::{Duration, Timer};
 use embassy_usb::control::OutResponse;
 use embassy_usb::Builder;
 use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State};
-use futures::future::join;
 use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
 use {defmt_rtt as _, panic_probe as _};
 
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs
index b576a7353..7484dc832 100644
--- a/examples/stm32l5/src/bin/usb_serial.rs
+++ b/examples/stm32l5/src/bin/usb_serial.rs
@@ -4,13 +4,13 @@
 
 use defmt::{panic, *};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_stm32::rcc::*;
 use embassy_stm32::usb::{Driver, Instance};
 use embassy_stm32::{interrupt, Config};
 use embassy_usb::driver::EndpointError;
 use embassy_usb::Builder;
 use embassy_usb_serial::{CdcAcmClass, State};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 4d6877ccd..11ecb9169 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -8,6 +8,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["de
 embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
 embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] }
 embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits"]  }
+embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
 
 defmt = "0.3.0"
 defmt-rtt = "0.3.0"
diff --git a/tests/rp/src/bin/gpio_async.rs b/tests/rp/src/bin/gpio_async.rs
index 1eeaac1f6..f20b8fcbd 100644
--- a/tests/rp/src/bin/gpio_async.rs
+++ b/tests/rp/src/bin/gpio_async.rs
@@ -4,9 +4,9 @@
 
 use defmt::{assert, *};
 use embassy_executor::Spawner;
+use embassy_futures::join::join;
 use embassy_rp::gpio::{Input, Level, Output, Pull};
 use embassy_time::{Duration, Instant, Timer};
-use futures::future::join;
 use {defmt_rtt as _, panic_probe as _};
 
 #[embassy_executor::main]