aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/uart/buffered.rs47
-rw-r--r--embassy-rp/src/uart/mod.rs49
2 files changed, 95 insertions, 1 deletions
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index cb0461930..b87345ee9 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -5,8 +5,10 @@ use core::task::Poll;
5use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 5use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
6use embassy_hal_common::atomic_ring_buffer::RingBuffer; 6use embassy_hal_common::atomic_ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embassy_time::{Duration, Timer};
8 9
9use super::*; 10use super::*;
11use crate::clocks::clk_peri_freq;
10use crate::RegExt; 12use crate::RegExt;
11 13
12pub struct State { 14pub struct State {
@@ -136,6 +138,14 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
136 self.rx.blocking_read(buffer) 138 self.rx.blocking_read(buffer)
137 } 139 }
138 140
141 pub fn busy(&self) -> bool {
142 self.tx.busy()
143 }
144
145 pub async fn send_break(&mut self, bits: u32) {
146 self.tx.send_break(bits).await
147 }
148
139 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) { 149 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
140 (self.rx, self.tx) 150 (self.rx, self.tx)
141 } 151 }
@@ -371,6 +381,43 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
371 } 381 }
372 } 382 }
373 } 383 }
384
385 pub fn busy(&self) -> bool {
386 unsafe { T::regs().uartfr().read().busy() }
387 }
388
389 /// Assert a break condition after waiting for the transmit buffers to empty,
390 /// for the specified number of bit times. This condition must be asserted
391 /// for at least two frame times to be effective, `bits` will adjusted
392 /// according to frame size, parity, and stop bit settings to ensure this.
393 ///
394 /// This method may block for a long amount of time since it has to wait
395 /// for the transmit fifo to empty, which may take a while on slow links.
396 pub async fn send_break(&mut self, bits: u32) {
397 let regs = T::regs();
398 let bits = bits.max(unsafe {
399 let lcr = regs.uartlcr_h().read();
400 let width = lcr.wlen() as u32 + 5;
401 let parity = lcr.pen() as u32;
402 let stops = 1 + lcr.stp2() as u32;
403 2 * (1 + width + parity + stops)
404 });
405 let divx64 = unsafe {
406 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32
407 } as u64;
408 let div_clk = clk_peri_freq() as u64 * 64;
409 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
410
411 Self::flush().await.unwrap();
412 while self.busy() {}
413 unsafe {
414 regs.uartlcr_h().write_set(|w| w.set_brk(true));
415 }
416 Timer::after(Duration::from_micros(wait_usecs)).await;
417 unsafe {
418 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
419 }
420 }
374} 421}
375 422
376impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { 423impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
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>) {