From 3d1c8a053a712a60b4dbe9e1fb66648e95f3c2be Mon Sep 17 00:00:00 2001 From: Andelf Date: Sat, 28 Oct 2023 12:06:39 +0800 Subject: [PATCH] feat(uart): bidi-uart --- src/gpio.rs | 29 ++++++++++---------- src/i2c.rs | 16 +++++------ src/rt.rs | 4 +-- src/spi.rs | 7 +++-- src/uart.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 104 insertions(+), 31 deletions(-) diff --git a/src/gpio.rs b/src/gpio.rs index da22a13..3d3edd5 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -515,25 +515,26 @@ pub(crate) mod sealed { } } - // input floatingZF #[inline] - fn set_as_input(&self) { + fn set_as_input(&self, pull: Pull) { let rb = self.block(); let pin = self._pin(); unsafe { rb.dir.modify(|r, w| w.bits(r.bits() & !(1 << pin))); - rb.pu.modify(|r, w| w.bits(r.bits() & !(1 << pin))); - rb.pd_drv.modify(|r, w| w.bits(r.bits() & !(1 << pin))); - } - } - - #[inline] - fn set_pullup(&self) { - let rb = self.block(); - let pin = self._pin(); - unsafe { - rb.pu.modify(|r, w| w.bits(r.bits() | (1 << pin))); - rb.pd_drv.modify(|r, w| w.bits(r.bits() & !(1 << pin))); + match pull { + Pull::None => { + rb.pu.modify(|r, w| w.bits(r.bits() & !(1 << pin))); + rb.pd_drv.modify(|r, w| w.bits(r.bits() & !(1 << pin))); + } + Pull::Up => { + rb.pu.modify(|r, w| w.bits(r.bits() | (1 << pin))); + rb.pd_drv.modify(|r, w| w.bits(r.bits() & !(1 << pin))); + } + Pull::Down => { + rb.pu.modify(|r, w| w.bits(r.bits() & !(1 << pin))); + rb.pd_drv.modify(|r, w| w.bits(r.bits() | (1 << pin))); + } + } } } diff --git a/src/i2c.rs b/src/i2c.rs index 6533610..c8da4d3 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -7,6 +7,7 @@ use core::marker::PhantomData; use fugit::HertzU32 as Hertz; +use crate::gpio::Pull; use crate::{interrupt, into_ref, peripherals, Peripheral}; // Any of BERR=1;ARLO=1;AF=1;OVR=1;PECERR=1; TIMEOUT=1;SMBAlert=1。 @@ -95,19 +96,16 @@ impl<'d, T: Instance> I2c<'d, T> { config: Config, ) -> Self { into_ref!(peri, scl, sda); + let _ = peri; if REMAP { let gpioctl = unsafe { &*crate::pac::GPIOCTL::PTR }; gpioctl.pin_alternate.modify(|_, w| w.i2c().set_bit()); } - scl.set_as_input(); - sda.set_as_input(); - if config.scl_pullup { - scl.set_pullup(); - } - if config.sda_pullup { - sda.set_pullup(); - } + let scl_pull = if config.scl_pullup { Pull::Up } else { Pull::None }; + let sda_pull = if config.sda_pullup { Pull::Up } else { Pull::None }; + scl.set_as_input(scl_pull); + sda.set_as_input(sda_pull); let rb = T::regs(); @@ -297,7 +295,7 @@ impl<'d, T: Instance> I2c<'d, T> { ) -> Result<(), Error> { if let Some((last, buffer)) = buffer.split_last_mut() { // Send a START condition and set ACK bit - T::regs().ctrl1.modify(|r, w| w.start().set_bit().ack().set_bit()); + T::regs().ctrl1.modify(|_, w| w.start().set_bit().ack().set_bit()); // Wait until START condition was generated while !self.check_and_clear_error_flags()?.sb().bit() { diff --git a/src/rt.rs b/src/rt.rs index 24b8a80..27bf34c 100644 --- a/src/rt.rs +++ b/src/rt.rs @@ -76,7 +76,7 @@ pub enum Interrupt { // Overwrites PAC's interrupt handlers extern "C" { - fn Reset() -> !; + // fn Reset() -> !; fn NonMaskableInt(); @@ -165,7 +165,7 @@ pub static __INTERRUPTS: [Vector; 36] = [ Vector { handler: TMR3 }, Vector { handler: UART2 }, Vector { handler: UART3 }, - Vector { reserved: 0xaaaaaaaa }, + Vector { handler: WDOG_BAT }, ]; macro_rules! cfg_global_asm { diff --git a/src/spi.rs b/src/spi.rs index d94f86f..9a43460 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -7,7 +7,7 @@ pub use embedded_hal_02::spi::{Mode, Polarity, MODE_0, MODE_3}; -use crate::gpio::{AnyPin, OutputDrive}; +use crate::gpio::{AnyPin, OutputDrive, Pull}; use crate::prelude::Hertz; use crate::{into_ref, peripherals, Peripheral, PeripheralRef}; @@ -49,6 +49,7 @@ impl Default for Config { } // TODO +#[allow(unused)] pub struct Spi<'d, T: Instance> { _peri: PeripheralRef<'d, T>, sck: Option>, @@ -73,7 +74,7 @@ impl<'d, T: Instance> Spi<'d, T> { } sck.set_as_output(OutputDrive::Standard); mosi.set_as_output(OutputDrive::Standard); - miso.set_as_input(); + miso.set_as_input(Pull::None); if REMAP { T::set_remap(); @@ -102,7 +103,7 @@ impl<'d, T: Instance> Spi<'d, T> { sck.set_high(); } sck.set_as_output(OutputDrive::Standard); - miso.set_as_input(); + miso.set_as_input(Pull::None); if REMAP { T::set_remap(); diff --git a/src/uart.rs b/src/uart.rs index fe06cb2..ba657ee 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -177,9 +177,9 @@ impl<'d, T: BasicInstance> UartRx<'d, T> { ) -> Result { use crate::interrupt::Interrupt; into_ref!(peri, rx); + let _ = peri; - rx.set_as_input(); - rx.set_pullup(); + rx.set_as_input(Pull::Up); if REMAP { T::set_remap(); } @@ -236,13 +236,86 @@ impl<'d, T: BasicInstance> UartRx<'d, T> { pub fn nb_read(&mut self) -> Result> { let rb = T::regs(); if self.check_rx_flags()? { - Ok(unsafe { rb.rbr().read().bits() as u8 }) + Ok(rb.rbr().read().bits() as u8) } else { Err(nb::Error::WouldBlock) } } } +pub struct Uart<'d, T: BasicInstance> { + tx: UartTx<'d, T>, + rx: UartRx<'d, T>, +} + +impl<'d, T: BasicInstance> Uart<'d, T> { + pub fn new( + peri: impl Peripheral

+ 'd, + tx: impl Peripheral

> + 'd, + rx: impl Peripheral

> + 'd, + config: Config, + ) -> Result { + // T::enable(); + + Self::new_inner(peri, tx, rx, config) + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + tx: impl Peripheral

> + 'd, + rx: impl Peripheral

> + 'd, + config: Config, + ) -> Result { + use crate::interrupt::Interrupt; + into_ref!(peri, tx, rx); + let _ = peri; + + tx.set_as_output(OutputDrive::Standard); + rx.set_as_input(Pull::Up); + + if REMAP { + T::set_remap(); + } + + let rb = T::regs(); + configure(rb, &config, true, true)?; + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + // create state once! + //let _s = T::state(); + + Ok(Self { + tx: UartTx { phantom: PhantomData }, + rx: UartRx { phantom: PhantomData }, + }) + } + + pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { + self.tx.blocking_write(buffer) + } + + pub fn blocking_flush(&mut self) -> Result<(), Error> { + self.tx.blocking_flush() + } + + pub fn nb_read(&mut self) -> Result> { + self.rx.nb_read() + } + + pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + self.rx.blocking_read(buffer) + } + + /// Split the Uart into a transmitter and receiver, which is + /// particularly useful when having two tasks correlating to + /// transmitting and receiving. + pub fn split(self) -> (UartTx<'d, T>, UartRx<'d, T>) { + (self.tx, self.rx) + } +} + impl<'d, T: BasicInstance> core::fmt::Write for UartTx<'d, T> { fn write_str(&mut self, s: &str) -> core::fmt::Result { self.blocking_write(s.as_bytes()).unwrap();