Resolve C-EXAMPLE: Uart (#3712)

* feat: Add examples to Uart

* feat: Simplify doc examples based on review comments

* feat: Use `uart` as variable name and use UART0

* feat: Remove empty lines

* feat: Include initialization lines

* docs: Add general into_blocking/async examples
This commit is contained in:
Sergio Gasquez Arcos 2025-07-01 14:49:15 +02:00 committed by GitHub
parent 72fd9a0c74
commit f0913769d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 233 additions and 21 deletions

View File

@ -397,6 +397,25 @@ pub trait DriverMode: crate::private::Sealed {}
/// Drivers are constructed in blocking mode by default. To learn about the
/// differences between blocking and async drivers, see the [`Async`] mode
/// documentation.
///
/// [`Async`] drivers can be converted to a [`Blocking`] driver using the
/// `into_blocking` method, for example:
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2)
/// .into_async();
///
/// let blocking_uart = uart.into_blocking();
///
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
#[non_exhaustive]
pub struct Blocking;
@ -405,8 +424,24 @@ pub struct Blocking;
///
/// Drivers are constructed in blocking mode by default. To set up an async
/// driver, a [`Blocking`] driver must be converted to an `Async` driver using
/// the `into_async` method. Drivers can be converted back to blocking mode
/// using the `into_blocking` method.
/// the `into_async` method, for example:
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2)
/// .into_async();
///
/// # Ok(())
/// # }
/// ```
///
/// Drivers can be converted back to blocking mode using the `into_blocking`
/// method, see [`Blocking`] documentation for more details.
///
/// Async mode drivers offer most of the same features as blocking drivers, but
/// with the addition of async APIs. Interrupt-related functions are not

View File

@ -473,6 +473,8 @@ where
/// UART (Full-duplex)
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
@ -911,7 +913,7 @@ impl<'d> UartRx<'d, Blocking> {
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, UartRx};
/// let rx = UartRx::new(
/// peripherals.UART1,
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO2);
/// # Ok(())
@ -1237,8 +1239,8 @@ impl<'d> Uart<'d, Blocking> {
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart1 = Uart::new(
/// peripherals.UART1,
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2);
@ -1250,6 +1252,9 @@ impl<'d> Uart<'d, Blocking> {
}
/// Reconfigures the driver to operate in [`Async`] mode.
///
/// See the [`Async`] documentation for an example on how to use this
/// method.
pub fn into_async(self) -> Uart<'d, Async> {
Uart {
rx: self.rx.into_async(),
@ -1292,16 +1297,16 @@ impl<'d> Uart<'d, Blocking> {
/// # let config = Config::default().with_rx(
/// # RxConfig::default().with_fifo_full_threshold(30)
/// # );
/// # let mut uart0 = Uart::new(
/// # let mut uart = Uart::new(
/// # peripherals.UART0,
/// # config)?;
/// uart0.set_interrupt_handler(interrupt_handler);
/// uart.set_interrupt_handler(interrupt_handler);
///
/// critical_section::with(|cs| {
/// uart0.set_at_cmd(AtCmdConfig::default().with_cmd_char(b'#'));
/// uart0.listen(UartInterrupt::AtCmd | UartInterrupt::RxFifoFull);
/// uart.set_at_cmd(AtCmdConfig::default().with_cmd_char(b'#'));
/// uart.listen(UartInterrupt::AtCmd | UartInterrupt::RxFifoFull);
///
/// SERIAL.borrow_ref_mut(cs).replace(uart0);
/// SERIAL.borrow_ref_mut(cs).replace(uart);
/// });
///
/// loop {
@ -1368,6 +1373,9 @@ impl<'d> Uart<'d, Blocking> {
impl<'d> Uart<'d, Async> {
/// Reconfigures the driver to operate in [`Blocking`] mode.
///
/// See the [`Blocking`] documentation for an example on how to use this
/// method.
pub fn into_blocking(self) -> Uart<'d, Blocking> {
Uart {
rx: self.rx.into_blocking(),
@ -1390,6 +1398,24 @@ impl<'d> Uart<'d, Async> {
/// ## Cancellation
///
/// This function is cancellation safe.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2)
/// .into_async();
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write_async(&MESSAGE).await?;
/// # Ok(())
/// # }
/// ```
pub async fn write_async(&mut self, words: &[u8]) -> Result<usize, TxError> {
self.tx.write_async(words).await
}
@ -1403,6 +1429,25 @@ impl<'d> Uart<'d, Async> {
/// ## Cancellation
///
/// This function is cancellation safe.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2)
/// .into_async();
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write_async(&MESSAGE).await?;
/// uart.flush_async().await?;
/// # Ok(())
/// # }
/// ```
pub async fn flush_async(&mut self) -> Result<(), TxError> {
self.tx.flush_async().await
}
@ -1425,6 +1470,28 @@ impl<'d> Uart<'d, Async> {
/// ## Cancellation
///
/// This function is cancellation safe.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2)
/// .into_async();
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write_async(&MESSAGE).await?;
/// uart.flush_async().await?;
///
/// let mut buf = [0u8; MESSAGE.len()];
/// uart.read_async(&mut buf[..]).await.unwrap();
/// # Ok(())
/// # }
/// ```
pub async fn read_async(&mut self, buf: &mut [u8]) -> Result<usize, RxError> {
self.rx.read_async(buf).await
}
@ -1483,6 +1550,20 @@ where
/// configure the driver side (i.e. the TX pin), or ensure that the line is
/// initially high, to avoid receiving a non-data byte caused by an
/// initial low signal level.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1);
///
/// # Ok(())
/// # }
/// ```
pub fn with_rx(mut self, rx: impl PeripheralInput<'d>) -> Self {
self.rx = self.rx.with_rx(rx);
self
@ -1492,18 +1573,62 @@ where
///
/// Sets the specified pin to push-pull output and connects it to the UART
/// TX signal.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_tx(peripherals.GPIO2);
///
/// # Ok(())
/// # }
/// ```
pub fn with_tx(mut self, tx: impl PeripheralOutput<'d>) -> Self {
self.tx = self.tx.with_tx(tx);
self
}
/// Configure CTS pin
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_cts(peripherals.GPIO3);
///
/// # Ok(())
/// # }
/// ```
pub fn with_cts(mut self, cts: impl PeripheralInput<'d>) -> Self {
self.rx = self.rx.with_cts(cts);
self
}
/// Configure RTS pin
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_tx(peripherals.GPIO2)
/// .with_rts(peripherals.GPIO3);
///
/// # Ok(())
/// # }
/// ```
pub fn with_rts(mut self, rts: impl PeripheralOutput<'d>) -> Self {
self.tx = self.tx.with_rts(rts);
self
@ -1541,11 +1666,12 @@ where
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// # let mut uart1 = Uart::new(
/// # peripherals.UART1,
/// # Config::default())?;
/// // Write bytes out over the UART:
/// uart1.write(b"Hello, world!")?;
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?;
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write(&MESSAGE)?;
/// # Ok(())
/// # }
/// ```
@ -1554,6 +1680,22 @@ where
}
/// Flush the transmit buffer of the UART
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?;
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write(&MESSAGE)?;
/// uart.flush()?;
/// # Ok(())
/// # }
/// ```
pub fn flush(&mut self) -> Result<(), TxError> {
self.tx.flush()
}
@ -1583,6 +1725,26 @@ where
///
/// If the error occurred before this function was called, the contents of
/// the FIFO are not modified.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?;
///
/// const MESSAGE: &[u8] = b"Hello, world!";
/// uart.write(&MESSAGE)?;
/// uart.flush()?;
///
/// let mut buf = [0u8; MESSAGE.len()];
/// uart.read(&mut buf[..])?;
///
/// # Ok(())
/// # }
/// ```
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, RxError> {
self.rx.read(buf)
}
@ -1593,6 +1755,20 @@ where
///
/// This function returns a [`ConfigError`] if the configuration is not
/// supported by the hardware.
///
/// ## Example
///
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?;
///
/// uart.apply_config(&Config::default().with_baudrate(19_200))?;
/// # Ok(())
/// # }
/// ```
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
// Must apply the common settings first, as `rx.apply_config` reads back symbol
// size.
@ -1612,13 +1788,14 @@ where
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::uart::{Config, Uart};
/// # let mut uart1 = Uart::new(
/// # peripherals.UART1,
/// # Config::default())?
/// # .with_rx(peripherals.GPIO1)
/// # .with_tx(peripherals.GPIO2);
/// let mut uart = Uart::new(
/// peripherals.UART0,
/// Config::default())?
/// .with_rx(peripherals.GPIO1)
/// .with_tx(peripherals.GPIO2);
///
/// // The UART can be split into separate Transmit and Receive components:
/// let (mut rx, mut tx) = uart1.split();
/// let (mut rx, mut tx) = uart.split();
///
/// // Each component can be used individually to interact with the UART:
/// tx.write(&[42u8])?;