diff options
| author | Jan Špaček <[email protected]> | 2024-04-18 18:50:30 +0200 |
|---|---|---|
| committer | Jan Špaček <[email protected]> | 2024-05-23 16:32:15 +0200 |
| commit | 183f2f6913032600d74ea058b50a1fcedbebe719 (patch) | |
| tree | d9673481a086e7efde8dd165b277d367163423fc | |
| parent | ded1f9d33520fc847dce8fe72f2fb80f6fa86350 (diff) | |
stm32/usart: remove instance generic params
| -rw-r--r-- | embassy-stm32/build.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/buffered.rs | 372 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 450 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 57 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/usart_split.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/usart_split.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7rs/src/bin/usart_split.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/usart_rx_ringbuffered.rs | 4 |
8 files changed, 467 insertions, 431 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 4eed6fe7d..7bf6ffba2 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -387,7 +387,6 @@ fn main() { | |||
| 387 | struct ClockGen<'a> { | 387 | struct ClockGen<'a> { |
| 388 | rcc_registers: &'a PeripheralRegisters, | 388 | rcc_registers: &'a PeripheralRegisters, |
| 389 | chained_muxes: HashMap<&'a str, &'a PeripheralRccRegister>, | 389 | chained_muxes: HashMap<&'a str, &'a PeripheralRccRegister>, |
| 390 | force_refcount: HashSet<&'a str>, | ||
| 391 | 390 | ||
| 392 | refcount_statics: BTreeSet<Ident>, | 391 | refcount_statics: BTreeSet<Ident>, |
| 393 | clock_names: BTreeSet<String>, | 392 | clock_names: BTreeSet<String>, |
| @@ -397,7 +396,6 @@ fn main() { | |||
| 397 | let mut clock_gen = ClockGen { | 396 | let mut clock_gen = ClockGen { |
| 398 | rcc_registers, | 397 | rcc_registers, |
| 399 | chained_muxes: HashMap::new(), | 398 | chained_muxes: HashMap::new(), |
| 400 | force_refcount: HashSet::from(["usart"]), | ||
| 401 | 399 | ||
| 402 | refcount_statics: BTreeSet::new(), | 400 | refcount_statics: BTreeSet::new(), |
| 403 | clock_names: BTreeSet::new(), | 401 | clock_names: BTreeSet::new(), |
| @@ -542,7 +540,6 @@ fn main() { | |||
| 542 | None => (TokenStream::new(), TokenStream::new()), | 540 | None => (TokenStream::new(), TokenStream::new()), |
| 543 | }; | 541 | }; |
| 544 | 542 | ||
| 545 | let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" }; | ||
| 546 | let pname = format_ident!("{}", p.name); | 543 | let pname = format_ident!("{}", p.name); |
| 547 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); | 544 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); |
| 548 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); | 545 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); |
| @@ -570,8 +567,7 @@ fn main() { | |||
| 570 | }; | 567 | }; |
| 571 | let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap(); | 568 | let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap(); |
| 572 | 569 | ||
| 573 | let refcount = | 570 | let refcount = *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1; |
| 574 | clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1; | ||
| 575 | let (before_enable, before_disable) = if refcount { | 571 | let (before_enable, before_disable) = if refcount { |
| 576 | let refcount_static = | 572 | let refcount_static = |
| 577 | format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); | 573 | format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); |
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 52011cd1f..492ad334b 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | use core::slice; | 3 | use core::slice; |
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | 4 | use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; |
| 5 | use core::task::Poll; | 5 | use core::task::Poll; |
| 6 | 6 | ||
| 7 | use embassy_embedded_hal::SetConfig; | 7 | use embassy_embedded_hal::SetConfig; |
| @@ -12,154 +12,163 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 12 | #[cfg(not(any(usart_v1, usart_v2)))] | 12 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 13 | use super::DePin; | 13 | use super::DePin; |
| 14 | use super::{ | 14 | use super::{ |
| 15 | clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, BasicInstance, Config, ConfigError, CtsPin, Error, | 15 | clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance, |
| 16 | RtsPin, RxPin, TxPin, | 16 | Regs, RtsPin, RxPin, TxPin, |
| 17 | }; | 17 | }; |
| 18 | use crate::gpio::AFType; | 18 | use crate::gpio::AFType; |
| 19 | use crate::interrupt; | 19 | use crate::interrupt::typelevel::Interrupt as _; |
| 20 | use crate::interrupt::typelevel::Interrupt; | 20 | use crate::interrupt::{self, InterruptExt}; |
| 21 | use crate::time::Hertz; | ||
| 21 | 22 | ||
| 22 | /// Interrupt handler. | 23 | /// Interrupt handler. |
| 23 | pub struct InterruptHandler<T: BasicInstance> { | 24 | pub struct InterruptHandler<T: Instance> { |
| 24 | _phantom: PhantomData<T>, | 25 | _phantom: PhantomData<T>, |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 28 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 28 | unsafe fn on_interrupt() { | 29 | unsafe fn on_interrupt() { |
| 29 | let r = T::regs(); | 30 | on_interrupt(T::info().regs, T::buffered_state()) |
| 30 | let state = T::buffered_state(); | 31 | } |
| 31 | 32 | } | |
| 32 | // RX | 33 | |
| 33 | let sr_val = sr(r).read(); | 34 | unsafe fn on_interrupt(r: Regs, state: &'static State) { |
| 34 | // On v1 & v2, reading DR clears the rxne, error and idle interrupt | 35 | // RX |
| 35 | // flags. Keep this close to the SR read to reduce the chance of a | 36 | let sr_val = sr(r).read(); |
| 36 | // flag being set in-between. | 37 | // On v1 & v2, reading DR clears the rxne, error and idle interrupt |
| 37 | let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { | 38 | // flags. Keep this close to the SR read to reduce the chance of a |
| 38 | Some(rdr(r).read_volatile()) | 39 | // flag being set in-between. |
| 39 | } else { | 40 | let dr = if sr_val.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr_val.ore() || sr_val.idle()) { |
| 40 | None | 41 | Some(rdr(r).read_volatile()) |
| 41 | }; | 42 | } else { |
| 42 | clear_interrupt_flags(r, sr_val); | 43 | None |
| 43 | 44 | }; | |
| 44 | if sr_val.pe() { | 45 | clear_interrupt_flags(r, sr_val); |
| 45 | warn!("Parity error"); | 46 | |
| 46 | } | 47 | if sr_val.pe() { |
| 47 | if sr_val.fe() { | 48 | warn!("Parity error"); |
| 48 | warn!("Framing error"); | 49 | } |
| 49 | } | 50 | if sr_val.fe() { |
| 50 | if sr_val.ne() { | 51 | warn!("Framing error"); |
| 51 | warn!("Noise error"); | 52 | } |
| 52 | } | 53 | if sr_val.ne() { |
| 53 | if sr_val.ore() { | 54 | warn!("Noise error"); |
| 54 | warn!("Overrun error"); | 55 | } |
| 55 | } | 56 | if sr_val.ore() { |
| 56 | if sr_val.rxne() { | 57 | warn!("Overrun error"); |
| 57 | let mut rx_writer = state.rx_buf.writer(); | 58 | } |
| 58 | let buf = rx_writer.push_slice(); | 59 | if sr_val.rxne() { |
| 59 | if !buf.is_empty() { | 60 | let mut rx_writer = state.rx_buf.writer(); |
| 60 | if let Some(byte) = dr { | 61 | let buf = rx_writer.push_slice(); |
| 61 | buf[0] = byte; | 62 | if !buf.is_empty() { |
| 62 | rx_writer.push_done(1); | 63 | if let Some(byte) = dr { |
| 63 | } | 64 | buf[0] = byte; |
| 64 | } else { | 65 | rx_writer.push_done(1); |
| 65 | // FIXME: Should we disable any further RX interrupts when the buffer becomes full. | ||
| 66 | } | ||
| 67 | |||
| 68 | if !state.rx_buf.is_empty() { | ||
| 69 | state.rx_waker.wake(); | ||
| 70 | } | 66 | } |
| 67 | } else { | ||
| 68 | // FIXME: Should we disable any further RX interrupts when the buffer becomes full. | ||
| 71 | } | 69 | } |
| 72 | 70 | ||
| 73 | if sr_val.idle() { | 71 | if !state.rx_buf.is_empty() { |
| 74 | state.rx_waker.wake(); | 72 | state.rx_waker.wake(); |
| 75 | } | 73 | } |
| 74 | } | ||
| 76 | 75 | ||
| 77 | // With `usart_v4` hardware FIFO is enabled and Transmission complete (TC) | 76 | if sr_val.idle() { |
| 78 | // indicates that all bytes are pushed out from the FIFO. | 77 | state.rx_waker.wake(); |
| 79 | // For other usart variants it shows that last byte from the buffer was just sent. | 78 | } |
| 80 | if sr_val.tc() { | ||
| 81 | // For others it is cleared above with `clear_interrupt_flags`. | ||
| 82 | #[cfg(any(usart_v1, usart_v2))] | ||
| 83 | sr(r).modify(|w| w.set_tc(false)); | ||
| 84 | 79 | ||
| 85 | r.cr1().modify(|w| { | 80 | // With `usart_v4` hardware FIFO is enabled and Transmission complete (TC) |
| 86 | w.set_tcie(false); | 81 | // indicates that all bytes are pushed out from the FIFO. |
| 87 | }); | 82 | // For other usart variants it shows that last byte from the buffer was just sent. |
| 83 | if sr_val.tc() { | ||
| 84 | // For others it is cleared above with `clear_interrupt_flags`. | ||
| 85 | #[cfg(any(usart_v1, usart_v2))] | ||
| 86 | sr(r).modify(|w| w.set_tc(false)); | ||
| 88 | 87 | ||
| 89 | state.tx_done.store(true, Ordering::Release); | 88 | r.cr1().modify(|w| { |
| 90 | state.tx_waker.wake(); | 89 | w.set_tcie(false); |
| 91 | } | 90 | }); |
| 92 | 91 | ||
| 93 | // TX | 92 | state.tx_done.store(true, Ordering::Release); |
| 94 | if sr(r).read().txe() { | 93 | state.tx_waker.wake(); |
| 95 | let mut tx_reader = state.tx_buf.reader(); | 94 | } |
| 96 | let buf = tx_reader.pop_slice(); | ||
| 97 | if !buf.is_empty() { | ||
| 98 | r.cr1().modify(|w| { | ||
| 99 | w.set_txeie(true); | ||
| 100 | }); | ||
| 101 | 95 | ||
| 102 | // Enable transmission complete interrupt when last byte is going to be sent out. | 96 | // TX |
| 103 | if buf.len() == 1 { | 97 | if sr(r).read().txe() { |
| 104 | r.cr1().modify(|w| { | 98 | let mut tx_reader = state.tx_buf.reader(); |
| 105 | w.set_tcie(true); | 99 | let buf = tx_reader.pop_slice(); |
| 106 | }); | 100 | if !buf.is_empty() { |
| 107 | } | 101 | r.cr1().modify(|w| { |
| 102 | w.set_txeie(true); | ||
| 103 | }); | ||
| 108 | 104 | ||
| 109 | tdr(r).write_volatile(buf[0].into()); | 105 | // Enable transmission complete interrupt when last byte is going to be sent out. |
| 110 | tx_reader.pop_done(1); | 106 | if buf.len() == 1 { |
| 111 | } else { | ||
| 112 | // Disable interrupt until we have something to transmit again. | ||
| 113 | r.cr1().modify(|w| { | 107 | r.cr1().modify(|w| { |
| 114 | w.set_txeie(false); | 108 | w.set_tcie(true); |
| 115 | }); | 109 | }); |
| 116 | } | 110 | } |
| 111 | |||
| 112 | tdr(r).write_volatile(buf[0].into()); | ||
| 113 | tx_reader.pop_done(1); | ||
| 114 | } else { | ||
| 115 | // Disable interrupt until we have something to transmit again. | ||
| 116 | r.cr1().modify(|w| { | ||
| 117 | w.set_txeie(false); | ||
| 118 | }); | ||
| 117 | } | 119 | } |
| 118 | } | 120 | } |
| 119 | } | 121 | } |
| 120 | 122 | ||
| 121 | pub(crate) struct State { | 123 | pub(super) struct State { |
| 122 | pub(crate) rx_waker: AtomicWaker, | 124 | rx_waker: AtomicWaker, |
| 123 | pub(crate) rx_buf: RingBuffer, | 125 | rx_buf: RingBuffer, |
| 124 | pub(crate) tx_waker: AtomicWaker, | 126 | tx_waker: AtomicWaker, |
| 125 | pub(crate) tx_buf: RingBuffer, | 127 | tx_buf: RingBuffer, |
| 126 | pub(crate) tx_done: AtomicBool, | 128 | tx_done: AtomicBool, |
| 129 | tx_rx_refcount: AtomicU8, | ||
| 127 | } | 130 | } |
| 128 | 131 | ||
| 129 | impl State { | 132 | impl State { |
| 130 | /// Create new state | 133 | pub(super) const fn new() -> Self { |
| 131 | pub(crate) const fn new() -> Self { | ||
| 132 | Self { | 134 | Self { |
| 133 | rx_buf: RingBuffer::new(), | 135 | rx_buf: RingBuffer::new(), |
| 134 | tx_buf: RingBuffer::new(), | 136 | tx_buf: RingBuffer::new(), |
| 135 | rx_waker: AtomicWaker::new(), | 137 | rx_waker: AtomicWaker::new(), |
| 136 | tx_waker: AtomicWaker::new(), | 138 | tx_waker: AtomicWaker::new(), |
| 137 | tx_done: AtomicBool::new(true), | 139 | tx_done: AtomicBool::new(true), |
| 140 | tx_rx_refcount: AtomicU8::new(0), | ||
| 138 | } | 141 | } |
| 139 | } | 142 | } |
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | /// Bidirectional buffered UART | 145 | /// Bidirectional buffered UART |
| 143 | pub struct BufferedUart<'d, T: BasicInstance> { | 146 | pub struct BufferedUart<'d> { |
| 144 | rx: BufferedUartRx<'d, T>, | 147 | rx: BufferedUartRx<'d>, |
| 145 | tx: BufferedUartTx<'d, T>, | 148 | tx: BufferedUartTx<'d>, |
| 146 | } | 149 | } |
| 147 | 150 | ||
| 148 | /// Tx-only buffered UART | 151 | /// Tx-only buffered UART |
| 149 | /// | 152 | /// |
| 150 | /// Created with [BufferedUart::split] | 153 | /// Created with [BufferedUart::split] |
| 151 | pub struct BufferedUartTx<'d, T: BasicInstance> { | 154 | pub struct BufferedUartTx<'d> { |
| 152 | phantom: PhantomData<&'d mut T>, | 155 | info: &'static Info, |
| 156 | state: &'static State, | ||
| 157 | kernel_clock: Hertz, | ||
| 158 | _phantom: PhantomData<&'d mut ()>, | ||
| 153 | } | 159 | } |
| 154 | 160 | ||
| 155 | /// Rx-only buffered UART | 161 | /// Rx-only buffered UART |
| 156 | /// | 162 | /// |
| 157 | /// Created with [BufferedUart::split] | 163 | /// Created with [BufferedUart::split] |
| 158 | pub struct BufferedUartRx<'d, T: BasicInstance> { | 164 | pub struct BufferedUartRx<'d> { |
| 159 | phantom: PhantomData<&'d mut T>, | 165 | info: &'static Info, |
| 166 | state: &'static State, | ||
| 167 | kernel_clock: Hertz, | ||
| 168 | _phantom: PhantomData<&'d mut ()>, | ||
| 160 | } | 169 | } |
| 161 | 170 | ||
| 162 | impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> { | 171 | impl<'d> SetConfig for BufferedUart<'d> { |
| 163 | type Config = Config; | 172 | type Config = Config; |
| 164 | type ConfigError = ConfigError; | 173 | type ConfigError = ConfigError; |
| 165 | 174 | ||
| @@ -168,7 +177,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> { | |||
| 168 | } | 177 | } |
| 169 | } | 178 | } |
| 170 | 179 | ||
| 171 | impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> { | 180 | impl<'d> SetConfig for BufferedUartRx<'d> { |
| 172 | type Config = Config; | 181 | type Config = Config; |
| 173 | type ConfigError = ConfigError; | 182 | type ConfigError = ConfigError; |
| 174 | 183 | ||
| @@ -177,7 +186,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> { | |||
| 177 | } | 186 | } |
| 178 | } | 187 | } |
| 179 | 188 | ||
| 180 | impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> { | 189 | impl<'d> SetConfig for BufferedUartTx<'d> { |
| 181 | type Config = Config; | 190 | type Config = Config; |
| 182 | type ConfigError = ConfigError; | 191 | type ConfigError = ConfigError; |
| 183 | 192 | ||
| @@ -186,9 +195,9 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> { | |||
| 186 | } | 195 | } |
| 187 | } | 196 | } |
| 188 | 197 | ||
| 189 | impl<'d, T: BasicInstance> BufferedUart<'d, T> { | 198 | impl<'d> BufferedUart<'d> { |
| 190 | /// Create a new bidirectional buffered UART driver | 199 | /// Create a new bidirectional buffered UART driver |
| 191 | pub fn new( | 200 | pub fn new<T: Instance>( |
| 192 | peri: impl Peripheral<P = T> + 'd, | 201 | peri: impl Peripheral<P = T> + 'd, |
| 193 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 202 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 194 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 203 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -197,15 +206,13 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 197 | rx_buffer: &'d mut [u8], | 206 | rx_buffer: &'d mut [u8], |
| 198 | config: Config, | 207 | config: Config, |
| 199 | ) -> Result<Self, ConfigError> { | 208 | ) -> Result<Self, ConfigError> { |
| 200 | // UartRx and UartTx have one refcount ea. | ||
| 201 | T::enable_and_reset(); | ||
| 202 | T::enable_and_reset(); | 209 | T::enable_and_reset(); |
| 203 | 210 | ||
| 204 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 211 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) |
| 205 | } | 212 | } |
| 206 | 213 | ||
| 207 | /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins | 214 | /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins |
| 208 | pub fn new_with_rtscts( | 215 | pub fn new_with_rtscts<T: Instance>( |
| 209 | peri: impl Peripheral<P = T> + 'd, | 216 | peri: impl Peripheral<P = T> + 'd, |
| 210 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 217 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 211 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 218 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -218,13 +225,11 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 218 | ) -> Result<Self, ConfigError> { | 225 | ) -> Result<Self, ConfigError> { |
| 219 | into_ref!(cts, rts); | 226 | into_ref!(cts, rts); |
| 220 | 227 | ||
| 221 | // UartRx and UartTx have one refcount ea. | ||
| 222 | T::enable_and_reset(); | ||
| 223 | T::enable_and_reset(); | 228 | T::enable_and_reset(); |
| 224 | 229 | ||
| 225 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 230 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); |
| 226 | cts.set_as_af(cts.af_num(), AFType::Input); | 231 | cts.set_as_af(cts.af_num(), AFType::Input); |
| 227 | T::regs().cr3().write(|w| { | 232 | T::info().regs.cr3().write(|w| { |
| 228 | w.set_rtse(true); | 233 | w.set_rtse(true); |
| 229 | w.set_ctse(true); | 234 | w.set_ctse(true); |
| 230 | }); | 235 | }); |
| @@ -234,7 +239,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 234 | 239 | ||
| 235 | /// Create a new bidirectional buffered UART driver with a driver-enable pin | 240 | /// Create a new bidirectional buffered UART driver with a driver-enable pin |
| 236 | #[cfg(not(any(usart_v1, usart_v2)))] | 241 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 237 | pub fn new_with_de( | 242 | pub fn new_with_de<T: Instance>( |
| 238 | peri: impl Peripheral<P = T> + 'd, | 243 | peri: impl Peripheral<P = T> + 'd, |
| 239 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 244 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 240 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 245 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -246,19 +251,17 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 246 | ) -> Result<Self, ConfigError> { | 251 | ) -> Result<Self, ConfigError> { |
| 247 | into_ref!(de); | 252 | into_ref!(de); |
| 248 | 253 | ||
| 249 | // UartRx and UartTx have one refcount ea. | ||
| 250 | T::enable_and_reset(); | ||
| 251 | T::enable_and_reset(); | 254 | T::enable_and_reset(); |
| 252 | 255 | ||
| 253 | de.set_as_af(de.af_num(), AFType::OutputPushPull); | 256 | de.set_as_af(de.af_num(), AFType::OutputPushPull); |
| 254 | T::regs().cr3().write(|w| { | 257 | T::info().regs.cr3().write(|w| { |
| 255 | w.set_dem(true); | 258 | w.set_dem(true); |
| 256 | }); | 259 | }); |
| 257 | 260 | ||
| 258 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 261 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) |
| 259 | } | 262 | } |
| 260 | 263 | ||
| 261 | fn new_inner( | 264 | fn new_inner<T: Instance>( |
| 262 | _peri: impl Peripheral<P = T> + 'd, | 265 | _peri: impl Peripheral<P = T> + 'd, |
| 263 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 266 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 264 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 267 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -268,17 +271,19 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 268 | ) -> Result<Self, ConfigError> { | 271 | ) -> Result<Self, ConfigError> { |
| 269 | into_ref!(_peri, rx, tx); | 272 | into_ref!(_peri, rx, tx); |
| 270 | 273 | ||
| 274 | let info = T::info(); | ||
| 271 | let state = T::buffered_state(); | 275 | let state = T::buffered_state(); |
| 276 | let kernel_clock = T::frequency(); | ||
| 272 | let len = tx_buffer.len(); | 277 | let len = tx_buffer.len(); |
| 273 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | 278 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; |
| 274 | let len = rx_buffer.len(); | 279 | let len = rx_buffer.len(); |
| 275 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; | 280 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; |
| 276 | 281 | ||
| 277 | let r = T::regs(); | 282 | let r = info.regs; |
| 278 | rx.set_as_af(rx.af_num(), AFType::Input); | 283 | rx.set_as_af(rx.af_num(), AFType::Input); |
| 279 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 284 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 280 | 285 | ||
| 281 | configure(r, &config, T::frequency(), T::KIND, true, true)?; | 286 | configure(info, kernel_clock, &config, true, true)?; |
| 282 | 287 | ||
| 283 | r.cr1().modify(|w| { | 288 | r.cr1().modify(|w| { |
| 284 | w.set_rxneie(true); | 289 | w.set_rxneie(true); |
| @@ -288,22 +293,34 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 288 | T::Interrupt::unpend(); | 293 | T::Interrupt::unpend(); |
| 289 | unsafe { T::Interrupt::enable() }; | 294 | unsafe { T::Interrupt::enable() }; |
| 290 | 295 | ||
| 296 | state.tx_rx_refcount.store(2, Ordering::Relaxed); | ||
| 297 | |||
| 291 | Ok(Self { | 298 | Ok(Self { |
| 292 | rx: BufferedUartRx { phantom: PhantomData }, | 299 | rx: BufferedUartRx { |
| 293 | tx: BufferedUartTx { phantom: PhantomData }, | 300 | info, |
| 301 | state, | ||
| 302 | kernel_clock, | ||
| 303 | _phantom: PhantomData, | ||
| 304 | }, | ||
| 305 | tx: BufferedUartTx { | ||
| 306 | info, | ||
| 307 | state, | ||
| 308 | kernel_clock, | ||
| 309 | _phantom: PhantomData, | ||
| 310 | }, | ||
| 294 | }) | 311 | }) |
| 295 | } | 312 | } |
| 296 | 313 | ||
| 297 | /// Split the driver into a Tx and Rx part (useful for sending to separate tasks) | 314 | /// Split the driver into a Tx and Rx part (useful for sending to separate tasks) |
| 298 | pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { | 315 | pub fn split(self) -> (BufferedUartTx<'d>, BufferedUartRx<'d>) { |
| 299 | (self.tx, self.rx) | 316 | (self.tx, self.rx) |
| 300 | } | 317 | } |
| 301 | 318 | ||
| 302 | /// Reconfigure the driver | 319 | /// Reconfigure the driver |
| 303 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 320 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 304 | reconfigure::<T>(config)?; | 321 | reconfigure(self.rx.info, self.rx.kernel_clock, config)?; |
| 305 | 322 | ||
| 306 | T::regs().cr1().modify(|w| { | 323 | self.rx.info.regs.cr1().modify(|w| { |
| 307 | w.set_rxneie(true); | 324 | w.set_rxneie(true); |
| 308 | w.set_idleie(true); | 325 | w.set_idleie(true); |
| 309 | }); | 326 | }); |
| @@ -312,10 +329,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 312 | } | 329 | } |
| 313 | } | 330 | } |
| 314 | 331 | ||
| 315 | impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | 332 | impl<'d> BufferedUartRx<'d> { |
| 316 | async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { | 333 | async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { |
| 317 | poll_fn(move |cx| { | 334 | poll_fn(move |cx| { |
| 318 | let state = T::buffered_state(); | 335 | let state = self.state; |
| 319 | let mut rx_reader = unsafe { state.rx_buf.reader() }; | 336 | let mut rx_reader = unsafe { state.rx_buf.reader() }; |
| 320 | let data = rx_reader.pop_slice(); | 337 | let data = rx_reader.pop_slice(); |
| 321 | 338 | ||
| @@ -327,7 +344,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 327 | rx_reader.pop_done(len); | 344 | rx_reader.pop_done(len); |
| 328 | 345 | ||
| 329 | if do_pend { | 346 | if do_pend { |
| 330 | T::Interrupt::pend(); | 347 | self.info.interrupt.pend(); |
| 331 | } | 348 | } |
| 332 | 349 | ||
| 333 | return Poll::Ready(Ok(len)); | 350 | return Poll::Ready(Ok(len)); |
| @@ -341,7 +358,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 341 | 358 | ||
| 342 | fn blocking_read(&self, buf: &mut [u8]) -> Result<usize, Error> { | 359 | fn blocking_read(&self, buf: &mut [u8]) -> Result<usize, Error> { |
| 343 | loop { | 360 | loop { |
| 344 | let state = T::buffered_state(); | 361 | let state = self.state; |
| 345 | let mut rx_reader = unsafe { state.rx_buf.reader() }; | 362 | let mut rx_reader = unsafe { state.rx_buf.reader() }; |
| 346 | let data = rx_reader.pop_slice(); | 363 | let data = rx_reader.pop_slice(); |
| 347 | 364 | ||
| @@ -353,7 +370,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 353 | rx_reader.pop_done(len); | 370 | rx_reader.pop_done(len); |
| 354 | 371 | ||
| 355 | if do_pend { | 372 | if do_pend { |
| 356 | T::Interrupt::pend(); | 373 | self.info.interrupt.pend(); |
| 357 | } | 374 | } |
| 358 | 375 | ||
| 359 | return Ok(len); | 376 | return Ok(len); |
| @@ -363,7 +380,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 363 | 380 | ||
| 364 | async fn fill_buf(&self) -> Result<&[u8], Error> { | 381 | async fn fill_buf(&self) -> Result<&[u8], Error> { |
| 365 | poll_fn(move |cx| { | 382 | poll_fn(move |cx| { |
| 366 | let state = T::buffered_state(); | 383 | let state = self.state; |
| 367 | let mut rx_reader = unsafe { state.rx_buf.reader() }; | 384 | let mut rx_reader = unsafe { state.rx_buf.reader() }; |
| 368 | let (p, n) = rx_reader.pop_buf(); | 385 | let (p, n) = rx_reader.pop_buf(); |
| 369 | if n == 0 { | 386 | if n == 0 { |
| @@ -378,20 +395,20 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 378 | } | 395 | } |
| 379 | 396 | ||
| 380 | fn consume(&self, amt: usize) { | 397 | fn consume(&self, amt: usize) { |
| 381 | let state = T::buffered_state(); | 398 | let state = self.state; |
| 382 | let mut rx_reader = unsafe { state.rx_buf.reader() }; | 399 | let mut rx_reader = unsafe { state.rx_buf.reader() }; |
| 383 | let full = state.rx_buf.is_full(); | 400 | let full = state.rx_buf.is_full(); |
| 384 | rx_reader.pop_done(amt); | 401 | rx_reader.pop_done(amt); |
| 385 | if full { | 402 | if full { |
| 386 | T::Interrupt::pend(); | 403 | self.info.interrupt.pend(); |
| 387 | } | 404 | } |
| 388 | } | 405 | } |
| 389 | 406 | ||
| 390 | /// Reconfigure the driver | 407 | /// Reconfigure the driver |
| 391 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 408 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 392 | reconfigure::<T>(config)?; | 409 | reconfigure(self.info, self.kernel_clock, config)?; |
| 393 | 410 | ||
| 394 | T::regs().cr1().modify(|w| { | 411 | self.info.regs.cr1().modify(|w| { |
| 395 | w.set_rxneie(true); | 412 | w.set_rxneie(true); |
| 396 | w.set_idleie(true); | 413 | w.set_idleie(true); |
| 397 | }); | 414 | }); |
| @@ -400,10 +417,10 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { | |||
| 400 | } | 417 | } |
| 401 | } | 418 | } |
| 402 | 419 | ||
| 403 | impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | 420 | impl<'d> BufferedUartTx<'d> { |
| 404 | async fn write(&self, buf: &[u8]) -> Result<usize, Error> { | 421 | async fn write(&self, buf: &[u8]) -> Result<usize, Error> { |
| 405 | poll_fn(move |cx| { | 422 | poll_fn(move |cx| { |
| 406 | let state = T::buffered_state(); | 423 | let state = self.state; |
| 407 | state.tx_done.store(false, Ordering::Release); | 424 | state.tx_done.store(false, Ordering::Release); |
| 408 | 425 | ||
| 409 | let empty = state.tx_buf.is_empty(); | 426 | let empty = state.tx_buf.is_empty(); |
| @@ -420,7 +437,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 420 | tx_writer.push_done(n); | 437 | tx_writer.push_done(n); |
| 421 | 438 | ||
| 422 | if empty { | 439 | if empty { |
| 423 | T::Interrupt::pend(); | 440 | self.info.interrupt.pend(); |
| 424 | } | 441 | } |
| 425 | 442 | ||
| 426 | Poll::Ready(Ok(n)) | 443 | Poll::Ready(Ok(n)) |
| @@ -430,7 +447,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 430 | 447 | ||
| 431 | async fn flush(&self) -> Result<(), Error> { | 448 | async fn flush(&self) -> Result<(), Error> { |
| 432 | poll_fn(move |cx| { | 449 | poll_fn(move |cx| { |
| 433 | let state = T::buffered_state(); | 450 | let state = self.state; |
| 434 | 451 | ||
| 435 | if !state.tx_done.load(Ordering::Acquire) { | 452 | if !state.tx_done.load(Ordering::Acquire) { |
| 436 | state.tx_waker.register(cx.waker()); | 453 | state.tx_waker.register(cx.waker()); |
| @@ -444,7 +461,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 444 | 461 | ||
| 445 | fn blocking_write(&self, buf: &[u8]) -> Result<usize, Error> { | 462 | fn blocking_write(&self, buf: &[u8]) -> Result<usize, Error> { |
| 446 | loop { | 463 | loop { |
| 447 | let state = T::buffered_state(); | 464 | let state = self.state; |
| 448 | let empty = state.tx_buf.is_empty(); | 465 | let empty = state.tx_buf.is_empty(); |
| 449 | 466 | ||
| 450 | let mut tx_writer = unsafe { state.tx_buf.writer() }; | 467 | let mut tx_writer = unsafe { state.tx_buf.writer() }; |
| @@ -455,7 +472,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 455 | tx_writer.push_done(n); | 472 | tx_writer.push_done(n); |
| 456 | 473 | ||
| 457 | if empty { | 474 | if empty { |
| 458 | T::Interrupt::pend(); | 475 | self.info.interrupt.pend(); |
| 459 | } | 476 | } |
| 460 | 477 | ||
| 461 | return Ok(n); | 478 | return Ok(n); |
| @@ -465,7 +482,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 465 | 482 | ||
| 466 | fn blocking_flush(&self) -> Result<(), Error> { | 483 | fn blocking_flush(&self) -> Result<(), Error> { |
| 467 | loop { | 484 | loop { |
| 468 | let state = T::buffered_state(); | 485 | let state = self.state; |
| 469 | if state.tx_buf.is_empty() { | 486 | if state.tx_buf.is_empty() { |
| 470 | return Ok(()); | 487 | return Ok(()); |
| 471 | } | 488 | } |
| @@ -474,9 +491,9 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 474 | 491 | ||
| 475 | /// Reconfigure the driver | 492 | /// Reconfigure the driver |
| 476 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 493 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 477 | reconfigure::<T>(config)?; | 494 | reconfigure(self.info, self.kernel_clock, config)?; |
| 478 | 495 | ||
| 479 | T::regs().cr1().modify(|w| { | 496 | self.info.regs.cr1().modify(|w| { |
| 480 | w.set_rxneie(true); | 497 | w.set_rxneie(true); |
| 481 | w.set_idleie(true); | 498 | w.set_idleie(true); |
| 482 | }); | 499 | }); |
| @@ -485,65 +502,78 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { | |||
| 485 | } | 502 | } |
| 486 | } | 503 | } |
| 487 | 504 | ||
| 488 | impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { | 505 | impl<'d> Drop for BufferedUartRx<'d> { |
| 489 | fn drop(&mut self) { | 506 | fn drop(&mut self) { |
| 490 | let state = T::buffered_state(); | 507 | let state = self.state; |
| 491 | unsafe { | 508 | unsafe { |
| 492 | state.rx_buf.deinit(); | 509 | state.rx_buf.deinit(); |
| 493 | 510 | ||
| 494 | // TX is inactive if the the buffer is not available. | 511 | // TX is inactive if the the buffer is not available. |
| 495 | // We can now unregister the interrupt handler | 512 | // We can now unregister the interrupt handler |
| 496 | if state.tx_buf.len() == 0 { | 513 | if state.tx_buf.len() == 0 { |
| 497 | T::Interrupt::disable(); | 514 | self.info.interrupt.disable(); |
| 498 | } | 515 | } |
| 499 | } | 516 | } |
| 500 | 517 | ||
| 501 | T::disable(); | 518 | drop_tx_rx(self.info, state); |
| 502 | } | 519 | } |
| 503 | } | 520 | } |
| 504 | 521 | ||
| 505 | impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> { | 522 | impl<'d> Drop for BufferedUartTx<'d> { |
| 506 | fn drop(&mut self) { | 523 | fn drop(&mut self) { |
| 507 | let state = T::buffered_state(); | 524 | let state = self.state; |
| 508 | unsafe { | 525 | unsafe { |
| 509 | state.tx_buf.deinit(); | 526 | state.tx_buf.deinit(); |
| 510 | 527 | ||
| 511 | // RX is inactive if the the buffer is not available. | 528 | // RX is inactive if the the buffer is not available. |
| 512 | // We can now unregister the interrupt handler | 529 | // We can now unregister the interrupt handler |
| 513 | if state.rx_buf.len() == 0 { | 530 | if state.rx_buf.len() == 0 { |
| 514 | T::Interrupt::disable(); | 531 | self.info.interrupt.disable(); |
| 515 | } | 532 | } |
| 516 | } | 533 | } |
| 517 | 534 | ||
| 518 | T::disable(); | 535 | drop_tx_rx(self.info, state); |
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | fn drop_tx_rx(info: &Info, state: &State) { | ||
| 540 | // We cannot use atomic subtraction here, because it's not supported for all targets | ||
| 541 | let is_last_drop = critical_section::with(|_| { | ||
| 542 | let refcount = state.tx_rx_refcount.load(Ordering::Relaxed); | ||
| 543 | assert!(refcount >= 1); | ||
| 544 | state.tx_rx_refcount.store(refcount - 1, Ordering::Relaxed); | ||
| 545 | refcount == 1 | ||
| 546 | }); | ||
| 547 | if is_last_drop { | ||
| 548 | info.enable_bit.disable(); | ||
| 519 | } | 549 | } |
| 520 | } | 550 | } |
| 521 | 551 | ||
| 522 | impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUart<'d, T> { | 552 | impl<'d> embedded_io_async::ErrorType for BufferedUart<'d> { |
| 523 | type Error = Error; | 553 | type Error = Error; |
| 524 | } | 554 | } |
| 525 | 555 | ||
| 526 | impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUartRx<'d, T> { | 556 | impl<'d> embedded_io_async::ErrorType for BufferedUartRx<'d> { |
| 527 | type Error = Error; | 557 | type Error = Error; |
| 528 | } | 558 | } |
| 529 | 559 | ||
| 530 | impl<'d, T: BasicInstance> embedded_io_async::ErrorType for BufferedUartTx<'d, T> { | 560 | impl<'d> embedded_io_async::ErrorType for BufferedUartTx<'d> { |
| 531 | type Error = Error; | 561 | type Error = Error; |
| 532 | } | 562 | } |
| 533 | 563 | ||
| 534 | impl<'d, T: BasicInstance> embedded_io_async::Read for BufferedUart<'d, T> { | 564 | impl<'d> embedded_io_async::Read for BufferedUart<'d> { |
| 535 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 565 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 536 | self.rx.read(buf).await | 566 | self.rx.read(buf).await |
| 537 | } | 567 | } |
| 538 | } | 568 | } |
| 539 | 569 | ||
| 540 | impl<'d, T: BasicInstance> embedded_io_async::Read for BufferedUartRx<'d, T> { | 570 | impl<'d> embedded_io_async::Read for BufferedUartRx<'d> { |
| 541 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 571 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 542 | Self::read(self, buf).await | 572 | Self::read(self, buf).await |
| 543 | } | 573 | } |
| 544 | } | 574 | } |
| 545 | 575 | ||
| 546 | impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUart<'d, T> { | 576 | impl<'d> embedded_io_async::BufRead for BufferedUart<'d> { |
| 547 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { | 577 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { |
| 548 | self.rx.fill_buf().await | 578 | self.rx.fill_buf().await |
| 549 | } | 579 | } |
| @@ -553,7 +583,7 @@ impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUart<'d, T> { | |||
| 553 | } | 583 | } |
| 554 | } | 584 | } |
| 555 | 585 | ||
| 556 | impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUartRx<'d, T> { | 586 | impl<'d> embedded_io_async::BufRead for BufferedUartRx<'d> { |
| 557 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { | 587 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { |
| 558 | Self::fill_buf(self).await | 588 | Self::fill_buf(self).await |
| 559 | } | 589 | } |
| @@ -563,7 +593,7 @@ impl<'d, T: BasicInstance> embedded_io_async::BufRead for BufferedUartRx<'d, T> | |||
| 563 | } | 593 | } |
| 564 | } | 594 | } |
| 565 | 595 | ||
| 566 | impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUart<'d, T> { | 596 | impl<'d> embedded_io_async::Write for BufferedUart<'d> { |
| 567 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 597 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 568 | self.tx.write(buf).await | 598 | self.tx.write(buf).await |
| 569 | } | 599 | } |
| @@ -573,7 +603,7 @@ impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUart<'d, T> { | |||
| 573 | } | 603 | } |
| 574 | } | 604 | } |
| 575 | 605 | ||
| 576 | impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUartTx<'d, T> { | 606 | impl<'d> embedded_io_async::Write for BufferedUartTx<'d> { |
| 577 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 607 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 578 | Self::write(self, buf).await | 608 | Self::write(self, buf).await |
| 579 | } | 609 | } |
| @@ -583,19 +613,19 @@ impl<'d, T: BasicInstance> embedded_io_async::Write for BufferedUartTx<'d, T> { | |||
| 583 | } | 613 | } |
| 584 | } | 614 | } |
| 585 | 615 | ||
| 586 | impl<'d, T: BasicInstance> embedded_io::Read for BufferedUart<'d, T> { | 616 | impl<'d> embedded_io::Read for BufferedUart<'d> { |
| 587 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 617 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 588 | self.rx.blocking_read(buf) | 618 | self.rx.blocking_read(buf) |
| 589 | } | 619 | } |
| 590 | } | 620 | } |
| 591 | 621 | ||
| 592 | impl<'d, T: BasicInstance> embedded_io::Read for BufferedUartRx<'d, T> { | 622 | impl<'d> embedded_io::Read for BufferedUartRx<'d> { |
| 593 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 623 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 594 | self.blocking_read(buf) | 624 | self.blocking_read(buf) |
| 595 | } | 625 | } |
| 596 | } | 626 | } |
| 597 | 627 | ||
| 598 | impl<'d, T: BasicInstance> embedded_io::Write for BufferedUart<'d, T> { | 628 | impl<'d> embedded_io::Write for BufferedUart<'d> { |
| 599 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 629 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 600 | self.tx.blocking_write(buf) | 630 | self.tx.blocking_write(buf) |
| 601 | } | 631 | } |
| @@ -605,7 +635,7 @@ impl<'d, T: BasicInstance> embedded_io::Write for BufferedUart<'d, T> { | |||
| 605 | } | 635 | } |
| 606 | } | 636 | } |
| 607 | 637 | ||
| 608 | impl<'d, T: BasicInstance> embedded_io::Write for BufferedUartTx<'d, T> { | 638 | impl<'d> embedded_io::Write for BufferedUartTx<'d> { |
| 609 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 639 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 610 | Self::blocking_write(self, buf) | 640 | Self::blocking_write(self, buf) |
| 611 | } | 641 | } |
| @@ -615,11 +645,11 @@ impl<'d, T: BasicInstance> embedded_io::Write for BufferedUartTx<'d, T> { | |||
| 615 | } | 645 | } |
| 616 | } | 646 | } |
| 617 | 647 | ||
| 618 | impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T> { | 648 | impl<'d> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d> { |
| 619 | type Error = Error; | 649 | type Error = Error; |
| 620 | 650 | ||
| 621 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 651 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 622 | let r = T::regs(); | 652 | let r = self.info.regs; |
| 623 | unsafe { | 653 | unsafe { |
| 624 | let sr = sr(r).read(); | 654 | let sr = sr(r).read(); |
| 625 | if sr.pe() { | 655 | if sr.pe() { |
| @@ -643,7 +673,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUartRx< | |||
| 643 | } | 673 | } |
| 644 | } | 674 | } |
| 645 | 675 | ||
| 646 | impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d, T> { | 676 | impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d> { |
| 647 | type Error = Error; | 677 | type Error = Error; |
| 648 | 678 | ||
| 649 | fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { | 679 | fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { |
| @@ -662,7 +692,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for Buff | |||
| 662 | } | 692 | } |
| 663 | } | 693 | } |
| 664 | 694 | ||
| 665 | impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T> { | 695 | impl<'d> embedded_hal_02::serial::Read<u8> for BufferedUart<'d> { |
| 666 | type Error = Error; | 696 | type Error = Error; |
| 667 | 697 | ||
| 668 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 698 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| @@ -670,7 +700,7 @@ impl<'d, T: BasicInstance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d | |||
| 670 | } | 700 | } |
| 671 | } | 701 | } |
| 672 | 702 | ||
| 673 | impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d, T> { | 703 | impl<'d> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d> { |
| 674 | type Error = Error; | 704 | type Error = Error; |
| 675 | 705 | ||
| 676 | fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { | 706 | fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> { |
| @@ -689,25 +719,25 @@ impl<'d, T: BasicInstance> embedded_hal_02::blocking::serial::Write<u8> for Buff | |||
| 689 | } | 719 | } |
| 690 | } | 720 | } |
| 691 | 721 | ||
| 692 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUart<'d, T> { | 722 | impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUart<'d> { |
| 693 | type Error = Error; | 723 | type Error = Error; |
| 694 | } | 724 | } |
| 695 | 725 | ||
| 696 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d, T> { | 726 | impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d> { |
| 697 | type Error = Error; | 727 | type Error = Error; |
| 698 | } | 728 | } |
| 699 | 729 | ||
| 700 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d, T> { | 730 | impl<'d> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d> { |
| 701 | type Error = Error; | 731 | type Error = Error; |
| 702 | } | 732 | } |
| 703 | 733 | ||
| 704 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::Read for BufferedUartRx<'d, T> { | 734 | impl<'d> embedded_hal_nb::serial::Read for BufferedUartRx<'d> { |
| 705 | fn read(&mut self) -> nb::Result<u8, Self::Error> { | 735 | fn read(&mut self) -> nb::Result<u8, Self::Error> { |
| 706 | embedded_hal_02::serial::Read::read(self) | 736 | embedded_hal_02::serial::Read::read(self) |
| 707 | } | 737 | } |
| 708 | } | 738 | } |
| 709 | 739 | ||
| 710 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> { | 740 | impl<'d> embedded_hal_nb::serial::Write for BufferedUartTx<'d> { |
| 711 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 741 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 712 | self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) | 742 | self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) |
| 713 | } | 743 | } |
| @@ -717,13 +747,13 @@ impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, | |||
| 717 | } | 747 | } |
| 718 | } | 748 | } |
| 719 | 749 | ||
| 720 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::Read for BufferedUart<'d, T> { | 750 | impl<'d> embedded_hal_nb::serial::Read for BufferedUart<'d> { |
| 721 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 751 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 722 | embedded_hal_02::serial::Read::read(&mut self.rx) | 752 | embedded_hal_02::serial::Read::read(&mut self.rx) |
| 723 | } | 753 | } |
| 724 | } | 754 | } |
| 725 | 755 | ||
| 726 | impl<'d, T: BasicInstance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> { | 756 | impl<'d> embedded_hal_nb::serial::Write for BufferedUart<'d> { |
| 727 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 757 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 728 | self.tx.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) | 758 | self.tx.blocking_write(&[char]).map(drop).map_err(nb::Error::Other) |
| 729 | } | 759 | } |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index a6dfbd482..b24335f3a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | 6 | use core::marker::PhantomData; |
| 7 | use core::sync::atomic::{compiler_fence, Ordering}; | 7 | use core::sync::atomic::{compiler_fence, AtomicU8, Ordering}; |
| 8 | use core::task::Poll; | 8 | use core::task::Poll; |
| 9 | 9 | ||
| 10 | use embassy_embedded_hal::SetConfig; | 10 | use embassy_embedded_hal::SetConfig; |
| @@ -15,7 +15,8 @@ use futures_util::future::{select, Either}; | |||
| 15 | 15 | ||
| 16 | use crate::dma::ChannelAndRequest; | 16 | use crate::dma::ChannelAndRequest; |
| 17 | use crate::gpio::{AFType, AnyPin, SealedPin}; | 17 | use crate::gpio::{AFType, AnyPin, SealedPin}; |
| 18 | use crate::interrupt::typelevel::Interrupt; | 18 | use crate::interrupt::typelevel::Interrupt as _; |
| 19 | use crate::interrupt::{self, Interrupt, InterruptExt}; | ||
| 19 | use crate::mode::{Async, Blocking, Mode}; | 20 | use crate::mode::{Async, Blocking, Mode}; |
| 20 | #[allow(unused_imports)] | 21 | #[allow(unused_imports)] |
| 21 | #[cfg(not(any(usart_v1, usart_v2)))] | 22 | #[cfg(not(any(usart_v1, usart_v2)))] |
| @@ -27,55 +28,57 @@ use crate::pac::usart::Lpuart as Regs; | |||
| 27 | #[cfg(any(usart_v1, usart_v2))] | 28 | #[cfg(any(usart_v1, usart_v2))] |
| 28 | use crate::pac::usart::Usart as Regs; | 29 | use crate::pac::usart::Usart as Regs; |
| 29 | use crate::pac::usart::{regs, vals}; | 30 | use crate::pac::usart::{regs, vals}; |
| 31 | use crate::rcc::{ClockEnableBit, SealedRccPeripheral}; | ||
| 30 | use crate::time::Hertz; | 32 | use crate::time::Hertz; |
| 31 | use crate::{interrupt, peripherals, Peripheral}; | 33 | use crate::Peripheral; |
| 32 | 34 | ||
| 33 | /// Interrupt handler. | 35 | /// Interrupt handler. |
| 34 | pub struct InterruptHandler<T: BasicInstance> { | 36 | pub struct InterruptHandler<T: Instance> { |
| 35 | _phantom: PhantomData<T>, | 37 | _phantom: PhantomData<T>, |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 40 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 39 | unsafe fn on_interrupt() { | 41 | unsafe fn on_interrupt() { |
| 40 | let r = T::regs(); | 42 | on_interrupt(T::info().regs, T::state()) |
| 41 | let s = T::state(); | 43 | } |
| 42 | 44 | } | |
| 43 | let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); | ||
| 44 | 45 | ||
| 45 | let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); | 46 | unsafe fn on_interrupt(r: Regs, s: &'static State) { |
| 46 | if has_errors { | 47 | let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read()); |
| 47 | // clear all interrupts and DMA Rx Request | ||
| 48 | r.cr1().modify(|w| { | ||
| 49 | // disable RXNE interrupt | ||
| 50 | w.set_rxneie(false); | ||
| 51 | // disable parity interrupt | ||
| 52 | w.set_peie(false); | ||
| 53 | // disable idle line interrupt | ||
| 54 | w.set_idleie(false); | ||
| 55 | }); | ||
| 56 | r.cr3().modify(|w| { | ||
| 57 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) | ||
| 58 | w.set_eie(false); | ||
| 59 | // disable DMA Rx Request | ||
| 60 | w.set_dmar(false); | ||
| 61 | }); | ||
| 62 | } else if cr1.idleie() && sr.idle() { | ||
| 63 | // IDLE detected: no more data will come | ||
| 64 | r.cr1().modify(|w| { | ||
| 65 | // disable idle line detection | ||
| 66 | w.set_idleie(false); | ||
| 67 | }); | ||
| 68 | } else if cr1.rxneie() { | ||
| 69 | // We cannot check the RXNE flag as it is auto-cleared by the DMA controller | ||
| 70 | 48 | ||
| 71 | // It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection | 49 | let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie()); |
| 72 | } else { | 50 | if has_errors { |
| 73 | return; | 51 | // clear all interrupts and DMA Rx Request |
| 74 | } | 52 | r.cr1().modify(|w| { |
| 53 | // disable RXNE interrupt | ||
| 54 | w.set_rxneie(false); | ||
| 55 | // disable parity interrupt | ||
| 56 | w.set_peie(false); | ||
| 57 | // disable idle line interrupt | ||
| 58 | w.set_idleie(false); | ||
| 59 | }); | ||
| 60 | r.cr3().modify(|w| { | ||
| 61 | // disable Error Interrupt: (Frame error, Noise error, Overrun error) | ||
| 62 | w.set_eie(false); | ||
| 63 | // disable DMA Rx Request | ||
| 64 | w.set_dmar(false); | ||
| 65 | }); | ||
| 66 | } else if cr1.idleie() && sr.idle() { | ||
| 67 | // IDLE detected: no more data will come | ||
| 68 | r.cr1().modify(|w| { | ||
| 69 | // disable idle line detection | ||
| 70 | w.set_idleie(false); | ||
| 71 | }); | ||
| 72 | } else if cr1.rxneie() { | ||
| 73 | // We cannot check the RXNE flag as it is auto-cleared by the DMA controller | ||
| 75 | 74 | ||
| 76 | compiler_fence(Ordering::SeqCst); | 75 | // It is up to the listener to determine if this in fact was a RX event and disable the RXNE detection |
| 77 | s.rx_waker.wake(); | 76 | } else { |
| 77 | return; | ||
| 78 | } | 78 | } |
| 79 | |||
| 80 | compiler_fence(Ordering::SeqCst); | ||
| 81 | s.rx_waker.wake(); | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | 84 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| @@ -239,12 +242,12 @@ enum ReadCompletionEvent { | |||
| 239 | /// | 242 | /// |
| 240 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] | 243 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] |
| 241 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. | 244 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. |
| 242 | pub struct Uart<'d, T: BasicInstance, M: Mode> { | 245 | pub struct Uart<'d, M: Mode> { |
| 243 | tx: UartTx<'d, T, M>, | 246 | tx: UartTx<'d, M>, |
| 244 | rx: UartRx<'d, T, M>, | 247 | rx: UartRx<'d, M>, |
| 245 | } | 248 | } |
| 246 | 249 | ||
| 247 | impl<'d, T: BasicInstance, M: Mode> SetConfig for Uart<'d, T, M> { | 250 | impl<'d, M: Mode> SetConfig for Uart<'d, M> { |
| 248 | type Config = Config; | 251 | type Config = Config; |
| 249 | type ConfigError = ConfigError; | 252 | type ConfigError = ConfigError; |
| 250 | 253 | ||
| @@ -258,15 +261,18 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for Uart<'d, T, M> { | |||
| 258 | /// | 261 | /// |
| 259 | /// Can be obtained from [`Uart::split`], or can be constructed independently, | 262 | /// Can be obtained from [`Uart::split`], or can be constructed independently, |
| 260 | /// if you do not need the receiving half of the driver. | 263 | /// if you do not need the receiving half of the driver. |
| 261 | pub struct UartTx<'d, T: BasicInstance, M: Mode> { | 264 | pub struct UartTx<'d, M: Mode> { |
| 262 | _phantom: PhantomData<(T, M)>, | 265 | info: &'static Info, |
| 266 | state: &'static State, | ||
| 267 | kernel_clock: Hertz, | ||
| 263 | tx: Option<PeripheralRef<'d, AnyPin>>, | 268 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 264 | cts: Option<PeripheralRef<'d, AnyPin>>, | 269 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| 265 | de: Option<PeripheralRef<'d, AnyPin>>, | 270 | de: Option<PeripheralRef<'d, AnyPin>>, |
| 266 | tx_dma: Option<ChannelAndRequest<'d>>, | 271 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 272 | _phantom: PhantomData<M>, | ||
| 267 | } | 273 | } |
| 268 | 274 | ||
| 269 | impl<'d, T: BasicInstance, M: Mode> SetConfig for UartTx<'d, T, M> { | 275 | impl<'d, M: Mode> SetConfig for UartTx<'d, M> { |
| 270 | type Config = Config; | 276 | type Config = Config; |
| 271 | type ConfigError = ConfigError; | 277 | type ConfigError = ConfigError; |
| 272 | 278 | ||
| @@ -304,17 +310,20 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for UartTx<'d, T, M> { | |||
| 304 | /// store data received between calls. | 310 | /// store data received between calls. |
| 305 | /// | 311 | /// |
| 306 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). | 312 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). |
| 307 | pub struct UartRx<'d, T: BasicInstance, M: Mode> { | 313 | pub struct UartRx<'d, M: Mode> { |
| 308 | _phantom: PhantomData<(T, M)>, | 314 | info: &'static Info, |
| 315 | state: &'static State, | ||
| 316 | kernel_clock: Hertz, | ||
| 309 | rx: Option<PeripheralRef<'d, AnyPin>>, | 317 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 310 | rts: Option<PeripheralRef<'d, AnyPin>>, | 318 | rts: Option<PeripheralRef<'d, AnyPin>>, |
| 311 | rx_dma: Option<ChannelAndRequest<'d>>, | 319 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 312 | detect_previous_overrun: bool, | 320 | detect_previous_overrun: bool, |
| 313 | #[cfg(any(usart_v1, usart_v2))] | 321 | #[cfg(any(usart_v1, usart_v2))] |
| 314 | buffered_sr: stm32_metapac::usart::regs::Sr, | 322 | buffered_sr: stm32_metapac::usart::regs::Sr, |
| 323 | _phantom: PhantomData<M>, | ||
| 315 | } | 324 | } |
| 316 | 325 | ||
| 317 | impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> { | 326 | impl<'d, M: Mode> SetConfig for UartRx<'d, M> { |
| 318 | type Config = Config; | 327 | type Config = Config; |
| 319 | type ConfigError = ConfigError; | 328 | type ConfigError = ConfigError; |
| 320 | 329 | ||
| @@ -323,9 +332,9 @@ impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> { | |||
| 323 | } | 332 | } |
| 324 | } | 333 | } |
| 325 | 334 | ||
| 326 | impl<'d, T: BasicInstance> UartTx<'d, T, Async> { | 335 | impl<'d> UartTx<'d, Async> { |
| 327 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. | 336 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. |
| 328 | pub fn new( | 337 | pub fn new<T: Instance>( |
| 329 | peri: impl Peripheral<P = T> + 'd, | 338 | peri: impl Peripheral<P = T> + 'd, |
| 330 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 339 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 331 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, | 340 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| @@ -341,7 +350,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> { | |||
| 341 | } | 350 | } |
| 342 | 351 | ||
| 343 | /// Create a new tx-only UART with a clear-to-send pin | 352 | /// Create a new tx-only UART with a clear-to-send pin |
| 344 | pub fn new_with_cts( | 353 | pub fn new_with_cts<T: Instance>( |
| 345 | peri: impl Peripheral<P = T> + 'd, | 354 | peri: impl Peripheral<P = T> + 'd, |
| 346 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 355 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 347 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | 356 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
| @@ -359,7 +368,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> { | |||
| 359 | 368 | ||
| 360 | /// Initiate an asynchronous UART write | 369 | /// Initiate an asynchronous UART write |
| 361 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 370 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 362 | let r = T::regs(); | 371 | let r = self.info.regs; |
| 363 | 372 | ||
| 364 | // Disable Receiver for Half-Duplex mode | 373 | // Disable Receiver for Half-Duplex mode |
| 365 | if r.cr3().read().hdsel() { | 374 | if r.cr3().read().hdsel() { |
| @@ -377,21 +386,17 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Async> { | |||
| 377 | Ok(()) | 386 | Ok(()) |
| 378 | } | 387 | } |
| 379 | 388 | ||
| 380 | async fn flush_inner() -> Result<(), Error> { | ||
| 381 | Self::blocking_flush_inner() | ||
| 382 | } | ||
| 383 | |||
| 384 | /// Wait until transmission complete | 389 | /// Wait until transmission complete |
| 385 | pub async fn flush(&mut self) -> Result<(), Error> { | 390 | pub async fn flush(&mut self) -> Result<(), Error> { |
| 386 | Self::flush_inner().await | 391 | self.blocking_flush() |
| 387 | } | 392 | } |
| 388 | } | 393 | } |
| 389 | 394 | ||
| 390 | impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { | 395 | impl<'d> UartTx<'d, Blocking> { |
| 391 | /// Create a new blocking tx-only UART with no hardware flow control. | 396 | /// Create a new blocking tx-only UART with no hardware flow control. |
| 392 | /// | 397 | /// |
| 393 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. | 398 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. |
| 394 | pub fn new_blocking( | 399 | pub fn new_blocking<T: Instance>( |
| 395 | peri: impl Peripheral<P = T> + 'd, | 400 | peri: impl Peripheral<P = T> + 'd, |
| 396 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 401 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 397 | config: Config, | 402 | config: Config, |
| @@ -400,7 +405,7 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { | |||
| 400 | } | 405 | } |
| 401 | 406 | ||
| 402 | /// Create a new blocking tx-only UART with a clear-to-send pin | 407 | /// Create a new blocking tx-only UART with a clear-to-send pin |
| 403 | pub fn new_blocking_with_cts( | 408 | pub fn new_blocking_with_cts<T: Instance>( |
| 404 | peri: impl Peripheral<P = T> + 'd, | 409 | peri: impl Peripheral<P = T> + 'd, |
| 405 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 410 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 406 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | 411 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
| @@ -416,8 +421,8 @@ impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { | |||
| 416 | } | 421 | } |
| 417 | } | 422 | } |
| 418 | 423 | ||
| 419 | impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { | 424 | impl<'d, M: Mode> UartTx<'d, M> { |
| 420 | fn new_inner( | 425 | fn new_inner<T: Instance>( |
| 421 | _peri: impl Peripheral<P = T> + 'd, | 426 | _peri: impl Peripheral<P = T> + 'd, |
| 422 | tx: Option<PeripheralRef<'d, AnyPin>>, | 427 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 423 | cts: Option<PeripheralRef<'d, AnyPin>>, | 428 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -426,16 +431,21 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { | |||
| 426 | ) -> Result<Self, ConfigError> { | 431 | ) -> Result<Self, ConfigError> { |
| 427 | T::enable_and_reset(); | 432 | T::enable_and_reset(); |
| 428 | 433 | ||
| 429 | let r = T::regs(); | 434 | let info = T::info(); |
| 435 | let state = T::state(); | ||
| 436 | let kernel_clock = T::frequency(); | ||
| 437 | let r = info.regs; | ||
| 430 | r.cr3().modify(|w| { | 438 | r.cr3().modify(|w| { |
| 431 | w.set_ctse(cts.is_some()); | 439 | w.set_ctse(cts.is_some()); |
| 432 | }); | 440 | }); |
| 433 | configure(r, &config, T::frequency(), T::KIND, false, true)?; | 441 | configure(info, kernel_clock, &config, false, true)?; |
| 434 | 442 | ||
| 435 | // create state once! | 443 | state.tx_rx_refcount.store(1, Ordering::Relaxed); |
| 436 | let _s = T::state(); | ||
| 437 | 444 | ||
| 438 | Ok(Self { | 445 | Ok(Self { |
| 446 | info, | ||
| 447 | state, | ||
| 448 | kernel_clock, | ||
| 439 | tx, | 449 | tx, |
| 440 | cts, | 450 | cts, |
| 441 | de: None, | 451 | de: None, |
| @@ -446,12 +456,12 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { | |||
| 446 | 456 | ||
| 447 | /// Reconfigure the driver | 457 | /// Reconfigure the driver |
| 448 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 458 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 449 | reconfigure::<T>(config) | 459 | reconfigure(self.info, self.kernel_clock, config) |
| 450 | } | 460 | } |
| 451 | 461 | ||
| 452 | /// Perform a blocking UART write | 462 | /// Perform a blocking UART write |
| 453 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 463 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 454 | let r = T::regs(); | 464 | let r = self.info.regs; |
| 455 | 465 | ||
| 456 | // Disable Receiver for Half-Duplex mode | 466 | // Disable Receiver for Half-Duplex mode |
| 457 | if r.cr3().read().hdsel() { | 467 | if r.cr3().read().hdsel() { |
| @@ -465,28 +475,29 @@ impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { | |||
| 465 | Ok(()) | 475 | Ok(()) |
| 466 | } | 476 | } |
| 467 | 477 | ||
| 468 | fn blocking_flush_inner() -> Result<(), Error> { | ||
| 469 | let r = T::regs(); | ||
| 470 | while !sr(r).read().tc() {} | ||
| 471 | |||
| 472 | // Enable Receiver after transmission complete for Half-Duplex mode | ||
| 473 | if r.cr3().read().hdsel() { | ||
| 474 | r.cr1().modify(|reg| reg.set_re(true)); | ||
| 475 | } | ||
| 476 | Ok(()) | ||
| 477 | } | ||
| 478 | |||
| 479 | /// Block until transmission complete | 478 | /// Block until transmission complete |
| 480 | pub fn blocking_flush(&mut self) -> Result<(), Error> { | 479 | pub fn blocking_flush(&mut self) -> Result<(), Error> { |
| 481 | Self::blocking_flush_inner() | 480 | blocking_flush(self.info) |
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | fn blocking_flush(info: &Info) -> Result<(), Error> { | ||
| 485 | let r = info.regs; | ||
| 486 | while !sr(r).read().tc() {} | ||
| 487 | |||
| 488 | // Enable Receiver after transmission complete for Half-Duplex mode | ||
| 489 | if r.cr3().read().hdsel() { | ||
| 490 | r.cr1().modify(|reg| reg.set_re(true)); | ||
| 482 | } | 491 | } |
| 492 | |||
| 493 | Ok(()) | ||
| 483 | } | 494 | } |
| 484 | 495 | ||
| 485 | impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | 496 | impl<'d> UartRx<'d, Async> { |
| 486 | /// Create a new rx-only UART with no hardware flow control. | 497 | /// Create a new rx-only UART with no hardware flow control. |
| 487 | /// | 498 | /// |
| 488 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. | 499 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. |
| 489 | pub fn new( | 500 | pub fn new<T: Instance>( |
| 490 | peri: impl Peripheral<P = T> + 'd, | 501 | peri: impl Peripheral<P = T> + 'd, |
| 491 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 502 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 492 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 503 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -497,7 +508,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 497 | } | 508 | } |
| 498 | 509 | ||
| 499 | /// Create a new rx-only UART with a request-to-send pin | 510 | /// Create a new rx-only UART with a request-to-send pin |
| 500 | pub fn new_with_rts( | 511 | pub fn new_with_rts<T: Instance>( |
| 501 | peri: impl Peripheral<P = T> + 'd, | 512 | peri: impl Peripheral<P = T> + 'd, |
| 502 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 513 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 503 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 514 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -531,11 +542,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 531 | buffer: &mut [u8], | 542 | buffer: &mut [u8], |
| 532 | enable_idle_line_detection: bool, | 543 | enable_idle_line_detection: bool, |
| 533 | ) -> Result<ReadCompletionEvent, Error> { | 544 | ) -> Result<ReadCompletionEvent, Error> { |
| 534 | let r = T::regs(); | 545 | let r = self.info.regs; |
| 535 | 546 | ||
| 536 | // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. | 547 | // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. |
| 537 | if r.cr3().read().hdsel() { | 548 | if r.cr3().read().hdsel() { |
| 538 | UartTx::<'d, T, Async>::flush_inner().await?; | 549 | blocking_flush(self.info)?; |
| 539 | } | 550 | } |
| 540 | 551 | ||
| 541 | // make sure USART state is restored to neutral state when this future is dropped | 552 | // make sure USART state is restored to neutral state when this future is dropped |
| @@ -565,7 +576,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 565 | // Start USART DMA | 576 | // Start USART DMA |
| 566 | // will not do anything yet because DMAR is not yet set | 577 | // will not do anything yet because DMAR is not yet set |
| 567 | // future which will complete when DMA Read request completes | 578 | // future which will complete when DMA Read request completes |
| 568 | let transfer = unsafe { ch.read(rdr(T::regs()), buffer, Default::default()) }; | 579 | let transfer = unsafe { ch.read(rdr(r), buffer, Default::default()) }; |
| 569 | 580 | ||
| 570 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer | 581 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer |
| 571 | if !self.detect_previous_overrun { | 582 | if !self.detect_previous_overrun { |
| @@ -640,9 +651,8 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 640 | compiler_fence(Ordering::SeqCst); | 651 | compiler_fence(Ordering::SeqCst); |
| 641 | 652 | ||
| 642 | // future which completes when idle line or error is detected | 653 | // future which completes when idle line or error is detected |
| 654 | let s = self.state; | ||
| 643 | let abort = poll_fn(move |cx| { | 655 | let abort = poll_fn(move |cx| { |
| 644 | let s = T::state(); | ||
| 645 | |||
| 646 | s.rx_waker.register(cx.waker()); | 656 | s.rx_waker.register(cx.waker()); |
| 647 | 657 | ||
| 648 | let sr = sr(r).read(); | 658 | let sr = sr(r).read(); |
| @@ -728,11 +738,11 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 728 | } | 738 | } |
| 729 | } | 739 | } |
| 730 | 740 | ||
| 731 | impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> { | 741 | impl<'d> UartRx<'d, Blocking> { |
| 732 | /// Create a new rx-only UART with no hardware flow control. | 742 | /// Create a new rx-only UART with no hardware flow control. |
| 733 | /// | 743 | /// |
| 734 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. | 744 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. |
| 735 | pub fn new_blocking( | 745 | pub fn new_blocking<T: Instance>( |
| 736 | peri: impl Peripheral<P = T> + 'd, | 746 | peri: impl Peripheral<P = T> + 'd, |
| 737 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 747 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 738 | config: Config, | 748 | config: Config, |
| @@ -741,7 +751,7 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> { | |||
| 741 | } | 751 | } |
| 742 | 752 | ||
| 743 | /// Create a new rx-only UART with a request-to-send pin | 753 | /// Create a new rx-only UART with a request-to-send pin |
| 744 | pub fn new_blocking_with_rts( | 754 | pub fn new_blocking_with_rts<T: Instance>( |
| 745 | peri: impl Peripheral<P = T> + 'd, | 755 | peri: impl Peripheral<P = T> + 'd, |
| 746 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 756 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 747 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, | 757 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
| @@ -757,8 +767,8 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> { | |||
| 757 | } | 767 | } |
| 758 | } | 768 | } |
| 759 | 769 | ||
| 760 | impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | 770 | impl<'d, M: Mode> UartRx<'d, M> { |
| 761 | fn new_inner( | 771 | fn new_inner<T: Instance>( |
| 762 | _peri: impl Peripheral<P = T> + 'd, | 772 | _peri: impl Peripheral<P = T> + 'd, |
| 763 | rx: Option<PeripheralRef<'d, AnyPin>>, | 773 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 764 | rts: Option<PeripheralRef<'d, AnyPin>>, | 774 | rts: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -767,20 +777,25 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 767 | ) -> Result<Self, ConfigError> { | 777 | ) -> Result<Self, ConfigError> { |
| 768 | T::enable_and_reset(); | 778 | T::enable_and_reset(); |
| 769 | 779 | ||
| 770 | let r = T::regs(); | 780 | let info = T::info(); |
| 781 | let state = T::state(); | ||
| 782 | let kernel_clock = T::frequency(); | ||
| 783 | let r = info.regs; | ||
| 771 | r.cr3().write(|w| { | 784 | r.cr3().write(|w| { |
| 772 | w.set_rtse(rts.is_some()); | 785 | w.set_rtse(rts.is_some()); |
| 773 | }); | 786 | }); |
| 774 | configure(r, &config, T::frequency(), T::KIND, true, false)?; | 787 | configure(info, kernel_clock, &config, true, false)?; |
| 775 | 788 | ||
| 776 | T::Interrupt::unpend(); | 789 | T::Interrupt::unpend(); |
| 777 | unsafe { T::Interrupt::enable() }; | 790 | unsafe { T::Interrupt::enable() }; |
| 778 | 791 | ||
| 779 | // create state once! | 792 | state.tx_rx_refcount.store(1, Ordering::Relaxed); |
| 780 | let _s = T::state(); | ||
| 781 | 793 | ||
| 782 | Ok(Self { | 794 | Ok(Self { |
| 783 | _phantom: PhantomData, | 795 | _phantom: PhantomData, |
| 796 | info, | ||
| 797 | state, | ||
| 798 | kernel_clock, | ||
| 784 | rx, | 799 | rx, |
| 785 | rts, | 800 | rts, |
| 786 | rx_dma, | 801 | rx_dma, |
| @@ -792,12 +807,12 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 792 | 807 | ||
| 793 | /// Reconfigure the driver | 808 | /// Reconfigure the driver |
| 794 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 809 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 795 | reconfigure::<T>(config) | 810 | reconfigure(self.info, self.kernel_clock, config) |
| 796 | } | 811 | } |
| 797 | 812 | ||
| 798 | #[cfg(any(usart_v1, usart_v2))] | 813 | #[cfg(any(usart_v1, usart_v2))] |
| 799 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | 814 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
| 800 | let r = T::regs(); | 815 | let r = self.info.regs; |
| 801 | loop { | 816 | loop { |
| 802 | // Handle all buffered error flags. | 817 | // Handle all buffered error flags. |
| 803 | if self.buffered_sr.pe() { | 818 | if self.buffered_sr.pe() { |
| @@ -830,7 +845,7 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 830 | 845 | ||
| 831 | #[cfg(any(usart_v3, usart_v4))] | 846 | #[cfg(any(usart_v3, usart_v4))] |
| 832 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | 847 | fn check_rx_flags(&mut self) -> Result<bool, Error> { |
| 833 | let r = T::regs(); | 848 | let r = self.info.regs; |
| 834 | let sr = r.isr().read(); | 849 | let sr = r.isr().read(); |
| 835 | if sr.pe() { | 850 | if sr.pe() { |
| 836 | r.icr().write(|w| w.set_pe(true)); | 851 | r.icr().write(|w| w.set_pe(true)); |
| @@ -850,7 +865,7 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 850 | 865 | ||
| 851 | /// Read a single u8 if there is one available, otherwise return WouldBlock | 866 | /// Read a single u8 if there is one available, otherwise return WouldBlock |
| 852 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { | 867 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { |
| 853 | let r = T::regs(); | 868 | let r = self.info.regs; |
| 854 | if self.check_rx_flags()? { | 869 | if self.check_rx_flags()? { |
| 855 | Ok(unsafe { rdr(r).read_volatile() }) | 870 | Ok(unsafe { rdr(r).read_volatile() }) |
| 856 | } else { | 871 | } else { |
| @@ -860,11 +875,11 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 860 | 875 | ||
| 861 | /// Perform a blocking read into `buffer` | 876 | /// Perform a blocking read into `buffer` |
| 862 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 877 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 863 | let r = T::regs(); | 878 | let r = self.info.regs; |
| 864 | 879 | ||
| 865 | // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. | 880 | // Call flush for Half-Duplex mode. It prevents reading of bytes which have just been written. |
| 866 | if r.cr3().read().hdsel() { | 881 | if r.cr3().read().hdsel() { |
| 867 | UartTx::<'d, T, M>::blocking_flush_inner()?; | 882 | blocking_flush(self.info)?; |
| 868 | } | 883 | } |
| 869 | 884 | ||
| 870 | for b in buffer { | 885 | for b in buffer { |
| @@ -875,26 +890,39 @@ impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | |||
| 875 | } | 890 | } |
| 876 | } | 891 | } |
| 877 | 892 | ||
| 878 | impl<'d, T: BasicInstance, M: Mode> Drop for UartTx<'d, T, M> { | 893 | impl<'d, M: Mode> Drop for UartTx<'d, M> { |
| 879 | fn drop(&mut self) { | 894 | fn drop(&mut self) { |
| 880 | self.tx.as_ref().map(|x| x.set_as_disconnected()); | 895 | self.tx.as_ref().map(|x| x.set_as_disconnected()); |
| 881 | self.cts.as_ref().map(|x| x.set_as_disconnected()); | 896 | self.cts.as_ref().map(|x| x.set_as_disconnected()); |
| 882 | self.de.as_ref().map(|x| x.set_as_disconnected()); | 897 | self.de.as_ref().map(|x| x.set_as_disconnected()); |
| 883 | T::disable(); | 898 | drop_tx_rx(self.info, self.state); |
| 884 | } | 899 | } |
| 885 | } | 900 | } |
| 886 | 901 | ||
| 887 | impl<'d, T: BasicInstance, M: Mode> Drop for UartRx<'d, T, M> { | 902 | impl<'d, M: Mode> Drop for UartRx<'d, M> { |
| 888 | fn drop(&mut self) { | 903 | fn drop(&mut self) { |
| 889 | self.rx.as_ref().map(|x| x.set_as_disconnected()); | 904 | self.rx.as_ref().map(|x| x.set_as_disconnected()); |
| 890 | self.rts.as_ref().map(|x| x.set_as_disconnected()); | 905 | self.rts.as_ref().map(|x| x.set_as_disconnected()); |
| 891 | T::disable(); | 906 | drop_tx_rx(self.info, self.state); |
| 892 | } | 907 | } |
| 893 | } | 908 | } |
| 894 | 909 | ||
| 895 | impl<'d, T: BasicInstance> Uart<'d, T, Async> { | 910 | fn drop_tx_rx(info: &Info, state: &State) { |
| 911 | // We cannot use atomic subtraction here, because it's not supported for all targets | ||
| 912 | let is_last_drop = critical_section::with(|_| { | ||
| 913 | let refcount = state.tx_rx_refcount.load(Ordering::Relaxed); | ||
| 914 | assert!(refcount >= 1); | ||
| 915 | state.tx_rx_refcount.store(refcount - 1, Ordering::Relaxed); | ||
| 916 | refcount == 1 | ||
| 917 | }); | ||
| 918 | if is_last_drop { | ||
| 919 | info.enable_bit.disable(); | ||
| 920 | } | ||
| 921 | } | ||
| 922 | |||
| 923 | impl<'d> Uart<'d, Async> { | ||
| 896 | /// Create a new bidirectional UART | 924 | /// Create a new bidirectional UART |
| 897 | pub fn new( | 925 | pub fn new<T: Instance>( |
| 898 | peri: impl Peripheral<P = T> + 'd, | 926 | peri: impl Peripheral<P = T> + 'd, |
| 899 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 927 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 900 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 928 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -917,7 +945,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> { | |||
| 917 | } | 945 | } |
| 918 | 946 | ||
| 919 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins | 947 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
| 920 | pub fn new_with_rtscts( | 948 | pub fn new_with_rtscts<T: Instance>( |
| 921 | peri: impl Peripheral<P = T> + 'd, | 949 | peri: impl Peripheral<P = T> + 'd, |
| 922 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 950 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 923 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 951 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -943,7 +971,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> { | |||
| 943 | 971 | ||
| 944 | #[cfg(not(any(usart_v1, usart_v2)))] | 972 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 945 | /// Create a new bidirectional UART with a driver-enable pin | 973 | /// Create a new bidirectional UART with a driver-enable pin |
| 946 | pub fn new_with_de( | 974 | pub fn new_with_de<T: Instance>( |
| 947 | peri: impl Peripheral<P = T> + 'd, | 975 | peri: impl Peripheral<P = T> + 'd, |
| 948 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 976 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 949 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 977 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -977,7 +1005,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> { | |||
| 977 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | 1005 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
| 978 | /// on the line must be managed by software (for instance by using a centralized arbiter). | 1006 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
| 979 | #[doc(alias("HDSEL"))] | 1007 | #[doc(alias("HDSEL"))] |
| 980 | pub fn new_half_duplex( | 1008 | pub fn new_half_duplex<T: Instance>( |
| 981 | peri: impl Peripheral<P = T> + 'd, | 1009 | peri: impl Peripheral<P = T> + 'd, |
| 982 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1010 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 983 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 1011 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| @@ -1015,7 +1043,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> { | |||
| 1015 | /// on the line must be managed by software (for instance by using a centralized arbiter). | 1043 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
| 1016 | #[cfg(not(any(usart_v1, usart_v2)))] | 1044 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 1017 | #[doc(alias("HDSEL"))] | 1045 | #[doc(alias("HDSEL"))] |
| 1018 | pub fn new_half_duplex_on_rx( | 1046 | pub fn new_half_duplex_on_rx<T: Instance>( |
| 1019 | peri: impl Peripheral<P = T> + 'd, | 1047 | peri: impl Peripheral<P = T> + 'd, |
| 1020 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1048 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 1021 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 1049 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| @@ -1055,9 +1083,9 @@ impl<'d, T: BasicInstance> Uart<'d, T, Async> { | |||
| 1055 | } | 1083 | } |
| 1056 | } | 1084 | } |
| 1057 | 1085 | ||
| 1058 | impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | 1086 | impl<'d> Uart<'d, Blocking> { |
| 1059 | /// Create a new blocking bidirectional UART. | 1087 | /// Create a new blocking bidirectional UART. |
| 1060 | pub fn new_blocking( | 1088 | pub fn new_blocking<T: Instance>( |
| 1061 | peri: impl Peripheral<P = T> + 'd, | 1089 | peri: impl Peripheral<P = T> + 'd, |
| 1062 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1090 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 1063 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1091 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -1077,7 +1105,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | |||
| 1077 | } | 1105 | } |
| 1078 | 1106 | ||
| 1079 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins | 1107 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
| 1080 | pub fn new_blocking_with_rtscts( | 1108 | pub fn new_blocking_with_rtscts<T: Instance>( |
| 1081 | peri: impl Peripheral<P = T> + 'd, | 1109 | peri: impl Peripheral<P = T> + 'd, |
| 1082 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1110 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 1083 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1111 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -1100,7 +1128,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | |||
| 1100 | 1128 | ||
| 1101 | #[cfg(not(any(usart_v1, usart_v2)))] | 1129 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 1102 | /// Create a new bidirectional UART with a driver-enable pin | 1130 | /// Create a new bidirectional UART with a driver-enable pin |
| 1103 | pub fn new_blocking_with_de( | 1131 | pub fn new_blocking_with_de<T: Instance>( |
| 1104 | peri: impl Peripheral<P = T> + 'd, | 1132 | peri: impl Peripheral<P = T> + 'd, |
| 1105 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1133 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 1106 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1134 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| @@ -1131,7 +1159,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | |||
| 1131 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | 1159 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict |
| 1132 | /// on the line must be managed by software (for instance by using a centralized arbiter). | 1160 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
| 1133 | #[doc(alias("HDSEL"))] | 1161 | #[doc(alias("HDSEL"))] |
| 1134 | pub fn new_blocking_half_duplex( | 1162 | pub fn new_blocking_half_duplex<T: Instance>( |
| 1135 | peri: impl Peripheral<P = T> + 'd, | 1163 | peri: impl Peripheral<P = T> + 'd, |
| 1136 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1164 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 1137 | mut config: Config, | 1165 | mut config: Config, |
| @@ -1166,7 +1194,7 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | |||
| 1166 | /// on the line must be managed by software (for instance by using a centralized arbiter). | 1194 | /// on the line must be managed by software (for instance by using a centralized arbiter). |
| 1167 | #[cfg(not(any(usart_v1, usart_v2)))] | 1195 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 1168 | #[doc(alias("HDSEL"))] | 1196 | #[doc(alias("HDSEL"))] |
| 1169 | pub fn new_blocking_half_duplex_on_rx( | 1197 | pub fn new_blocking_half_duplex_on_rx<T: Instance>( |
| 1170 | peri: impl Peripheral<P = T> + 'd, | 1198 | peri: impl Peripheral<P = T> + 'd, |
| 1171 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1199 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 1172 | mut config: Config, | 1200 | mut config: Config, |
| @@ -1188,8 +1216,8 @@ impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { | |||
| 1188 | } | 1216 | } |
| 1189 | } | 1217 | } |
| 1190 | 1218 | ||
| 1191 | impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | 1219 | impl<'d, M: Mode> Uart<'d, M> { |
| 1192 | fn new_inner( | 1220 | fn new_inner<T: Instance>( |
| 1193 | _peri: impl Peripheral<P = T> + 'd, | 1221 | _peri: impl Peripheral<P = T> + 'd, |
| 1194 | rx: Option<PeripheralRef<'d, AnyPin>>, | 1222 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 1195 | tx: Option<PeripheralRef<'d, AnyPin>>, | 1223 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -1200,11 +1228,12 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | |||
| 1200 | rx_dma: Option<ChannelAndRequest<'d>>, | 1228 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 1201 | config: Config, | 1229 | config: Config, |
| 1202 | ) -> Result<Self, ConfigError> { | 1230 | ) -> Result<Self, ConfigError> { |
| 1203 | // UartRx and UartTx have one refcount each. | ||
| 1204 | T::enable_and_reset(); | ||
| 1205 | T::enable_and_reset(); | 1231 | T::enable_and_reset(); |
| 1206 | 1232 | ||
| 1207 | let r = T::regs(); | 1233 | let info = T::info(); |
| 1234 | let state = T::state(); | ||
| 1235 | let kernel_clock = T::frequency(); | ||
| 1236 | let r = info.regs; | ||
| 1208 | 1237 | ||
| 1209 | r.cr3().write(|w| { | 1238 | r.cr3().write(|w| { |
| 1210 | w.set_rtse(rts.is_some()); | 1239 | w.set_rtse(rts.is_some()); |
| @@ -1212,17 +1241,19 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | |||
| 1212 | #[cfg(not(any(usart_v1, usart_v2)))] | 1241 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 1213 | w.set_dem(de.is_some()); | 1242 | w.set_dem(de.is_some()); |
| 1214 | }); | 1243 | }); |
| 1215 | configure(r, &config, T::frequency(), T::KIND, true, true)?; | 1244 | configure(info, kernel_clock, &config, true, true)?; |
| 1216 | 1245 | ||
| 1217 | T::Interrupt::unpend(); | 1246 | T::Interrupt::unpend(); |
| 1218 | unsafe { T::Interrupt::enable() }; | 1247 | unsafe { T::Interrupt::enable() }; |
| 1219 | 1248 | ||
| 1220 | // create state once! | 1249 | state.tx_rx_refcount.store(2, Ordering::Relaxed); |
| 1221 | let _s = T::state(); | ||
| 1222 | 1250 | ||
| 1223 | Ok(Self { | 1251 | Ok(Self { |
| 1224 | tx: UartTx { | 1252 | tx: UartTx { |
| 1225 | _phantom: PhantomData, | 1253 | _phantom: PhantomData, |
| 1254 | info, | ||
| 1255 | state, | ||
| 1256 | kernel_clock, | ||
| 1226 | tx, | 1257 | tx, |
| 1227 | cts, | 1258 | cts, |
| 1228 | de, | 1259 | de, |
| @@ -1230,6 +1261,9 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | |||
| 1230 | }, | 1261 | }, |
| 1231 | rx: UartRx { | 1262 | rx: UartRx { |
| 1232 | _phantom: PhantomData, | 1263 | _phantom: PhantomData, |
| 1264 | info, | ||
| 1265 | state, | ||
| 1266 | kernel_clock, | ||
| 1233 | rx, | 1267 | rx, |
| 1234 | rts, | 1268 | rts, |
| 1235 | rx_dma, | 1269 | rx_dma, |
| @@ -1263,32 +1297,34 @@ impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | |||
| 1263 | /// Split the Uart into a transmitter and receiver, which is | 1297 | /// Split the Uart into a transmitter and receiver, which is |
| 1264 | /// particularly useful when having two tasks correlating to | 1298 | /// particularly useful when having two tasks correlating to |
| 1265 | /// transmitting and receiving. | 1299 | /// transmitting and receiving. |
| 1266 | pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { | 1300 | pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { |
| 1267 | (self.tx, self.rx) | 1301 | (self.tx, self.rx) |
| 1268 | } | 1302 | } |
| 1269 | } | 1303 | } |
| 1270 | 1304 | ||
| 1271 | fn reconfigure<T: BasicInstance>(config: &Config) -> Result<(), ConfigError> { | 1305 | fn reconfigure(info: &Info, kernel_clock: Hertz, config: &Config) -> Result<(), ConfigError> { |
| 1272 | T::Interrupt::disable(); | 1306 | info.interrupt.disable(); |
| 1273 | let r = T::regs(); | 1307 | let r = info.regs; |
| 1274 | 1308 | ||
| 1275 | let cr = r.cr1().read(); | 1309 | let cr = r.cr1().read(); |
| 1276 | configure(r, config, T::frequency(), T::KIND, cr.re(), cr.te())?; | 1310 | configure(info, kernel_clock, config, cr.re(), cr.te())?; |
| 1277 | 1311 | ||
| 1278 | T::Interrupt::unpend(); | 1312 | info.interrupt.unpend(); |
| 1279 | unsafe { T::Interrupt::enable() }; | 1313 | unsafe { info.interrupt.enable() }; |
| 1280 | 1314 | ||
| 1281 | Ok(()) | 1315 | Ok(()) |
| 1282 | } | 1316 | } |
| 1283 | 1317 | ||
| 1284 | fn configure( | 1318 | fn configure( |
| 1285 | r: Regs, | 1319 | info: &Info, |
| 1320 | kernel_clock: Hertz, | ||
| 1286 | config: &Config, | 1321 | config: &Config, |
| 1287 | pclk_freq: Hertz, | ||
| 1288 | kind: Kind, | ||
| 1289 | enable_rx: bool, | 1322 | enable_rx: bool, |
| 1290 | enable_tx: bool, | 1323 | enable_tx: bool, |
| 1291 | ) -> Result<(), ConfigError> { | 1324 | ) -> Result<(), ConfigError> { |
| 1325 | let r = info.regs; | ||
| 1326 | let kind = info.kind; | ||
| 1327 | |||
| 1292 | if !enable_rx && !enable_tx { | 1328 | if !enable_rx && !enable_tx { |
| 1293 | return Err(ConfigError::RxOrTxNotEnabled); | 1329 | return Err(ConfigError::RxOrTxNotEnabled); |
| 1294 | } | 1330 | } |
| @@ -1348,7 +1384,7 @@ fn configure( | |||
| 1348 | let mut over8 = false; | 1384 | let mut over8 = false; |
| 1349 | let mut found_brr = None; | 1385 | let mut found_brr = None; |
| 1350 | for &(presc, _presc_val) in &DIVS { | 1386 | for &(presc, _presc_val) in &DIVS { |
| 1351 | let brr = calculate_brr(config.baudrate, pclk_freq.0, presc as u32, mul); | 1387 | let brr = calculate_brr(config.baudrate, kernel_clock.0, presc as u32, mul); |
| 1352 | trace!( | 1388 | trace!( |
| 1353 | "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})", | 1389 | "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})", |
| 1354 | presc, | 1390 | presc, |
| @@ -1389,7 +1425,7 @@ fn configure( | |||
| 1389 | "Using {} oversampling, desired baudrate: {}, actual baudrate: {}", | 1425 | "Using {} oversampling, desired baudrate: {}, actual baudrate: {}", |
| 1390 | oversampling, | 1426 | oversampling, |
| 1391 | config.baudrate, | 1427 | config.baudrate, |
| 1392 | pclk_freq.0 / brr * mul | 1428 | kernel_clock.0 / brr * mul |
| 1393 | ); | 1429 | ); |
| 1394 | 1430 | ||
| 1395 | r.cr2().write(|w| { | 1431 | r.cr2().write(|w| { |
| @@ -1458,14 +1494,14 @@ fn configure( | |||
| 1458 | Ok(()) | 1494 | Ok(()) |
| 1459 | } | 1495 | } |
| 1460 | 1496 | ||
| 1461 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> { | 1497 | impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> { |
| 1462 | type Error = Error; | 1498 | type Error = Error; |
| 1463 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1499 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1464 | self.nb_read() | 1500 | self.nb_read() |
| 1465 | } | 1501 | } |
| 1466 | } | 1502 | } |
| 1467 | 1503 | ||
| 1468 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> { | 1504 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> { |
| 1469 | type Error = Error; | 1505 | type Error = Error; |
| 1470 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 1506 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 1471 | self.blocking_write(buffer) | 1507 | self.blocking_write(buffer) |
| @@ -1475,14 +1511,14 @@ impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> | |||
| 1475 | } | 1511 | } |
| 1476 | } | 1512 | } |
| 1477 | 1513 | ||
| 1478 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> { | 1514 | impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> { |
| 1479 | type Error = Error; | 1515 | type Error = Error; |
| 1480 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1516 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1481 | self.nb_read() | 1517 | self.nb_read() |
| 1482 | } | 1518 | } |
| 1483 | } | 1519 | } |
| 1484 | 1520 | ||
| 1485 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> { | 1521 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> { |
| 1486 | type Error = Error; | 1522 | type Error = Error; |
| 1487 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 1523 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 1488 | self.blocking_write(buffer) | 1524 | self.blocking_write(buffer) |
| @@ -1504,25 +1540,25 @@ impl embedded_hal_nb::serial::Error for Error { | |||
| 1504 | } | 1540 | } |
| 1505 | } | 1541 | } |
| 1506 | 1542 | ||
| 1507 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> { | 1543 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, M> { |
| 1508 | type Error = Error; | 1544 | type Error = Error; |
| 1509 | } | 1545 | } |
| 1510 | 1546 | ||
| 1511 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> { | 1547 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> { |
| 1512 | type Error = Error; | 1548 | type Error = Error; |
| 1513 | } | 1549 | } |
| 1514 | 1550 | ||
| 1515 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> { | 1551 | impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> { |
| 1516 | type Error = Error; | 1552 | type Error = Error; |
| 1517 | } | 1553 | } |
| 1518 | 1554 | ||
| 1519 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { | 1555 | impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> { |
| 1520 | fn read(&mut self) -> nb::Result<u8, Self::Error> { | 1556 | fn read(&mut self) -> nb::Result<u8, Self::Error> { |
| 1521 | self.nb_read() | 1557 | self.nb_read() |
| 1522 | } | 1558 | } |
| 1523 | } | 1559 | } |
| 1524 | 1560 | ||
| 1525 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> { | 1561 | impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> { |
| 1526 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 1562 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 1527 | self.blocking_write(&[char]).map_err(nb::Error::Other) | 1563 | self.blocking_write(&[char]).map_err(nb::Error::Other) |
| 1528 | } | 1564 | } |
| @@ -1532,13 +1568,13 @@ impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d | |||
| 1532 | } | 1568 | } |
| 1533 | } | 1569 | } |
| 1534 | 1570 | ||
| 1535 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> { | 1571 | impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> { |
| 1536 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1572 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1537 | self.nb_read() | 1573 | self.nb_read() |
| 1538 | } | 1574 | } |
| 1539 | } | 1575 | } |
| 1540 | 1576 | ||
| 1541 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> { | 1577 | impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> { |
| 1542 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 1578 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 1543 | self.blocking_write(&[char]).map_err(nb::Error::Other) | 1579 | self.blocking_write(&[char]).map_err(nb::Error::Other) |
| 1544 | } | 1580 | } |
| @@ -1554,24 +1590,15 @@ impl embedded_io::Error for Error { | |||
| 1554 | } | 1590 | } |
| 1555 | } | 1591 | } |
| 1556 | 1592 | ||
| 1557 | impl<T, M: Mode> embedded_io::ErrorType for Uart<'_, T, M> | 1593 | impl<M: Mode> embedded_io::ErrorType for Uart<'_, M> { |
| 1558 | where | ||
| 1559 | T: BasicInstance, | ||
| 1560 | { | ||
| 1561 | type Error = Error; | 1594 | type Error = Error; |
| 1562 | } | 1595 | } |
| 1563 | 1596 | ||
| 1564 | impl<T, M: Mode> embedded_io::ErrorType for UartTx<'_, T, M> | 1597 | impl<M: Mode> embedded_io::ErrorType for UartTx<'_, M> { |
| 1565 | where | ||
| 1566 | T: BasicInstance, | ||
| 1567 | { | ||
| 1568 | type Error = Error; | 1598 | type Error = Error; |
| 1569 | } | 1599 | } |
| 1570 | 1600 | ||
| 1571 | impl<T, M: Mode> embedded_io::Write for Uart<'_, T, M> | 1601 | impl<M: Mode> embedded_io::Write for Uart<'_, M> { |
| 1572 | where | ||
| 1573 | T: BasicInstance, | ||
| 1574 | { | ||
| 1575 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1602 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1576 | self.blocking_write(buf)?; | 1603 | self.blocking_write(buf)?; |
| 1577 | Ok(buf.len()) | 1604 | Ok(buf.len()) |
| @@ -1582,10 +1609,7 @@ where | |||
| 1582 | } | 1609 | } |
| 1583 | } | 1610 | } |
| 1584 | 1611 | ||
| 1585 | impl<T, M: Mode> embedded_io::Write for UartTx<'_, T, M> | 1612 | impl<M: Mode> embedded_io::Write for UartTx<'_, M> { |
| 1586 | where | ||
| 1587 | T: BasicInstance, | ||
| 1588 | { | ||
| 1589 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1613 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1590 | self.blocking_write(buf)?; | 1614 | self.blocking_write(buf)?; |
| 1591 | Ok(buf.len()) | 1615 | Ok(buf.len()) |
| @@ -1596,10 +1620,7 @@ where | |||
| 1596 | } | 1620 | } |
| 1597 | } | 1621 | } |
| 1598 | 1622 | ||
| 1599 | impl<T> embedded_io_async::Write for Uart<'_, T, Async> | 1623 | impl embedded_io_async::Write for Uart<'_, Async> { |
| 1600 | where | ||
| 1601 | T: BasicInstance, | ||
| 1602 | { | ||
| 1603 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1624 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1604 | self.write(buf).await?; | 1625 | self.write(buf).await?; |
| 1605 | Ok(buf.len()) | 1626 | Ok(buf.len()) |
| @@ -1610,10 +1631,7 @@ where | |||
| 1610 | } | 1631 | } |
| 1611 | } | 1632 | } |
| 1612 | 1633 | ||
| 1613 | impl<T> embedded_io_async::Write for UartTx<'_, T, Async> | 1634 | impl embedded_io_async::Write for UartTx<'_, Async> { |
| 1614 | where | ||
| 1615 | T: BasicInstance, | ||
| 1616 | { | ||
| 1617 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1635 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1618 | self.write(buf).await?; | 1636 | self.write(buf).await?; |
| 1619 | Ok(buf.len()) | 1637 | Ok(buf.len()) |
| @@ -1686,72 +1704,75 @@ enum Kind { | |||
| 1686 | 1704 | ||
| 1687 | struct State { | 1705 | struct State { |
| 1688 | rx_waker: AtomicWaker, | 1706 | rx_waker: AtomicWaker, |
| 1707 | tx_rx_refcount: AtomicU8, | ||
| 1689 | } | 1708 | } |
| 1690 | 1709 | ||
| 1691 | impl State { | 1710 | impl State { |
| 1692 | const fn new() -> Self { | 1711 | const fn new() -> Self { |
| 1693 | Self { | 1712 | Self { |
| 1694 | rx_waker: AtomicWaker::new(), | 1713 | rx_waker: AtomicWaker::new(), |
| 1714 | tx_rx_refcount: AtomicU8::new(0), | ||
| 1695 | } | 1715 | } |
| 1696 | } | 1716 | } |
| 1697 | } | 1717 | } |
| 1698 | 1718 | ||
| 1699 | trait SealedBasicInstance: crate::rcc::RccPeripheral { | 1719 | struct Info { |
| 1700 | const KIND: Kind; | 1720 | regs: Regs, |
| 1721 | enable_bit: ClockEnableBit, | ||
| 1722 | interrupt: Interrupt, | ||
| 1723 | kind: Kind, | ||
| 1724 | } | ||
| 1701 | 1725 | ||
| 1702 | fn regs() -> Regs; | 1726 | #[allow(private_interfaces)] |
| 1727 | pub(crate) trait SealedInstance: crate::rcc::RccPeripheral { | ||
| 1728 | fn info() -> &'static Info; | ||
| 1703 | fn state() -> &'static State; | 1729 | fn state() -> &'static State; |
| 1704 | |||
| 1705 | fn buffered_state() -> &'static buffered::State; | 1730 | fn buffered_state() -> &'static buffered::State; |
| 1706 | } | 1731 | } |
| 1707 | 1732 | ||
| 1708 | trait SealedFullInstance: SealedBasicInstance { | 1733 | /// USART peripheral instance trait. |
| 1709 | #[allow(unused)] | ||
| 1710 | fn regs_uart() -> crate::pac::usart::Usart; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | /// Basic UART driver instance | ||
| 1714 | #[allow(private_bounds)] | 1734 | #[allow(private_bounds)] |
| 1715 | pub trait BasicInstance: Peripheral<P = Self> + SealedBasicInstance + 'static + Send { | 1735 | pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send { |
| 1716 | /// Interrupt for this instance. | 1736 | /// Interrupt for this peripheral. |
| 1717 | type Interrupt: interrupt::typelevel::Interrupt; | 1737 | type Interrupt: interrupt::typelevel::Interrupt; |
| 1718 | } | 1738 | } |
| 1719 | 1739 | ||
| 1720 | /// Full UART driver instance | 1740 | pin_trait!(RxPin, Instance); |
| 1721 | #[allow(private_bounds)] | 1741 | pin_trait!(TxPin, Instance); |
| 1722 | pub trait FullInstance: SealedFullInstance {} | 1742 | pin_trait!(CtsPin, Instance); |
| 1743 | pin_trait!(RtsPin, Instance); | ||
| 1744 | pin_trait!(CkPin, Instance); | ||
| 1745 | pin_trait!(DePin, Instance); | ||
| 1723 | 1746 | ||
| 1724 | pin_trait!(RxPin, BasicInstance); | 1747 | dma_trait!(TxDma, Instance); |
| 1725 | pin_trait!(TxPin, BasicInstance); | 1748 | dma_trait!(RxDma, Instance); |
| 1726 | pin_trait!(CtsPin, BasicInstance); | ||
| 1727 | pin_trait!(RtsPin, BasicInstance); | ||
| 1728 | pin_trait!(CkPin, BasicInstance); | ||
| 1729 | pin_trait!(DePin, BasicInstance); | ||
| 1730 | |||
| 1731 | dma_trait!(TxDma, BasicInstance); | ||
| 1732 | dma_trait!(RxDma, BasicInstance); | ||
| 1733 | 1749 | ||
| 1734 | macro_rules! impl_usart { | 1750 | macro_rules! impl_usart { |
| 1735 | ($inst:ident, $irq:ident, $kind:expr) => { | 1751 | ($inst:ident, $irq:ident, $kind:expr) => { |
| 1736 | impl SealedBasicInstance for crate::peripherals::$inst { | 1752 | #[allow(private_interfaces)] |
| 1737 | const KIND: Kind = $kind; | 1753 | impl SealedInstance for crate::peripherals::$inst { |
| 1738 | 1754 | fn info() -> &'static Info { | |
| 1739 | fn regs() -> Regs { | 1755 | static INFO: Info = Info { |
| 1740 | unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } | 1756 | regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }, |
| 1757 | enable_bit: crate::peripherals::$inst::ENABLE_BIT, | ||
| 1758 | interrupt: crate::interrupt::typelevel::$irq::IRQ, | ||
| 1759 | kind: $kind, | ||
| 1760 | }; | ||
| 1761 | &INFO | ||
| 1741 | } | 1762 | } |
| 1742 | 1763 | ||
| 1743 | fn state() -> &'static crate::usart::State { | 1764 | fn state() -> &'static State { |
| 1744 | static STATE: crate::usart::State = crate::usart::State::new(); | 1765 | static STATE: State = State::new(); |
| 1745 | &STATE | 1766 | &STATE |
| 1746 | } | 1767 | } |
| 1747 | 1768 | ||
| 1748 | fn buffered_state() -> &'static buffered::State { | 1769 | fn buffered_state() -> &'static buffered::State { |
| 1749 | static STATE: buffered::State = buffered::State::new(); | 1770 | static BUFFERED_STATE: buffered::State = buffered::State::new(); |
| 1750 | &STATE | 1771 | &BUFFERED_STATE |
| 1751 | } | 1772 | } |
| 1752 | } | 1773 | } |
| 1753 | 1774 | ||
| 1754 | impl BasicInstance for peripherals::$inst { | 1775 | impl Instance for crate::peripherals::$inst { |
| 1755 | type Interrupt = crate::interrupt::typelevel::$irq; | 1776 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 1756 | } | 1777 | } |
| 1757 | }; | 1778 | }; |
| @@ -1761,16 +1782,7 @@ foreach_interrupt!( | |||
| 1761 | ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => { | 1782 | ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => { |
| 1762 | impl_usart!($inst, $irq, Kind::Lpuart); | 1783 | impl_usart!($inst, $irq, Kind::Lpuart); |
| 1763 | }; | 1784 | }; |
| 1764 | |||
| 1765 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { | 1785 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { |
| 1766 | impl_usart!($inst, $irq, Kind::Uart); | 1786 | impl_usart!($inst, $irq, Kind::Uart); |
| 1767 | |||
| 1768 | impl SealedFullInstance for peripherals::$inst { | ||
| 1769 | fn regs_uart() -> crate::pac::usart::Usart { | ||
| 1770 | crate::pac::$inst | ||
| 1771 | } | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | impl FullInstance for peripherals::$inst {} | ||
| 1775 | }; | 1787 | }; |
| 1776 | ); | 1788 | ); |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 0a6491bd5..f3a88b93f 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | ||
| 3 | use core::mem; | 2 | use core::mem; |
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 3 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 5 | use core::task::Poll; | 4 | use core::task::Poll; |
| @@ -7,20 +6,23 @@ use core::task::Poll; | |||
| 7 | use embassy_embedded_hal::SetConfig; | 6 | use embassy_embedded_hal::SetConfig; |
| 8 | use futures_util::future::{select, Either}; | 7 | use futures_util::future::{select, Either}; |
| 9 | 8 | ||
| 10 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx}; | 9 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx}; |
| 11 | use crate::dma::ReadableRingBuffer; | 10 | use crate::dma::ReadableRingBuffer; |
| 12 | use crate::mode::Async; | 11 | use crate::mode::Async; |
| 12 | use crate::time::Hertz; | ||
| 13 | use crate::usart::{Regs, Sr}; | 13 | use crate::usart::{Regs, Sr}; |
| 14 | 14 | ||
| 15 | /// Rx-only Ring-buffered UART Driver | 15 | /// Rx-only Ring-buffered UART Driver |
| 16 | /// | 16 | /// |
| 17 | /// Created with [UartRx::into_ring_buffered] | 17 | /// Created with [UartRx::into_ring_buffered] |
| 18 | pub struct RingBufferedUartRx<'d, T: BasicInstance> { | 18 | pub struct RingBufferedUartRx<'d> { |
| 19 | _phantom: PhantomData<T>, | 19 | info: &'static Info, |
| 20 | state: &'static State, | ||
| 21 | kernel_clock: Hertz, | ||
| 20 | ring_buf: ReadableRingBuffer<'d, u8>, | 22 | ring_buf: ReadableRingBuffer<'d, u8>, |
| 21 | } | 23 | } |
| 22 | 24 | ||
| 23 | impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> { | 25 | impl<'d> SetConfig for RingBufferedUartRx<'d> { |
| 24 | type Config = Config; | 26 | type Config = Config; |
| 25 | type ConfigError = ConfigError; | 27 | type ConfigError = ConfigError; |
| 26 | 28 | ||
| @@ -29,11 +31,11 @@ impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> { | |||
| 29 | } | 31 | } |
| 30 | } | 32 | } |
| 31 | 33 | ||
| 32 | impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | 34 | impl<'d> UartRx<'d, Async> { |
| 33 | /// Turn the `UartRx` into a buffered uart which can continously receive in the background | 35 | /// Turn the `UartRx` into a buffered uart which can continously receive in the background |
| 34 | /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the | 36 | /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the |
| 35 | /// DMA controller, and must be large enough to prevent overflows. | 37 | /// DMA controller, and must be large enough to prevent overflows. |
| 36 | pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> { | 38 | pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d> { |
| 37 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 39 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 38 | 40 | ||
| 39 | let opts = Default::default(); | 41 | let opts = Default::default(); |
| @@ -43,19 +45,24 @@ impl<'d, T: BasicInstance> UartRx<'d, T, Async> { | |||
| 43 | let request = rx_dma.request; | 45 | let request = rx_dma.request; |
| 44 | let rx_dma = unsafe { rx_dma.channel.clone_unchecked() }; | 46 | let rx_dma = unsafe { rx_dma.channel.clone_unchecked() }; |
| 45 | 47 | ||
| 46 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; | 48 | let info = self.info; |
| 49 | let state = self.state; | ||
| 50 | let kernel_clock = self.kernel_clock; | ||
| 51 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; | ||
| 47 | 52 | ||
| 48 | // Don't disable the clock | 53 | // Don't disable the clock |
| 49 | mem::forget(self); | 54 | mem::forget(self); |
| 50 | 55 | ||
| 51 | RingBufferedUartRx { | 56 | RingBufferedUartRx { |
| 52 | _phantom: PhantomData, | 57 | info, |
| 58 | state, | ||
| 59 | kernel_clock, | ||
| 53 | ring_buf, | 60 | ring_buf, |
| 54 | } | 61 | } |
| 55 | } | 62 | } |
| 56 | } | 63 | } |
| 57 | 64 | ||
| 58 | impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | 65 | impl<'d> RingBufferedUartRx<'d> { |
| 59 | /// Clear the ring buffer and start receiving in the background | 66 | /// Clear the ring buffer and start receiving in the background |
| 60 | pub fn start(&mut self) -> Result<(), Error> { | 67 | pub fn start(&mut self) -> Result<(), Error> { |
| 61 | // Clear the ring buffer so that it is ready to receive data | 68 | // Clear the ring buffer so that it is ready to receive data |
| @@ -74,7 +81,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 74 | 81 | ||
| 75 | /// Reconfigure the driver | 82 | /// Reconfigure the driver |
| 76 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | 83 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { |
| 77 | reconfigure::<T>(config) | 84 | reconfigure(self.info, self.kernel_clock, config) |
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | /// Start uart background receive | 87 | /// Start uart background receive |
| @@ -85,7 +92,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 85 | // start the dma controller | 92 | // start the dma controller |
| 86 | self.ring_buf.start(); | 93 | self.ring_buf.start(); |
| 87 | 94 | ||
| 88 | let r = T::regs(); | 95 | let r = self.info.regs; |
| 89 | // clear all interrupts and DMA Rx Request | 96 | // clear all interrupts and DMA Rx Request |
| 90 | r.cr1().modify(|w| { | 97 | r.cr1().modify(|w| { |
| 91 | // disable RXNE interrupt | 98 | // disable RXNE interrupt |
| @@ -107,7 +114,7 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 107 | fn teardown_uart(&mut self) { | 114 | fn teardown_uart(&mut self) { |
| 108 | self.ring_buf.request_stop(); | 115 | self.ring_buf.request_stop(); |
| 109 | 116 | ||
| 110 | let r = T::regs(); | 117 | let r = self.info.regs; |
| 111 | // clear all interrupts and DMA Rx Request | 118 | // clear all interrupts and DMA Rx Request |
| 112 | r.cr1().modify(|w| { | 119 | r.cr1().modify(|w| { |
| 113 | // disable RXNE interrupt | 120 | // disable RXNE interrupt |
| @@ -136,14 +143,14 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 136 | /// Receive in the background is terminated if an error is returned. | 143 | /// Receive in the background is terminated if an error is returned. |
| 137 | /// It must then manually be started again by calling `start()` or by re-calling `read()`. | 144 | /// It must then manually be started again by calling `start()` or by re-calling `read()`. |
| 138 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 145 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| 139 | let r = T::regs(); | 146 | let r = self.info.regs; |
| 140 | 147 | ||
| 141 | // Start background receive if it was not already started | 148 | // Start background receive if it was not already started |
| 142 | if !r.cr3().read().dmar() { | 149 | if !r.cr3().read().dmar() { |
| 143 | self.start()?; | 150 | self.start()?; |
| 144 | } | 151 | } |
| 145 | 152 | ||
| 146 | check_for_errors(clear_idle_flag(T::regs()))?; | 153 | check_for_errors(clear_idle_flag(r))?; |
| 147 | 154 | ||
| 148 | loop { | 155 | loop { |
| 149 | match self.ring_buf.read(buf) { | 156 | match self.ring_buf.read(buf) { |
| @@ -184,15 +191,15 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 184 | }); | 191 | }); |
| 185 | 192 | ||
| 186 | // Future which completes when idle line is detected | 193 | // Future which completes when idle line is detected |
| 194 | let s = self.state; | ||
| 187 | let uart = poll_fn(|cx| { | 195 | let uart = poll_fn(|cx| { |
| 188 | let s = T::state(); | ||
| 189 | s.rx_waker.register(cx.waker()); | 196 | s.rx_waker.register(cx.waker()); |
| 190 | 197 | ||
| 191 | compiler_fence(Ordering::SeqCst); | 198 | compiler_fence(Ordering::SeqCst); |
| 192 | 199 | ||
| 193 | // Critical section is needed so that IDLE isn't set after | 200 | // Critical section is needed so that IDLE isn't set after |
| 194 | // our read but before we clear it. | 201 | // our read but before we clear it. |
| 195 | let sr = critical_section::with(|_| clear_idle_flag(T::regs())); | 202 | let sr = critical_section::with(|_| clear_idle_flag(self.info.regs)); |
| 196 | 203 | ||
| 197 | check_for_errors(sr)?; | 204 | check_for_errors(sr)?; |
| 198 | 205 | ||
| @@ -211,13 +218,13 @@ impl<'d, T: BasicInstance> RingBufferedUartRx<'d, T> { | |||
| 211 | } | 218 | } |
| 212 | } | 219 | } |
| 213 | 220 | ||
| 214 | impl<T: BasicInstance> Drop for RingBufferedUartRx<'_, T> { | 221 | impl Drop for RingBufferedUartRx<'_> { |
| 215 | fn drop(&mut self) { | 222 | fn drop(&mut self) { |
| 216 | self.teardown_uart(); | 223 | self.teardown_uart(); |
| 217 | 224 | super::drop_tx_rx(self.info, self.state); | |
| 218 | T::disable(); | ||
| 219 | } | 225 | } |
| 220 | } | 226 | } |
| 227 | |||
| 221 | /// Return an error result if the Sr register has errors | 228 | /// Return an error result if the Sr register has errors |
| 222 | fn check_for_errors(s: Sr) -> Result<(), Error> { | 229 | fn check_for_errors(s: Sr) -> Result<(), Error> { |
| 223 | if s.pe() { | 230 | if s.pe() { |
| @@ -248,17 +255,11 @@ fn clear_idle_flag(r: Regs) -> Sr { | |||
| 248 | sr | 255 | sr |
| 249 | } | 256 | } |
| 250 | 257 | ||
| 251 | impl<T> embedded_io_async::ErrorType for RingBufferedUartRx<'_, T> | 258 | impl embedded_io_async::ErrorType for RingBufferedUartRx<'_> { |
| 252 | where | ||
| 253 | T: BasicInstance, | ||
| 254 | { | ||
| 255 | type Error = Error; | 259 | type Error = Error; |
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | impl<T> embedded_io_async::Read for RingBufferedUartRx<'_, T> | 262 | impl embedded_io_async::Read for RingBufferedUartRx<'_> { |
| 259 | where | ||
| 260 | T: BasicInstance, | ||
| 261 | { | ||
| 262 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 263 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 263 | self.read(buf).await | 264 | self.read(buf).await |
| 264 | } | 265 | } |
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs index 77b4caa9e..d26c5003c 100644 --- a/examples/stm32h5/src/bin/usart_split.rs +++ b/examples/stm32h5/src/bin/usart_split.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::mode::Async; | 6 | use embassy_stm32::mode::Async; |
| 7 | use embassy_stm32::peripherals::UART7; | ||
| 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 7 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 9 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| @@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 41 | async fn reader(mut rx: UartRx<'static, UART7, Async>) { | 40 | async fn reader(mut rx: UartRx<'static, Async>) { |
| 42 | let mut buf = [0; 8]; | 41 | let mut buf = [0; 8]; |
| 43 | loop { | 42 | loop { |
| 44 | info!("reading..."); | 43 | info!("reading..."); |
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs index 4ad8e77ce..2bb58be5e 100644 --- a/examples/stm32h7/src/bin/usart_split.rs +++ b/examples/stm32h7/src/bin/usart_split.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::mode::Async; | 6 | use embassy_stm32::mode::Async; |
| 7 | use embassy_stm32::peripherals::UART7; | ||
| 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 7 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 9 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| @@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 41 | async fn reader(mut rx: UartRx<'static, UART7, Async>) { | 40 | async fn reader(mut rx: UartRx<'static, Async>) { |
| 42 | let mut buf = [0; 8]; | 41 | let mut buf = [0; 8]; |
| 43 | loop { | 42 | loop { |
| 44 | info!("reading..."); | 43 | info!("reading..."); |
diff --git a/examples/stm32h7rs/src/bin/usart_split.rs b/examples/stm32h7rs/src/bin/usart_split.rs index 77b4caa9e..d26c5003c 100644 --- a/examples/stm32h7rs/src/bin/usart_split.rs +++ b/examples/stm32h7rs/src/bin/usart_split.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::mode::Async; | 6 | use embassy_stm32::mode::Async; |
| 7 | use embassy_stm32::peripherals::UART7; | ||
| 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 7 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 9 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| @@ -38,7 +37,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 41 | async fn reader(mut rx: UartRx<'static, UART7, Async>) { | 40 | async fn reader(mut rx: UartRx<'static, Async>) { |
| 42 | let mut buf = [0; 8]; | 41 | let mut buf = [0; 8]; |
| 43 | loop { | 42 | loop { |
| 44 | info!("reading..."); | 43 | info!("reading..."); |
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs index 908452eaf..ea1e52358 100644 --- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs +++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs | |||
| @@ -52,7 +52,7 @@ async fn main(spawner: Spawner) { | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | #[embassy_executor::task] | 54 | #[embassy_executor::task] |
| 55 | async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) { | 55 | async fn transmit_task(mut tx: UartTx<'static, Async>) { |
| 56 | // workaround https://github.com/embassy-rs/embassy/issues/1426 | 56 | // workaround https://github.com/embassy-rs/embassy/issues/1426 |
| 57 | Timer::after_millis(100).await; | 57 | Timer::after_millis(100).await; |
| 58 | 58 | ||
| @@ -75,7 +75,7 @@ async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) { | |||
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | #[embassy_executor::task] | 77 | #[embassy_executor::task] |
| 78 | async fn receive_task(mut rx: RingBufferedUartRx<'static, peris::UART>) { | 78 | async fn receive_task(mut rx: RingBufferedUartRx<'static>) { |
| 79 | info!("Ready to receive..."); | 79 | info!("Ready to receive..."); |
| 80 | 80 | ||
| 81 | let mut rng = ChaCha8Rng::seed_from_u64(1337); | 81 | let mut rng = ChaCha8Rng::seed_from_u64(1337); |
