diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml
index 79d5660f4..50449dd46 100644
--- a/embassy-lora/Cargo.toml
+++ b/embassy-lora/Cargo.toml
@@ -38,5 +38,5 @@ futures = { version = "0.3.17", default-features = false, features = [ "async-aw
 embedded-hal = { version = "0.2", features = ["unproven"] }
 bit_field = { version = "0.10" }
 
-lorawan-device = { version = "0.8.0", default-features = false, features = ["async"] }
-lorawan = { version = "0.7.1", default-features = false }
+lorawan-device = { version = "0.9.0", default-features = false, features = ["async"] }
+lorawan = { version = "0.7.2", default-features = false }
diff --git a/embassy-lora/src/lib.rs b/embassy-lora/src/lib.rs
index 3e4748430..5c919cbb6 100644
--- a/embassy-lora/src/lib.rs
+++ b/embassy-lora/src/lib.rs
@@ -1,5 +1,6 @@
 #![no_std]
-#![feature(type_alias_impl_trait)]
+#![feature(async_fn_in_trait, impl_trait_projections)]
+#![allow(incomplete_features)]
 //! embassy-lora is a collection of async radio drivers that integrate with the lorawan-device
 //! crate's async LoRaWAN MAC implementation.
 
@@ -34,13 +35,11 @@ impl lorawan_device::async_device::radio::Timer for LoraTimer {
         self.start = Instant::now();
     }
 
-    type AtFuture<'m> = impl core::future::Future<Output = ()> + 'm;
-    fn at<'m>(&'m mut self, millis: u64) -> Self::AtFuture<'m> {
-        Timer::at(self.start + Duration::from_millis(millis))
+    async fn at(&mut self, millis: u64) {
+        Timer::at(self.start + Duration::from_millis(millis)).await
     }
 
-    type DelayFuture<'m> = impl core::future::Future<Output = ()> + 'm;
-    fn delay_ms<'m>(&'m mut self, millis: u64) -> Self::DelayFuture<'m> {
-        Timer::after(Duration::from_millis(millis))
+    async fn delay_ms(&mut self, millis: u64) {
+        Timer::after(Duration::from_millis(millis)).await
     }
 }
diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs
index 3d52c1cc7..d76e8c43b 100644
--- a/embassy-lora/src/stm32wl/mod.rs
+++ b/embassy-lora/src/stm32wl/mod.rs
@@ -1,5 +1,5 @@
 //! A radio driver integration for the radio found on STM32WL family devices.
-use core::future::{poll_fn, Future};
+use core::future::poll_fn;
 use core::task::Poll;
 
 use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
@@ -241,14 +241,12 @@ fn configure_radio(radio: &mut SubGhz<'_, NoDma, NoDma>, config: SubGhzRadioConf
 impl<'d, RS: RadioSwitch> PhyRxTx for SubGhzRadio<'d, RS> {
     type PhyError = RadioError;
 
-    type TxFuture<'m> = impl Future<Output = Result<u32, Self::PhyError>> + 'm where Self: 'm;
-    fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> {
-        async move { self.do_tx(config, buf).await }
+    async fn tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, Self::PhyError> {
+        self.do_tx(config, buf).await
     }
 
-    type RxFuture<'m> = impl Future<Output = Result<(usize, RxQuality), Self::PhyError>> + 'm  where Self: 'm;
-    fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> {
-        async move { self.do_rx(config, buf).await }
+    async fn rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), Self::PhyError> {
+        self.do_rx(config, buf).await
     }
 }
 
diff --git a/embassy-lora/src/sx126x/mod.rs b/embassy-lora/src/sx126x/mod.rs
index 8559574cb..2f0b8c8e3 100644
--- a/embassy-lora/src/sx126x/mod.rs
+++ b/embassy-lora/src/sx126x/mod.rs
@@ -1,5 +1,3 @@
-use core::future::Future;
-
 use defmt::Format;
 use embedded_hal::digital::v2::OutputPin;
 use embedded_hal_async::digital::Wait;
@@ -71,83 +69,69 @@ where
 {
     type PhyError = RadioError<BUS>;
 
-    type TxFuture<'m> = impl Future<Output = Result<u32, Self::PhyError>> + 'm
-    where
-        SPI: 'm,
-        CTRL: 'm,
-        WAIT: 'm,
-        BUS: 'm;
-
-    fn tx<'m>(&'m mut self, config: TxConfig, buffer: &'m [u8]) -> Self::TxFuture<'m> {
+    async fn tx(&mut self, config: TxConfig, buffer: &[u8]) -> Result<u32, Self::PhyError> {
         trace!("TX START");
-        async move {
-            self.lora
-                .set_tx_config(
-                    config.pw,
-                    config.rf.spreading_factor.into(),
-                    config.rf.bandwidth.into(),
-                    config.rf.coding_rate.into(),
-                    8,
-                    false,
-                    true,
-                    false,
-                    0,
-                    false,
-                )
-                .await?;
-            self.lora.set_max_payload_length(buffer.len() as u8).await?;
-            self.lora.set_channel(config.rf.frequency).await?;
-            self.lora.send(buffer, 0xffffff).await?;
-            self.lora.process_irq(None, None, None).await?;
-            trace!("TX DONE");
-            return Ok(0);
-        }
+        self.lora
+            .set_tx_config(
+                config.pw,
+                config.rf.spreading_factor.into(),
+                config.rf.bandwidth.into(),
+                config.rf.coding_rate.into(),
+                8,
+                false,
+                true,
+                false,
+                0,
+                false,
+            )
+            .await?;
+        self.lora.set_max_payload_length(buffer.len() as u8).await?;
+        self.lora.set_channel(config.rf.frequency).await?;
+        self.lora.send(buffer, 0xffffff).await?;
+        self.lora.process_irq(None, None, None).await?;
+        trace!("TX DONE");
+        return Ok(0);
     }
 
-    type RxFuture<'m> = impl Future<Output = Result<(usize, RxQuality), Self::PhyError>> + 'm
-    where
-        SPI: 'm,
-        CTRL: 'm,
-        WAIT: 'm,
-        BUS: 'm;
-
-    fn rx<'m>(&'m mut self, config: RfConfig, receiving_buffer: &'m mut [u8]) -> Self::RxFuture<'m> {
+    async fn rx(
+        &mut self,
+        config: RfConfig,
+        receiving_buffer: &mut [u8],
+    ) -> Result<(usize, RxQuality), Self::PhyError> {
         trace!("RX START");
-        async move {
-            self.lora
-                .set_rx_config(
-                    config.spreading_factor.into(),
-                    config.bandwidth.into(),
-                    config.coding_rate.into(),
-                    8,
-                    4,
-                    false,
-                    0u8,
-                    true,
-                    false,
-                    0,
-                    true,
-                    true,
-                )
-                .await?;
-            self.lora.set_max_payload_length(receiving_buffer.len() as u8).await?;
-            self.lora.set_channel(config.frequency).await?;
-            self.lora.rx(90 * 1000).await?;
-            let mut received_len = 0u8;
-            self.lora
-                .process_irq(Some(receiving_buffer), Some(&mut received_len), None)
-                .await?;
-            trace!("RX DONE");
+        self.lora
+            .set_rx_config(
+                config.spreading_factor.into(),
+                config.bandwidth.into(),
+                config.coding_rate.into(),
+                8,
+                4,
+                false,
+                0u8,
+                true,
+                false,
+                0,
+                true,
+                true,
+            )
+            .await?;
+        self.lora.set_max_payload_length(receiving_buffer.len() as u8).await?;
+        self.lora.set_channel(config.frequency).await?;
+        self.lora.rx(90 * 1000).await?;
+        let mut received_len = 0u8;
+        self.lora
+            .process_irq(Some(receiving_buffer), Some(&mut received_len), None)
+            .await?;
+        trace!("RX DONE");
 
-            let packet_status = self.lora.get_latest_packet_status();
-            let mut rssi = 0i16;
-            let mut snr = 0i8;
-            if packet_status.is_some() {
-                rssi = packet_status.unwrap().rssi as i16;
-                snr = packet_status.unwrap().snr;
-            }
-
-            Ok((received_len as usize, RxQuality::new(rssi, snr)))
+        let packet_status = self.lora.get_latest_packet_status();
+        let mut rssi = 0i16;
+        let mut snr = 0i8;
+        if packet_status.is_some() {
+            rssi = packet_status.unwrap().rssi as i16;
+            snr = packet_status.unwrap().snr;
         }
+
+        Ok((received_len as usize, RxQuality::new(rssi, snr)))
     }
 }
diff --git a/embassy-lora/src/sx127x/mod.rs b/embassy-lora/src/sx127x/mod.rs
index 8904c9a13..4e8dc2232 100644
--- a/embassy-lora/src/sx127x/mod.rs
+++ b/embassy-lora/src/sx127x/mod.rs
@@ -1,5 +1,3 @@
-use core::future::Future;
-
 use embedded_hal::digital::v2::OutputPin;
 use embedded_hal_async::digital::Wait;
 use embedded_hal_async::spi::*;
@@ -88,101 +86,78 @@ where
 {
     type PhyError = Sx127xError;
 
-    type TxFuture<'m> = impl Future<Output = Result<u32, Self::PhyError>> + 'm
-    where
-        SPI: 'm,
-        CS: 'm,
-        RESET: 'm,
-        E: 'm,
-        I: 'm,
-        RFS: 'm;
-
-    fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> {
+    async fn tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, Self::PhyError> {
         trace!("TX START");
-        async move {
+        self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap();
+        self.rfs.set_tx();
+        self.radio.set_tx_power(14, 0).await?;
+        self.radio.set_frequency(config.rf.frequency).await?;
+        // TODO: Modify radio to support other coding rates
+        self.radio.set_coding_rate_4(5).await?;
+        self.radio
+            .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth))
+            .await?;
+        self.radio
+            .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor))
+            .await?;
+
+        self.radio.set_preamble_length(8).await?;
+        self.radio.set_lora_pa_ramp().await?;
+        self.radio.set_lora_sync_word().await?;
+        self.radio.set_invert_iq(false).await?;
+        self.radio.set_crc(true).await?;
+
+        self.radio.set_dio0_tx_done().await?;
+
+        self.radio.transmit_start(buf).await?;
+
+        loop {
+            self.irq.wait_for_rising_edge().await.unwrap();
             self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap();
-            self.rfs.set_tx();
-            self.radio.set_tx_power(14, 0).await?;
-            self.radio.set_frequency(config.rf.frequency).await?;
-            // TODO: Modify radio to support other coding rates
-            self.radio.set_coding_rate_4(5).await?;
-            self.radio
-                .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth))
-                .await?;
-            self.radio
-                .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor))
-                .await?;
-
-            self.radio.set_preamble_length(8).await?;
-            self.radio.set_lora_pa_ramp().await?;
-            self.radio.set_lora_sync_word().await?;
-            self.radio.set_invert_iq(false).await?;
-            self.radio.set_crc(true).await?;
-
-            self.radio.set_dio0_tx_done().await?;
-
-            self.radio.transmit_start(buf).await?;
-
-            loop {
-                self.irq.wait_for_rising_edge().await.unwrap();
-                self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap();
-                let irq = self.radio.clear_irq().await.ok().unwrap();
-                if (irq & IRQ::IrqTxDoneMask.addr()) != 0 {
-                    trace!("TX DONE");
-                    return Ok(0);
-                }
+            let irq = self.radio.clear_irq().await.ok().unwrap();
+            if (irq & IRQ::IrqTxDoneMask.addr()) != 0 {
+                trace!("TX DONE");
+                return Ok(0);
             }
         }
     }
 
-    type RxFuture<'m> = impl Future<Output = Result<(usize, RxQuality), Self::PhyError>> + 'm
-    where
-        SPI: 'm,
-        CS: 'm,
-        RESET: 'm,
-        E: 'm,
-        I: 'm,
-        RFS: 'm;
+    async fn rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), Self::PhyError> {
+        self.rfs.set_rx();
+        self.radio.reset_payload_length().await?;
+        self.radio.set_frequency(config.frequency).await?;
+        // TODO: Modify radio to support other coding rates
+        self.radio.set_coding_rate_4(5).await?;
+        self.radio
+            .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth))
+            .await?;
+        self.radio
+            .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor))
+            .await?;
 
-    fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> {
-        trace!("RX START");
-        async move {
-            self.rfs.set_rx();
-            self.radio.reset_payload_length().await?;
-            self.radio.set_frequency(config.frequency).await?;
-            // TODO: Modify radio to support other coding rates
-            self.radio.set_coding_rate_4(5).await?;
-            self.radio
-                .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth))
-                .await?;
-            self.radio
-                .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor))
-                .await?;
+        self.radio.set_preamble_length(8).await?;
+        self.radio.set_lora_sync_word().await?;
+        self.radio.set_invert_iq(true).await?;
+        self.radio.set_crc(true).await?;
 
-            self.radio.set_preamble_length(8).await?;
-            self.radio.set_lora_sync_word().await?;
-            self.radio.set_invert_iq(true).await?;
-            self.radio.set_crc(true).await?;
+        self.radio.set_dio0_rx_done().await?;
+        self.radio.set_mode(RadioMode::RxContinuous).await?;
 
-            self.radio.set_dio0_rx_done().await?;
-            self.radio.set_mode(RadioMode::RxContinuous).await?;
-
-            loop {
-                self.irq.wait_for_rising_edge().await.unwrap();
-                self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap();
-                let irq = self.radio.clear_irq().await.ok().unwrap();
-                if (irq & IRQ::IrqRxDoneMask.addr()) != 0 {
-                    let rssi = self.radio.get_packet_rssi().await.unwrap_or(0) as i16;
-                    let snr = self.radio.get_packet_snr().await.unwrap_or(0.0) as i8;
-                    let response = if let Ok(size) = self.radio.read_packet_size().await {
-                        self.radio.read_packet(buf).await?;
-                        Ok((size, RxQuality::new(rssi, snr)))
-                    } else {
-                        Ok((0, RxQuality::new(rssi, snr)))
-                    };
-                    trace!("RX DONE");
-                    return response;
-                }
+        loop {
+            self.irq.wait_for_rising_edge().await.unwrap();
+            self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap();
+            let irq = self.radio.clear_irq().await.ok().unwrap();
+            if (irq & IRQ::IrqRxDoneMask.addr()) != 0 {
+                let rssi = self.radio.get_packet_rssi().await.unwrap_or(0) as i16;
+                let snr = self.radio.get_packet_snr().await.unwrap_or(0.0) as i8;
+                let response = if let Ok(size) = self.radio.read_packet_size().await {
+                    self.radio.read_packet(buf).await?;
+                    Ok((size, RxQuality::new(rssi, snr)))
+                } else {
+                    Ok((0, RxQuality::new(rssi, snr)))
+                };
+                trace!("RX DONE");
+                return response;
             }
         }
     }
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index fc614cb80..af19413cc 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -20,8 +20,8 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm
 embedded-io = "0.4.0"
 embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
 
-lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true }
-lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true }
+lorawan-device = { version = "0.9.0", default-features = false, features = ["async"], optional = true }
+lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"], optional = true }
 
 defmt = "0.3"
 defmt-rtt = "0.4"
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index d446d41b2..b04faf535 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -15,8 +15,8 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de
 embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"]  }
 embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true}
 
-lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true }
-lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true }
+lorawan-device = { version = "0.9.0", default-features = false, features = ["async"], optional = true }
+lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"], optional = true }
 
 defmt = "0.3"
 defmt-rtt = "0.4"
diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs
index 27d7c29c2..ea01f610c 100644
--- a/examples/stm32l0/src/bin/lorawan.rs
+++ b/examples/stm32l0/src/bin/lorawan.rs
@@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) {
 
     let radio = Sx127xRadio::new(spi, cs, reset, ready_pin, DummySwitch).await.unwrap();
 
-    let region = region::EU868::default().into();
+    let region = region::Configuration::new(region::Region::EU868);
     let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG));
 
     defmt::info!("Joining LoRaWAN network");
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index df295ca49..cb3526fa4 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -11,8 +11,8 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de
 embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"]  }
 embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
 
-lorawan-device = { version = "0.8.0", default-features = false, features = ["async"] }
-lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"] }
+lorawan-device = { version = "0.9.0", default-features = false, features = ["async"] }
+lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"] }
 
 defmt = "0.3"
 defmt-rtt = "0.4"
diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs
index 7f34dd306..32f29cc5d 100644
--- a/examples/stm32wl/src/bin/lorawan.rs
+++ b/examples/stm32wl/src/bin/lorawan.rs
@@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) {
     radio_config.calibrate_image = CalibrateImage::ISM_863_870;
     let radio = SubGhzRadio::new(radio, rfs, irq, radio_config).unwrap();
 
-    let mut region: region::Configuration = region::EU868::default().into();
+    let mut region = region::Configuration::new(region::Region::EU868);
 
     // NOTE: This is specific for TTN, as they have a special RX1 delay
     region.set_receive_delay1(5000);