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 /// Drivers are constructed in blocking mode by default. To learn about the
/// differences between blocking and async drivers, see the [`Async`] mode /// differences between blocking and async drivers, see the [`Async`] mode
/// documentation. /// 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)] #[derive(Debug)]
#[non_exhaustive] #[non_exhaustive]
pub struct Blocking; pub struct Blocking;
@ -405,8 +424,24 @@ pub struct Blocking;
/// ///
/// Drivers are constructed in blocking mode by default. To set up an async /// 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 /// driver, a [`Blocking`] driver must be converted to an `Async` driver using
/// the `into_async` method. Drivers can be converted back to blocking mode /// the `into_async` method, for example:
/// using the `into_blocking` method. ///
/// ```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 /// Async mode drivers offer most of the same features as blocking drivers, but
/// with the addition of async APIs. Interrupt-related functions are not /// with the addition of async APIs. Interrupt-related functions are not

View File

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