diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 7e7bcaf30..bbbf97c01 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -98,7 +98,19 @@ pub struct UartRx<'d, T: Instance, M: Mode> {
 }
 
 impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
-    fn new(tx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
+    /// Create a new DMA-enabled UART which can only send data
+    pub fn new(
+        _uart: impl Peripheral<P = T> + 'd,
+        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
+        tx_dma: impl Peripheral<P = impl Channel> + 'd,
+        config: Config,
+    ) -> Self {
+        into_ref!(tx, tx_dma);
+        Uart::<T, M>::init(Some(tx.map_into()), None, None, None, config);
+        Self::new_inner(Some(tx_dma.map_into()))
+    }
+
+    fn new_inner(tx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
         Self {
             tx_dma,
             phantom: PhantomData,
@@ -140,7 +152,19 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
 }
 
 impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
-    fn new(rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
+    /// Create a new DMA-enabled UART which can only send data
+    pub fn new(
+        _uart: impl Peripheral<P = T> + 'd,
+        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
+        rx_dma: impl Peripheral<P = impl Channel> + 'd,
+        config: Config,
+    ) -> Self {
+        into_ref!(rx, rx_dma);
+        Uart::<T, M>::init(Some(rx.map_into()), None, None, None, config);
+        Self::new_inner(Some(rx_dma.map_into()))
+    }
+
+    fn new_inner(rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
         Self {
             rx_dma,
             phantom: PhantomData,
@@ -295,8 +319,8 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
         );
 
         Self {
-            tx: UartTx::new(tx_dma),
-            rx: UartRx::new(rx_dma),
+            tx: UartTx::new_inner(tx_dma),
+            rx: UartRx::new_inner(rx_dma),
         }
     }
 
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
new file mode 100644
index 000000000..f56e7009f
--- /dev/null
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -0,0 +1,42 @@
+//! test TX-only and RX-only UARTs. You need to connect GPIO0 to GPIO5 for
+//! this to work
+
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+
+use defmt::*;
+use embassy_executor::Spawner;
+use embassy_rp::peripherals::UART1;
+use embassy_rp::uart::{Async, Config, UartRx, UartTx};
+use embassy_time::{Duration, Timer};
+use {defmt_rtt as _, panic_probe as _};
+
+#[embassy_executor::main]
+async fn main(spawner: Spawner) {
+    let p = embassy_rp::init(Default::default());
+
+    let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
+    let uart_rx = UartRx::new(p.UART1, p.PIN_5, p.DMA_CH1, Config::default());
+
+    unwrap!(spawner.spawn(reader(uart_rx)));
+
+    info!("Writing...");
+    loop {
+        let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
+        info!("TX {:?}", data);
+        uart_tx.write(&data).await.unwrap();
+        Timer::after(Duration::from_secs(1)).await;
+    }
+}
+
+#[embassy_executor::task]
+async fn reader(mut rx: UartRx<'static, UART1, Async>) {
+    info!("Reading...");
+    loop {
+        // read a total of 4 transmissions (32 / 8) and then print the result
+        let mut buf = [0; 32];
+        rx.read(&mut buf).await.unwrap();
+        info!("RX {:?}", buf);
+    }
+}