aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-15 10:08:01 +0000
committerGitHub <[email protected]>2022-03-15 10:08:01 +0000
commitda9c0efaad594b48cfcdf641d353133d14cf98fe (patch)
tree9cda4709ae2a498b6429f0a98b31d329b2d93e9f
parentcb1be3983a47029e0e6a1c07082dd6ed18eda2a7 (diff)
parente09bde93457737a043497dab41cd18a937790618 (diff)
Merge #661
661: Add support for splitting stm32 usart into TX and RX r=lulf a=lulf * Keeps existing API for usart, but wraps it in Tx and Rx sub-types * Adds split() method similar to nRF for getting indepdendent TX and RX parts * Implements e-h traits for TX and RX types Co-authored-by: Ulf Lilleengen <[email protected]>
-rw-r--r--embassy-stm32/src/usart/mod.rs257
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs67
2 files changed, 250 insertions, 74 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index a62c49c7b..80d928786 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -72,57 +72,26 @@ pub enum Error {
72} 72}
73 73
74pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { 74pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
75 inner: T,
76 phantom: PhantomData<&'d mut T>, 75 phantom: PhantomData<&'d mut T>,
77 tx_dma: TxDma, 76 tx: UartTx<'d, T, TxDma>,
78 rx_dma: RxDma, 77 rx: UartRx<'d, T, RxDma>,
79} 78}
80 79
81impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 80pub struct UartTx<'d, T: Instance, TxDma = NoDma> {
82 pub fn new( 81 phantom: PhantomData<&'d mut T>,
83 inner: impl Unborrow<Target = T> + 'd, 82 tx_dma: TxDma,
84 rx: impl Unborrow<Target = impl RxPin<T>> + 'd, 83}
85 tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
86 tx_dma: impl Unborrow<Target = TxDma> + 'd,
87 rx_dma: impl Unborrow<Target = RxDma> + 'd,
88 config: Config,
89 ) -> Self {
90 unborrow!(inner, rx, tx, tx_dma, rx_dma);
91
92 T::enable();
93 let pclk_freq = T::frequency();
94
95 // TODO: better calculation, including error checking and OVER8 if possible.
96 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
97
98 let r = inner.regs();
99
100 unsafe {
101 rx.set_as_af(rx.af_num(), AFType::Input);
102 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
103 84
104 r.cr2().write(|_w| {}); 85pub struct UartRx<'d, T: Instance, RxDma = NoDma> {
105 r.cr3().write(|_w| {}); 86 phantom: PhantomData<&'d mut T>,
106 r.brr().write_value(regs::Brr(div)); 87 rx_dma: RxDma,
107 r.cr1().write(|w| { 88}
108 w.set_ue(true);
109 w.set_te(true);
110 w.set_re(true);
111 w.set_m0(vals::M0::BIT8);
112 w.set_pce(config.parity != Parity::ParityNone);
113 w.set_ps(match config.parity {
114 Parity::ParityOdd => vals::Ps::ODD,
115 Parity::ParityEven => vals::Ps::EVEN,
116 _ => vals::Ps::EVEN,
117 });
118 });
119 }
120 89
90impl<'d, T: Instance, TxDma> UartTx<'d, T, TxDma> {
91 fn new(tx_dma: TxDma) -> Self {
121 Self { 92 Self {
122 inner,
123 phantom: PhantomData,
124 tx_dma, 93 tx_dma,
125 rx_dma, 94 phantom: PhantomData,
126 } 95 }
127 } 96 }
128 97
@@ -133,16 +102,43 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
133 let ch = &mut self.tx_dma; 102 let ch = &mut self.tx_dma;
134 let request = ch.request(); 103 let request = ch.request();
135 unsafe { 104 unsafe {
136 self.inner.regs().cr3().modify(|reg| { 105 T::regs().cr3().modify(|reg| {
137 reg.set_dmat(true); 106 reg.set_dmat(true);
138 }); 107 });
139 } 108 }
140 let r = self.inner.regs(); 109 let dst = tdr(T::regs());
141 let dst = tdr(r);
142 crate::dma::write(ch, request, buffer, dst).await; 110 crate::dma::write(ch, request, buffer, dst).await;
143 Ok(()) 111 Ok(())
144 } 112 }
145 113
114 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
115 unsafe {
116 let r = T::regs();
117 for &b in buffer {
118 while !sr(r).read().txe() {}
119 tdr(r).write_volatile(b);
120 }
121 }
122 Ok(())
123 }
124
125 pub fn blocking_flush(&mut self) -> Result<(), Error> {
126 unsafe {
127 let r = T::regs();
128 while !sr(r).read().tc() {}
129 }
130 Ok(())
131 }
132}
133
134impl<'d, T: Instance, RxDma> UartRx<'d, T, RxDma> {
135 fn new(rx_dma: RxDma) -> Self {
136 Self {
137 rx_dma,
138 phantom: PhantomData,
139 }
140 }
141
146 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 142 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
147 where 143 where
148 RxDma: crate::usart::RxDma<T>, 144 RxDma: crate::usart::RxDma<T>,
@@ -150,11 +146,11 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
150 let ch = &mut self.rx_dma; 146 let ch = &mut self.rx_dma;
151 let request = ch.request(); 147 let request = ch.request();
152 unsafe { 148 unsafe {
153 self.inner.regs().cr3().modify(|reg| { 149 T::regs().cr3().modify(|reg| {
154 reg.set_dmar(true); 150 reg.set_dmar(true);
155 }); 151 });
156 } 152 }
157 let r = self.inner.regs(); 153 let r = T::regs();
158 let src = rdr(r); 154 let src = rdr(r);
159 crate::dma::read(ch, request, src, buffer).await; 155 crate::dma::read(ch, request, src, buffer).await;
160 Ok(()) 156 Ok(())
@@ -162,7 +158,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
162 158
163 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 159 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
164 unsafe { 160 unsafe {
165 let r = self.inner.regs(); 161 let r = T::regs();
166 for b in buffer { 162 for b in buffer {
167 loop { 163 loop {
168 let sr = sr(r).read(); 164 let sr = sr(r).read();
@@ -187,36 +183,96 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
187 } 183 }
188 Ok(()) 184 Ok(())
189 } 185 }
186}
187
188impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
189 pub fn new(
190 _inner: impl Unborrow<Target = T> + 'd,
191 rx: impl Unborrow<Target = impl RxPin<T>> + 'd,
192 tx: impl Unborrow<Target = impl TxPin<T>> + 'd,
193 tx_dma: impl Unborrow<Target = TxDma> + 'd,
194 rx_dma: impl Unborrow<Target = RxDma> + 'd,
195 config: Config,
196 ) -> Self {
197 unborrow!(_inner, rx, tx, tx_dma, rx_dma);
198
199 T::enable();
200 let pclk_freq = T::frequency();
201
202 // TODO: better calculation, including error checking and OVER8 if possible.
203 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
204
205 let r = T::regs();
190 206
191 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
192 unsafe { 207 unsafe {
193 let r = self.inner.regs(); 208 rx.set_as_af(rx.af_num(), AFType::Input);
194 for &b in buffer { 209 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
195 while !sr(r).read().txe() {} 210
196 tdr(r).write_volatile(b); 211 r.cr2().write(|_w| {});
197 } 212 r.cr3().write(|_w| {});
213 r.brr().write_value(regs::Brr(div));
214 r.cr1().write(|w| {
215 w.set_ue(true);
216 w.set_te(true);
217 w.set_re(true);
218 w.set_m0(vals::M0::BIT8);
219 w.set_pce(config.parity != Parity::ParityNone);
220 w.set_ps(match config.parity {
221 Parity::ParityOdd => vals::Ps::ODD,
222 Parity::ParityEven => vals::Ps::EVEN,
223 _ => vals::Ps::EVEN,
224 });
225 });
198 } 226 }
199 Ok(()) 227
228 Self {
229 phantom: PhantomData,
230 tx: UartTx::new(tx_dma),
231 rx: UartRx::new(rx_dma),
232 }
233 }
234
235 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
236 where
237 TxDma: crate::usart::TxDma<T>,
238 {
239 self.tx.write(buffer).await
240 }
241
242 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
243 self.tx.blocking_write(buffer)
200 } 244 }
201 245
202 pub fn blocking_flush(&mut self) -> Result<(), Error> { 246 pub fn blocking_flush(&mut self) -> Result<(), Error> {
203 unsafe { 247 self.tx.blocking_flush()
204 let r = self.inner.regs(); 248 }
205 while !sr(r).read().tc() {} 249
206 } 250 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
207 Ok(()) 251 where
252 RxDma: crate::usart::RxDma<T>,
253 {
254 self.rx.read(buffer).await
255 }
256
257 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
258 self.rx.blocking_read(buffer)
259 }
260
261 /// Split the Uart into a transmitter and receiver, which is
262 /// particuarly useful when having two tasks correlating to
263 /// transmitting and receiving.
264 pub fn split(self) -> (UartTx<'d, T, TxDma>, UartRx<'d, T, RxDma>) {
265 (self.tx, self.rx)
208 } 266 }
209} 267}
210 268
211mod eh02 { 269mod eh02 {
212 use super::*; 270 use super::*;
213 271
214 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> 272 impl<'d, T: Instance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> {
215 for Uart<'d, T, TxDma, RxDma>
216 {
217 type Error = Error; 273 type Error = Error;
218 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 274 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
219 let r = self.inner.regs(); 275 let r = T::regs();
220 unsafe { 276 unsafe {
221 let sr = sr(r).read(); 277 let sr = sr(r).read();
222 if sr.pe() { 278 if sr.pe() {
@@ -240,6 +296,25 @@ mod eh02 {
240 } 296 }
241 } 297 }
242 298
299 impl<'d, T: Instance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> {
300 type Error = Error;
301 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
302 self.blocking_write(buffer)
303 }
304 fn bflush(&mut self) -> Result<(), Self::Error> {
305 self.blocking_flush()
306 }
307 }
308
309 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::serial::Read<u8>
310 for Uart<'d, T, TxDma, RxDma>
311 {
312 type Error = Error;
313 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
314 embedded_hal_02::serial::Read::read(&mut self.rx)
315 }
316 }
317
243 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8> 318 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8>
244 for Uart<'d, T, TxDma, RxDma> 319 for Uart<'d, T, TxDma, RxDma>
245 { 320 {
@@ -273,12 +348,48 @@ mod eh1 {
273 { 348 {
274 type Error = Error; 349 type Error = Error;
275 } 350 }
351
352 impl<'d, T: Instance, TxDma> embedded_hal_1::serial::ErrorType for UartTx<'d, T, TxDma> {
353 type Error = Error;
354 }
355
356 impl<'d, T: Instance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> {
357 type Error = Error;
358 }
276} 359}
277 360
278cfg_if::cfg_if! { 361cfg_if::cfg_if! {
279 if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { 362 if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
280 use core::future::Future; 363 use core::future::Future;
281 364
365 impl<'d, T: Instance, TxDma> embedded_hal_async::serial::Write for UartTx<'d, T, TxDma>
366 where
367 TxDma: crate::usart::TxDma<T>,
368 {
369 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
370
371 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
372 self.write(buf)
373 }
374
375 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
376
377 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
378 async move { Ok(()) }
379 }
380 }
381
382 impl<'d, T: Instance, RxDma> embedded_hal_async::serial::Read for UartRx<'d, T, RxDma>
383 where
384 RxDma: crate::usart::RxDma<T>,
385 {
386 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
387
388 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
389 self.read(buf)
390 }
391 }
392
282 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma> 393 impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma>
283 where 394 where
284 TxDma: crate::usart::TxDma<T>, 395 TxDma: crate::usart::TxDma<T>,
@@ -329,7 +440,6 @@ mod buffered {
329 } 440 }
330 441
331 struct StateInner<'d, T: Instance> { 442 struct StateInner<'d, T: Instance> {
332 uart: Uart<'d, T, NoDma, NoDma>,
333 phantom: PhantomData<&'d mut T>, 443 phantom: PhantomData<&'d mut T>,
334 444
335 rx_waker: WakerRegistration, 445 rx_waker: WakerRegistration,
@@ -351,14 +461,14 @@ mod buffered {
351 impl<'d, T: Instance> BufferedUart<'d, T> { 461 impl<'d, T: Instance> BufferedUart<'d, T> {
352 pub unsafe fn new( 462 pub unsafe fn new(
353 state: &'d mut State<'d, T>, 463 state: &'d mut State<'d, T>,
354 uart: Uart<'d, T, NoDma, NoDma>, 464 _uart: Uart<'d, T, NoDma, NoDma>,
355 irq: impl Unborrow<Target = T::Interrupt> + 'd, 465 irq: impl Unborrow<Target = T::Interrupt> + 'd,
356 tx_buffer: &'d mut [u8], 466 tx_buffer: &'d mut [u8],
357 rx_buffer: &'d mut [u8], 467 rx_buffer: &'d mut [u8],
358 ) -> BufferedUart<'d, T> { 468 ) -> BufferedUart<'d, T> {
359 unborrow!(irq); 469 unborrow!(irq);
360 470
361 let r = uart.inner.regs(); 471 let r = T::regs();
362 r.cr1().modify(|w| { 472 r.cr1().modify(|w| {
363 w.set_rxneie(true); 473 w.set_rxneie(true);
364 w.set_idleie(true); 474 w.set_idleie(true);
@@ -366,7 +476,6 @@ mod buffered {
366 476
367 Self { 477 Self {
368 inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { 478 inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
369 uart,
370 phantom: PhantomData, 479 phantom: PhantomData,
371 tx: RingBuffer::new(tx_buffer), 480 tx: RingBuffer::new(tx_buffer),
372 tx_waker: WakerRegistration::new(), 481 tx_waker: WakerRegistration::new(),
@@ -383,7 +492,7 @@ mod buffered {
383 Self: 'd, 492 Self: 'd,
384 { 493 {
385 fn on_rx(&mut self) { 494 fn on_rx(&mut self) {
386 let r = self.uart.inner.regs(); 495 let r = T::regs();
387 unsafe { 496 unsafe {
388 let sr = sr(r).read(); 497 let sr = sr(r).read();
389 clear_interrupt_flags(r, sr); 498 clear_interrupt_flags(r, sr);
@@ -425,7 +534,7 @@ mod buffered {
425 } 534 }
426 535
427 fn on_tx(&mut self) { 536 fn on_tx(&mut self) {
428 let r = self.uart.inner.regs(); 537 let r = T::regs();
429 unsafe { 538 unsafe {
430 if sr(r).read().txe() { 539 if sr(r).read().txe() {
431 let buf = self.tx.pop_buf(); 540 let buf = self.tx.pop_buf();
@@ -575,7 +684,7 @@ unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) {
575 684
576pub(crate) mod sealed { 685pub(crate) mod sealed {
577 pub trait Instance { 686 pub trait Instance {
578 fn regs(&self) -> crate::pac::usart::Usart; 687 fn regs() -> crate::pac::usart::Usart;
579 } 688 }
580} 689}
581 690
@@ -595,7 +704,7 @@ dma_trait!(RxDma, Instance);
595foreach_interrupt!( 704foreach_interrupt!(
596 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { 705 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
597 impl sealed::Instance for peripherals::$inst { 706 impl sealed::Instance for peripherals::$inst {
598 fn regs(&self) -> crate::pac::usart::Usart { 707 fn regs() -> crate::pac::usart::Usart {
599 crate::pac::$inst 708 crate::pac::$inst
600 } 709 }
601 } 710 }
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
new file mode 100644
index 000000000..b112290f9
--- /dev/null
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -0,0 +1,67 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use embassy::blocking_mutex::raw::NoopRawMutex;
8use embassy::channel::mpsc::{self, Channel, Sender};
9use embassy::executor::Spawner;
10use embassy::util::Forever;
11use embassy_stm32::dma::NoDma;
12use embassy_stm32::{
13 peripherals::{DMA1_CH1, UART7},
14 usart::{Config, Uart, UartRx},
15 Peripherals,
16};
17use example_common::*;
18
19#[embassy::task]
20async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
22 info!("wrote Hello, starting echo");
23
24 let mut buf = [0u8; 1];
25 loop {
26 unwrap!(usart.blocking_read(&mut buf));
27 unwrap!(usart.blocking_write(&buf));
28 }
29}
30
31static CHANNEL: Forever<Channel<NoopRawMutex, [u8; 8], 1>> = Forever::new();
32
33#[embassy::main]
34async fn main(spawner: Spawner, p: Peripherals) -> ! {
35 info!("Hello World!");
36
37 let config = Config::default();
38 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, p.DMA1_CH1, config);
39 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
40
41 let (mut tx, rx) = usart.split();
42
43 let c = CHANNEL.put(Channel::new());
44 let (s, mut r) = mpsc::split(c);
45
46 unwrap!(spawner.spawn(reader(rx, s)));
47
48 loop {
49 if let Some(buf) = r.recv().await {
50 info!("writing...");
51 unwrap!(tx.write(&buf).await);
52 }
53 }
54}
55
56#[embassy::task]
57async fn reader(
58 mut rx: UartRx<'static, UART7, DMA1_CH1>,
59 s: Sender<'static, NoopRawMutex, [u8; 8], 1>,
60) {
61 let mut buf = [0; 8];
62 loop {
63 info!("reading...");
64 unwrap!(rx.read(&mut buf).await);
65 unwrap!(s.send(buf).await);
66 }
67}