diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-23 01:45:10 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-23 01:45:10 +0100 |
| commit | a6a5d9913cda2ecfe89b63fa0bcf7afaebc2dac0 (patch) | |
| tree | 14124a6f34d351a979cb110a0ce566b588f5d272 /embassy-nrf/src | |
| parent | 5b7e2d88265b5633fa53047961598fbc38bffed0 (diff) | |
| parent | 2855bb69680a42a721fe88168657ea1e634e8766 (diff) | |
Merge branch 'main' into stm32l0-reset-rtc
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 755 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 2 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 23 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 88 |
4 files changed, 520 insertions, 348 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index fb72422bd..b04c96e09 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -17,29 +17,26 @@ use core::task::Poll; | |||
| 17 | 17 | ||
| 18 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; | 18 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; |
| 19 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 19 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 20 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 21 | // Re-export SVD variants to allow user to directly set values | 20 | // Re-export SVD variants to allow user to directly set values |
| 22 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 21 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| 23 | 22 | ||
| 24 | use crate::gpio::sealed::Pin; | 23 | use crate::gpio::sealed::Pin; |
| 25 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 24 | use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; |
| 26 | use crate::interrupt::typelevel::Interrupt; | 25 | use crate::interrupt::typelevel::Interrupt; |
| 27 | use crate::ppi::{ | 26 | use crate::ppi::{ |
| 28 | self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, | 27 | self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, |
| 29 | }; | 28 | }; |
| 30 | use crate::timer::{Instance as TimerInstance, Timer}; | 29 | use crate::timer::{Instance as TimerInstance, Timer}; |
| 31 | use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance}; | 30 | use crate::uarte::{configure, drop_tx_rx, Config, Instance as UarteInstance}; |
| 32 | use crate::{interrupt, pac, Peripheral}; | 31 | use crate::{interrupt, pac, Peripheral}; |
| 33 | 32 | ||
| 34 | mod sealed { | 33 | mod sealed { |
| 35 | use super::*; | 34 | use super::*; |
| 36 | 35 | ||
| 37 | pub struct State { | 36 | pub struct State { |
| 38 | pub tx_waker: AtomicWaker, | ||
| 39 | pub tx_buf: RingBuffer, | 37 | pub tx_buf: RingBuffer, |
| 40 | pub tx_count: AtomicUsize, | 38 | pub tx_count: AtomicUsize, |
| 41 | 39 | ||
| 42 | pub rx_waker: AtomicWaker, | ||
| 43 | pub rx_buf: RingBuffer, | 40 | pub rx_buf: RingBuffer, |
| 44 | pub rx_started: AtomicBool, | 41 | pub rx_started: AtomicBool, |
| 45 | pub rx_started_count: AtomicU8, | 42 | pub rx_started_count: AtomicU8, |
| @@ -61,11 +58,9 @@ pub(crate) use sealed::State; | |||
| 61 | impl State { | 58 | impl State { |
| 62 | pub(crate) const fn new() -> Self { | 59 | pub(crate) const fn new() -> Self { |
| 63 | Self { | 60 | Self { |
| 64 | tx_waker: AtomicWaker::new(), | ||
| 65 | tx_buf: RingBuffer::new(), | 61 | tx_buf: RingBuffer::new(), |
| 66 | tx_count: AtomicUsize::new(0), | 62 | tx_count: AtomicUsize::new(0), |
| 67 | 63 | ||
| 68 | rx_waker: AtomicWaker::new(), | ||
| 69 | rx_buf: RingBuffer::new(), | 64 | rx_buf: RingBuffer::new(), |
| 70 | rx_started: AtomicBool::new(false), | 65 | rx_started: AtomicBool::new(false), |
| 71 | rx_started_count: AtomicU8::new(0), | 66 | rx_started_count: AtomicU8::new(0), |
| @@ -84,128 +79,131 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt | |||
| 84 | unsafe fn on_interrupt() { | 79 | unsafe fn on_interrupt() { |
| 85 | //trace!("irq: start"); | 80 | //trace!("irq: start"); |
| 86 | let r = U::regs(); | 81 | let r = U::regs(); |
| 82 | let ss = U::state(); | ||
| 87 | let s = U::buffered_state(); | 83 | let s = U::buffered_state(); |
| 88 | 84 | ||
| 89 | let buf_len = s.rx_buf.len(); | 85 | if let Some(mut rx) = unsafe { s.rx_buf.try_writer() } { |
| 90 | let half_len = buf_len / 2; | 86 | let buf_len = s.rx_buf.len(); |
| 91 | let mut tx = unsafe { s.tx_buf.reader() }; | 87 | let half_len = buf_len / 2; |
| 92 | let mut rx = unsafe { s.rx_buf.writer() }; | ||
| 93 | 88 | ||
| 94 | if r.events_error.read().bits() != 0 { | 89 | if r.events_error.read().bits() != 0 { |
| 95 | r.events_error.reset(); | 90 | r.events_error.reset(); |
| 96 | let errs = r.errorsrc.read(); | 91 | let errs = r.errorsrc.read(); |
| 97 | r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) }); | 92 | r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) }); |
| 98 | 93 | ||
| 99 | if errs.overrun().bit() { | 94 | if errs.overrun().bit() { |
| 100 | panic!("BufferedUarte overrun"); | 95 | panic!("BufferedUarte overrun"); |
| 96 | } | ||
| 101 | } | 97 | } |
| 102 | } | ||
| 103 | 98 | ||
| 104 | // Received some bytes, wake task. | 99 | // Received some bytes, wake task. |
| 105 | if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 { | 100 | if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 { |
| 106 | r.intenclr.write(|w| w.rxdrdy().clear()); | 101 | r.intenclr.write(|w| w.rxdrdy().clear()); |
| 107 | r.events_rxdrdy.reset(); | 102 | r.events_rxdrdy.reset(); |
| 108 | s.rx_waker.wake(); | 103 | ss.rx_waker.wake(); |
| 109 | } | 104 | } |
| 110 | 105 | ||
| 111 | if r.events_endrx.read().bits() != 0 { | 106 | if r.events_endrx.read().bits() != 0 { |
| 112 | //trace!(" irq_rx: endrx"); | 107 | //trace!(" irq_rx: endrx"); |
| 113 | r.events_endrx.reset(); | 108 | r.events_endrx.reset(); |
| 114 | 109 | ||
| 115 | let val = s.rx_ended_count.load(Ordering::Relaxed); | 110 | let val = s.rx_ended_count.load(Ordering::Relaxed); |
| 116 | s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); | 111 | s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); |
| 117 | } | 112 | } |
| 118 | 113 | ||
| 119 | if r.events_rxstarted.read().bits() != 0 || !s.rx_started.load(Ordering::Relaxed) { | 114 | if r.events_rxstarted.read().bits() != 0 || !s.rx_started.load(Ordering::Relaxed) { |
| 120 | //trace!(" irq_rx: rxstarted"); | 115 | //trace!(" irq_rx: rxstarted"); |
| 121 | let (ptr, len) = rx.push_buf(); | 116 | let (ptr, len) = rx.push_buf(); |
| 122 | if len >= half_len { | 117 | if len >= half_len { |
| 123 | r.events_rxstarted.reset(); | 118 | r.events_rxstarted.reset(); |
| 124 | 119 | ||
| 125 | //trace!(" irq_rx: starting second {:?}", half_len); | 120 | //trace!(" irq_rx: starting second {:?}", half_len); |
| 126 | 121 | ||
| 127 | // Set up the DMA read | 122 | // Set up the DMA read |
| 128 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 123 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 129 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); | 124 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); |
| 130 | 125 | ||
| 131 | let chn = s.rx_ppi_ch.load(Ordering::Relaxed); | 126 | let chn = s.rx_ppi_ch.load(Ordering::Relaxed); |
| 132 | 127 | ||
| 133 | // Enable endrx -> startrx PPI channel. | 128 | // Enable endrx -> startrx PPI channel. |
| 134 | // From this point on, if endrx happens, startrx is automatically fired. | 129 | // From this point on, if endrx happens, startrx is automatically fired. |
| 135 | ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) }); | 130 | ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) }); |
| 136 | 131 | ||
| 137 | // It is possible that endrx happened BEFORE enabling the PPI. In this case | 132 | // It is possible that endrx happened BEFORE enabling the PPI. In this case |
| 138 | // the PPI channel doesn't trigger, and we'd hang. We have to detect this | 133 | // the PPI channel doesn't trigger, and we'd hang. We have to detect this |
| 139 | // and manually start. | 134 | // and manually start. |
| 140 | 135 | ||
| 141 | // check again in case endrx has happened between the last check and now. | 136 | // check again in case endrx has happened between the last check and now. |
| 142 | if r.events_endrx.read().bits() != 0 { | 137 | if r.events_endrx.read().bits() != 0 { |
| 143 | //trace!(" irq_rx: endrx"); | 138 | //trace!(" irq_rx: endrx"); |
| 144 | r.events_endrx.reset(); | 139 | r.events_endrx.reset(); |
| 145 | 140 | ||
| 146 | let val = s.rx_ended_count.load(Ordering::Relaxed); | 141 | let val = s.rx_ended_count.load(Ordering::Relaxed); |
| 147 | s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); | 142 | s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed); |
| 148 | } | 143 | } |
| 149 | 144 | ||
| 150 | let rx_ended = s.rx_ended_count.load(Ordering::Relaxed); | 145 | let rx_ended = s.rx_ended_count.load(Ordering::Relaxed); |
| 151 | let rx_started = s.rx_started_count.load(Ordering::Relaxed); | 146 | let rx_started = s.rx_started_count.load(Ordering::Relaxed); |
| 152 | 147 | ||
| 153 | // If we started the same amount of transfers as ended, the last rxend has | 148 | // If we started the same amount of transfers as ended, the last rxend has |
| 154 | // already occured. | 149 | // already occured. |
| 155 | let rxend_happened = rx_started == rx_ended; | 150 | let rxend_happened = rx_started == rx_ended; |
| 156 | 151 | ||
| 157 | // Check if the PPI channel is still enabled. The PPI channel disables itself | 152 | // Check if the PPI channel is still enabled. The PPI channel disables itself |
| 158 | // when it fires, so if it's still enabled it hasn't fired. | 153 | // when it fires, so if it's still enabled it hasn't fired. |
| 159 | let ppi_ch_enabled = ppi::regs().chen.read().bits() & (1 << chn) != 0; | 154 | let ppi_ch_enabled = ppi::regs().chen.read().bits() & (1 << chn) != 0; |
| 160 | 155 | ||
| 161 | // if rxend happened, and the ppi channel hasn't fired yet, the rxend got missed. | 156 | // if rxend happened, and the ppi channel hasn't fired yet, the rxend got missed. |
| 162 | // this condition also naturally matches if `!started`, needed to kickstart the DMA. | 157 | // this condition also naturally matches if `!started`, needed to kickstart the DMA. |
| 163 | if rxend_happened && ppi_ch_enabled { | 158 | if rxend_happened && ppi_ch_enabled { |
| 164 | //trace!("manually starting."); | 159 | //trace!("manually starting."); |
| 165 | 160 | ||
| 166 | // disable the ppi ch, it's of no use anymore. | 161 | // disable the ppi ch, it's of no use anymore. |
| 167 | ppi::regs().chenclr.write(|w| unsafe { w.bits(1 << chn) }); | 162 | ppi::regs().chenclr.write(|w| unsafe { w.bits(1 << chn) }); |
| 168 | 163 | ||
| 169 | // manually start | 164 | // manually start |
| 170 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 165 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 171 | } | 166 | } |
| 172 | 167 | ||
| 173 | rx.push_done(half_len); | 168 | rx.push_done(half_len); |
| 174 | 169 | ||
| 175 | s.rx_started_count.store(rx_started.wrapping_add(1), Ordering::Relaxed); | 170 | s.rx_started_count.store(rx_started.wrapping_add(1), Ordering::Relaxed); |
| 176 | s.rx_started.store(true, Ordering::Relaxed); | 171 | s.rx_started.store(true, Ordering::Relaxed); |
| 177 | } else { | 172 | } else { |
| 178 | //trace!(" irq_rx: rxstarted no buf"); | 173 | //trace!(" irq_rx: rxstarted no buf"); |
| 179 | r.intenclr.write(|w| w.rxstarted().clear()); | 174 | r.intenclr.write(|w| w.rxstarted().clear()); |
| 175 | } | ||
| 180 | } | 176 | } |
| 181 | } | 177 | } |
| 182 | 178 | ||
| 183 | // ============================= | 179 | // ============================= |
| 184 | 180 | ||
| 185 | // TX end | 181 | if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } { |
| 186 | if r.events_endtx.read().bits() != 0 { | 182 | // TX end |
| 187 | r.events_endtx.reset(); | 183 | if r.events_endtx.read().bits() != 0 { |
| 184 | r.events_endtx.reset(); | ||
| 188 | 185 | ||
| 189 | let n = s.tx_count.load(Ordering::Relaxed); | 186 | let n = s.tx_count.load(Ordering::Relaxed); |
| 190 | //trace!(" irq_tx: endtx {:?}", n); | 187 | //trace!(" irq_tx: endtx {:?}", n); |
| 191 | tx.pop_done(n); | 188 | tx.pop_done(n); |
| 192 | s.tx_waker.wake(); | 189 | ss.tx_waker.wake(); |
| 193 | s.tx_count.store(0, Ordering::Relaxed); | 190 | s.tx_count.store(0, Ordering::Relaxed); |
| 194 | } | 191 | } |
| 195 | 192 | ||
| 196 | // If not TXing, start. | 193 | // If not TXing, start. |
| 197 | if s.tx_count.load(Ordering::Relaxed) == 0 { | 194 | if s.tx_count.load(Ordering::Relaxed) == 0 { |
| 198 | let (ptr, len) = tx.pop_buf(); | 195 | let (ptr, len) = tx.pop_buf(); |
| 199 | if len != 0 { | 196 | if len != 0 { |
| 200 | //trace!(" irq_tx: starting {:?}", len); | 197 | //trace!(" irq_tx: starting {:?}", len); |
| 201 | s.tx_count.store(len, Ordering::Relaxed); | 198 | s.tx_count.store(len, Ordering::Relaxed); |
| 202 | 199 | ||
| 203 | // Set up the DMA write | 200 | // Set up the DMA write |
| 204 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 201 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 205 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 202 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 206 | 203 | ||
| 207 | // Start UARTE Transmit transaction | 204 | // Start UARTE Transmit transaction |
| 208 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 205 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); |
| 206 | } | ||
| 209 | } | 207 | } |
| 210 | } | 208 | } |
| 211 | 209 | ||
| @@ -215,11 +213,8 @@ impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for Interrupt | |||
| 215 | 213 | ||
| 216 | /// Buffered UARTE driver. | 214 | /// Buffered UARTE driver. |
| 217 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { | 215 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { |
| 218 | _peri: PeripheralRef<'d, U>, | 216 | tx: BufferedUarteTx<'d, U>, |
| 219 | timer: Timer<'d, T>, | 217 | rx: BufferedUarteRx<'d, U, T>, |
| 220 | _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>, | ||
| 221 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>, | ||
| 222 | _ppi_group: PpiGroup<'d, AnyGroup>, | ||
| 223 | } | 218 | } |
| 224 | 219 | ||
| 225 | impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} | 220 | impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} |
| @@ -243,7 +238,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 243 | rx_buffer: &'d mut [u8], | 238 | rx_buffer: &'d mut [u8], |
| 244 | tx_buffer: &'d mut [u8], | 239 | tx_buffer: &'d mut [u8], |
| 245 | ) -> Self { | 240 | ) -> Self { |
| 246 | into_ref!(rxd, txd, ppi_ch1, ppi_ch2, ppi_group); | 241 | into_ref!(uarte, timer, rxd, txd, ppi_ch1, ppi_ch2, ppi_group); |
| 247 | Self::new_inner( | 242 | Self::new_inner( |
| 248 | uarte, | 243 | uarte, |
| 249 | timer, | 244 | timer, |
| @@ -280,7 +275,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 280 | rx_buffer: &'d mut [u8], | 275 | rx_buffer: &'d mut [u8], |
| 281 | tx_buffer: &'d mut [u8], | 276 | tx_buffer: &'d mut [u8], |
| 282 | ) -> Self { | 277 | ) -> Self { |
| 283 | into_ref!(rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group); | 278 | into_ref!(uarte, timer, rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group); |
| 284 | Self::new_inner( | 279 | Self::new_inner( |
| 285 | uarte, | 280 | uarte, |
| 286 | timer, | 281 | timer, |
| @@ -298,8 +293,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 298 | } | 293 | } |
| 299 | 294 | ||
| 300 | fn new_inner( | 295 | fn new_inner( |
| 301 | peri: impl Peripheral<P = U> + 'd, | 296 | peri: PeripheralRef<'d, U>, |
| 302 | timer: impl Peripheral<P = T> + 'd, | 297 | timer: PeripheralRef<'d, T>, |
| 303 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, | 298 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, |
| 304 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, | 299 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, |
| 305 | ppi_group: PeripheralRef<'d, AnyGroup>, | 300 | ppi_group: PeripheralRef<'d, AnyGroup>, |
| @@ -311,16 +306,127 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 311 | rx_buffer: &'d mut [u8], | 306 | rx_buffer: &'d mut [u8], |
| 312 | tx_buffer: &'d mut [u8], | 307 | tx_buffer: &'d mut [u8], |
| 313 | ) -> Self { | 308 | ) -> Self { |
| 314 | into_ref!(peri, timer); | 309 | configure(U::regs(), config, cts.is_some()); |
| 315 | 310 | ||
| 316 | assert!(rx_buffer.len() % 2 == 0); | 311 | let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer); |
| 312 | let rx = BufferedUarteRx::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer); | ||
| 317 | 313 | ||
| 314 | U::Interrupt::pend(); | ||
| 315 | unsafe { U::Interrupt::enable() }; | ||
| 316 | |||
| 317 | U::state().tx_rx_refcount.store(2, Ordering::Relaxed); | ||
| 318 | |||
| 319 | Self { tx, rx } | ||
| 320 | } | ||
| 321 | |||
| 322 | /// Adjust the baud rate to the provided value. | ||
| 323 | pub fn set_baudrate(&mut self, baudrate: Baudrate) { | ||
| 318 | let r = U::regs(); | 324 | let r = U::regs(); |
| 325 | r.baudrate.write(|w| w.baudrate().variant(baudrate)); | ||
| 326 | } | ||
| 319 | 327 | ||
| 320 | let hwfc = cts.is_some(); | 328 | /// Split the UART in reader and writer parts. |
| 329 | /// | ||
| 330 | /// This allows reading and writing concurrently from independent tasks. | ||
| 331 | pub fn split(self) -> (BufferedUarteRx<'d, U, T>, BufferedUarteTx<'d, U>) { | ||
| 332 | (self.rx, self.tx) | ||
| 333 | } | ||
| 321 | 334 | ||
| 322 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | 335 | /// Split the UART in reader and writer parts, by reference. |
| 323 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | 336 | /// |
| 337 | /// The returned halves borrow from `self`, so you can drop them and go back to using | ||
| 338 | /// the "un-split" `self`. This allows temporarily splitting the UART. | ||
| 339 | pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d, U, T>, &mut BufferedUarteTx<'d, U>) { | ||
| 340 | (&mut self.rx, &mut self.tx) | ||
| 341 | } | ||
| 342 | |||
| 343 | /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. | ||
| 344 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | ||
| 345 | self.rx.read(buf).await | ||
| 346 | } | ||
| 347 | |||
| 348 | /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. | ||
| 349 | pub async fn fill_buf(&mut self) -> Result<&[u8], Error> { | ||
| 350 | self.rx.fill_buf().await | ||
| 351 | } | ||
| 352 | |||
| 353 | /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. | ||
| 354 | pub fn consume(&mut self, amt: usize) { | ||
| 355 | self.rx.consume(amt) | ||
| 356 | } | ||
| 357 | |||
| 358 | /// Write a buffer into this writer, returning how many bytes were written. | ||
| 359 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | ||
| 360 | self.tx.write(buf).await | ||
| 361 | } | ||
| 362 | |||
| 363 | /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. | ||
| 364 | pub async fn flush(&mut self) -> Result<(), Error> { | ||
| 365 | self.tx.flush().await | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | /// Reader part of the buffered UARTE driver. | ||
| 370 | pub struct BufferedUarteTx<'d, U: UarteInstance> { | ||
| 371 | _peri: PeripheralRef<'d, U>, | ||
| 372 | } | ||
| 373 | |||
| 374 | impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { | ||
| 375 | /// Create a new BufferedUarteTx without hardware flow control. | ||
| 376 | pub fn new( | ||
| 377 | uarte: impl Peripheral<P = U> + 'd, | ||
| 378 | _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd, | ||
| 379 | txd: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 380 | config: Config, | ||
| 381 | tx_buffer: &'d mut [u8], | ||
| 382 | ) -> Self { | ||
| 383 | into_ref!(uarte, txd); | ||
| 384 | Self::new_inner(uarte, txd.map_into(), None, config, tx_buffer) | ||
| 385 | } | ||
| 386 | |||
| 387 | /// Create a new BufferedUarte with hardware flow control (RTS/CTS) | ||
| 388 | /// | ||
| 389 | /// # Panics | ||
| 390 | /// | ||
| 391 | /// Panics if `rx_buffer.len()` is odd. | ||
| 392 | pub fn new_with_cts( | ||
| 393 | uarte: impl Peripheral<P = U> + 'd, | ||
| 394 | _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd, | ||
| 395 | txd: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 396 | cts: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 397 | config: Config, | ||
| 398 | tx_buffer: &'d mut [u8], | ||
| 399 | ) -> Self { | ||
| 400 | into_ref!(uarte, txd, cts); | ||
| 401 | Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config, tx_buffer) | ||
| 402 | } | ||
| 403 | |||
| 404 | fn new_inner( | ||
| 405 | peri: PeripheralRef<'d, U>, | ||
| 406 | txd: PeripheralRef<'d, AnyPin>, | ||
| 407 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 408 | config: Config, | ||
| 409 | tx_buffer: &'d mut [u8], | ||
| 410 | ) -> Self { | ||
| 411 | configure(U::regs(), config, cts.is_some()); | ||
| 412 | |||
| 413 | let this = Self::new_innerer(peri, txd, cts, tx_buffer); | ||
| 414 | |||
| 415 | U::Interrupt::pend(); | ||
| 416 | unsafe { U::Interrupt::enable() }; | ||
| 417 | |||
| 418 | U::state().tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 419 | |||
| 420 | this | ||
| 421 | } | ||
| 422 | |||
| 423 | fn new_innerer( | ||
| 424 | peri: PeripheralRef<'d, U>, | ||
| 425 | txd: PeripheralRef<'d, AnyPin>, | ||
| 426 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 427 | tx_buffer: &'d mut [u8], | ||
| 428 | ) -> Self { | ||
| 429 | let r = U::regs(); | ||
| 324 | 430 | ||
| 325 | txd.set_high(); | 431 | txd.set_high(); |
| 326 | txd.conf().write(|w| w.dir().output().drive().h0h1()); | 432 | txd.conf().write(|w| w.dir().output().drive().h0h1()); |
| @@ -331,6 +437,203 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 331 | } | 437 | } |
| 332 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | 438 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 333 | 439 | ||
| 440 | // Initialize state | ||
| 441 | let s = U::buffered_state(); | ||
| 442 | s.tx_count.store(0, Ordering::Relaxed); | ||
| 443 | let len = tx_buffer.len(); | ||
| 444 | unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | ||
| 445 | |||
| 446 | r.events_txstarted.reset(); | ||
| 447 | |||
| 448 | // Enable interrupts | ||
| 449 | r.intenset.write(|w| { | ||
| 450 | w.endtx().set(); | ||
| 451 | w | ||
| 452 | }); | ||
| 453 | |||
| 454 | Self { _peri: peri } | ||
| 455 | } | ||
| 456 | |||
| 457 | /// Write a buffer into this writer, returning how many bytes were written. | ||
| 458 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | ||
| 459 | poll_fn(move |cx| { | ||
| 460 | //trace!("poll_write: {:?}", buf.len()); | ||
| 461 | let ss = U::state(); | ||
| 462 | let s = U::buffered_state(); | ||
| 463 | let mut tx = unsafe { s.tx_buf.writer() }; | ||
| 464 | |||
| 465 | let tx_buf = tx.push_slice(); | ||
| 466 | if tx_buf.is_empty() { | ||
| 467 | //trace!("poll_write: pending"); | ||
| 468 | ss.tx_waker.register(cx.waker()); | ||
| 469 | return Poll::Pending; | ||
| 470 | } | ||
| 471 | |||
| 472 | let n = min(tx_buf.len(), buf.len()); | ||
| 473 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 474 | tx.push_done(n); | ||
| 475 | |||
| 476 | //trace!("poll_write: queued {:?}", n); | ||
| 477 | |||
| 478 | compiler_fence(Ordering::SeqCst); | ||
| 479 | U::Interrupt::pend(); | ||
| 480 | |||
| 481 | Poll::Ready(Ok(n)) | ||
| 482 | }) | ||
| 483 | .await | ||
| 484 | } | ||
| 485 | |||
| 486 | /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. | ||
| 487 | pub async fn flush(&mut self) -> Result<(), Error> { | ||
| 488 | poll_fn(move |cx| { | ||
| 489 | //trace!("poll_flush"); | ||
| 490 | let ss = U::state(); | ||
| 491 | let s = U::buffered_state(); | ||
| 492 | if !s.tx_buf.is_empty() { | ||
| 493 | //trace!("poll_flush: pending"); | ||
| 494 | ss.tx_waker.register(cx.waker()); | ||
| 495 | return Poll::Pending; | ||
| 496 | } | ||
| 497 | |||
| 498 | Poll::Ready(Ok(())) | ||
| 499 | }) | ||
| 500 | .await | ||
| 501 | } | ||
| 502 | } | ||
| 503 | |||
| 504 | impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> { | ||
| 505 | fn drop(&mut self) { | ||
| 506 | let r = U::regs(); | ||
| 507 | |||
| 508 | r.intenclr.write(|w| { | ||
| 509 | w.txdrdy().set_bit(); | ||
| 510 | w.txstarted().set_bit(); | ||
| 511 | w.txstopped().set_bit(); | ||
| 512 | w | ||
| 513 | }); | ||
| 514 | r.events_txstopped.reset(); | ||
| 515 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | ||
| 516 | while r.events_txstopped.read().bits() == 0 {} | ||
| 517 | |||
| 518 | let s = U::buffered_state(); | ||
| 519 | unsafe { s.tx_buf.deinit() } | ||
| 520 | |||
| 521 | let s = U::state(); | ||
| 522 | drop_tx_rx(r, s); | ||
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | /// Reader part of the buffered UARTE driver. | ||
| 527 | pub struct BufferedUarteRx<'d, U: UarteInstance, T: TimerInstance> { | ||
| 528 | _peri: PeripheralRef<'d, U>, | ||
| 529 | timer: Timer<'d, T>, | ||
| 530 | _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>, | ||
| 531 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>, | ||
| 532 | _ppi_group: PpiGroup<'d, AnyGroup>, | ||
| 533 | } | ||
| 534 | |||
| 535 | impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { | ||
| 536 | /// Create a new BufferedUarte without hardware flow control. | ||
| 537 | /// | ||
| 538 | /// # Panics | ||
| 539 | /// | ||
| 540 | /// Panics if `rx_buffer.len()` is odd. | ||
| 541 | pub fn new( | ||
| 542 | uarte: impl Peripheral<P = U> + 'd, | ||
| 543 | timer: impl Peripheral<P = T> + 'd, | ||
| 544 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, | ||
| 545 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, | ||
| 546 | ppi_group: impl Peripheral<P = impl Group> + 'd, | ||
| 547 | _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd, | ||
| 548 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 549 | config: Config, | ||
| 550 | rx_buffer: &'d mut [u8], | ||
| 551 | ) -> Self { | ||
| 552 | into_ref!(uarte, timer, rxd, ppi_ch1, ppi_ch2, ppi_group); | ||
| 553 | Self::new_inner( | ||
| 554 | uarte, | ||
| 555 | timer, | ||
| 556 | ppi_ch1.map_into(), | ||
| 557 | ppi_ch2.map_into(), | ||
| 558 | ppi_group.map_into(), | ||
| 559 | rxd.map_into(), | ||
| 560 | None, | ||
| 561 | config, | ||
| 562 | rx_buffer, | ||
| 563 | ) | ||
| 564 | } | ||
| 565 | |||
| 566 | /// Create a new BufferedUarte with hardware flow control (RTS/CTS) | ||
| 567 | /// | ||
| 568 | /// # Panics | ||
| 569 | /// | ||
| 570 | /// Panics if `rx_buffer.len()` is odd. | ||
| 571 | pub fn new_with_rts( | ||
| 572 | uarte: impl Peripheral<P = U> + 'd, | ||
| 573 | timer: impl Peripheral<P = T> + 'd, | ||
| 574 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, | ||
| 575 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, | ||
| 576 | ppi_group: impl Peripheral<P = impl Group> + 'd, | ||
| 577 | _irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd, | ||
| 578 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 579 | rts: impl Peripheral<P = impl GpioPin> + 'd, | ||
| 580 | config: Config, | ||
| 581 | rx_buffer: &'d mut [u8], | ||
| 582 | ) -> Self { | ||
| 583 | into_ref!(uarte, timer, rxd, rts, ppi_ch1, ppi_ch2, ppi_group); | ||
| 584 | Self::new_inner( | ||
| 585 | uarte, | ||
| 586 | timer, | ||
| 587 | ppi_ch1.map_into(), | ||
| 588 | ppi_ch2.map_into(), | ||
| 589 | ppi_group.map_into(), | ||
| 590 | rxd.map_into(), | ||
| 591 | Some(rts.map_into()), | ||
| 592 | config, | ||
| 593 | rx_buffer, | ||
| 594 | ) | ||
| 595 | } | ||
| 596 | |||
| 597 | fn new_inner( | ||
| 598 | peri: PeripheralRef<'d, U>, | ||
| 599 | timer: PeripheralRef<'d, T>, | ||
| 600 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, | ||
| 601 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, | ||
| 602 | ppi_group: PeripheralRef<'d, AnyGroup>, | ||
| 603 | rxd: PeripheralRef<'d, AnyPin>, | ||
| 604 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 605 | config: Config, | ||
| 606 | rx_buffer: &'d mut [u8], | ||
| 607 | ) -> Self { | ||
| 608 | configure(U::regs(), config, rts.is_some()); | ||
| 609 | |||
| 610 | let this = Self::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer); | ||
| 611 | |||
| 612 | U::Interrupt::pend(); | ||
| 613 | unsafe { U::Interrupt::enable() }; | ||
| 614 | |||
| 615 | U::state().tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 616 | |||
| 617 | this | ||
| 618 | } | ||
| 619 | |||
| 620 | fn new_innerer( | ||
| 621 | peri: PeripheralRef<'d, U>, | ||
| 622 | timer: PeripheralRef<'d, T>, | ||
| 623 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, | ||
| 624 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, | ||
| 625 | ppi_group: PeripheralRef<'d, AnyGroup>, | ||
| 626 | rxd: PeripheralRef<'d, AnyPin>, | ||
| 627 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 628 | rx_buffer: &'d mut [u8], | ||
| 629 | ) -> Self { | ||
| 630 | assert!(rx_buffer.len() % 2 == 0); | ||
| 631 | |||
| 632 | let r = U::regs(); | ||
| 633 | |||
| 634 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | ||
| 635 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | ||
| 636 | |||
| 334 | if let Some(pin) = &rts { | 637 | if let Some(pin) = &rts { |
| 335 | pin.set_high(); | 638 | pin.set_high(); |
| 336 | pin.conf().write(|w| w.dir().output().drive().h0h1()); | 639 | pin.conf().write(|w| w.dir().output().drive().h0h1()); |
| @@ -339,35 +642,21 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 339 | 642 | ||
| 340 | // Initialize state | 643 | // Initialize state |
| 341 | let s = U::buffered_state(); | 644 | let s = U::buffered_state(); |
| 342 | s.tx_count.store(0, Ordering::Relaxed); | ||
| 343 | s.rx_started_count.store(0, Ordering::Relaxed); | 645 | s.rx_started_count.store(0, Ordering::Relaxed); |
| 344 | s.rx_ended_count.store(0, Ordering::Relaxed); | 646 | s.rx_ended_count.store(0, Ordering::Relaxed); |
| 345 | s.rx_started.store(false, Ordering::Relaxed); | 647 | s.rx_started.store(false, Ordering::Relaxed); |
| 346 | let len = tx_buffer.len(); | ||
| 347 | unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | ||
| 348 | let len = rx_buffer.len(); | 648 | let len = rx_buffer.len(); |
| 349 | unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; | 649 | unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; |
| 350 | 650 | ||
| 351 | // Configure | ||
| 352 | r.config.write(|w| { | ||
| 353 | w.hwfc().bit(hwfc); | ||
| 354 | w.parity().variant(config.parity); | ||
| 355 | w | ||
| 356 | }); | ||
| 357 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); | ||
| 358 | |||
| 359 | // clear errors | 651 | // clear errors |
| 360 | let errors = r.errorsrc.read().bits(); | 652 | let errors = r.errorsrc.read().bits(); |
| 361 | r.errorsrc.write(|w| unsafe { w.bits(errors) }); | 653 | r.errorsrc.write(|w| unsafe { w.bits(errors) }); |
| 362 | 654 | ||
| 363 | r.events_rxstarted.reset(); | 655 | r.events_rxstarted.reset(); |
| 364 | r.events_txstarted.reset(); | ||
| 365 | r.events_error.reset(); | 656 | r.events_error.reset(); |
| 366 | r.events_endrx.reset(); | 657 | r.events_endrx.reset(); |
| 367 | r.events_endtx.reset(); | ||
| 368 | 658 | ||
| 369 | // Enable interrupts | 659 | // Enable interrupts |
| 370 | r.intenclr.write(|w| unsafe { w.bits(!0) }); | ||
| 371 | r.intenset.write(|w| { | 660 | r.intenset.write(|w| { |
| 372 | w.endtx().set(); | 661 | w.endtx().set(); |
| 373 | w.rxstarted().set(); | 662 | w.rxstarted().set(); |
| @@ -376,10 +665,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 376 | w | 665 | w |
| 377 | }); | 666 | }); |
| 378 | 667 | ||
| 379 | // Enable UARTE instance | ||
| 380 | apply_workaround_for_enable_anomaly(r); | ||
| 381 | r.enable.write(|w| w.enable().enabled()); | ||
| 382 | |||
| 383 | // Configure byte counter. | 668 | // Configure byte counter. |
| 384 | let timer = Timer::new_counter(timer); | 669 | let timer = Timer::new_counter(timer); |
| 385 | timer.cc(1).write(rx_buffer.len() as u32 * 2); | 670 | timer.cc(1).write(rx_buffer.len() as u32 * 2); |
| @@ -401,9 +686,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 401 | ppi_ch2.disable(); | 686 | ppi_ch2.disable(); |
| 402 | ppi_group.add_channel(&ppi_ch2); | 687 | ppi_group.add_channel(&ppi_ch2); |
| 403 | 688 | ||
| 404 | U::Interrupt::pend(); | ||
| 405 | unsafe { U::Interrupt::enable() }; | ||
| 406 | |||
| 407 | Self { | 689 | Self { |
| 408 | _peri: peri, | 690 | _peri: peri, |
| 409 | timer, | 691 | timer, |
| @@ -413,80 +695,24 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 413 | } | 695 | } |
| 414 | } | 696 | } |
| 415 | 697 | ||
| 416 | fn pend_irq() { | 698 | /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. |
| 417 | U::Interrupt::pend() | 699 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { |
| 418 | } | 700 | let data = self.fill_buf().await?; |
| 419 | |||
| 420 | /// Adjust the baud rate to the provided value. | ||
| 421 | pub fn set_baudrate(&mut self, baudrate: Baudrate) { | ||
| 422 | let r = U::regs(); | ||
| 423 | r.baudrate.write(|w| w.baudrate().variant(baudrate)); | ||
| 424 | } | ||
| 425 | |||
| 426 | /// Split the UART in reader and writer parts. | ||
| 427 | /// | ||
| 428 | /// This allows reading and writing concurrently from independent tasks. | ||
| 429 | pub fn split<'u>(&'u mut self) -> (BufferedUarteRx<'u, 'd, U, T>, BufferedUarteTx<'u, 'd, U, T>) { | ||
| 430 | (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self }) | ||
| 431 | } | ||
| 432 | |||
| 433 | async fn inner_read(&self, buf: &mut [u8]) -> Result<usize, Error> { | ||
| 434 | let data = self.inner_fill_buf().await?; | ||
| 435 | let n = data.len().min(buf.len()); | 701 | let n = data.len().min(buf.len()); |
| 436 | buf[..n].copy_from_slice(&data[..n]); | 702 | buf[..n].copy_from_slice(&data[..n]); |
| 437 | self.inner_consume(n); | 703 | self.consume(n); |
| 438 | Ok(n) | 704 | Ok(n) |
| 439 | } | 705 | } |
| 440 | 706 | ||
| 441 | async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, Error> { | 707 | /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. |
| 442 | poll_fn(move |cx| { | 708 | pub async fn fill_buf(&mut self) -> Result<&[u8], Error> { |
| 443 | //trace!("poll_write: {:?}", buf.len()); | ||
| 444 | let s = U::buffered_state(); | ||
| 445 | let mut tx = unsafe { s.tx_buf.writer() }; | ||
| 446 | |||
| 447 | let tx_buf = tx.push_slice(); | ||
| 448 | if tx_buf.is_empty() { | ||
| 449 | //trace!("poll_write: pending"); | ||
| 450 | s.tx_waker.register(cx.waker()); | ||
| 451 | return Poll::Pending; | ||
| 452 | } | ||
| 453 | |||
| 454 | let n = min(tx_buf.len(), buf.len()); | ||
| 455 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 456 | tx.push_done(n); | ||
| 457 | |||
| 458 | //trace!("poll_write: queued {:?}", n); | ||
| 459 | |||
| 460 | compiler_fence(Ordering::SeqCst); | ||
| 461 | Self::pend_irq(); | ||
| 462 | |||
| 463 | Poll::Ready(Ok(n)) | ||
| 464 | }) | ||
| 465 | .await | ||
| 466 | } | ||
| 467 | |||
| 468 | async fn inner_flush<'a>(&'a self) -> Result<(), Error> { | ||
| 469 | poll_fn(move |cx| { | ||
| 470 | //trace!("poll_flush"); | ||
| 471 | let s = U::buffered_state(); | ||
| 472 | if !s.tx_buf.is_empty() { | ||
| 473 | //trace!("poll_flush: pending"); | ||
| 474 | s.tx_waker.register(cx.waker()); | ||
| 475 | return Poll::Pending; | ||
| 476 | } | ||
| 477 | |||
| 478 | Poll::Ready(Ok(())) | ||
| 479 | }) | ||
| 480 | .await | ||
| 481 | } | ||
| 482 | |||
| 483 | async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], Error> { | ||
| 484 | poll_fn(move |cx| { | 709 | poll_fn(move |cx| { |
| 485 | compiler_fence(Ordering::SeqCst); | 710 | compiler_fence(Ordering::SeqCst); |
| 486 | //trace!("poll_read"); | 711 | //trace!("poll_read"); |
| 487 | 712 | ||
| 488 | let r = U::regs(); | 713 | let r = U::regs(); |
| 489 | let s = U::buffered_state(); | 714 | let s = U::buffered_state(); |
| 715 | let ss = U::state(); | ||
| 490 | 716 | ||
| 491 | // Read the RXDRDY counter. | 717 | // Read the RXDRDY counter. |
| 492 | T::regs().tasks_capture[0].write(|w| unsafe { w.bits(1) }); | 718 | T::regs().tasks_capture[0].write(|w| unsafe { w.bits(1) }); |
| @@ -510,7 +736,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 510 | let len = s.rx_buf.len(); | 736 | let len = s.rx_buf.len(); |
| 511 | if start == end { | 737 | if start == end { |
| 512 | //trace!(" empty"); | 738 | //trace!(" empty"); |
| 513 | s.rx_waker.register(cx.waker()); | 739 | ss.rx_waker.register(cx.waker()); |
| 514 | r.intenset.write(|w| w.rxdrdy().set_bit()); | 740 | r.intenset.write(|w| w.rxdrdy().set_bit()); |
| 515 | return Poll::Pending; | 741 | return Poll::Pending; |
| 516 | } | 742 | } |
| @@ -532,7 +758,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 532 | .await | 758 | .await |
| 533 | } | 759 | } |
| 534 | 760 | ||
| 535 | fn inner_consume(&self, amt: usize) { | 761 | /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. |
| 762 | pub fn consume(&mut self, amt: usize) { | ||
| 536 | if amt == 0 { | 763 | if amt == 0 { |
| 537 | return; | 764 | return; |
| 538 | } | 765 | } |
| @@ -542,69 +769,31 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 542 | rx.pop_done(amt); | 769 | rx.pop_done(amt); |
| 543 | U::regs().intenset.write(|w| w.rxstarted().set()); | 770 | U::regs().intenset.write(|w| w.rxstarted().set()); |
| 544 | } | 771 | } |
| 545 | |||
| 546 | /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. | ||
| 547 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | ||
| 548 | self.inner_read(buf).await | ||
| 549 | } | ||
| 550 | |||
| 551 | /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. | ||
| 552 | pub async fn fill_buf(&mut self) -> Result<&[u8], Error> { | ||
| 553 | self.inner_fill_buf().await | ||
| 554 | } | ||
| 555 | |||
| 556 | /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. | ||
| 557 | pub fn consume(&mut self, amt: usize) { | ||
| 558 | self.inner_consume(amt) | ||
| 559 | } | ||
| 560 | |||
| 561 | /// Write a buffer into this writer, returning how many bytes were written. | ||
| 562 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | ||
| 563 | self.inner_write(buf).await | ||
| 564 | } | ||
| 565 | |||
| 566 | /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. | ||
| 567 | pub async fn flush(&mut self) -> Result<(), Error> { | ||
| 568 | self.inner_flush().await | ||
| 569 | } | ||
| 570 | } | 772 | } |
| 571 | 773 | ||
| 572 | /// Reader part of the buffered UARTE driver. | 774 | impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarteRx<'a, U, T> { |
| 573 | pub struct BufferedUarteTx<'u, 'd, U: UarteInstance, T: TimerInstance> { | 775 | fn drop(&mut self) { |
| 574 | inner: &'u BufferedUarte<'d, U, T>, | 776 | self._ppi_group.disable_all(); |
| 575 | } | ||
| 576 | |||
| 577 | impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteTx<'u, 'd, U, T> { | ||
| 578 | /// Write a buffer into this writer, returning how many bytes were written. | ||
| 579 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | ||
| 580 | self.inner.inner_write(buf).await | ||
| 581 | } | ||
| 582 | 777 | ||
| 583 | /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. | 778 | let r = U::regs(); |
| 584 | pub async fn flush(&mut self) -> Result<(), Error> { | ||
| 585 | self.inner.inner_flush().await | ||
| 586 | } | ||
| 587 | } | ||
| 588 | 779 | ||
| 589 | /// Writer part of the buffered UARTE driver. | 780 | self.timer.stop(); |
| 590 | pub struct BufferedUarteRx<'u, 'd, U: UarteInstance, T: TimerInstance> { | ||
| 591 | inner: &'u BufferedUarte<'d, U, T>, | ||
| 592 | } | ||
| 593 | 781 | ||
| 594 | impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'u, 'd, U, T> { | 782 | r.intenclr.write(|w| { |
| 595 | /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. | 783 | w.rxdrdy().set_bit(); |
| 596 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { | 784 | w.rxstarted().set_bit(); |
| 597 | self.inner.inner_read(buf).await | 785 | w.rxto().set_bit(); |
| 598 | } | 786 | w |
| 787 | }); | ||
| 788 | r.events_rxto.reset(); | ||
| 789 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 790 | while r.events_rxto.read().bits() == 0 {} | ||
| 599 | 791 | ||
| 600 | /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. | 792 | let s = U::buffered_state(); |
| 601 | pub async fn fill_buf(&mut self) -> Result<&[u8], Error> { | 793 | unsafe { s.rx_buf.deinit() } |
| 602 | self.inner.inner_fill_buf().await | ||
| 603 | } | ||
| 604 | 794 | ||
| 605 | /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`. | 795 | let s = U::state(); |
| 606 | pub fn consume(&mut self, amt: usize) { | 796 | drop_tx_rx(r, s); |
| 607 | self.inner.inner_consume(amt) | ||
| 608 | } | 797 | } |
| 609 | } | 798 | } |
| 610 | 799 | ||
| @@ -621,95 +810,63 @@ mod _embedded_io { | |||
| 621 | type Error = Error; | 810 | type Error = Error; |
| 622 | } | 811 | } |
| 623 | 812 | ||
| 624 | impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::ErrorType for BufferedUarteRx<'u, 'd, U, T> { | 813 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::ErrorType for BufferedUarteRx<'d, U, T> { |
| 625 | type Error = Error; | 814 | type Error = Error; |
| 626 | } | 815 | } |
| 627 | 816 | ||
| 628 | impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::ErrorType for BufferedUarteTx<'u, 'd, U, T> { | 817 | impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteTx<'d, U> { |
| 629 | type Error = Error; | 818 | type Error = Error; |
| 630 | } | 819 | } |
| 631 | 820 | ||
| 632 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarte<'d, U, T> { | 821 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarte<'d, U, T> { |
| 633 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 822 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 634 | self.inner_read(buf).await | 823 | self.read(buf).await |
| 635 | } | 824 | } |
| 636 | } | 825 | } |
| 637 | 826 | ||
| 638 | impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarteRx<'u, 'd, U, T> { | 827 | impl<'d: 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarteRx<'d, U, T> { |
| 639 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 828 | async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 640 | self.inner.inner_read(buf).await | 829 | self.read(buf).await |
| 641 | } | 830 | } |
| 642 | } | 831 | } |
| 643 | 832 | ||
| 644 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarte<'d, U, T> { | 833 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarte<'d, U, T> { |
| 645 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { | 834 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { |
| 646 | self.inner_fill_buf().await | 835 | self.fill_buf().await |
| 647 | } | 836 | } |
| 648 | 837 | ||
| 649 | fn consume(&mut self, amt: usize) { | 838 | fn consume(&mut self, amt: usize) { |
| 650 | self.inner_consume(amt) | 839 | self.consume(amt) |
| 651 | } | 840 | } |
| 652 | } | 841 | } |
| 653 | 842 | ||
| 654 | impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarteRx<'u, 'd, U, T> { | 843 | impl<'d: 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarteRx<'d, U, T> { |
| 655 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { | 844 | async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { |
| 656 | self.inner.inner_fill_buf().await | 845 | self.fill_buf().await |
| 657 | } | 846 | } |
| 658 | 847 | ||
| 659 | fn consume(&mut self, amt: usize) { | 848 | fn consume(&mut self, amt: usize) { |
| 660 | self.inner.inner_consume(amt) | 849 | self.consume(amt) |
| 661 | } | 850 | } |
| 662 | } | 851 | } |
| 663 | 852 | ||
| 664 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Write for BufferedUarte<'d, U, T> { | 853 | impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Write for BufferedUarte<'d, U, T> { |
| 665 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 854 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 666 | self.inner_write(buf).await | 855 | self.write(buf).await |
| 667 | } | 856 | } |
| 668 | 857 | ||
| 669 | async fn flush(&mut self) -> Result<(), Self::Error> { | 858 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 670 | self.inner_flush().await | 859 | self.flush().await |
| 671 | } | 860 | } |
| 672 | } | 861 | } |
| 673 | 862 | ||
| 674 | impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io_async::Write for BufferedUarteTx<'u, 'd, U, T> { | 863 | impl<'d: 'd, U: UarteInstance> embedded_io_async::Write for BufferedUarteTx<'d, U> { |
| 675 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 864 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 676 | self.inner.inner_write(buf).await | 865 | self.write(buf).await |
| 677 | } | 866 | } |
| 678 | 867 | ||
| 679 | async fn flush(&mut self) -> Result<(), Self::Error> { | 868 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 680 | self.inner.inner_flush().await | 869 | self.flush().await |
| 681 | } | ||
| 682 | } | ||
| 683 | } | ||
| 684 | |||
| 685 | impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarte<'a, U, T> { | ||
| 686 | fn drop(&mut self) { | ||
| 687 | self._ppi_group.disable_all(); | ||
| 688 | |||
| 689 | let r = U::regs(); | ||
| 690 | |||
| 691 | self.timer.stop(); | ||
| 692 | |||
| 693 | r.inten.reset(); | ||
| 694 | r.events_rxto.reset(); | ||
| 695 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 696 | r.events_txstopped.reset(); | ||
| 697 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | ||
| 698 | |||
| 699 | while r.events_txstopped.read().bits() == 0 {} | ||
| 700 | while r.events_rxto.read().bits() == 0 {} | ||
| 701 | |||
| 702 | r.enable.write(|w| w.enable().disabled()); | ||
| 703 | |||
| 704 | gpio::deconfigure_pin(r.psel.rxd.read().bits()); | ||
| 705 | gpio::deconfigure_pin(r.psel.txd.read().bits()); | ||
| 706 | gpio::deconfigure_pin(r.psel.rts.read().bits()); | ||
| 707 | gpio::deconfigure_pin(r.psel.cts.read().bits()); | ||
| 708 | |||
| 709 | let s = U::buffered_state(); | ||
| 710 | unsafe { | ||
| 711 | s.rx_buf.deinit(); | ||
| 712 | s.tx_buf.deinit(); | ||
| 713 | } | 870 | } |
| 714 | } | 871 | } |
| 715 | } | 872 | } |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index b2f987109..3649ea61a 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -189,7 +189,7 @@ impl<'d> Output<'d> { | |||
| 189 | } | 189 | } |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | fn convert_drive(drive: OutputDrive) -> DRIVE_A { | 192 | pub(crate) fn convert_drive(drive: OutputDrive) -> DRIVE_A { |
| 193 | match drive { | 193 | match drive { |
| 194 | OutputDrive::Standard => DRIVE_A::S0S1, | 194 | OutputDrive::Standard => DRIVE_A::S0S1, |
| 195 | OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1, | 195 | OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1, |
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 2d70732a8..3538afa2b 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -15,7 +15,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency; | |||
| 15 | 15 | ||
| 16 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 16 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 17 | use crate::gpio::sealed::Pin as _; | 17 | use crate::gpio::sealed::Pin as _; |
| 18 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 18 | use crate::gpio::{self, convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits}; |
| 19 | use crate::interrupt::typelevel::Interrupt; | 19 | use crate::interrupt::typelevel::Interrupt; |
| 20 | use crate::util::{slice_in_ram_or, slice_ptr_len, slice_ptr_parts, slice_ptr_parts_mut}; | 20 | use crate::util::{slice_in_ram_or, slice_ptr_len, slice_ptr_parts, slice_ptr_parts_mut}; |
| 21 | use crate::{interrupt, pac, Peripheral}; | 21 | use crate::{interrupt, pac, Peripheral}; |
| @@ -46,6 +46,15 @@ pub struct Config { | |||
| 46 | /// When doing bidirectional transfers, if the TX buffer is shorter than the RX buffer, | 46 | /// When doing bidirectional transfers, if the TX buffer is shorter than the RX buffer, |
| 47 | /// this byte will be transmitted in the MOSI line for the left-over bytes. | 47 | /// this byte will be transmitted in the MOSI line for the left-over bytes. |
| 48 | pub orc: u8, | 48 | pub orc: u8, |
| 49 | |||
| 50 | /// Drive strength for the SCK line. | ||
| 51 | pub sck_drive: OutputDrive, | ||
| 52 | |||
| 53 | /// Drive strength for the MOSI line. | ||
| 54 | pub mosi_drive: OutputDrive, | ||
| 55 | |||
| 56 | /// Drive strength for the MISO line. | ||
| 57 | pub miso_drive: OutputDrive, | ||
| 49 | } | 58 | } |
| 50 | 59 | ||
| 51 | impl Default for Config { | 60 | impl Default for Config { |
| @@ -55,6 +64,9 @@ impl Default for Config { | |||
| 55 | mode: MODE_0, | 64 | mode: MODE_0, |
| 56 | bit_order: BitOrder::MSB_FIRST, | 65 | bit_order: BitOrder::MSB_FIRST, |
| 57 | orc: 0x00, | 66 | orc: 0x00, |
| 67 | sck_drive: OutputDrive::HighDrive, | ||
| 68 | mosi_drive: OutputDrive::HighDrive, | ||
| 69 | miso_drive: OutputDrive::HighDrive, | ||
| 58 | } | 70 | } |
| 59 | } | 71 | } |
| 60 | } | 72 | } |
| @@ -159,13 +171,16 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 159 | 171 | ||
| 160 | // Configure pins | 172 | // Configure pins |
| 161 | if let Some(sck) = &sck { | 173 | if let Some(sck) = &sck { |
| 162 | sck.conf().write(|w| w.dir().output().drive().h0h1()); | 174 | sck.conf() |
| 175 | .write(|w| w.dir().output().drive().variant(convert_drive(config.sck_drive))); | ||
| 163 | } | 176 | } |
| 164 | if let Some(mosi) = &mosi { | 177 | if let Some(mosi) = &mosi { |
| 165 | mosi.conf().write(|w| w.dir().output().drive().h0h1()); | 178 | mosi.conf() |
| 179 | .write(|w| w.dir().output().drive().variant(convert_drive(config.mosi_drive))); | ||
| 166 | } | 180 | } |
| 167 | if let Some(miso) = &miso { | 181 | if let Some(miso) = &miso { |
| 168 | miso.conf().write(|w| w.input().connect().drive().h0h1()); | 182 | miso.conf() |
| 183 | .write(|w| w.input().connect().drive().variant(convert_drive(config.miso_drive))); | ||
| 169 | } | 184 | } |
| 170 | 185 | ||
| 171 | match config.mode.polarity { | 186 | match config.mode.polarity { |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 9e5b85dea..cbd5dccbc 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -115,7 +115,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 115 | let endrx = r.events_endrx.read().bits(); | 115 | let endrx = r.events_endrx.read().bits(); |
| 116 | let error = r.events_error.read().bits(); | 116 | let error = r.events_error.read().bits(); |
| 117 | if endrx != 0 || error != 0 { | 117 | if endrx != 0 || error != 0 { |
| 118 | s.endrx_waker.wake(); | 118 | s.rx_waker.wake(); |
| 119 | if endrx != 0 { | 119 | if endrx != 0 { |
| 120 | r.intenclr.write(|w| w.endrx().clear()); | 120 | r.intenclr.write(|w| w.endrx().clear()); |
| 121 | } | 121 | } |
| @@ -124,7 +124,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 124 | } | 124 | } |
| 125 | } | 125 | } |
| 126 | if r.events_endtx.read().bits() != 0 { | 126 | if r.events_endtx.read().bits() != 0 { |
| 127 | s.endtx_waker.wake(); | 127 | s.tx_waker.wake(); |
| 128 | r.intenclr.write(|w| w.endtx().clear()); | 128 | r.intenclr.write(|w| w.endtx().clear()); |
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| @@ -159,7 +159,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 159 | txd: impl Peripheral<P = impl GpioPin> + 'd, | 159 | txd: impl Peripheral<P = impl GpioPin> + 'd, |
| 160 | config: Config, | 160 | config: Config, |
| 161 | ) -> Self { | 161 | ) -> Self { |
| 162 | into_ref!(rxd, txd); | 162 | into_ref!(uarte, rxd, txd); |
| 163 | Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config) | 163 | Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config) |
| 164 | } | 164 | } |
| 165 | 165 | ||
| @@ -173,7 +173,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 173 | rts: impl Peripheral<P = impl GpioPin> + 'd, | 173 | rts: impl Peripheral<P = impl GpioPin> + 'd, |
| 174 | config: Config, | 174 | config: Config, |
| 175 | ) -> Self { | 175 | ) -> Self { |
| 176 | into_ref!(rxd, txd, cts, rts); | 176 | into_ref!(uarte, rxd, txd, cts, rts); |
| 177 | Self::new_inner( | 177 | Self::new_inner( |
| 178 | uarte, | 178 | uarte, |
| 179 | rxd.map_into(), | 179 | rxd.map_into(), |
| @@ -185,17 +185,22 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | fn new_inner( | 187 | fn new_inner( |
| 188 | uarte: impl Peripheral<P = T> + 'd, | 188 | uarte: PeripheralRef<'d, T>, |
| 189 | rxd: PeripheralRef<'d, AnyPin>, | 189 | rxd: PeripheralRef<'d, AnyPin>, |
| 190 | txd: PeripheralRef<'d, AnyPin>, | 190 | txd: PeripheralRef<'d, AnyPin>, |
| 191 | cts: Option<PeripheralRef<'d, AnyPin>>, | 191 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| 192 | rts: Option<PeripheralRef<'d, AnyPin>>, | 192 | rts: Option<PeripheralRef<'d, AnyPin>>, |
| 193 | config: Config, | 193 | config: Config, |
| 194 | ) -> Self { | 194 | ) -> Self { |
| 195 | into_ref!(uarte); | ||
| 196 | |||
| 197 | let r = T::regs(); | 195 | let r = T::regs(); |
| 198 | 196 | ||
| 197 | let hardware_flow_control = match (rts.is_some(), cts.is_some()) { | ||
| 198 | (false, false) => false, | ||
| 199 | (true, true) => true, | ||
| 200 | _ => panic!("RTS and CTS pins must be either both set or none set."), | ||
| 201 | }; | ||
| 202 | configure(r, config, hardware_flow_control); | ||
| 203 | |||
| 199 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | 204 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 200 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | 205 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
| 201 | 206 | ||
| @@ -217,13 +222,6 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 217 | T::Interrupt::unpend(); | 222 | T::Interrupt::unpend(); |
| 218 | unsafe { T::Interrupt::enable() }; | 223 | unsafe { T::Interrupt::enable() }; |
| 219 | 224 | ||
| 220 | let hardware_flow_control = match (rts.is_some(), cts.is_some()) { | ||
| 221 | (false, false) => false, | ||
| 222 | (true, true) => true, | ||
| 223 | _ => panic!("RTS and CTS pins must be either both set or none set."), | ||
| 224 | }; | ||
| 225 | configure(r, config, hardware_flow_control); | ||
| 226 | |||
| 227 | let s = T::state(); | 225 | let s = T::state(); |
| 228 | s.tx_rx_refcount.store(2, Ordering::Relaxed); | 226 | s.tx_rx_refcount.store(2, Ordering::Relaxed); |
| 229 | 227 | ||
| @@ -242,6 +240,14 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 242 | (self.tx, self.rx) | 240 | (self.tx, self.rx) |
| 243 | } | 241 | } |
| 244 | 242 | ||
| 243 | /// Split the UART in reader and writer parts, by reference. | ||
| 244 | /// | ||
| 245 | /// The returned halves borrow from `self`, so you can drop them and go back to using | ||
| 246 | /// the "un-split" `self`. This allows temporarily splitting the UART. | ||
| 247 | pub fn split_by_ref(&mut self) -> (&mut UarteTx<'d, T>, &mut UarteRx<'d, T>) { | ||
| 248 | (&mut self.tx, &mut self.rx) | ||
| 249 | } | ||
| 250 | |||
| 245 | /// Split the Uarte into the transmitter and receiver with idle support parts. | 251 | /// Split the Uarte into the transmitter and receiver with idle support parts. |
| 246 | /// | 252 | /// |
| 247 | /// This is useful to concurrently transmit and receive from independent tasks. | 253 | /// This is useful to concurrently transmit and receive from independent tasks. |
| @@ -291,7 +297,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 291 | } | 297 | } |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { | 300 | pub(crate) fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { |
| 295 | r.config.write(|w| { | 301 | r.config.write(|w| { |
| 296 | w.hwfc().bit(hardware_flow_control); | 302 | w.hwfc().bit(hardware_flow_control); |
| 297 | w.parity().variant(config.parity); | 303 | w.parity().variant(config.parity); |
| @@ -307,6 +313,12 @@ fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { | |||
| 307 | r.events_rxstarted.reset(); | 313 | r.events_rxstarted.reset(); |
| 308 | r.events_txstarted.reset(); | 314 | r.events_txstarted.reset(); |
| 309 | 315 | ||
| 316 | // reset all pins | ||
| 317 | r.psel.txd.write(|w| w.connect().disconnected()); | ||
| 318 | r.psel.rxd.write(|w| w.connect().disconnected()); | ||
| 319 | r.psel.cts.write(|w| w.connect().disconnected()); | ||
| 320 | r.psel.rts.write(|w| w.connect().disconnected()); | ||
| 321 | |||
| 310 | // Enable | 322 | // Enable |
| 311 | apply_workaround_for_enable_anomaly(r); | 323 | apply_workaround_for_enable_anomaly(r); |
| 312 | r.enable.write(|w| w.enable().enabled()); | 324 | r.enable.write(|w| w.enable().enabled()); |
| @@ -320,7 +332,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 320 | txd: impl Peripheral<P = impl GpioPin> + 'd, | 332 | txd: impl Peripheral<P = impl GpioPin> + 'd, |
| 321 | config: Config, | 333 | config: Config, |
| 322 | ) -> Self { | 334 | ) -> Self { |
| 323 | into_ref!(txd); | 335 | into_ref!(uarte, txd); |
| 324 | Self::new_inner(uarte, txd.map_into(), None, config) | 336 | Self::new_inner(uarte, txd.map_into(), None, config) |
| 325 | } | 337 | } |
| 326 | 338 | ||
| @@ -332,20 +344,20 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 332 | cts: impl Peripheral<P = impl GpioPin> + 'd, | 344 | cts: impl Peripheral<P = impl GpioPin> + 'd, |
| 333 | config: Config, | 345 | config: Config, |
| 334 | ) -> Self { | 346 | ) -> Self { |
| 335 | into_ref!(txd, cts); | 347 | into_ref!(uarte, txd, cts); |
| 336 | Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config) | 348 | Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config) |
| 337 | } | 349 | } |
| 338 | 350 | ||
| 339 | fn new_inner( | 351 | fn new_inner( |
| 340 | uarte: impl Peripheral<P = T> + 'd, | 352 | uarte: PeripheralRef<'d, T>, |
| 341 | txd: PeripheralRef<'d, AnyPin>, | 353 | txd: PeripheralRef<'d, AnyPin>, |
| 342 | cts: Option<PeripheralRef<'d, AnyPin>>, | 354 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| 343 | config: Config, | 355 | config: Config, |
| 344 | ) -> Self { | 356 | ) -> Self { |
| 345 | into_ref!(uarte); | ||
| 346 | |||
| 347 | let r = T::regs(); | 357 | let r = T::regs(); |
| 348 | 358 | ||
| 359 | configure(r, config, cts.is_some()); | ||
| 360 | |||
| 349 | txd.set_high(); | 361 | txd.set_high(); |
| 350 | txd.conf().write(|w| w.dir().output().drive().s0s1()); | 362 | txd.conf().write(|w| w.dir().output().drive().s0s1()); |
| 351 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | 363 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); |
| @@ -355,12 +367,6 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 355 | } | 367 | } |
| 356 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | 368 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 357 | 369 | ||
| 358 | r.psel.rxd.write(|w| w.connect().disconnected()); | ||
| 359 | r.psel.rts.write(|w| w.connect().disconnected()); | ||
| 360 | |||
| 361 | let hardware_flow_control = cts.is_some(); | ||
| 362 | configure(r, config, hardware_flow_control); | ||
| 363 | |||
| 364 | T::Interrupt::unpend(); | 370 | T::Interrupt::unpend(); |
| 365 | unsafe { T::Interrupt::enable() }; | 371 | unsafe { T::Interrupt::enable() }; |
| 366 | 372 | ||
| @@ -425,7 +431,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 425 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 431 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); |
| 426 | 432 | ||
| 427 | poll_fn(|cx| { | 433 | poll_fn(|cx| { |
| 428 | s.endtx_waker.register(cx.waker()); | 434 | s.tx_waker.register(cx.waker()); |
| 429 | if r.events_endtx.read().bits() != 0 { | 435 | if r.events_endtx.read().bits() != 0 { |
| 430 | return Poll::Ready(()); | 436 | return Poll::Ready(()); |
| 431 | } | 437 | } |
| @@ -516,7 +522,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 516 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | 522 | rxd: impl Peripheral<P = impl GpioPin> + 'd, |
| 517 | config: Config, | 523 | config: Config, |
| 518 | ) -> Self { | 524 | ) -> Self { |
| 519 | into_ref!(rxd); | 525 | into_ref!(uarte, rxd); |
| 520 | Self::new_inner(uarte, rxd.map_into(), None, config) | 526 | Self::new_inner(uarte, rxd.map_into(), None, config) |
| 521 | } | 527 | } |
| 522 | 528 | ||
| @@ -528,7 +534,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 528 | rts: impl Peripheral<P = impl GpioPin> + 'd, | 534 | rts: impl Peripheral<P = impl GpioPin> + 'd, |
| 529 | config: Config, | 535 | config: Config, |
| 530 | ) -> Self { | 536 | ) -> Self { |
| 531 | into_ref!(rxd, rts); | 537 | into_ref!(uarte, rxd, rts); |
| 532 | Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) | 538 | Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) |
| 533 | } | 539 | } |
| 534 | 540 | ||
| @@ -541,15 +547,15 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 541 | } | 547 | } |
| 542 | 548 | ||
| 543 | fn new_inner( | 549 | fn new_inner( |
| 544 | uarte: impl Peripheral<P = T> + 'd, | 550 | uarte: PeripheralRef<'d, T>, |
| 545 | rxd: PeripheralRef<'d, AnyPin>, | 551 | rxd: PeripheralRef<'d, AnyPin>, |
| 546 | rts: Option<PeripheralRef<'d, AnyPin>>, | 552 | rts: Option<PeripheralRef<'d, AnyPin>>, |
| 547 | config: Config, | 553 | config: Config, |
| 548 | ) -> Self { | 554 | ) -> Self { |
| 549 | into_ref!(uarte); | ||
| 550 | |||
| 551 | let r = T::regs(); | 555 | let r = T::regs(); |
| 552 | 556 | ||
| 557 | configure(r, config, rts.is_some()); | ||
| 558 | |||
| 553 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | 559 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 554 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | 560 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
| 555 | 561 | ||
| @@ -559,15 +565,9 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 559 | } | 565 | } |
| 560 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | 566 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); |
| 561 | 567 | ||
| 562 | r.psel.txd.write(|w| w.connect().disconnected()); | ||
| 563 | r.psel.cts.write(|w| w.connect().disconnected()); | ||
| 564 | |||
| 565 | T::Interrupt::unpend(); | 568 | T::Interrupt::unpend(); |
| 566 | unsafe { T::Interrupt::enable() }; | 569 | unsafe { T::Interrupt::enable() }; |
| 567 | 570 | ||
| 568 | let hardware_flow_control = rts.is_some(); | ||
| 569 | configure(r, config, hardware_flow_control); | ||
| 570 | |||
| 571 | let s = T::state(); | 571 | let s = T::state(); |
| 572 | s.tx_rx_refcount.store(1, Ordering::Relaxed); | 572 | s.tx_rx_refcount.store(1, Ordering::Relaxed); |
| 573 | 573 | ||
| @@ -672,7 +672,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 672 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 672 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 673 | 673 | ||
| 674 | let result = poll_fn(|cx| { | 674 | let result = poll_fn(|cx| { |
| 675 | s.endrx_waker.register(cx.waker()); | 675 | s.rx_waker.register(cx.waker()); |
| 676 | 676 | ||
| 677 | if let Err(e) = self.check_and_clear_errors() { | 677 | if let Err(e) = self.check_and_clear_errors() { |
| 678 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 678 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| @@ -819,7 +819,7 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 819 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 819 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 820 | 820 | ||
| 821 | let result = poll_fn(|cx| { | 821 | let result = poll_fn(|cx| { |
| 822 | s.endrx_waker.register(cx.waker()); | 822 | s.rx_waker.register(cx.waker()); |
| 823 | 823 | ||
| 824 | if let Err(e) = self.rx.check_and_clear_errors() { | 824 | if let Err(e) = self.rx.check_and_clear_errors() { |
| 825 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 825 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| @@ -962,15 +962,15 @@ pub(crate) mod sealed { | |||
| 962 | use super::*; | 962 | use super::*; |
| 963 | 963 | ||
| 964 | pub struct State { | 964 | pub struct State { |
| 965 | pub endrx_waker: AtomicWaker, | 965 | pub rx_waker: AtomicWaker, |
| 966 | pub endtx_waker: AtomicWaker, | 966 | pub tx_waker: AtomicWaker, |
| 967 | pub tx_rx_refcount: AtomicU8, | 967 | pub tx_rx_refcount: AtomicU8, |
| 968 | } | 968 | } |
| 969 | impl State { | 969 | impl State { |
| 970 | pub const fn new() -> Self { | 970 | pub const fn new() -> Self { |
| 971 | Self { | 971 | Self { |
| 972 | endrx_waker: AtomicWaker::new(), | 972 | rx_waker: AtomicWaker::new(), |
| 973 | endtx_waker: AtomicWaker::new(), | 973 | tx_waker: AtomicWaker::new(), |
| 974 | tx_rx_refcount: AtomicU8::new(0), | 974 | tx_rx_refcount: AtomicU8::new(0), |
| 975 | } | 975 | } |
| 976 | } | 976 | } |
