diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-01-13 22:24:13 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-01-13 23:56:39 +0100 |
| commit | 3e503e73356f4805d459d50fa1cded7b65ecd6d8 (patch) | |
| tree | 3398ee381190c0ad187dc5df30ee05e86540cc1d | |
| parent | c432d036c78480303827d832db3611cc7d2680f5 (diff) | |
nrf/uarte: expose all functionality as inherent methods.
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 441 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart.rs | 1 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart_idle.rs | 10 | ||||
| -rw-r--r-- | examples/nrf/src/bin/uart_split.rs | 9 |
4 files changed, 264 insertions, 197 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 38480ecca..07cec5d6b 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -13,12 +13,10 @@ | |||
| 13 | //! memory may be used given that buffers are passed in directly to its read and write | 13 | //! memory may be used given that buffers are passed in directly to its read and write |
| 14 | //! methods. | 14 | //! methods. |
| 15 | 15 | ||
| 16 | use core::future::Future; | ||
| 17 | use core::marker::PhantomData; | 16 | use core::marker::PhantomData; |
| 18 | use core::sync::atomic::{compiler_fence, Ordering}; | 17 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 19 | use core::task::Poll; | 18 | use core::task::Poll; |
| 20 | use embassy::interrupt::InterruptExt; | 19 | use embassy::interrupt::InterruptExt; |
| 21 | use embassy::traits::uart::{Error as TraitError, Read, ReadUntilIdle, Write}; | ||
| 22 | use embassy::util::Unborrow; | 20 | use embassy::util::Unborrow; |
| 23 | use embassy_hal_common::drop::OnDrop; | 21 | use embassy_hal_common::drop::OnDrop; |
| 24 | use embassy_hal_common::unborrow; | 22 | use embassy_hal_common::unborrow; |
| @@ -32,6 +30,7 @@ use crate::pac; | |||
| 32 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 30 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 33 | use crate::timer::Instance as TimerInstance; | 31 | use crate::timer::Instance as TimerInstance; |
| 34 | use crate::timer::{Frequency, Timer}; | 32 | use crate::timer::{Frequency, Timer}; |
| 33 | use crate::util::slice_in_ram_or; | ||
| 35 | 34 | ||
| 36 | // Re-export SVD variants to allow user to directly set values. | 35 | // Re-export SVD variants to allow user to directly set values. |
| 37 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 36 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| @@ -51,6 +50,16 @@ impl Default for Config { | |||
| 51 | } | 50 | } |
| 52 | } | 51 | } |
| 53 | 52 | ||
| 53 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| 54 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 55 | #[non_exhaustive] | ||
| 56 | pub enum Error { | ||
| 57 | BufferTooLong, | ||
| 58 | BufferZeroLength, | ||
| 59 | DMABufferNotInDataMemory, | ||
| 60 | // TODO: add other error variants. | ||
| 61 | } | ||
| 62 | |||
| 54 | /// Interface to the UARTE peripheral | 63 | /// Interface to the UARTE peripheral |
| 55 | pub struct Uarte<'d, T: Instance> { | 64 | pub struct Uarte<'d, T: Instance> { |
| 56 | phantom: PhantomData<&'d mut T>, | 65 | phantom: PhantomData<&'d mut T>, |
| @@ -139,8 +148,12 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 139 | 148 | ||
| 140 | Self { | 149 | Self { |
| 141 | phantom: PhantomData, | 150 | phantom: PhantomData, |
| 142 | tx: UarteTx::new(), | 151 | tx: UarteTx { |
| 143 | rx: UarteRx::new(), | 152 | phantom: PhantomData, |
| 153 | }, | ||
| 154 | rx: UarteRx { | ||
| 155 | phantom: PhantomData, | ||
| 156 | }, | ||
| 144 | } | 157 | } |
| 145 | } | 158 | } |
| 146 | 159 | ||
| @@ -170,92 +183,110 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 170 | r.intenclr.write(|w| w.endtx().clear()); | 183 | r.intenclr.write(|w| w.endtx().clear()); |
| 171 | } | 184 | } |
| 172 | } | 185 | } |
| 173 | } | ||
| 174 | 186 | ||
| 175 | impl<'d, T: Instance> Read for Uarte<'d, T> { | 187 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 176 | type ReadFuture<'a> | 188 | self.rx.read(buffer).await |
| 177 | where | 189 | } |
| 178 | Self: 'a, | ||
| 179 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 180 | 190 | ||
| 181 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 191 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 182 | self.rx.read(rx_buffer) | 192 | self.tx.write(buffer).await |
| 183 | } | 193 | } |
| 184 | } | ||
| 185 | 194 | ||
| 186 | impl<'d, T: Instance> Write for Uarte<'d, T> { | 195 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 187 | type WriteFuture<'a> | 196 | self.rx.blocking_read(buffer) |
| 188 | where | 197 | } |
| 189 | Self: 'a, | ||
| 190 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 191 | 198 | ||
| 192 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 199 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 193 | self.tx.write(tx_buffer) | 200 | self.tx.blocking_write(buffer) |
| 194 | } | 201 | } |
| 195 | } | 202 | } |
| 196 | 203 | ||
| 197 | impl<'d, T: Instance> UarteTx<'d, T> { | 204 | impl<'d, T: Instance> UarteTx<'d, T> { |
| 198 | pub fn new() -> Self { | 205 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 199 | Self { | 206 | slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; |
| 200 | phantom: PhantomData, | 207 | if buffer.len() == 0 { |
| 208 | return Err(Error::BufferZeroLength); | ||
| 209 | } | ||
| 210 | if buffer.len() > EASY_DMA_SIZE { | ||
| 211 | return Err(Error::BufferTooLong); | ||
| 201 | } | 212 | } |
| 202 | } | ||
| 203 | } | ||
| 204 | 213 | ||
| 205 | impl<'d, T: Instance> Write for UarteTx<'d, T> { | 214 | let ptr = buffer.as_ptr(); |
| 206 | type WriteFuture<'a> | 215 | let len = buffer.len(); |
| 207 | where | ||
| 208 | Self: 'a, | ||
| 209 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 210 | 216 | ||
| 211 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 217 | let r = T::regs(); |
| 212 | async move { | 218 | let s = T::state(); |
| 213 | let ptr = tx_buffer.as_ptr(); | ||
| 214 | let len = tx_buffer.len(); | ||
| 215 | assert!(len <= EASY_DMA_SIZE); | ||
| 216 | // TODO: panic if buffer is not in SRAM | ||
| 217 | 219 | ||
| 218 | let r = T::regs(); | 220 | let drop = OnDrop::new(move || { |
| 219 | let s = T::state(); | 221 | trace!("write drop: stopping"); |
| 220 | 222 | ||
| 221 | let drop = OnDrop::new(move || { | 223 | r.intenclr.write(|w| w.endtx().clear()); |
| 222 | trace!("write drop: stopping"); | 224 | r.events_txstopped.reset(); |
| 225 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | ||
| 223 | 226 | ||
| 224 | r.intenclr.write(|w| w.endtx().clear()); | 227 | // TX is stopped almost instantly, spinning is fine. |
| 225 | r.events_txstopped.reset(); | 228 | while r.events_endtx.read().bits() == 0 {} |
| 226 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | 229 | trace!("write drop: stopped"); |
| 230 | }); | ||
| 227 | 231 | ||
| 228 | // TX is stopped almost instantly, spinning is fine. | 232 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 229 | while r.events_endtx.read().bits() == 0 {} | 233 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 230 | trace!("write drop: stopped"); | ||
| 231 | }); | ||
| 232 | 234 | ||
| 233 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 235 | r.events_endtx.reset(); |
| 234 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 236 | r.intenset.write(|w| w.endtx().set()); |
| 235 | 237 | ||
| 236 | r.events_endtx.reset(); | 238 | compiler_fence(Ordering::SeqCst); |
| 237 | r.intenset.write(|w| w.endtx().set()); | ||
| 238 | 239 | ||
| 239 | compiler_fence(Ordering::SeqCst); | 240 | trace!("starttx"); |
| 241 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 240 | 242 | ||
| 241 | trace!("starttx"); | 243 | poll_fn(|cx| { |
| 242 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 244 | s.endtx_waker.register(cx.waker()); |
| 245 | if r.events_endtx.read().bits() != 0 { | ||
| 246 | return Poll::Ready(()); | ||
| 247 | } | ||
| 248 | Poll::Pending | ||
| 249 | }) | ||
| 250 | .await; | ||
| 243 | 251 | ||
| 244 | poll_fn(|cx| { | 252 | compiler_fence(Ordering::SeqCst); |
| 245 | s.endtx_waker.register(cx.waker()); | 253 | r.events_txstarted.reset(); |
| 246 | if r.events_endtx.read().bits() != 0 { | 254 | drop.defuse(); |
| 247 | return Poll::Ready(()); | ||
| 248 | } | ||
| 249 | Poll::Pending | ||
| 250 | }) | ||
| 251 | .await; | ||
| 252 | 255 | ||
| 253 | compiler_fence(Ordering::SeqCst); | 256 | Ok(()) |
| 254 | r.events_txstarted.reset(); | 257 | } |
| 255 | drop.defuse(); | ||
| 256 | 258 | ||
| 257 | Ok(()) | 259 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 260 | slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; | ||
| 261 | if buffer.len() == 0 { | ||
| 262 | return Err(Error::BufferZeroLength); | ||
| 263 | } | ||
| 264 | if buffer.len() > EASY_DMA_SIZE { | ||
| 265 | return Err(Error::BufferTooLong); | ||
| 258 | } | 266 | } |
| 267 | |||
| 268 | let ptr = buffer.as_ptr(); | ||
| 269 | let len = buffer.len(); | ||
| 270 | |||
| 271 | let r = T::regs(); | ||
| 272 | |||
| 273 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 274 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 275 | |||
| 276 | r.events_endtx.reset(); | ||
| 277 | r.intenclr.write(|w| w.endtx().clear()); | ||
| 278 | |||
| 279 | compiler_fence(Ordering::SeqCst); | ||
| 280 | |||
| 281 | trace!("starttx"); | ||
| 282 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 283 | |||
| 284 | while r.events_endtx.read().bits() == 0 {} | ||
| 285 | |||
| 286 | compiler_fence(Ordering::SeqCst); | ||
| 287 | r.events_txstarted.reset(); | ||
| 288 | |||
| 289 | Ok(()) | ||
| 259 | } | 290 | } |
| 260 | } | 291 | } |
| 261 | 292 | ||
| @@ -278,66 +309,89 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> { | |||
| 278 | } | 309 | } |
| 279 | 310 | ||
| 280 | impl<'d, T: Instance> UarteRx<'d, T> { | 311 | impl<'d, T: Instance> UarteRx<'d, T> { |
| 281 | pub fn new() -> Self { | 312 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 282 | Self { | 313 | if buffer.len() == 0 { |
| 283 | phantom: PhantomData, | 314 | return Err(Error::BufferZeroLength); |
| 315 | } | ||
| 316 | if buffer.len() > EASY_DMA_SIZE { | ||
| 317 | return Err(Error::BufferTooLong); | ||
| 284 | } | 318 | } |
| 285 | } | ||
| 286 | } | ||
| 287 | 319 | ||
| 288 | impl<'d, T: Instance> Read for UarteRx<'d, T> { | 320 | let ptr = buffer.as_ptr(); |
| 289 | type ReadFuture<'a> | 321 | let len = buffer.len(); |
| 290 | where | ||
| 291 | Self: 'a, | ||
| 292 | = impl Future<Output = Result<(), TraitError>> + 'a; | ||
| 293 | 322 | ||
| 294 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 323 | let r = T::regs(); |
| 295 | async move { | 324 | let s = T::state(); |
| 296 | let ptr = rx_buffer.as_ptr(); | ||
| 297 | let len = rx_buffer.len(); | ||
| 298 | assert!(len <= EASY_DMA_SIZE); | ||
| 299 | 325 | ||
| 300 | let r = T::regs(); | 326 | let drop = OnDrop::new(move || { |
| 301 | let s = T::state(); | 327 | trace!("read drop: stopping"); |
| 302 | 328 | ||
| 303 | let drop = OnDrop::new(move || { | 329 | r.intenclr.write(|w| w.endrx().clear()); |
| 304 | trace!("read drop: stopping"); | 330 | r.events_rxto.reset(); |
| 331 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 305 | 332 | ||
| 306 | r.intenclr.write(|w| w.endrx().clear()); | 333 | while r.events_endrx.read().bits() == 0 {} |
| 307 | r.events_rxto.reset(); | ||
| 308 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 309 | 334 | ||
| 310 | while r.events_endrx.read().bits() == 0 {} | 335 | trace!("read drop: stopped"); |
| 336 | }); | ||
| 311 | 337 | ||
| 312 | trace!("read drop: stopped"); | 338 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 313 | }); | 339 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 314 | 340 | ||
| 315 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 341 | r.events_endrx.reset(); |
| 316 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 342 | r.intenset.write(|w| w.endrx().set()); |
| 317 | 343 | ||
| 318 | r.events_endrx.reset(); | 344 | compiler_fence(Ordering::SeqCst); |
| 319 | r.intenset.write(|w| w.endrx().set()); | ||
| 320 | 345 | ||
| 321 | compiler_fence(Ordering::SeqCst); | 346 | trace!("startrx"); |
| 347 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 322 | 348 | ||
| 323 | trace!("startrx"); | 349 | poll_fn(|cx| { |
| 324 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 350 | s.endrx_waker.register(cx.waker()); |
| 351 | if r.events_endrx.read().bits() != 0 { | ||
| 352 | return Poll::Ready(()); | ||
| 353 | } | ||
| 354 | Poll::Pending | ||
| 355 | }) | ||
| 356 | .await; | ||
| 325 | 357 | ||
| 326 | poll_fn(|cx| { | 358 | compiler_fence(Ordering::SeqCst); |
| 327 | s.endrx_waker.register(cx.waker()); | 359 | r.events_rxstarted.reset(); |
| 328 | if r.events_endrx.read().bits() != 0 { | 360 | drop.defuse(); |
| 329 | return Poll::Ready(()); | ||
| 330 | } | ||
| 331 | Poll::Pending | ||
| 332 | }) | ||
| 333 | .await; | ||
| 334 | 361 | ||
| 335 | compiler_fence(Ordering::SeqCst); | 362 | Ok(()) |
| 336 | r.events_rxstarted.reset(); | 363 | } |
| 337 | drop.defuse(); | ||
| 338 | 364 | ||
| 339 | Ok(()) | 365 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 366 | if buffer.len() == 0 { | ||
| 367 | return Err(Error::BufferZeroLength); | ||
| 368 | } | ||
| 369 | if buffer.len() > EASY_DMA_SIZE { | ||
| 370 | return Err(Error::BufferTooLong); | ||
| 340 | } | 371 | } |
| 372 | |||
| 373 | let ptr = buffer.as_ptr(); | ||
| 374 | let len = buffer.len(); | ||
| 375 | |||
| 376 | let r = T::regs(); | ||
| 377 | |||
| 378 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 379 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 380 | |||
| 381 | r.events_endrx.reset(); | ||
| 382 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 383 | |||
| 384 | compiler_fence(Ordering::SeqCst); | ||
| 385 | |||
| 386 | trace!("startrx"); | ||
| 387 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 388 | |||
| 389 | while r.events_endrx.read().bits() == 0 {} | ||
| 390 | |||
| 391 | compiler_fence(Ordering::SeqCst); | ||
| 392 | r.events_rxstarted.reset(); | ||
| 393 | |||
| 394 | Ok(()) | ||
| 341 | } | 395 | } |
| 342 | } | 396 | } |
| 343 | 397 | ||
| @@ -439,14 +493,7 @@ pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { | |||
| 439 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | 493 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { |
| 440 | /// Creates the interface to a UARTE instance. | 494 | /// Creates the interface to a UARTE instance. |
| 441 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | 495 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. |
| 442 | /// | 496 | pub fn new( |
| 443 | /// # Safety | ||
| 444 | /// | ||
| 445 | /// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms) | ||
| 446 | /// on stack allocated buffers which which have been passed to [`send()`](Uarte::send) | ||
| 447 | /// or [`receive`](Uarte::receive). | ||
| 448 | #[allow(unused_unsafe)] | ||
| 449 | pub unsafe fn new( | ||
| 450 | uarte: impl Unborrow<Target = U> + 'd, | 497 | uarte: impl Unborrow<Target = U> + 'd, |
| 451 | timer: impl Unborrow<Target = T> + 'd, | 498 | timer: impl Unborrow<Target = T> + 'd, |
| 452 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | 499 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, |
| @@ -501,93 +548,119 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | |||
| 501 | _ppi_ch2: ppi_ch2, | 548 | _ppi_ch2: ppi_ch2, |
| 502 | } | 549 | } |
| 503 | } | 550 | } |
| 504 | } | ||
| 505 | 551 | ||
| 506 | impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> { | 552 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 507 | type ReadUntilIdleFuture<'a> | 553 | self.ppi_ch1.disable(); |
| 508 | where | 554 | self.uarte.read(buffer).await |
| 509 | Self: 'a, | 555 | } |
| 510 | = impl Future<Output = Result<usize, TraitError>> + 'a; | ||
| 511 | fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> { | ||
| 512 | async move { | ||
| 513 | let ptr = rx_buffer.as_ptr(); | ||
| 514 | let len = rx_buffer.len(); | ||
| 515 | assert!(len <= EASY_DMA_SIZE); | ||
| 516 | 556 | ||
| 517 | let r = U::regs(); | 557 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 518 | let s = U::state(); | 558 | self.uarte.write(buffer).await |
| 559 | } | ||
| 519 | 560 | ||
| 520 | let drop = OnDrop::new(|| { | 561 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 521 | trace!("read drop: stopping"); | 562 | self.ppi_ch1.disable(); |
| 563 | self.uarte.blocking_read(buffer) | ||
| 564 | } | ||
| 522 | 565 | ||
| 523 | self.timer.stop(); | 566 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 567 | self.uarte.blocking_write(buffer) | ||
| 568 | } | ||
| 524 | 569 | ||
| 525 | r.intenclr.write(|w| w.endrx().clear()); | 570 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 526 | r.events_rxto.reset(); | 571 | if buffer.len() == 0 { |
| 527 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 572 | return Err(Error::BufferZeroLength); |
| 573 | } | ||
| 574 | if buffer.len() > EASY_DMA_SIZE { | ||
| 575 | return Err(Error::BufferTooLong); | ||
| 576 | } | ||
| 528 | 577 | ||
| 529 | while r.events_endrx.read().bits() == 0 {} | 578 | let ptr = buffer.as_ptr(); |
| 579 | let len = buffer.len(); | ||
| 530 | 580 | ||
| 531 | trace!("read drop: stopped"); | 581 | let r = U::regs(); |
| 532 | }); | 582 | let s = U::state(); |
| 533 | 583 | ||
| 534 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 584 | self.ppi_ch1.enable(); |
| 535 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 536 | 585 | ||
| 537 | r.events_endrx.reset(); | 586 | let drop = OnDrop::new(|| { |
| 538 | r.intenset.write(|w| w.endrx().set()); | 587 | trace!("read drop: stopping"); |
| 539 | 588 | ||
| 540 | compiler_fence(Ordering::SeqCst); | 589 | self.timer.stop(); |
| 541 | 590 | ||
| 542 | trace!("startrx"); | 591 | r.intenclr.write(|w| w.endrx().clear()); |
| 543 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 592 | r.events_rxto.reset(); |
| 593 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 544 | 594 | ||
| 545 | poll_fn(|cx| { | 595 | while r.events_endrx.read().bits() == 0 {} |
| 546 | s.endrx_waker.register(cx.waker()); | ||
| 547 | if r.events_endrx.read().bits() != 0 { | ||
| 548 | return Poll::Ready(()); | ||
| 549 | } | ||
| 550 | Poll::Pending | ||
| 551 | }) | ||
| 552 | .await; | ||
| 553 | 596 | ||
| 554 | compiler_fence(Ordering::SeqCst); | 597 | trace!("read drop: stopped"); |
| 555 | let n = r.rxd.amount.read().amount().bits() as usize; | 598 | }); |
| 556 | 599 | ||
| 557 | // Stop timer | 600 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 558 | self.timer.stop(); | 601 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 559 | r.events_rxstarted.reset(); | ||
| 560 | 602 | ||
| 561 | drop.defuse(); | 603 | r.events_endrx.reset(); |
| 604 | r.intenset.write(|w| w.endrx().set()); | ||
| 562 | 605 | ||
| 563 | Ok(n) | 606 | compiler_fence(Ordering::SeqCst); |
| 564 | } | 607 | |
| 608 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 609 | |||
| 610 | poll_fn(|cx| { | ||
| 611 | s.endrx_waker.register(cx.waker()); | ||
| 612 | if r.events_endrx.read().bits() != 0 { | ||
| 613 | return Poll::Ready(()); | ||
| 614 | } | ||
| 615 | Poll::Pending | ||
| 616 | }) | ||
| 617 | .await; | ||
| 618 | |||
| 619 | compiler_fence(Ordering::SeqCst); | ||
| 620 | let n = r.rxd.amount.read().amount().bits() as usize; | ||
| 621 | |||
| 622 | self.timer.stop(); | ||
| 623 | r.events_rxstarted.reset(); | ||
| 624 | |||
| 625 | drop.defuse(); | ||
| 626 | |||
| 627 | Ok(n) | ||
| 565 | } | 628 | } |
| 566 | } | ||
| 567 | 629 | ||
| 568 | impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> { | 630 | pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 569 | type ReadFuture<'a> | 631 | if buffer.len() == 0 { |
| 570 | where | 632 | return Err(Error::BufferZeroLength); |
| 571 | Self: 'a, | 633 | } |
| 572 | = impl Future<Output = Result<(), TraitError>> + 'a; | 634 | if buffer.len() > EASY_DMA_SIZE { |
| 573 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 635 | return Err(Error::BufferTooLong); |
| 574 | async move { | ||
| 575 | self.ppi_ch1.disable(); | ||
| 576 | let result = self.uarte.read(rx_buffer).await; | ||
| 577 | self.ppi_ch1.enable(); | ||
| 578 | result | ||
| 579 | } | 636 | } |
| 580 | } | ||
| 581 | } | ||
| 582 | 637 | ||
| 583 | impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> { | 638 | let ptr = buffer.as_ptr(); |
| 584 | type WriteFuture<'a> | 639 | let len = buffer.len(); |
| 585 | where | 640 | |
| 586 | Self: 'a, | 641 | let r = U::regs(); |
| 587 | = impl Future<Output = Result<(), TraitError>> + 'a; | 642 | |
| 643 | self.ppi_ch1.enable(); | ||
| 644 | |||
| 645 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 646 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 647 | |||
| 648 | r.events_endrx.reset(); | ||
| 649 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 650 | |||
| 651 | compiler_fence(Ordering::SeqCst); | ||
| 652 | |||
| 653 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 654 | |||
| 655 | while r.events_endrx.read().bits() == 0 {} | ||
| 656 | |||
| 657 | compiler_fence(Ordering::SeqCst); | ||
| 658 | let n = r.rxd.amount.read().amount().bits() as usize; | ||
| 659 | |||
| 660 | self.timer.stop(); | ||
| 661 | r.events_rxstarted.reset(); | ||
| 588 | 662 | ||
| 589 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 663 | Ok(n) |
| 590 | self.uarte.write(tx_buffer) | ||
| 591 | } | 664 | } |
| 592 | } | 665 | } |
| 593 | 666 | ||
diff --git a/examples/nrf/src/bin/uart.rs b/examples/nrf/src/bin/uart.rs index 208961c8b..68ee3978a 100644 --- a/examples/nrf/src/bin/uart.rs +++ b/examples/nrf/src/bin/uart.rs | |||
| @@ -7,7 +7,6 @@ mod example_common; | |||
| 7 | use example_common::*; | 7 | use example_common::*; |
| 8 | 8 | ||
| 9 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 10 | use embassy::traits::uart::{Read, Write}; | ||
| 11 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 12 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 11 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 13 | 12 | ||
diff --git a/examples/nrf/src/bin/uart_idle.rs b/examples/nrf/src/bin/uart_idle.rs index ec9a36026..76449c0e3 100644 --- a/examples/nrf/src/bin/uart_idle.rs +++ b/examples/nrf/src/bin/uart_idle.rs | |||
| @@ -4,11 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #[path = "../example_common.rs"] | 5 | #[path = "../example_common.rs"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use embassy_traits::uart::ReadUntilIdle; | ||
| 8 | use example_common::*; | 7 | use example_common::*; |
| 9 | 8 | ||
| 10 | use embassy::executor::Spawner; | 9 | use embassy::executor::Spawner; |
| 11 | use embassy::traits::uart::Write; | ||
| 12 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 13 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 11 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 14 | 12 | ||
| @@ -19,11 +17,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 19 | config.baudrate = uarte::Baudrate::BAUD115200; | 17 | config.baudrate = uarte::Baudrate::BAUD115200; |
| 20 | 18 | ||
| 21 | let irq = interrupt::take!(UARTE0_UART0); | 19 | let irq = interrupt::take!(UARTE0_UART0); |
| 22 | let mut uart = unsafe { | 20 | let mut uart = uarte::UarteWithIdle::new( |
| 23 | uarte::UarteWithIdle::new( | 21 | p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, |
| 24 | p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, | 22 | ); |
| 25 | ) | ||
| 26 | }; | ||
| 27 | 23 | ||
| 28 | info!("uarte initialized!"); | 24 | info!("uarte initialized!"); |
| 29 | 25 | ||
diff --git a/examples/nrf/src/bin/uart_split.rs b/examples/nrf/src/bin/uart_split.rs index 4b5dbb21f..a9c02e796 100644 --- a/examples/nrf/src/bin/uart_split.rs +++ b/examples/nrf/src/bin/uart_split.rs | |||
| @@ -4,16 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | #[path = "../example_common.rs"] | 5 | #[path = "../example_common.rs"] |
| 6 | mod example_common; | 6 | mod example_common; |
| 7 | use example_common::*; | ||
| 8 | |||
| 7 | use embassy::blocking_mutex::kind::Noop; | 9 | use embassy::blocking_mutex::kind::Noop; |
| 8 | use embassy::channel::mpsc::{self, Channel, Sender}; | 10 | use embassy::channel::mpsc::{self, Channel, Sender}; |
| 11 | use embassy::executor::Spawner; | ||
| 9 | use embassy::util::Forever; | 12 | use embassy::util::Forever; |
| 13 | use embassy_nrf::gpio::NoPin; | ||
| 10 | use embassy_nrf::peripherals::UARTE0; | 14 | use embassy_nrf::peripherals::UARTE0; |
| 11 | use embassy_nrf::uarte::UarteRx; | 15 | use embassy_nrf::uarte::UarteRx; |
| 12 | use example_common::*; | ||
| 13 | |||
| 14 | use embassy::executor::Spawner; | ||
| 15 | use embassy::traits::uart::{Read, Write}; | ||
| 16 | use embassy_nrf::gpio::NoPin; | ||
| 17 | use embassy_nrf::{interrupt, uarte, Peripherals}; | 16 | use embassy_nrf::{interrupt, uarte, Peripherals}; |
| 18 | 17 | ||
| 19 | static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new(); | 18 | static CHANNEL: Forever<Channel<Noop, [u8; 8], 1>> = Forever::new(); |
