From 369ac5a23ffed5395869ba430a86c40c6eba59fb Mon Sep 17 00:00:00 2001 From: 9names <60134748+9names@users.noreply.github.com> Date: Sun, 8 Aug 2021 15:36:56 +1000 Subject: [PATCH] Add UART example + core::fmt support to UART (#73) * Add standalone UART example * Add UART example to docs in UART module * Add core::fmt::write_str to UART module to allow easy use of format! macro in user code --- rp2040-hal/examples/uart.rs | 67 +++++++++++++++++++++++++++++++++++++ rp2040-hal/src/uart.rs | 31 ++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 rp2040-hal/examples/uart.rs diff --git a/rp2040-hal/examples/uart.rs b/rp2040-hal/examples/uart.rs new file mode 100644 index 0000000..27a4710 --- /dev/null +++ b/rp2040-hal/examples/uart.rs @@ -0,0 +1,67 @@ +//! Print an incrementing number to UART0 in a loop +#![no_std] +#![no_main] + +use core::fmt::Write; +use cortex_m_rt::entry; +use hal::clocks::init_clocks_and_plls; +use hal::gpio::{self, Pins}; +use hal::pac; +use hal::sio::Sio; +use hal::uart::UartPeripheral; +use hal::watchdog::Watchdog; +use panic_halt as _; +use rp2040_hal as hal; + +#[link_section = ".boot2"] +#[used] +pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; + +#[entry] +fn main() -> ! { + let mut pac = pac::Peripherals::take().unwrap(); + let mut watchdog = Watchdog::new(pac.WATCHDOG); + let sio = Sio::new(pac.SIO); + + // External high-speed crystal on the pico board is 12Mhz + let external_xtal_freq_hz = 12_000_000u32; + let clocks = init_clocks_and_plls( + external_xtal_freq_hz, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let pins = Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + let mut uart = UartPeripheral::<_, _>::enable( + pac.UART0, + &mut pac.RESETS, + hal::uart::common_configs::_9600_8_N_1, + clocks.peripheral_clock.into(), + ) + .unwrap(); + + // UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1) + let _tx_pin = pins.gpio0.into_mode::(); + let _rx_pin = pins.gpio1.into_mode::(); + + uart.write_full_blocking(b"UART example\r\n"); + + let mut value = 0u32; + loop { + writeln!(uart, "value: {:02}\r", value).unwrap(); + cortex_m::asm::delay(10_000_000); + value += 1 + } +} diff --git a/rp2040-hal/src/uart.rs b/rp2040-hal/src/uart.rs index 71b1f3b..fbab75d 100644 --- a/rp2040-hal/src/uart.rs +++ b/rp2040-hal/src/uart.rs @@ -1,7 +1,28 @@ //! Universal Asynchronous Receiver Transmitter (UART) -// See [Chapter 4 Section 2](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details +//! +//! See [Chapter 4 Section 2](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) of the datasheet for more details +//! +//! ## Usage +//! +//! See [examples/uart.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples/uart.rs) for a more complete example +//! ```rust +//! // Need to perform clock init before using UART or it will freeze. +//! // Skipping it here for brevity +//! let uart = UartPeripheral::<_, _>::enable( +//! pac.UART0, +//! &mut pac.RESETS, +//! hal::uart::common_configs::_9600_8_N_1, +//! clocks.peripheral_clock.into(), +//! ).unwrap(); +//! +//! // Set up UART on GP0 and GP1 (Pico pins 1 and 2) +//! let _tx_pin = pins.gpio0.into_mode::(); +//! let _rx_pin = pins.gpio1.into_mode::(); +//! uart.write_full_blocking(b"Hello World!\r\n"); +//! ``` use core::convert::Infallible; +use core::fmt; use core::ops::Deref; use embedded_time::fixed_point::FixedPoint; use embedded_time::rate::Baud; @@ -480,3 +501,11 @@ impl Write for UartPeripheral { self.transmit_flushed() } } + +impl fmt::Write for UartPeripheral { + fn write_str(&mut self, s: &str) -> fmt::Result { + s.bytes() + .try_for_each(|c| nb::block!(self.write(c))) + .map_err(|_| fmt::Error) + } +}