Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dedicated APIs for USART transmitter and receiver #122

Merged
merged 4 commits into from
Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions examples/i2c_vl53l0x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ fn main() -> ! {
&mut swm.handle,
);

let mut serial = p.USART0.enable(
let serial = p.USART0.enable(
&BaudRate::new(&syscon.uartfrg, 0),
&mut syscon.handle,
u0_rxd,
u0_txd,
);

serial.bwrite_all(b"Initializing I2C...\n")
serial.tx().bwrite_all(b"Initializing I2C...\n")
.expect("Write should never fail");

let (i2c0_sda, _) = swm.fixed_functions.i2c0_sda.assign(
Expand All @@ -95,30 +95,30 @@ fn main() -> ! {

let mut i2c = i2c.enable(&mut syscon.handle, i2c0_sda, i2c0_scl);

serial.bwrite_all(b"Writing data...\n")
serial.tx().bwrite_all(b"Writing data...\n")
.expect("Write should never fail");

// Write index of reference register
i2c.write(0x52, &[0xC0])
.expect("Failed to write data");

serial.bwrite_all(b"Receiving data...\n")
serial.tx().bwrite_all(b"Receiving data...\n")
.expect("Write should never fail");

// Read value from reference register
let mut buffer = [0u8; 1];
i2c.read(0x52, &mut buffer)
.expect("Failed to read data");

write!(serial, "{:#X}\n", buffer[0])
write!(serial.tx(), "{:#X}\n", buffer[0])
.expect("Write should never fail");

if buffer[0] == 0xEE {
serial.bwrite_all(b"SUCCESS!\n")
serial.tx().bwrite_all(b"SUCCESS!\n")
.expect("Write should never fail");
}
else {
serial.bwrite_all(b"FAILURE!\n")
serial.tx().bwrite_all(b"FAILURE!\n")
.expect("Write should never fail");
}

Expand Down
16 changes: 8 additions & 8 deletions examples/pmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn main() -> ! {
&mut swm.handle,
);

let mut serial = p.USART0.enable(
let serial = p.USART0.enable(
&baud_rate,
&mut syscon.handle,
u0_rxd,
Expand Down Expand Up @@ -75,7 +75,7 @@ fn main() -> ! {
nvic.enable(Interrupt::WKT);

// Busy Waiting
serial.bwrite_all(b"5 seconds of busy waiting...\n")
serial.tx().bwrite_all(b"5 seconds of busy waiting...\n")
.expect("UART write shouldn't fail");
wkt.start(five_seconds);
while let Err(nb::Error::WouldBlock) = wkt.wait() {}
Expand All @@ -89,7 +89,7 @@ fn main() -> ! {
// the timer from here on out.

// Sleep mode
serial.bwrite_all(b"5 seconds of sleep mode...\n")
serial.tx().bwrite_all(b"5 seconds of sleep mode...\n")
.expect("UART write shouldn't fail");
wkt.start(five_seconds);
nvic.clear_pending(Interrupt::WKT);
Expand All @@ -102,9 +102,9 @@ fn main() -> ! {
syscon.enable_interrupt_wakeup::<WktWakeup>();

// Deep-sleep mode
serial.bwrite_all(b"5 seconds of deep-sleep mode...\n")
serial.tx().bwrite_all(b"5 seconds of deep-sleep mode...\n")
.expect("UART write shouldn't fail");
block!(serial.flush())
block!(serial.tx().flush())
.expect("Flush shouldn't fail");
wkt.start(five_seconds);
nvic.clear_pending(Interrupt::WKT);
Expand All @@ -113,9 +113,9 @@ fn main() -> ! {
}

// Power-down mode
serial.bwrite_all(b"5 seconds of power-down mode...\n")
serial.tx().bwrite_all(b"5 seconds of power-down mode...\n")
.expect("UART write shouldn't fail");
block!(serial.flush())
block!(serial.tx().flush())
.expect("Flush shouldn't fail");
wkt.start(five_seconds);
nvic.clear_pending(Interrupt::WKT);
Expand All @@ -127,7 +127,7 @@ fn main() -> ! {
// this example, due to some problems with my setup that prevent me from
// testing it for the time being.

serial.bwrite_all(b"Done\n")
serial.tx().bwrite_all(b"Done\n")
.expect("UART write shouldn't fail");

loop {}
Expand Down
4 changes: 2 additions & 2 deletions examples/usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ fn main() -> ! {
// Initialize USART0. This should never fail, as the only reason `init`
// returns a `Result::Err` is when the transmitter is busy, which it
// shouldn't be right now.
let mut serial = p.USART0.enable(
let serial = p.USART0.enable(
&baud_rate,
&mut syscon.handle,
u0_rxd,
u0_txd,
);

// Write a string, blocking until it has finished writing
serial.bwrite_all(b"Hello, world!\n")
serial.tx().bwrite_all(b"Hello, world!\n")
.expect("UART write shouldn't fail");

loop {}
Expand Down
20 changes: 10 additions & 10 deletions src/syscon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,20 @@ impl SYSCON {
sysahbclkctrl: RegProxy::new(),
},

bod : BOD(PhantomData),
flash : FLASH(PhantomData),
irc : IRC(PhantomData),
ircout : IRCOUT(PhantomData),
mtb : MTB(PhantomData),
ram0_1 : RAM0_1(PhantomData),
rom : ROM(PhantomData),
sysosc : SYSOSC(PhantomData),
syspll : SYSPLL(PhantomData),
bod : BOD(PhantomData),
flash : FLASH(PhantomData),
irc : IRC(PhantomData),
ircout: IRCOUT(PhantomData),
mtb : MTB(PhantomData),
ram0_1: RAM0_1(PhantomData),
rom : ROM(PhantomData),
sysosc: SYSOSC(PhantomData),
syspll: SYSPLL(PhantomData),

uartfrg: UARTFRG {
uartclkdiv : RegProxy::new(),
uartfrgdiv : RegProxy::new(),
uartfrgmult: RegProxy::new(),

},

irc_derived_clock: IrcDerivedClock::new(),
Expand Down
85 changes: 51 additions & 34 deletions src/usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
//! );
//!
//! // Use a blocking method to write a string
//! serial.bwrite_all(b"Hello, world!");
//! serial.tx().bwrite_all(b"Hello, world!");
//! ```
//!
//! Please refer to the [examples in the repository] for more example code.
Expand Down Expand Up @@ -99,14 +99,16 @@ pub struct USART<UsartX, State = init_state::Enabled> {
_state: State,
}

impl<UsartX> USART<UsartX, init_state::Disabled> where UsartX: Peripheral {
impl<UsartX> USART<UsartX, init_state::Disabled> {
pub(crate) fn new(usart: UsartX) -> Self {
USART {
usart : usart,
_state: init_state::Disabled,
}
}
}

impl<UsartX> USART<UsartX, init_state::Disabled> where UsartX: Peripheral {
/// Enable the USART
///
/// This method is only available, if `USART` is in the [`Disabled`] state.
Expand Down Expand Up @@ -251,17 +253,47 @@ impl<UsartX> USART<UsartX, init_state::Enabled> where UsartX: Peripheral {
w.txrdyclr().set_bit()
);
}

/// Return USART receiver
pub fn rx(&self) -> Receiver<UsartX> {
Receiver(self)
}

/// Return USART transmitter
pub fn tx(&self) -> Transmitter<UsartX> {
Transmitter(self)
}
}

impl<UsartX, State> USART<UsartX, State> {
/// Return the raw peripheral
///
/// This method serves as an escape hatch from the HAL API. It returns the
/// raw peripheral, allowing you to do whatever you want with it, without
/// limitations imposed by the API.
///
/// If you are using this method because a feature you need is missing from
/// the HAL API, please [open an issue] or, if an issue for your feature
/// request already exists, comment on the existing issue, so we can
/// prioritize it accordingly.
///
/// [open an issue]: https://github.com/braun-robotics/rust-lpc82x-hal/issues
pub fn free(self) -> UsartX {
self.usart
}
}

impl<UsartX> Read<u8> for USART<UsartX, init_state::Enabled>

/// USART receiver
pub struct Receiver<'usart, UsartX: 'usart>(&'usart USART<UsartX>);

impl<'usart, UsartX> Read<u8> for Receiver<'usart, UsartX>
where UsartX: Peripheral,
{
type Error = Error;

fn read(&mut self) -> nb::Result<u8, Self::Error> {
let ref uart = self.usart;

let stat = uart.stat.read();
let stat = self.0.usart.stat.read();

if stat.rxbrk().bit_is_set() {
return Err(nb::Error::WouldBlock);
Expand All @@ -273,7 +305,7 @@ impl<UsartX> Read<u8> for USART<UsartX, init_state::Enabled>
if stat.rxrdy().bit_is_set() {
// It's important to read this register all at once, as reading
// it changes the status flags.
let rx_dat_stat = uart.rxdatstat.read();
let rx_dat_stat = self.0.usart.rxdatstat.read();

if rx_dat_stat.framerr().bit_is_set() {
return Err(nb::Error::Other(Error::Framing));
Expand All @@ -296,37 +328,41 @@ impl<UsartX> Read<u8> for USART<UsartX, init_state::Enabled>
}
}

impl<UsartX> Write<u8> for USART<UsartX, init_state::Enabled>

/// USART transmitter
pub struct Transmitter<'usart, UsartX: 'usart>(&'usart USART<UsartX>);

impl<'usart, UsartX> Write<u8> for Transmitter<'usart, UsartX>
where UsartX: Peripheral,
{
type Error = !;

fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
if self.usart.stat.read().txrdy().bit_is_clear() {
if self.0.usart.stat.read().txrdy().bit_is_clear() {
return Err(nb::Error::WouldBlock);
}

unsafe {
self.usart.txdat.write(|w| w.txdat().bits(word as u16));
self.0.usart.txdat.write(|w| w.txdat().bits(word as u16));
}

Ok(())
}

fn flush(&mut self) -> nb::Result<(), Self::Error> {
if self.usart.stat.read().txidle().bit_is_clear() {
if self.0.usart.stat.read().txidle().bit_is_clear() {
return Err(nb::Error::WouldBlock);
}

Ok(())
}
}

impl<UsartX> BlockingWriteDefault<u8> for USART<UsartX, init_state::Enabled>
impl<'usart, UsartX> BlockingWriteDefault<u8> for Transmitter<'usart, UsartX>
where UsartX: Peripheral,
{}

impl<UsartX> fmt::Write for USART<UsartX, init_state::Enabled>
impl<'usart, UsartX> fmt::Write for Transmitter<'usart, UsartX>
where
Self : BlockingWriteDefault<u8>,
UsartX: Peripheral,
Expand All @@ -343,25 +379,7 @@ impl<UsartX> fmt::Write for USART<UsartX, init_state::Enabled>
}
}

impl<UsartX, State> USART<UsartX, State> {
/// Return the raw peripheral
///
/// This method serves as an escape hatch from the HAL API. It returns the
/// raw peripheral, allowing you to do whatever you want with it, without
/// limitations imposed by the API.
///
/// If you are using this method because a feature you need is missing from
/// the HAL API, please [open an issue] or, if an issue for your feature
/// request already exists, comment on the existing issue, so we can
/// prioritize it accordingly.
///
/// [open an issue]: https://github.com/braun-robotics/rust-lpc82x-hal/issues
pub fn free(self) -> UsartX {
self.usart
}
}

impl<UsartX> dma::Dest for USART<UsartX, init_state::Enabled>
impl<'usart, UsartX> dma::Dest for Transmitter<'usart, UsartX>
where UsartX: Peripheral,
{
type Error = !;
Expand All @@ -371,12 +389,11 @@ impl<UsartX> dma::Dest for USART<UsartX, init_state::Enabled>
}

fn end_addr(&mut self) -> *mut u8 {
&self.usart.txdat as *const _ as *mut TXDAT as *mut u8
&self.0.usart.txdat as *const _ as *mut TXDAT as *mut u8
}
}



/// Internal trait for USART peripherals
///
/// This trait is an internal implementation detail and should neither be
Expand Down