rp2040_hal/uart/
writer.rs1use super::{FifoWatermark, UartDevice, ValidUartPinout};
6use crate::dma::{EndlessWriteTarget, WriteTarget};
7use crate::pac::uart0::RegisterBlock;
8use core::fmt;
9use core::{convert::Infallible, marker::PhantomData};
10use embedded_hal_0_2::serial::Write as Write02;
11use embedded_hal_nb::serial::{ErrorType, Write};
12use nb::Error::*;
13
14pub fn set_tx_watermark(rb: &RegisterBlock, watermark: FifoWatermark) {
18 let wm = match watermark {
19 FifoWatermark::Bytes4 => 4,
20 FifoWatermark::Bytes8 => 3,
21 FifoWatermark::Bytes16 => 2,
22 FifoWatermark::Bytes24 => 1,
23 FifoWatermark::Bytes28 => 0,
24 };
25 rb.uartifls()
26 .modify(|_r, w| unsafe { w.txiflsel().bits(wm) });
27}
28
29pub(crate) fn transmit_flushed(rb: &RegisterBlock) -> nb::Result<(), Infallible> {
33 if rb.uartfr().read().busy().bit_is_set() {
34 Err(WouldBlock)
35 } else {
36 Ok(())
37 }
38}
39
40pub(crate) fn uart_is_writable(rb: &RegisterBlock) -> bool {
42 rb.uartfr().read().txff().bit_is_clear()
43}
44
45pub(crate) fn uart_is_busy(rb: &RegisterBlock) -> bool {
48 rb.uartfr().read().busy().bit_is_set()
49}
50
51pub(crate) fn write_raw<'d>(
60 rb: &RegisterBlock,
61 data: &'d [u8],
62) -> nb::Result<&'d [u8], Infallible> {
63 let mut bytes_written = 0;
64
65 for c in data {
66 if !uart_is_writable(rb) {
67 if bytes_written == 0 {
68 return Err(WouldBlock);
69 } else {
70 return Ok(&data[bytes_written..]);
71 }
72 }
73
74 rb.uartdr().write(|w| unsafe {
75 w.data().bits(*c);
76 w
77 });
78
79 bytes_written += 1;
80 }
81 Ok(&data[bytes_written..])
82}
83
84pub(crate) fn write_full_blocking(rb: &RegisterBlock, data: &[u8]) {
88 let mut temp = data;
89
90 while !temp.is_empty() {
91 temp = match write_raw(rb, temp) {
92 Ok(remaining) => remaining,
93 Err(WouldBlock) => continue,
94 Err(_) => unreachable!(),
95 }
96 }
97}
98
99pub(crate) fn enable_tx_interrupt(rb: &RegisterBlock) {
103 rb.uartifls()
108 .modify(|_r, w| unsafe { w.txiflsel().bits(2) });
109
110 rb.uartimsc().modify(|_r, w| {
118 w.txim().set_bit();
119 w
120 });
121}
122
123pub(crate) fn disable_tx_interrupt(rb: &RegisterBlock) {
125 rb.uartimsc().modify(|_r, w| {
129 w.txim().clear_bit();
130 w
131 });
132}
133
134pub struct Writer<D: UartDevice, P: ValidUartPinout<D>> {
139 pub(super) device: D,
140 pub(super) device_marker: PhantomData<D>,
141 pub(super) pins: PhantomData<P>,
142}
143
144impl<D: UartDevice, P: ValidUartPinout<D>> Writer<D, P> {
145 pub fn write_raw<'d>(&self, data: &'d [u8]) -> nb::Result<&'d [u8], Infallible> {
154 write_raw(&self.device, data)
155 }
156
157 pub fn write_full_blocking(&self, data: &[u8]) {
161 write_full_blocking(&self.device, data);
162 }
163
164 pub fn enable_tx_interrupt(&mut self) {
168 enable_tx_interrupt(&self.device)
169 }
170
171 pub fn disable_tx_interrupt(&mut self) {
173 disable_tx_interrupt(&self.device)
174 }
175
176 pub fn lowlevel_break_start(&mut self) {
200 self.device.uartlcr_h().modify(|_, w| w.brk().set_bit());
201 }
202
203 pub fn lowlevel_break_stop(&mut self) {
207 self.device.uartlcr_h().modify(|_, w| w.brk().clear_bit());
208 }
209}
210
211impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::ErrorType for Writer<D, P> {
212 type Error = Infallible;
213}
214
215impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::Write for Writer<D, P> {
216 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
217 let remaining = nb::block!(write_raw(&self.device, buf)).unwrap(); Ok(buf.len() - remaining.len())
220 }
221 fn flush(&mut self) -> Result<(), Self::Error> {
222 nb::block!(transmit_flushed(&self.device)).unwrap(); Ok(())
224 }
225}
226
227impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::WriteReady for Writer<D, P> {
228 fn write_ready(&mut self) -> Result<bool, Self::Error> {
229 Ok(uart_is_writable(&self.device))
230 }
231}
232
233impl<D: UartDevice, P: ValidUartPinout<D>> Write02<u8> for Writer<D, P> {
234 type Error = Infallible;
235
236 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
237 if self.write_raw(&[word]).is_err() {
238 Err(WouldBlock)
239 } else {
240 Ok(())
241 }
242 }
243
244 fn flush(&mut self) -> nb::Result<(), Self::Error> {
245 transmit_flushed(&self.device)
246 }
247}
248
249unsafe impl<D: UartDevice, P: ValidUartPinout<D>> WriteTarget for Writer<D, P> {
252 type TransmittedWord = u8;
253
254 fn tx_treq() -> Option<u8> {
255 Some(D::tx_dreq())
256 }
257
258 fn tx_address_count(&mut self) -> (u32, u32) {
259 (self.device.uartdr().as_ptr() as u32, u32::MAX)
260 }
261
262 fn tx_increment(&self) -> bool {
263 false
264 }
265}
266
267impl<D: UartDevice, P: ValidUartPinout<D>> EndlessWriteTarget for Writer<D, P> {}
268
269impl<D: UartDevice, P: ValidUartPinout<D>> ErrorType for Writer<D, P> {
270 type Error = Infallible;
271}
272
273impl<D: UartDevice, P: ValidUartPinout<D>> Write<u8> for Writer<D, P> {
274 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
275 if self.write_raw(&[word]).is_err() {
276 Err(WouldBlock)
277 } else {
278 Ok(())
279 }
280 }
281
282 fn flush(&mut self) -> nb::Result<(), Self::Error> {
283 transmit_flushed(&self.device).map_err(|e| match e {
284 WouldBlock => WouldBlock,
285 Other(v) => match v {},
286 })
287 }
288}
289
290impl<D: UartDevice, P: ValidUartPinout<D>> fmt::Write for Writer<D, P> {
291 fn write_str(&mut self, s: &str) -> fmt::Result {
292 s.bytes()
293 .try_for_each(|c| nb::block!(Write::write(self, c)))
294 .map_err(|_| fmt::Error)
295 }
296}