Added pins to the uart constructor functions

This commit is contained in:
Victor Koenders 2021-11-25 13:55:14 +01:00
parent bdfb4d82c9
commit a4a0bcf987
No known key found for this signature in database
GPG key ID: 2E441540865B8A1C
3 changed files with 88 additions and 54 deletions

View file

@ -16,17 +16,20 @@
//! let mut watchdog = Watchdog::new(peripherals.WATCHDOG); //! let mut watchdog = Watchdog::new(peripherals.WATCHDOG);
//! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, peripherals.XOSC, peripherals.CLOCKS, peripherals.PLL_SYS, peripherals.PLL_USB, &mut peripherals.RESETS, &mut watchdog).ok().unwrap(); //! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, peripherals.XOSC, peripherals.CLOCKS, peripherals.PLL_SYS, peripherals.PLL_USB, &mut peripherals.RESETS, &mut watchdog).ok().unwrap();
//! //!
//! // Set up UART on GP0 and GP1 (Pico pins 1 and 2)
//! let pins = (
//! pins.gpio0.into_mode::<FunctionUart>(),
//! pins.gpio1.into_mode::<FunctionUart>(),
//! );
//! // Need to perform clock init before using UART or it will freeze. //! // Need to perform clock init before using UART or it will freeze.
//! let uart = UartPeripheral::<_, _>::enable( //! let uart = UartPeripheral::enable(
//! peripherals.UART0, //! peripherals.UART0,
//! pins,
//! &mut peripherals.RESETS, //! &mut peripherals.RESETS,
//! uart::common_configs::_9600_8_N_1, //! uart::common_configs::_9600_8_N_1,
//! clocks.peripheral_clock.into(), //! clocks.peripheral_clock.into(),
//! ).unwrap(); //! ).unwrap();
//! //!
//! // Set up UART on GP0 and GP1 (Pico pins 1 and 2)
//! let _tx_pin = pins.gpio0.into_mode::<FunctionUart>();
//! let _rx_pin = pins.gpio1.into_mode::<FunctionUart>();
//! uart.write_full_blocking(b"Hello World!\r\n"); //! uart.write_full_blocking(b"Hello World!\r\n");
//! ``` //! ```

View file

@ -53,40 +53,43 @@ impl eh1_0_alpha::serial::Error for ReadErrorType {
} }
/// An UART Peripheral based on an underlying UART device. /// An UART Peripheral based on an underlying UART device.
pub struct UartPeripheral<S: State, D: UartDevice> { pub struct UartPeripheral<S: State, D: UartDevice, P: ValidUartPinout<D>> {
device: D, device: D,
_state: S, _state: S,
pins: P,
config: UartConfig, config: UartConfig,
effective_baudrate: Baud, effective_baudrate: Baud,
} }
impl<S: State, D: UartDevice> UartPeripheral<S, D> { impl<S: State, D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<S, D, P> {
fn transition<To: State>(self, state: To) -> UartPeripheral<To, D> { fn transition<To: State>(self, state: To) -> UartPeripheral<To, D, P> {
UartPeripheral { UartPeripheral {
device: self.device, device: self.device,
pins: self.pins,
config: self.config, config: self.config,
effective_baudrate: self.effective_baudrate, effective_baudrate: self.effective_baudrate,
_state: state, _state: state,
} }
} }
/// Releases the underlying device. /// Releases the underlying device and pins.
pub fn free(self) -> D { pub fn free(self) -> (D, P) {
self.device (self.device, self.pins)
} }
} }
impl<D: UartDevice> UartPeripheral<Disabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Disabled, D, P> {
/// Creates an UartPeripheral in Disabled state. /// Creates an UartPeripheral in Disabled state.
pub fn new(device: D, resets: &mut pac::RESETS) -> UartPeripheral<Disabled, D> { pub fn new(device: D, pins: P, resets: &mut pac::RESETS) -> UartPeripheral<Disabled, D, P> {
device.reset_bring_down(resets); device.reset_bring_down(resets);
device.reset_bring_up(resets); device.reset_bring_up(resets);
UartPeripheral { UartPeripheral {
device, device,
_state: Disabled,
pins,
config: common_configs::_9600_8_N_1, // placeholder config: common_configs::_9600_8_N_1, // placeholder
effective_baudrate: Baud(0), effective_baudrate: Baud(0),
_state: Disabled,
} }
} }
@ -95,8 +98,8 @@ impl<D: UartDevice> UartPeripheral<Disabled, D> {
self, self,
config: UartConfig, config: UartConfig,
frequency: Hertz, frequency: Hertz,
) -> Result<UartPeripheral<Enabled, D>, Error> { ) -> Result<UartPeripheral<Enabled, D, P>, Error> {
let mut device = self.free(); let (mut device, pins) = self.free();
let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?; let effective_baudrate = configure_baudrate(&mut device, &config.baudrate, &frequency)?;
device.uartlcr_h.write(|w| { device.uartlcr_h.write(|w| {
@ -105,11 +108,14 @@ impl<D: UartDevice> UartPeripheral<Disabled, D> {
w w
}); });
// Enable the UART, both TX and RX // Enable the UART, and the TX,RC,CTS and RTS based on the pins
device.uartcr.write(|w| { device.uartcr.write(|w| {
w.uarten().set_bit(); w.uarten().set_bit();
w.txe().set_bit(); w.txe().bit(P::TX_ENABLED);
w.rxe().set_bit(); w.rxe().bit(P::RX_ENABLED);
w.ctsen().bit(P::CTS_ENABLED);
w.rtsen().bit(P::RTS_ENABLED);
w w
}); });
@ -122,20 +128,23 @@ impl<D: UartDevice> UartPeripheral<Disabled, D> {
Ok(UartPeripheral { Ok(UartPeripheral {
device, device,
config, config,
pins,
effective_baudrate, effective_baudrate,
_state: Enabled, _state: Enabled,
}) })
} }
} }
impl<D: UartDevice> UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Enabled, D, P> {
/// Disable this UART Peripheral, falling back to the Disabled state. /// Disable this UART Peripheral, falling back to the Disabled state.
pub fn disable(self) -> UartPeripheral<Disabled, D> { pub fn disable(self) -> UartPeripheral<Disabled, D, P> {
// Disable the UART, both TX and RX // Disable the UART, both TX and RX
self.device.uartcr.write(|w| { self.device.uartcr.write(|w| {
w.uarten().clear_bit(); w.uarten().clear_bit();
w.txe().clear_bit(); w.txe().clear_bit();
w.rxe().clear_bit(); w.rxe().clear_bit();
w.ctsen().clear_bit();
w.rtsen().clear_bit();
w w
}); });
@ -361,7 +370,7 @@ fn set_format<'w>(
w w
} }
impl<D: UartDevice> Read<u8> for UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> Read<u8> for UartPeripheral<Enabled, D, P> {
type Error = ReadErrorType; type Error = ReadErrorType;
fn read(&mut self) -> nb::Result<u8, Self::Error> { fn read(&mut self) -> nb::Result<u8, Self::Error> {
@ -378,7 +387,7 @@ impl<D: UartDevice> Read<u8> for UartPeripheral<Enabled, D> {
} }
#[cfg(feature = "eh1_0_alpha")] #[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice> eh1::Read<u8> for UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> eh1::Read<u8> for UartPeripheral<Enabled, D, P> {
type Error = ReadErrorType; type Error = ReadErrorType;
fn read(&mut self) -> nb::Result<u8, Self::Error> { fn read(&mut self) -> nb::Result<u8, Self::Error> {
@ -417,7 +426,7 @@ impl eh1_0_alpha::serial::Error for SerialInfallible {
} }
} }
impl<D: UartDevice> Write<u8> for UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> Write<u8> for UartPeripheral<Enabled, D, P> {
type Error = Infallible; type Error = Infallible;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
@ -434,7 +443,7 @@ impl<D: UartDevice> Write<u8> for UartPeripheral<Enabled, D> {
} }
#[cfg(feature = "eh1_0_alpha")] #[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice> eh1::Write<u8> for UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> eh1::Write<u8> for UartPeripheral<Enabled, D, P> {
type Error = SerialInfallible; type Error = SerialInfallible;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
@ -453,7 +462,7 @@ impl<D: UartDevice> eh1::Write<u8> for UartPeripheral<Enabled, D> {
} }
} }
impl<D: UartDevice> fmt::Write for UartPeripheral<Enabled, D> { impl<D: UartDevice, P: ValidUartPinout<D>> fmt::Write for UartPeripheral<Enabled, D, P> {
fn write_str(&mut self, s: &str) -> fmt::Result { fn write_str(&mut self, s: &str) -> fmt::Result {
s.bytes() s.bytes()
.try_for_each(|c| nb::block!(self.write(c))) .try_for_each(|c| nb::block!(self.write(c)))

View file

@ -2,7 +2,16 @@ use crate::gpio::{bank0, FunctionUart, Pin};
use crate::pac::{UART0, UART1}; use crate::pac::{UART0, UART1};
/// Declares a valid UART pinout. /// Declares a valid UART pinout.
pub trait ValidUartPinout<UART> {} pub trait ValidUartPinout<UART> {
/// Indicates TX should be enabled for this pinout
const TX_ENABLED: bool;
/// Indicates RX should be enabled for this pinout
const RX_ENABLED: bool;
/// Indicates CTS should be enabled for this pinout
const CTS_ENABLED: bool;
/// Indicates RTS should be enabled for this pinout
const RTS_ENABLED: bool;
}
impl<UART, TX, RX, CTS, RTS> ValidUartPinout<UART> for Pins<TX, RX, CTS, RTS> impl<UART, TX, RX, CTS, RTS> ValidUartPinout<UART> for Pins<TX, RX, CTS, RTS>
where where
@ -11,6 +20,10 @@ where
CTS: Cts<UART>, CTS: Cts<UART>,
RTS: Rts<UART>, RTS: Rts<UART>,
{ {
const TX_ENABLED: bool = TX::ENABLED;
const RX_ENABLED: bool = RX::ENABLED;
const CTS_ENABLED: bool = CTS::ENABLED;
const RTS_ENABLED: bool = RTS::ENABLED;
} }
impl<UART, TX, RX> ValidUartPinout<UART> for (TX, RX) impl<UART, TX, RX> ValidUartPinout<UART> for (TX, RX)
@ -18,6 +31,10 @@ where
TX: Tx<UART>, TX: Tx<UART>,
RX: Rx<UART>, RX: Rx<UART>,
{ {
const TX_ENABLED: bool = TX::ENABLED;
const RX_ENABLED: bool = RX::ENABLED;
const CTS_ENABLED: bool = false;
const RTS_ENABLED: bool = false;
} }
impl<UART, TX, RX, CTS, RTS> ValidUartPinout<UART> for (TX, RX, CTS, RTS) impl<UART, TX, RX, CTS, RTS> ValidUartPinout<UART> for (TX, RX, CTS, RTS)
@ -27,6 +44,10 @@ where
CTS: Cts<UART>, CTS: Cts<UART>,
RTS: Rts<UART>, RTS: Rts<UART>,
{ {
const TX_ENABLED: bool = TX::ENABLED;
const RX_ENABLED: bool = RX::ENABLED;
const CTS_ENABLED: bool = CTS::ENABLED;
const RTS_ENABLED: bool = RTS::ENABLED;
} }
/// Customizable Uart pinout, allowing you to set the pins individually. /// Customizable Uart pinout, allowing you to set the pins individually.
@ -41,6 +62,21 @@ where
/// Every field can be set to `()` to not configure them. /// Every field can be set to `()` to not configure them.
/// ///
/// Note that you can also use tuples `(RX, TX)` or `(RX, TX, CTS, RTS)` instead of this type. /// Note that you can also use tuples `(RX, TX)` or `(RX, TX, CTS, RTS)` instead of this type.
///
/// This struct can either be filled manually or with a builder pattern:
///
/// ```no_run
/// # use rp2040_hal::uart::{Pins, ValidUartPinout};
/// # use rp2040_hal::pac::UART0;
/// # let gpio_pins: rp2040_hal::gpio::Pins = unsafe { core::mem::zeroed() };
/// let pins = Pins::default()
/// .tx(gpio_pins.gpio0.into_mode())
/// .rx(gpio_pins.gpio1.into_mode());
///
/// fn assert_is_valid_uart0<T: ValidUartPinout<UART0>>(_: T) {}
///
/// assert_is_valid_uart0(pins);
/// ```
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Pins<TX, RX, CTS, RTS> { pub struct Pins<TX, RX, CTS, RTS> {
pub tx: TX, pub tx: TX,
@ -49,22 +85,8 @@ pub struct Pins<TX, RX, CTS, RTS> {
pub cts: CTS, pub cts: CTS,
} }
impl Pins<(), (), (), ()> { impl Default for Pins<(), (), (), ()> {
/// Create a new pinout. This can be used as a builder pattern fn default() -> Self {
///
/// ```no_run
/// # use rp2040_hal::uart::{Pins, ValidUartPinout};
/// # use rp2040_hal::pac::UART0;
/// # let gpio_pins: rp2040_hal::gpio::Pins = unsafe { core::mem::zeroed() };
/// let pins = Pins::new()
/// .tx(gpio_pins.gpio0.into_mode())
/// .rx(gpio_pins.gpio1.into_mode());
///
/// fn assert_is_valid_uart0<T: ValidUartPinout<UART0>>(_: T) {}
///
/// assert_is_valid_uart0(pins);
/// ```
pub fn new() -> Self {
Self { Self {
tx: (), tx: (),
rx: (), rx: (),
@ -116,35 +138,35 @@ impl<TX, RX, CTS, RTS> Pins<TX, RX, CTS, RTS> {
/// Indicates a valid TX pin for UART0 or UART1 /// Indicates a valid TX pin for UART0 or UART1
pub trait Tx<UART> { pub trait Tx<UART> {
#[allow(missing_docs)] #[allow(missing_docs)]
const IS_SET: bool; const ENABLED: bool;
} }
/// Indicates a valid RX pin for UART0 or UART1 /// Indicates a valid RX pin for UART0 or UART1
pub trait Rx<UART> { pub trait Rx<UART> {
#[allow(missing_docs)] #[allow(missing_docs)]
const IS_SET: bool; const ENABLED: bool;
} }
/// Indicates a valid CTS pin for UART0 or UART1 /// Indicates a valid CTS pin for UART0 or UART1
pub trait Cts<UART> { pub trait Cts<UART> {
#[allow(missing_docs)] #[allow(missing_docs)]
const IS_SET: bool; const ENABLED: bool;
} }
/// Indicates a valid RTS pin for UART0 or UART1 /// Indicates a valid RTS pin for UART0 or UART1
pub trait Rts<UART> { pub trait Rts<UART> {
#[allow(missing_docs)] #[allow(missing_docs)]
const IS_SET: bool; const ENABLED: bool;
} }
impl<UART> Tx<UART> for () { impl<UART> Tx<UART> for () {
const IS_SET: bool = false; const ENABLED: bool = false;
} }
impl<UART> Rx<UART> for () { impl<UART> Rx<UART> for () {
const IS_SET: bool = false; const ENABLED: bool = false;
} }
impl<UART> Cts<UART> for () { impl<UART> Cts<UART> for () {
const IS_SET: bool = false; const ENABLED: bool = false;
} }
impl<UART> Rts<UART> for () { impl<UART> Rts<UART> for () {
const IS_SET: bool = false; const ENABLED: bool = false;
} }
macro_rules! impl_valid_uart { macro_rules! impl_valid_uart {
@ -157,22 +179,22 @@ macro_rules! impl_valid_uart {
$( $(
$( $(
impl Tx<$uart> for Pin<bank0::$tx, FunctionUart> { impl Tx<$uart> for Pin<bank0::$tx, FunctionUart> {
const IS_SET: bool = true; const ENABLED: bool = true;
} }
)* )*
$( $(
impl Rx<$uart> for Pin<bank0::$rx, FunctionUart> { impl Rx<$uart> for Pin<bank0::$rx, FunctionUart> {
const IS_SET: bool = true; const ENABLED: bool = true;
} }
)* )*
$( $(
impl Cts<$uart> for Pin<bank0::$cts, FunctionUart> { impl Cts<$uart> for Pin<bank0::$cts, FunctionUart> {
const IS_SET: bool = true; const ENABLED: bool = true;
} }
)* )*
$( $(
impl Rts<$uart> for Pin<bank0::$rts, FunctionUart> { impl Rts<$uart> for Pin<bank0::$rts, FunctionUart> {
const IS_SET: bool = true; const ENABLED: bool = true;
} }
)* )*
)* )*