aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/uart/mod.rs
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-04-30 08:04:21 +0200
committerpennae <[email protected]>2023-05-01 15:16:30 +0200
commit1d2f6667df1bb0299c4e9b4e1660ee729ce2b463 (patch)
treea8232ffdd9997e01531250bd1c847fc1333f3bf8 /embassy-rp/src/uart/mod.rs
parent7336b8cd88daf5299ee7f5b329028bbb64051fc6 (diff)
rp/uart: add set-break functions
sending break conditions is necessary to implement some protocols, and the hardware supports this natively. we do have to make sure that we don't assert a break condition while the uart is busy though, otherwise the break may be inserted before the last character in the tx fifo.
Diffstat (limited to 'embassy-rp/src/uart/mod.rs')
-rw-r--r--embassy-rp/src/uart/mod.rs49
1 files changed, 48 insertions, 1 deletions
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index f4a93f637..dd4a1cce2 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -1,12 +1,14 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
4use embassy_time::{Duration, Timer};
4 5
6use crate::clocks::clk_peri_freq;
5use crate::dma::{AnyChannel, Channel}; 7use crate::dma::{AnyChannel, Channel};
6use crate::gpio::sealed::Pin; 8use crate::gpio::sealed::Pin;
7use crate::gpio::AnyPin; 9use crate::gpio::AnyPin;
8use crate::pac::io::vals::{Inover, Outover}; 10use crate::pac::io::vals::{Inover, Outover};
9use crate::{pac, peripherals, Peripheral}; 11use crate::{pac, peripherals, Peripheral, RegExt};
10 12
11#[cfg(feature = "nightly")] 13#[cfg(feature = "nightly")]
12mod buffered; 14mod buffered;
@@ -146,6 +148,43 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
146 unsafe { while !r.uartfr().read().txfe() {} } 148 unsafe { while !r.uartfr().read().txfe() {} }
147 Ok(()) 149 Ok(())
148 } 150 }
151
152 pub fn busy(&self) -> bool {
153 unsafe { T::regs().uartfr().read().busy() }
154 }
155
156 /// Assert a break condition after waiting for the transmit buffers to empty,
157 /// for the specified number of bit times. This condition must be asserted
158 /// for at least two frame times to be effective, `bits` will adjusted
159 /// according to frame size, parity, and stop bit settings to ensure this.
160 ///
161 /// This method may block for a long amount of time since it has to wait
162 /// for the transmit fifo to empty, which may take a while on slow links.
163 pub async fn send_break(&mut self, bits: u32) {
164 let regs = T::regs();
165 let bits = bits.max(unsafe {
166 let lcr = regs.uartlcr_h().read();
167 let width = lcr.wlen() as u32 + 5;
168 let parity = lcr.pen() as u32;
169 let stops = 1 + lcr.stp2() as u32;
170 2 * (1 + width + parity + stops)
171 });
172 let divx64 = unsafe {
173 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32
174 } as u64;
175 let div_clk = clk_peri_freq() as u64 * 64;
176 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
177
178 self.blocking_flush().unwrap();
179 while self.busy() {}
180 unsafe {
181 regs.uartlcr_h().write_set(|w| w.set_brk(true));
182 }
183 Timer::after(Duration::from_micros(wait_usecs)).await;
184 unsafe {
185 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
186 }
187 }
149} 188}
150 189
151impl<'d, T: Instance> UartTx<'d, T, Blocking> { 190impl<'d, T: Instance> UartTx<'d, T, Blocking> {
@@ -526,6 +565,14 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
526 self.rx.blocking_read(buffer) 565 self.rx.blocking_read(buffer)
527 } 566 }
528 567
568 pub fn busy(&self) -> bool {
569 self.tx.busy()
570 }
571
572 pub async fn send_break(&mut self, bits: u32) {
573 self.tx.send_break(bits).await
574 }
575
529 /// Split the Uart into a transmitter and receiver, which is particuarly 576 /// Split the Uart into a transmitter and receiver, which is particuarly
530 /// useful when having two tasks correlating to transmitting and receiving. 577 /// useful when having two tasks correlating to transmitting and receiving.
531 pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { 578 pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) {