aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-08 04:13:40 +0000
committerGitHub <[email protected]>2021-12-08 04:13:40 +0000
commit1c651e2b44696c70a4e26d9e34a419e84afc356f (patch)
tree5585ed71a2a89d22f9691af4e3905a4bf7607cae
parentb0da4dfa8c6613bc19980cd41e72ef9b410fce53 (diff)
parent4ddd23d6231dc5fe74f4e5cb41d76000939b5787 (diff)
Merge #526
526: stm32/usart: unify v1 and v2 r=Dirbaio a=Dirbaio Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-stm32/src/usart/mod.rs424
-rw-r--r--embassy-stm32/src/usart/v1.rs176
-rw-r--r--embassy-stm32/src/usart/v2.rs388
m---------stm32-data0
4 files changed, 418 insertions, 570 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 7cab10d05..a835093c5 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,14 +1,18 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg_attr(usart_v1, path = "v1.rs")] 3use core::future::Future;
4#[cfg_attr(usart_v2, path = "v2.rs")] 4use core::marker::PhantomData;
5mod _version; 5use embassy::interrupt::Interrupt;
6use crate::{dma, peripherals}; 6use embassy::util::Unborrow;
7pub use _version::*; 7use embassy_hal_common::unborrow;
8use futures::TryFutureExt;
8 9
10use crate::dma::NoDma;
11use crate::gpio::sealed::AFType::{OutputOpenDrain, OutputPushPull};
9use crate::gpio::Pin; 12use crate::gpio::Pin;
13use crate::pac::usart::{regs, vals};
10use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
11use embassy::interrupt::Interrupt; 15use crate::{dma, peripherals};
12 16
13#[derive(Clone, Copy, PartialEq, Eq, Debug)] 17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
14pub enum DataBits { 18pub enum DataBits {
@@ -70,6 +74,414 @@ pub enum Error {
70 Parity, 74 Parity,
71} 75}
72 76
77pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
78 inner: T,
79 phantom: PhantomData<&'d mut T>,
80 tx_dma: TxDma,
81 rx_dma: RxDma,
82}
83
84impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
85 pub fn new(
86 inner: impl Unborrow<Target = T>,
87 rx: impl Unborrow<Target = impl RxPin<T>>,
88 tx: impl Unborrow<Target = impl TxPin<T>>,
89 tx_dma: impl Unborrow<Target = TxDma>,
90 rx_dma: impl Unborrow<Target = RxDma>,
91 config: Config,
92 ) -> Self {
93 unborrow!(inner, rx, tx, tx_dma, rx_dma);
94
95 T::enable();
96 let pclk_freq = T::frequency();
97
98 // TODO: better calculation, including error checking and OVER8 if possible.
99 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
100
101 let r = inner.regs();
102
103 unsafe {
104 rx.set_as_af(rx.af_num(), OutputOpenDrain);
105 tx.set_as_af(tx.af_num(), OutputPushPull);
106
107 r.cr2().write(|_w| {});
108 r.cr3().write(|_w| {});
109 r.brr().write_value(regs::Brr(div));
110 r.cr1().write(|w| {
111 w.set_ue(true);
112 w.set_te(true);
113 w.set_re(true);
114 w.set_m0(vals::M0::BIT8);
115 w.set_pce(config.parity != Parity::ParityNone);
116 w.set_ps(match config.parity {
117 Parity::ParityOdd => vals::Ps::ODD,
118 Parity::ParityEven => vals::Ps::EVEN,
119 _ => vals::Ps::EVEN,
120 });
121 });
122 }
123
124 Self {
125 inner,
126 phantom: PhantomData,
127 tx_dma,
128 rx_dma,
129 }
130 }
131
132 async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error>
133 where
134 TxDma: crate::usart::TxDma<T>,
135 {
136 let ch = &mut self.tx_dma;
137 let request = ch.request();
138 unsafe {
139 self.inner.regs().cr3().modify(|reg| {
140 reg.set_dmat(true);
141 });
142 }
143 let r = self.inner.regs();
144 let dst = tdr(r);
145 crate::dma::write(ch, request, buffer, dst).await;
146 Ok(())
147 }
148
149 async fn read_dma(&mut self, buffer: &mut [u8]) -> Result<(), Error>
150 where
151 RxDma: crate::usart::RxDma<T>,
152 {
153 let ch = &mut self.rx_dma;
154 let request = ch.request();
155 unsafe {
156 self.inner.regs().cr3().modify(|reg| {
157 reg.set_dmar(true);
158 });
159 }
160 let r = self.inner.regs();
161 let src = rdr(r);
162 crate::dma::read(ch, request, src, buffer).await;
163 Ok(())
164 }
165
166 pub fn read_blocking(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
167 unsafe {
168 let r = self.inner.regs();
169 for b in buffer {
170 loop {
171 let sr = sr(r).read();
172 if sr.pe() {
173 rdr(r).read_volatile();
174 return Err(Error::Parity);
175 } else if sr.fe() {
176 rdr(r).read_volatile();
177 return Err(Error::Framing);
178 } else if sr.ne() {
179 rdr(r).read_volatile();
180 return Err(Error::Noise);
181 } else if sr.ore() {
182 rdr(r).read_volatile();
183 return Err(Error::Overrun);
184 } else if sr.rxne() {
185 break;
186 }
187 }
188 *b = rdr(r).read_volatile();
189 }
190 }
191 Ok(())
192 }
193}
194
195impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8>
196 for Uart<'d, T, NoDma, RxDma>
197{
198 type Error = Error;
199 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
200 unsafe {
201 let r = self.inner.regs();
202 for &b in buffer {
203 while !sr(r).read().txe() {}
204 tdr(r).write_volatile(b);
205 }
206 }
207 Ok(())
208 }
209 fn bflush(&mut self) -> Result<(), Self::Error> {
210 unsafe {
211 let r = self.inner.regs();
212 while !sr(r).read().tc() {}
213 }
214 Ok(())
215 }
216}
217
218impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma>
219where
220 TxDma: crate::usart::TxDma<T>,
221{
222 #[rustfmt::skip]
223 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a;
224
225 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
226 self.write_dma(buf)
227 .map_err(|_| embassy_traits::uart::Error::Other)
228 }
229}
230
231impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Read for Uart<'d, T, TxDma, RxDma>
232where
233 RxDma: crate::usart::RxDma<T>,
234{
235 #[rustfmt::skip]
236 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a;
237
238 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
239 self.read_dma(buf)
240 .map_err(|_| embassy_traits::uart::Error::Other)
241 }
242}
243
244#[cfg(usart_v2)]
245pub use buffered::*;
246#[cfg(usart_v2)]
247mod buffered {
248 use atomic_polyfill::{compiler_fence, Ordering};
249 use core::pin::Pin;
250 use core::task::Context;
251 use core::task::Poll;
252 use embassy::waitqueue::WakerRegistration;
253 use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
254 use embassy_hal_common::ring_buffer::RingBuffer;
255
256 use super::*;
257
258 pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>);
259 impl<'d, T: Instance> State<'d, T> {
260 pub fn new() -> Self {
261 Self(StateStorage::new())
262 }
263 }
264
265 struct StateInner<'d, T: Instance> {
266 uart: Uart<'d, T, NoDma, NoDma>,
267 phantom: PhantomData<&'d mut T>,
268
269 rx_waker: WakerRegistration,
270 rx: RingBuffer<'d>,
271
272 tx_waker: WakerRegistration,
273 tx: RingBuffer<'d>,
274 }
275
276 unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {}
277 unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {}
278
279 pub struct BufferedUart<'d, T: Instance> {
280 inner: PeripheralMutex<'d, StateInner<'d, T>>,
281 }
282
283 impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
284
285 impl<'d, T: Instance> BufferedUart<'d, T> {
286 pub unsafe fn new(
287 state: &'d mut State<'d, T>,
288 uart: Uart<'d, T, NoDma, NoDma>,
289 irq: impl Unborrow<Target = T::Interrupt> + 'd,
290 tx_buffer: &'d mut [u8],
291 rx_buffer: &'d mut [u8],
292 ) -> BufferedUart<'d, T> {
293 unborrow!(irq);
294
295 let r = uart.inner.regs();
296 r.cr1().modify(|w| {
297 w.set_rxneie(true);
298 w.set_idleie(true);
299 });
300
301 Self {
302 inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
303 uart,
304 phantom: PhantomData,
305 tx: RingBuffer::new(tx_buffer),
306 tx_waker: WakerRegistration::new(),
307
308 rx: RingBuffer::new(rx_buffer),
309 rx_waker: WakerRegistration::new(),
310 }),
311 }
312 }
313 }
314
315 impl<'d, T: Instance> StateInner<'d, T>
316 where
317 Self: 'd,
318 {
319 fn on_rx(&mut self) {
320 let r = self.uart.inner.regs();
321 unsafe {
322 let sr = r.isr().read();
323 if sr.pe() {
324 r.icr().write(|w| {
325 w.set_pe(true);
326 });
327 trace!("Parity error");
328 } else if sr.fe() {
329 r.icr().write(|w| {
330 w.set_fe(true);
331 });
332 trace!("Framing error");
333 } else if sr.ne() {
334 r.icr().write(|w| {
335 w.set_ne(true);
336 });
337 trace!("Noise error");
338 } else if sr.ore() {
339 r.icr().write(|w| {
340 w.set_ore(true);
341 });
342 trace!("Overrun error");
343 } else if sr.rxne() {
344 let buf = self.rx.push_buf();
345 if buf.is_empty() {
346 self.rx_waker.wake();
347 } else {
348 buf[0] = r.rdr().read().0 as u8;
349 self.rx.push(1);
350 }
351 } else if sr.idle() {
352 r.icr().write(|w| {
353 w.set_idle(true);
354 });
355 self.rx_waker.wake();
356 };
357 }
358 }
359
360 fn on_tx(&mut self) {
361 let r = self.uart.inner.regs();
362 unsafe {
363 if r.isr().read().txe() {
364 let buf = self.tx.pop_buf();
365 if !buf.is_empty() {
366 r.cr1().modify(|w| {
367 w.set_txeie(true);
368 });
369 r.tdr().write_value(regs::Dr(buf[0].into()));
370 self.tx.pop(1);
371 self.tx_waker.wake();
372 } else {
373 // Disable interrupt until we have something to transmit again
374 r.cr1().modify(|w| {
375 w.set_txeie(false);
376 });
377 }
378 }
379 }
380 }
381 }
382
383 impl<'d, T: Instance> PeripheralState for StateInner<'d, T>
384 where
385 Self: 'd,
386 {
387 type Interrupt = T::Interrupt;
388 fn on_interrupt(&mut self) {
389 self.on_rx();
390 self.on_tx();
391 }
392 }
393
394 impl<'d, T: Instance> embassy::io::AsyncBufRead for BufferedUart<'d, T> {
395 fn poll_fill_buf(
396 mut self: Pin<&mut Self>,
397 cx: &mut Context<'_>,
398 ) -> Poll<Result<&[u8], embassy::io::Error>> {
399 self.inner.with(|state| {
400 compiler_fence(Ordering::SeqCst);
401
402 // We have data ready in buffer? Return it.
403 let buf = state.rx.pop_buf();
404 if !buf.is_empty() {
405 let buf: &[u8] = buf;
406 // Safety: buffer lives as long as uart
407 let buf: &[u8] = unsafe { core::mem::transmute(buf) };
408 return Poll::Ready(Ok(buf));
409 }
410
411 state.rx_waker.register(cx.waker());
412 Poll::<Result<&[u8], embassy::io::Error>>::Pending
413 })
414 }
415 fn consume(mut self: Pin<&mut Self>, amt: usize) {
416 let signal = self.inner.with(|state| {
417 let full = state.rx.is_full();
418 state.rx.pop(amt);
419 full
420 });
421 if signal {
422 self.inner.pend();
423 }
424 }
425 }
426
427 impl<'d, T: Instance> embassy::io::AsyncWrite for BufferedUart<'d, T> {
428 fn poll_write(
429 mut self: Pin<&mut Self>,
430 cx: &mut Context<'_>,
431 buf: &[u8],
432 ) -> Poll<Result<usize, embassy::io::Error>> {
433 let (poll, empty) = self.inner.with(|state| {
434 let empty = state.tx.is_empty();
435 let tx_buf = state.tx.push_buf();
436 if tx_buf.is_empty() {
437 state.tx_waker.register(cx.waker());
438 return (Poll::Pending, empty);
439 }
440
441 let n = core::cmp::min(tx_buf.len(), buf.len());
442 tx_buf[..n].copy_from_slice(&buf[..n]);
443 state.tx.push(n);
444
445 (Poll::Ready(Ok(n)), empty)
446 });
447 if empty {
448 self.inner.pend();
449 }
450 poll
451 }
452 }
453}
454
455#[cfg(usart_v1)]
456fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
457 r.dr().ptr() as _
458}
459
460#[cfg(usart_v1)]
461fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
462 r.dr().ptr() as _
463}
464
465#[cfg(usart_v1)]
466fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> {
467 r.sr()
468}
469
470#[cfg(usart_v2)]
471fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
472 r.tdr().ptr() as _
473}
474
475#[cfg(usart_v2)]
476fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
477 r.rdr().ptr() as _
478}
479
480#[cfg(usart_v2)]
481fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate::pac::common::R> {
482 r.isr()
483}
484
73pub(crate) mod sealed { 485pub(crate) mod sealed {
74 use super::*; 486 use super::*;
75 487
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
deleted file mode 100644
index 10f87f2dd..000000000
--- a/embassy-stm32/src/usart/v1.rs
+++ /dev/null
@@ -1,176 +0,0 @@
1use crate::gpio::sealed::AFType::{OutputOpenDrain, OutputPushPull};
2use core::future::Future;
3use core::marker::PhantomData;
4use embassy::util::Unborrow;
5use embassy_hal_common::unborrow;
6use futures::TryFutureExt;
7
8use super::*;
9use crate::dma::NoDma;
10use crate::pac::usart::{regs, vals};
11
12pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
13 inner: T,
14 phantom: PhantomData<&'d mut T>,
15 tx_dma: TxDma,
16 #[allow(dead_code)]
17 rx_dma: RxDma,
18}
19
20impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
21 pub fn new(
22 inner: impl Unborrow<Target = T>,
23 rx: impl Unborrow<Target = impl RxPin<T>>,
24 tx: impl Unborrow<Target = impl TxPin<T>>,
25 tx_dma: impl Unborrow<Target = TxDma>,
26 rx_dma: impl Unborrow<Target = RxDma>,
27 config: Config,
28 ) -> Self {
29 unborrow!(inner, rx, tx, tx_dma, rx_dma);
30
31 T::enable();
32 let pclk_freq = T::frequency();
33
34 // TODO: better calculation, including error checking and OVER8 if possible.
35 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
36
37 let r = inner.regs();
38
39 unsafe {
40 rx.set_as_af(rx.af_num(), OutputOpenDrain);
41 tx.set_as_af(tx.af_num(), OutputPushPull);
42
43 r.brr().write_value(regs::Brr(div));
44 r.cr1().write(|w| {
45 w.set_ue(true);
46 w.set_te(true);
47 w.set_re(true);
48 w.set_m(vals::M::M8);
49 w.set_pce(config.parity != Parity::ParityNone);
50 w.set_ps(match config.parity {
51 Parity::ParityOdd => vals::Ps::ODD,
52 Parity::ParityEven => vals::Ps::EVEN,
53 _ => vals::Ps::EVEN,
54 });
55 });
56 r.cr2().write(|_w| {});
57 r.cr3().write(|_w| {});
58 }
59
60 Self {
61 inner,
62 phantom: PhantomData,
63 tx_dma,
64 rx_dma,
65 }
66 }
67
68 async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error>
69 where
70 TxDma: crate::usart::TxDma<T>,
71 {
72 let ch = &mut self.tx_dma;
73 let request = ch.request();
74 unsafe {
75 self.inner.regs().cr3().modify(|reg| {
76 reg.set_dmat(true);
77 });
78 }
79 let r = self.inner.regs();
80 let dst = r.dr().ptr() as *mut u8;
81 crate::dma::write(ch, request, buffer, dst).await;
82 Ok(())
83 }
84
85 async fn read_dma(&mut self, buffer: &mut [u8]) -> Result<(), Error>
86 where
87 RxDma: crate::usart::RxDma<T>,
88 {
89 let ch = &mut self.rx_dma;
90 let request = ch.request();
91 unsafe {
92 self.inner.regs().cr3().modify(|reg| {
93 reg.set_dmar(true);
94 });
95 }
96 let r = self.inner.regs();
97 let src = r.dr().ptr() as *mut u8;
98 crate::dma::read(ch, request, src, buffer).await;
99 Ok(())
100 }
101
102 pub fn read_blocking(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
103 unsafe {
104 let r = self.inner.regs();
105 for b in buffer {
106 loop {
107 let sr = r.sr().read();
108 if sr.pe() {
109 r.dr().read();
110 return Err(Error::Parity);
111 } else if sr.fe() {
112 r.dr().read();
113 return Err(Error::Framing);
114 } else if sr.ne() {
115 r.dr().read();
116 return Err(Error::Noise);
117 } else if sr.ore() {
118 r.dr().read();
119 return Err(Error::Overrun);
120 } else if sr.rxne() {
121 break;
122 }
123 }
124 *b = r.dr().read().0 as u8;
125 }
126 }
127 Ok(())
128 }
129}
130
131impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8>
132 for Uart<'d, T, NoDma, RxDma>
133{
134 type Error = Error;
135 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
136 unsafe {
137 let r = self.inner.regs();
138 for &b in buffer {
139 while !r.sr().read().txe() {}
140 r.dr().write_value(regs::Dr(b as u32))
141 }
142 }
143 Ok(())
144 }
145 fn bflush(&mut self) -> Result<(), Self::Error> {
146 unsafe {
147 let r = self.inner.regs();
148 while !r.sr().read().tc() {}
149 }
150 Ok(())
151 }
152}
153
154// rustfmt::skip because intellij removes the 'where' claus on the associated type.
155#[rustfmt::skip]
156impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma>
157 where TxDma: crate::usart::TxDma<T>
158{
159 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a;
160
161 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
162 self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other)
163 }
164}
165
166// rustfmt::skip because intellij removes the 'where' claus on the associated type.
167#[rustfmt::skip]
168impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Read for Uart<'d, T, TxDma, RxDma>
169 where RxDma: crate::usart::RxDma<T>
170{
171 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a;
172
173 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
174 self.read_dma(buf).map_err(|_| embassy_traits::uart::Error::Other)
175 }
176}
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs
deleted file mode 100644
index 697adf459..000000000
--- a/embassy-stm32/src/usart/v2.rs
+++ /dev/null
@@ -1,388 +0,0 @@
1use atomic_polyfill::{compiler_fence, Ordering};
2use core::future::Future;
3use core::marker::PhantomData;
4use core::pin::Pin;
5use core::task::Context;
6use core::task::Poll;
7use embassy::util::Unborrow;
8use embassy::waitqueue::WakerRegistration;
9use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
10use embassy_hal_common::ring_buffer::RingBuffer;
11use embassy_hal_common::unborrow;
12use futures::TryFutureExt;
13
14use super::*;
15use crate::dma::NoDma;
16use crate::gpio::sealed::AFType::{OutputOpenDrain, OutputPushPull};
17use crate::pac::usart::{regs, vals};
18
19pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
20 inner: T,
21 phantom: PhantomData<&'d mut T>,
22 tx_dma: TxDma,
23 rx_dma: RxDma,
24}
25
26impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
27 pub fn new(
28 inner: impl Unborrow<Target = T>,
29 rx: impl Unborrow<Target = impl RxPin<T>>,
30 tx: impl Unborrow<Target = impl TxPin<T>>,
31 tx_dma: impl Unborrow<Target = TxDma>,
32 rx_dma: impl Unborrow<Target = RxDma>,
33 config: Config,
34 ) -> Self {
35 unborrow!(inner, rx, tx, tx_dma, rx_dma);
36
37 T::enable();
38 let pclk_freq = T::frequency();
39
40 // TODO: better calculation, including error checking and OVER8 if possible.
41 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
42
43 let r = inner.regs();
44
45 unsafe {
46 rx.set_as_af(rx.af_num(), OutputOpenDrain);
47 tx.set_as_af(tx.af_num(), OutputPushPull);
48
49 r.cr2().write(|_w| {});
50 r.cr3().write(|_w| {});
51
52 r.brr().write(|w| w.set_brr(div as u16));
53 r.cr1().write(|w| {
54 w.set_ue(true);
55 w.set_te(true);
56 w.set_re(true);
57 w.set_m0(vals::M0::BIT8);
58 w.set_m1(vals::M1::M0);
59 w.set_pce(config.parity != Parity::ParityNone);
60 w.set_ps(match config.parity {
61 Parity::ParityOdd => vals::Ps::ODD,
62 Parity::ParityEven => vals::Ps::EVEN,
63 _ => vals::Ps::EVEN,
64 });
65 });
66 r.cr2().write(|_w| {});
67 r.cr3().write(|_w| {});
68 }
69
70 Self {
71 inner,
72 phantom: PhantomData,
73 tx_dma,
74 rx_dma,
75 }
76 }
77
78 async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error>
79 where
80 TxDma: crate::usart::TxDma<T>,
81 {
82 let ch = &mut self.tx_dma;
83 let request = ch.request();
84 unsafe {
85 self.inner.regs().cr3().modify(|reg| {
86 reg.set_dmat(true);
87 });
88 }
89 let r = self.inner.regs();
90 let dst = r.tdr().ptr() as *mut u8;
91 crate::dma::write(ch, request, buffer, dst).await;
92 Ok(())
93 }
94
95 async fn read_dma(&mut self, buffer: &mut [u8]) -> Result<(), Error>
96 where
97 RxDma: crate::usart::RxDma<T>,
98 {
99 let ch = &mut self.rx_dma;
100 let request = ch.request();
101 unsafe {
102 self.inner.regs().cr3().modify(|reg| {
103 reg.set_dmar(true);
104 });
105 }
106 let r = self.inner.regs();
107 let src = r.rdr().ptr() as *mut u8;
108
109 crate::dma::read(ch, request, src, buffer).await;
110 Ok(())
111 }
112
113 pub fn read_blocking(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
114 unsafe {
115 let r = self.inner.regs();
116 for b in buffer {
117 loop {
118 let sr = r.isr().read();
119 if sr.pe() {
120 r.rdr().read();
121 return Err(Error::Parity);
122 } else if sr.fe() {
123 r.rdr().read();
124 return Err(Error::Framing);
125 } else if sr.nf() {
126 r.rdr().read();
127 return Err(Error::Noise);
128 } else if sr.ore() {
129 r.rdr().read();
130 return Err(Error::Overrun);
131 } else if sr.rxne() {
132 break;
133 }
134 }
135 *b = r.rdr().read().0 as u8;
136 }
137 }
138 Ok(())
139 }
140}
141
142impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8>
143 for Uart<'d, T, NoDma, RxDma>
144{
145 type Error = Error;
146 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
147 unsafe {
148 let r = self.inner.regs();
149 for &b in buffer {
150 while !r.isr().read().txe() {}
151 r.tdr().write_value(regs::Dr(b as u32))
152 }
153 }
154 Ok(())
155 }
156 fn bflush(&mut self) -> Result<(), Self::Error> {
157 unsafe {
158 let r = self.inner.regs();
159 while !r.isr().read().tc() {}
160 }
161 Ok(())
162 }
163}
164
165// rustfmt::skip because intellij removes the 'where' claus on the associated type.
166impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma>
167where
168 TxDma: crate::usart::TxDma<T>,
169{
170 // rustfmt::skip because rustfmt removes the 'where' claus on the associated type.
171 #[rustfmt::skip]
172 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> +'a;
173
174 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
175 self.write_dma(buf)
176 .map_err(|_| embassy_traits::uart::Error::Other)
177 }
178}
179
180impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Read for Uart<'d, T, TxDma, RxDma>
181where
182 RxDma: crate::usart::RxDma<T>,
183{
184 // rustfmt::skip because rustfmt removes the 'where' claus on the associated type.
185 #[rustfmt::skip]
186 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a;
187
188 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
189 self.read_dma(buf)
190 .map_err(|_| embassy_traits::uart::Error::Other)
191 }
192}
193
194pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>);
195impl<'d, T: Instance> State<'d, T> {
196 pub fn new() -> Self {
197 Self(StateStorage::new())
198 }
199}
200
201pub struct StateInner<'d, T: Instance> {
202 uart: Uart<'d, T, NoDma, NoDma>,
203 phantom: PhantomData<&'d mut T>,
204
205 rx_waker: WakerRegistration,
206 rx: RingBuffer<'d>,
207
208 tx_waker: WakerRegistration,
209 tx: RingBuffer<'d>,
210}
211
212unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {}
213unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {}
214
215pub struct BufferedUart<'d, T: Instance> {
216 inner: PeripheralMutex<'d, StateInner<'d, T>>,
217}
218
219impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
220
221impl<'d, T: Instance> BufferedUart<'d, T> {
222 pub unsafe fn new(
223 state: &'d mut State<'d, T>,
224 uart: Uart<'d, T, NoDma, NoDma>,
225 irq: impl Unborrow<Target = T::Interrupt> + 'd,
226 tx_buffer: &'d mut [u8],
227 rx_buffer: &'d mut [u8],
228 ) -> BufferedUart<'d, T> {
229 unborrow!(irq);
230
231 let r = uart.inner.regs();
232 r.cr1().modify(|w| {
233 w.set_rxneie(true);
234 w.set_idleie(true);
235 });
236
237 Self {
238 inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
239 uart,
240 phantom: PhantomData,
241 tx: RingBuffer::new(tx_buffer),
242 tx_waker: WakerRegistration::new(),
243
244 rx: RingBuffer::new(rx_buffer),
245 rx_waker: WakerRegistration::new(),
246 }),
247 }
248 }
249}
250
251impl<'d, T: Instance> StateInner<'d, T>
252where
253 Self: 'd,
254{
255 fn on_rx(&mut self) {
256 let r = self.uart.inner.regs();
257 unsafe {
258 let sr = r.isr().read();
259 if sr.pe() {
260 r.icr().write(|w| {
261 w.set_pe(true);
262 });
263 trace!("Parity error");
264 } else if sr.fe() {
265 r.icr().write(|w| {
266 w.set_fe(true);
267 });
268 trace!("Framing error");
269 } else if sr.nf() {
270 r.icr().write(|w| {
271 w.set_nf(true);
272 });
273 trace!("Noise error");
274 } else if sr.ore() {
275 r.icr().write(|w| {
276 w.set_ore(true);
277 });
278 trace!("Overrun error");
279 } else if sr.rxne() {
280 let buf = self.rx.push_buf();
281 if buf.is_empty() {
282 self.rx_waker.wake();
283 } else {
284 buf[0] = r.rdr().read().0 as u8;
285 self.rx.push(1);
286 }
287 } else if sr.idle() {
288 r.icr().write(|w| {
289 w.set_idle(true);
290 });
291 self.rx_waker.wake();
292 };
293 }
294 }
295
296 fn on_tx(&mut self) {
297 let r = self.uart.inner.regs();
298 unsafe {
299 if r.isr().read().txe() {
300 let buf = self.tx.pop_buf();
301 if !buf.is_empty() {
302 r.cr1().modify(|w| {
303 w.set_txeie(true);
304 });
305 r.tdr().write_value(regs::Dr(buf[0].into()));
306 self.tx.pop(1);
307 self.tx_waker.wake();
308 } else {
309 // Disable interrupt until we have something to transmit again
310 r.cr1().modify(|w| {
311 w.set_txeie(false);
312 });
313 }
314 }
315 }
316 }
317}
318
319impl<'d, T: Instance> PeripheralState for StateInner<'d, T>
320where
321 Self: 'd,
322{
323 type Interrupt = T::Interrupt;
324 fn on_interrupt(&mut self) {
325 self.on_rx();
326 self.on_tx();
327 }
328}
329
330impl<'d, T: Instance> embassy::io::AsyncBufRead for BufferedUart<'d, T> {
331 fn poll_fill_buf(
332 mut self: Pin<&mut Self>,
333 cx: &mut Context<'_>,
334 ) -> Poll<Result<&[u8], embassy::io::Error>> {
335 self.inner.with(|state| {
336 compiler_fence(Ordering::SeqCst);
337
338 // We have data ready in buffer? Return it.
339 let buf = state.rx.pop_buf();
340 if !buf.is_empty() {
341 let buf: &[u8] = buf;
342 // Safety: buffer lives as long as uart
343 let buf: &[u8] = unsafe { core::mem::transmute(buf) };
344 return Poll::Ready(Ok(buf));
345 }
346
347 state.rx_waker.register(cx.waker());
348 Poll::<Result<&[u8], embassy::io::Error>>::Pending
349 })
350 }
351 fn consume(mut self: Pin<&mut Self>, amt: usize) {
352 let signal = self.inner.with(|state| {
353 let full = state.rx.is_full();
354 state.rx.pop(amt);
355 full
356 });
357 if signal {
358 self.inner.pend();
359 }
360 }
361}
362
363impl<'d, T: Instance> embassy::io::AsyncWrite for BufferedUart<'d, T> {
364 fn poll_write(
365 mut self: Pin<&mut Self>,
366 cx: &mut Context<'_>,
367 buf: &[u8],
368 ) -> Poll<Result<usize, embassy::io::Error>> {
369 let (poll, empty) = self.inner.with(|state| {
370 let empty = state.tx.is_empty();
371 let tx_buf = state.tx.push_buf();
372 if tx_buf.is_empty() {
373 state.tx_waker.register(cx.waker());
374 return (Poll::Pending, empty);
375 }
376
377 let n = core::cmp::min(tx_buf.len(), buf.len());
378 tx_buf[..n].copy_from_slice(&buf[..n]);
379 state.tx.push(n);
380
381 (Poll::Ready(Ok(n)), empty)
382 });
383 if empty {
384 self.inner.pend();
385 }
386 poll
387 }
388}
diff --git a/stm32-data b/stm32-data
Subproject 3e883bdff7fbb1f96be353d2c062be57ec8921a Subproject 5506d27471c7e3297450127c3279f3dab96c94f