Skip to content

Commit

Permalink
feat(uart): bidi-uart
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Oct 28, 2023
1 parent 01ddba7 commit 3d1c8a0
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 31 deletions.
29 changes: 15 additions & 14 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
}
}
}
}

Expand Down
16 changes: 7 additions & 9 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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。
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub enum Interrupt {

// Overwrites PAC's interrupt handlers
extern "C" {
fn Reset() -> !;
// fn Reset() -> !;

fn NonMaskableInt();

Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -49,6 +49,7 @@ impl Default for Config {
}

// TODO
#[allow(unused)]
pub struct Spi<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
sck: Option<PeripheralRef<'d, AnyPin>>,
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
79 changes: 76 additions & 3 deletions src/uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ impl<'d, T: BasicInstance> UartRx<'d, T> {
) -> Result<Self, ConfigError> {
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();
}
Expand Down Expand Up @@ -236,13 +236,86 @@ impl<'d, T: BasicInstance> UartRx<'d, T> {
pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
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<const REMAP: bool>(
peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T, REMAP>> + 'd,
rx: impl Peripheral<P = impl RxPin<T, REMAP>> + 'd,
config: Config,
) -> Result<Self, ConfigError> {
// T::enable();

Self::new_inner(peri, tx, rx, config)
}

fn new_inner<const REMAP: bool>(
peri: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T, REMAP>> + 'd,
rx: impl Peripheral<P = impl RxPin<T, REMAP>> + 'd,
config: Config,
) -> Result<Self, ConfigError> {
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<u8, nb::Error<Error>> {
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();
Expand Down

0 comments on commit 3d1c8a0

Please sign in to comment.