diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-05 20:17:52 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-03-06 00:17:51 +0100 |
| commit | 9cf000ef4edd8f230b348ede8d7ce015045a0035 (patch) | |
| tree | ed3db0facdb024479843691292121daa04f0975f /embassy-nrf/src/buffered_uarte.rs | |
| parent | 42c13c8c3d9514866c2842009f76e88e8cb01b22 (diff) | |
nrf/uart: switch to new interrupt binding.
Diffstat (limited to 'embassy-nrf/src/buffered_uarte.rs')
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 225 |
1 files changed, 114 insertions, 111 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index ab639aeea..75f93f904 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | use core::cmp::min; | 11 | use core::cmp::min; |
| 12 | use core::future::poll_fn; | 12 | use core::future::poll_fn; |
| 13 | use core::marker::PhantomData; | ||
| 13 | use core::slice; | 14 | use core::slice; |
| 14 | use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; | 15 | use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; |
| 15 | use core::task::Poll; | 16 | use core::task::Poll; |
| @@ -23,7 +24,7 @@ pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Pari | |||
| 23 | 24 | ||
| 24 | use crate::gpio::sealed::Pin; | 25 | use crate::gpio::sealed::Pin; |
| 25 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 26 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 26 | use crate::interrupt::InterruptExt; | 27 | use crate::interrupt::{self, InterruptExt}; |
| 27 | use crate::ppi::{ | 28 | use crate::ppi::{ |
| 28 | self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, | 29 | self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, |
| 29 | }; | 30 | }; |
| @@ -71,6 +72,113 @@ impl State { | |||
| 71 | } | 72 | } |
| 72 | } | 73 | } |
| 73 | 74 | ||
| 75 | /// Interrupt handler. | ||
| 76 | pub struct InterruptHandler<U: UarteInstance> { | ||
| 77 | _phantom: PhantomData<U>, | ||
| 78 | } | ||
| 79 | |||
| 80 | impl<U: UarteInstance> interrupt::Handler<U::Interrupt> for InterruptHandler<U> { | ||
| 81 | unsafe fn on_interrupt() { | ||
| 82 | //trace!("irq: start"); | ||
| 83 | let r = U::regs(); | ||
| 84 | let s = U::buffered_state(); | ||
| 85 | |||
| 86 | let buf_len = s.rx_buf.len(); | ||
| 87 | let half_len = buf_len / 2; | ||
| 88 | let mut tx = unsafe { s.tx_buf.reader() }; | ||
| 89 | let mut rx = unsafe { s.rx_buf.writer() }; | ||
| 90 | |||
| 91 | if r.events_error.read().bits() != 0 { | ||
| 92 | r.events_error.reset(); | ||
| 93 | let errs = r.errorsrc.read(); | ||
| 94 | r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) }); | ||
| 95 | |||
| 96 | if errs.overrun().bit() { | ||
| 97 | panic!("BufferedUarte overrun"); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | // Received some bytes, wake task. | ||
| 102 | if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 { | ||
| 103 | r.intenclr.write(|w| w.rxdrdy().clear()); | ||
| 104 | r.events_rxdrdy.reset(); | ||
| 105 | s.rx_waker.wake(); | ||
| 106 | } | ||
| 107 | |||
| 108 | // If not RXing, start. | ||
| 109 | if s.rx_bufs.load(Ordering::Relaxed) == 0 { | ||
| 110 | let (ptr, len) = rx.push_buf(); | ||
| 111 | if len >= half_len { | ||
| 112 | //trace!(" irq_rx: starting {:?}", half_len); | ||
| 113 | s.rx_bufs.store(1, Ordering::Relaxed); | ||
| 114 | |||
| 115 | // Set up the DMA read | ||
| 116 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 117 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); | ||
| 118 | |||
| 119 | // Start UARTE Receive transaction | ||
| 120 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 121 | rx.push_done(half_len); | ||
| 122 | r.intenset.write(|w| w.rxstarted().set()); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | if r.events_rxstarted.read().bits() != 0 { | ||
| 127 | //trace!(" irq_rx: rxstarted"); | ||
| 128 | let (ptr, len) = rx.push_buf(); | ||
| 129 | if len >= half_len { | ||
| 130 | //trace!(" irq_rx: starting second {:?}", half_len); | ||
| 131 | |||
| 132 | // Set up the DMA read | ||
| 133 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 134 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); | ||
| 135 | |||
| 136 | let chn = s.rx_ppi_ch.load(Ordering::Relaxed); | ||
| 137 | |||
| 138 | ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) }); | ||
| 139 | |||
| 140 | rx.push_done(half_len); | ||
| 141 | |||
| 142 | r.events_rxstarted.reset(); | ||
| 143 | } else { | ||
| 144 | //trace!(" irq_rx: rxstarted no buf"); | ||
| 145 | r.intenclr.write(|w| w.rxstarted().clear()); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | // ============================= | ||
| 150 | |||
| 151 | // TX end | ||
| 152 | if r.events_endtx.read().bits() != 0 { | ||
| 153 | r.events_endtx.reset(); | ||
| 154 | |||
| 155 | let n = s.tx_count.load(Ordering::Relaxed); | ||
| 156 | //trace!(" irq_tx: endtx {:?}", n); | ||
| 157 | tx.pop_done(n); | ||
| 158 | s.tx_waker.wake(); | ||
| 159 | s.tx_count.store(0, Ordering::Relaxed); | ||
| 160 | } | ||
| 161 | |||
| 162 | // If not TXing, start. | ||
| 163 | if s.tx_count.load(Ordering::Relaxed) == 0 { | ||
| 164 | let (ptr, len) = tx.pop_buf(); | ||
| 165 | if len != 0 { | ||
| 166 | //trace!(" irq_tx: starting {:?}", len); | ||
| 167 | s.tx_count.store(len, Ordering::Relaxed); | ||
| 168 | |||
| 169 | // Set up the DMA write | ||
| 170 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 171 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 172 | |||
| 173 | // Start UARTE Transmit transaction | ||
| 174 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | //trace!("irq: end"); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 74 | /// Buffered UARTE driver. | 182 | /// Buffered UARTE driver. |
| 75 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { | 183 | pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { |
| 76 | _peri: PeripheralRef<'d, U>, | 184 | _peri: PeripheralRef<'d, U>, |
| @@ -94,7 +202,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 94 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, | 202 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, |
| 95 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, | 203 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, |
| 96 | ppi_group: impl Peripheral<P = impl Group> + 'd, | 204 | ppi_group: impl Peripheral<P = impl Group> + 'd, |
| 97 | irq: impl Peripheral<P = U::Interrupt> + 'd, | 205 | _irq: impl interrupt::Binding<U::Interrupt, InterruptHandler<U>> + 'd, |
| 98 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | 206 | rxd: impl Peripheral<P = impl GpioPin> + 'd, |
| 99 | txd: impl Peripheral<P = impl GpioPin> + 'd, | 207 | txd: impl Peripheral<P = impl GpioPin> + 'd, |
| 100 | config: Config, | 208 | config: Config, |
| @@ -108,7 +216,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 108 | ppi_ch1.map_into(), | 216 | ppi_ch1.map_into(), |
| 109 | ppi_ch2.map_into(), | 217 | ppi_ch2.map_into(), |
| 110 | ppi_group.map_into(), | 218 | ppi_group.map_into(), |
| 111 | irq, | ||
| 112 | rxd.map_into(), | 219 | rxd.map_into(), |
| 113 | txd.map_into(), | 220 | txd.map_into(), |
| 114 | None, | 221 | None, |
| @@ -130,7 +237,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 130 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, | 237 | ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd, |
| 131 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, | 238 | ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd, |
| 132 | ppi_group: impl Peripheral<P = impl Group> + 'd, | 239 | ppi_group: impl Peripheral<P = impl Group> + 'd, |
| 133 | irq: impl Peripheral<P = U::Interrupt> + 'd, | 240 | _irq: impl interrupt::Binding<U::Interrupt, InterruptHandler<U>> + 'd, |
| 134 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | 241 | rxd: impl Peripheral<P = impl GpioPin> + 'd, |
| 135 | txd: impl Peripheral<P = impl GpioPin> + 'd, | 242 | txd: impl Peripheral<P = impl GpioPin> + 'd, |
| 136 | cts: impl Peripheral<P = impl GpioPin> + 'd, | 243 | cts: impl Peripheral<P = impl GpioPin> + 'd, |
| @@ -146,7 +253,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 146 | ppi_ch1.map_into(), | 253 | ppi_ch1.map_into(), |
| 147 | ppi_ch2.map_into(), | 254 | ppi_ch2.map_into(), |
| 148 | ppi_group.map_into(), | 255 | ppi_group.map_into(), |
| 149 | irq, | ||
| 150 | rxd.map_into(), | 256 | rxd.map_into(), |
| 151 | txd.map_into(), | 257 | txd.map_into(), |
| 152 | Some(cts.map_into()), | 258 | Some(cts.map_into()), |
| @@ -163,7 +269,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 163 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, | 269 | ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>, |
| 164 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, | 270 | ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>, |
| 165 | ppi_group: PeripheralRef<'d, AnyGroup>, | 271 | ppi_group: PeripheralRef<'d, AnyGroup>, |
| 166 | irq: impl Peripheral<P = U::Interrupt> + 'd, | ||
| 167 | rxd: PeripheralRef<'d, AnyPin>, | 272 | rxd: PeripheralRef<'d, AnyPin>, |
| 168 | txd: PeripheralRef<'d, AnyPin>, | 273 | txd: PeripheralRef<'d, AnyPin>, |
| 169 | cts: Option<PeripheralRef<'d, AnyPin>>, | 274 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| @@ -172,7 +277,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 172 | rx_buffer: &'d mut [u8], | 277 | rx_buffer: &'d mut [u8], |
| 173 | tx_buffer: &'d mut [u8], | 278 | tx_buffer: &'d mut [u8], |
| 174 | ) -> Self { | 279 | ) -> Self { |
| 175 | into_ref!(peri, timer, irq); | 280 | into_ref!(peri, timer); |
| 176 | 281 | ||
| 177 | assert!(rx_buffer.len() % 2 == 0); | 282 | assert!(rx_buffer.len() % 2 == 0); |
| 178 | 283 | ||
| @@ -257,10 +362,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 257 | ppi_ch2.disable(); | 362 | ppi_ch2.disable(); |
| 258 | ppi_group.add_channel(&ppi_ch2); | 363 | ppi_group.add_channel(&ppi_ch2); |
| 259 | 364 | ||
| 260 | irq.disable(); | 365 | unsafe { U::Interrupt::steal() }.pend(); |
| 261 | irq.set_handler(Self::on_interrupt); | 366 | unsafe { U::Interrupt::steal() }.enable(); |
| 262 | irq.pend(); | ||
| 263 | irq.enable(); | ||
| 264 | 367 | ||
| 265 | Self { | 368 | Self { |
| 266 | _peri: peri, | 369 | _peri: peri, |
| @@ -275,106 +378,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 275 | unsafe { <U::Interrupt as Interrupt>::steal() }.pend() | 378 | unsafe { <U::Interrupt as Interrupt>::steal() }.pend() |
| 276 | } | 379 | } |
| 277 | 380 | ||
| 278 | fn on_interrupt(_: *mut ()) { | ||
| 279 | //trace!("irq: start"); | ||
| 280 | let r = U::regs(); | ||
| 281 | let s = U::buffered_state(); | ||
| 282 | |||
| 283 | let buf_len = s.rx_buf.len(); | ||
| 284 | let half_len = buf_len / 2; | ||
| 285 | let mut tx = unsafe { s.tx_buf.reader() }; | ||
| 286 | let mut rx = unsafe { s.rx_buf.writer() }; | ||
| 287 | |||
| 288 | if r.events_error.read().bits() != 0 { | ||
| 289 | r.events_error.reset(); | ||
| 290 | let errs = r.errorsrc.read(); | ||
| 291 | r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) }); | ||
| 292 | |||
| 293 | if errs.overrun().bit() { | ||
| 294 | panic!("BufferedUarte overrun"); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | // Received some bytes, wake task. | ||
| 299 | if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 { | ||
| 300 | r.intenclr.write(|w| w.rxdrdy().clear()); | ||
| 301 | r.events_rxdrdy.reset(); | ||
| 302 | s.rx_waker.wake(); | ||
| 303 | } | ||
| 304 | |||
| 305 | // If not RXing, start. | ||
| 306 | if s.rx_bufs.load(Ordering::Relaxed) == 0 { | ||
| 307 | let (ptr, len) = rx.push_buf(); | ||
| 308 | if len >= half_len { | ||
| 309 | //trace!(" irq_rx: starting {:?}", half_len); | ||
| 310 | s.rx_bufs.store(1, Ordering::Relaxed); | ||
| 311 | |||
| 312 | // Set up the DMA read | ||
| 313 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 314 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); | ||
| 315 | |||
| 316 | // Start UARTE Receive transaction | ||
| 317 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 318 | rx.push_done(half_len); | ||
| 319 | r.intenset.write(|w| w.rxstarted().set()); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | if r.events_rxstarted.read().bits() != 0 { | ||
| 324 | //trace!(" irq_rx: rxstarted"); | ||
| 325 | let (ptr, len) = rx.push_buf(); | ||
| 326 | if len >= half_len { | ||
| 327 | //trace!(" irq_rx: starting second {:?}", half_len); | ||
| 328 | |||
| 329 | // Set up the DMA read | ||
| 330 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 331 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) }); | ||
| 332 | |||
| 333 | let chn = s.rx_ppi_ch.load(Ordering::Relaxed); | ||
| 334 | |||
| 335 | ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) }); | ||
| 336 | |||
| 337 | rx.push_done(half_len); | ||
| 338 | |||
| 339 | r.events_rxstarted.reset(); | ||
| 340 | } else { | ||
| 341 | //trace!(" irq_rx: rxstarted no buf"); | ||
| 342 | r.intenclr.write(|w| w.rxstarted().clear()); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | // ============================= | ||
| 347 | |||
| 348 | // TX end | ||
| 349 | if r.events_endtx.read().bits() != 0 { | ||
| 350 | r.events_endtx.reset(); | ||
| 351 | |||
| 352 | let n = s.tx_count.load(Ordering::Relaxed); | ||
| 353 | //trace!(" irq_tx: endtx {:?}", n); | ||
| 354 | tx.pop_done(n); | ||
| 355 | s.tx_waker.wake(); | ||
| 356 | s.tx_count.store(0, Ordering::Relaxed); | ||
| 357 | } | ||
| 358 | |||
| 359 | // If not TXing, start. | ||
| 360 | if s.tx_count.load(Ordering::Relaxed) == 0 { | ||
| 361 | let (ptr, len) = tx.pop_buf(); | ||
| 362 | if len != 0 { | ||
| 363 | //trace!(" irq_tx: starting {:?}", len); | ||
| 364 | s.tx_count.store(len, Ordering::Relaxed); | ||
| 365 | |||
| 366 | // Set up the DMA write | ||
| 367 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 368 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 369 | |||
| 370 | // Start UARTE Transmit transaction | ||
| 371 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | //trace!("irq: end"); | ||
| 376 | } | ||
| 377 | |||
| 378 | /// Adjust the baud rate to the provided value. | 381 | /// Adjust the baud rate to the provided value. |
| 379 | pub fn set_baudrate(&mut self, baudrate: Baudrate) { | 382 | pub fn set_baudrate(&mut self, baudrate: Baudrate) { |
| 380 | let r = U::regs(); | 383 | let r = U::regs(); |
