1use super::*;
2use crate::{
3 Steal,
4 common::{
5 dma::*,
6 embedded_io::{ErrorType, Read, Write},
7 },
8};
9
10pub struct UartDmaBufTx<U, CH, OS: OsInterface> {
13 _uart: U,
14 w: DmaRingbufTxWriter<u8, CH>,
15 timeout: MicrosDurationU32,
16 flush_timeout: MicrosDurationU32,
17 waiter: OS::NotifyWaiter,
18}
19
20impl<U, CH, OS> UartDmaBufTx<U, CH, OS>
21where
22 U: UartPeriphWithDma,
23 CH: DmaChannel,
24 OS: OsInterface,
25{
26 pub fn new(
27 mut uart: U,
28 dma_ch: CH,
29 buf_size: usize,
30 baudrate: u32,
31 timeout: MicrosDurationU32,
32 ) -> (Self, DmaRingbufTxLoader<u8, CH, OS>) {
33 let (notifier, waiter) = OS::notify();
34
35 uart.enable_dma_tx(true);
36 let (w, l) = DmaRingbufTx::new(dma_ch, uart.get_tx_data_reg_addr(), buf_size, notifier);
37 (
38 Self {
39 _uart: uart,
40 w,
41 timeout,
42 flush_timeout: calculate_timeout(baudrate, buf_size + 10),
43 waiter,
44 },
45 l,
46 )
47 }
48}
49
50impl<U, CH, OS> ErrorType for UartDmaBufTx<U, CH, OS>
51where
52 OS: OsInterface,
53{
54 type Error = Error;
55}
56
57impl<U, CH, OS> Write for UartDmaBufTx<U, CH, OS>
58where
59 CH: DmaChannel,
60 OS: OsInterface,
61{
62 #[inline(always)]
63 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
64 if buf.is_empty() {
65 return Err(Error::Other);
66 }
67
68 self.waiter
69 .wait_with(OS::O, self.timeout, 2, || {
70 if let n @ 1.. = self.w.write(buf) {
71 Some(n)
72 } else {
73 None
74 }
75 })
76 .ok_or(Error::Busy)
77 }
78
79 fn flush(&mut self) -> Result<(), Self::Error> {
80 self.waiter
81 .wait_with(OS::O, self.flush_timeout, 4, || {
82 if !self.w.in_progress() {
83 Some(())
84 } else {
85 None
86 }
87 })
88 .ok_or(Error::Other)
89 }
90}
91
92pub struct UartDmaRx<U, CH, OS: OsInterface> {
95 _uart: U,
96 ch: DmaCircularBufferRx<u8, CH>,
97 timeout: MicrosDurationU32,
98 waiter: OS::NotifyWaiter,
99}
100
101impl<U, CH, OS> UartDmaRx<U, CH, OS>
102where
103 U: UartPeriphWithDma,
104 CH: DmaChannel + Steal,
105 OS: OsInterface,
106{
107 pub fn new(
108 mut uart: U,
109 mut dma_ch: CH,
110 buf_size: usize,
111 timeout: MicrosDurationU32,
112 ) -> (Self, UartDmaRxNotify<CH, OS>) {
113 let (notifier, waiter) = OS::notify();
114 let dma_ch2 = unsafe { dma_ch.steal() };
115 let ch = DmaCircularBufferRx::<u8, CH>::new(dma_ch2, uart.get_rx_data_reg_addr(), buf_size);
116 uart.enable_dma_rx(true);
117 dma_ch.set_interrupt(DmaEvent::HalfTransfer, true);
118 dma_ch.set_interrupt(DmaEvent::TransferComplete, true);
119 (
120 Self {
121 _uart: uart,
122 ch,
123 timeout,
124 waiter,
125 },
126 UartDmaRxNotify {
127 notifier,
128 ch: dma_ch,
129 },
130 )
131 }
132}
133
134impl<U, CH, OS> ErrorType for UartDmaRx<U, CH, OS>
135where
136 OS: OsInterface,
137{
138 type Error = Error;
139}
140
141impl<U, CH, OS> Read for UartDmaRx<U, CH, OS>
142where
143 CH: DmaChannel,
144 OS: OsInterface,
145{
146 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
147 if buf.is_empty() {
148 return Err(Error::Other);
149 }
150
151 self.waiter
152 .wait_with(OS::O, self.timeout, 2, || {
153 if let Some(d) = self.ch.pop_slice(buf.len()) {
154 buf[..d.len()].copy_from_slice(d);
155 Some(d.len())
156 } else {
157 None
158 }
159 })
160 .ok_or(Error::Other)
161 }
162}
163
164pub struct UartDmaRxNotify<CH, OS: OsInterface> {
165 notifier: OS::Notifier,
166 ch: CH,
167}
168
169impl<CH, OS> UartDmaRxNotify<CH, OS>
170where
171 CH: DmaChannel,
172 OS: OsInterface,
173{
174 pub fn interrupt_notify(&mut self) {
175 if self.ch.is_interrupted(DmaEvent::HalfTransfer)
176 || self.ch.is_interrupted(DmaEvent::TransferComplete)
177 {
178 self.notifier.notify();
179 }
180 }
181}