diff options
Diffstat (limited to 'embassy-rp')
| -rw-r--r-- | embassy-rp/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-rp/src/pio/mod.rs | 26 | ||||
| -rw-r--r-- | embassy-rp/src/uart/buffered.rs | 13 | ||||
| -rw-r--r-- | embassy-rp/src/uart/mod.rs | 28 |
4 files changed, 52 insertions, 18 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 9ad4b47a3..421f0b0f6 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml | |||
| @@ -47,7 +47,7 @@ rt = [ "rp-pac/rt" ] | |||
| 47 | defmt = ["dep:defmt", "embassy-usb-driver/defmt", "embassy-hal-internal/defmt"] | 47 | defmt = ["dep:defmt", "embassy-usb-driver/defmt", "embassy-hal-internal/defmt"] |
| 48 | ## Enable log support | 48 | ## Enable log support |
| 49 | log = ["dep:log"] | 49 | log = ["dep:log"] |
| 50 | ## Enable chrono support | 50 | ## Enable chrono support |
| 51 | chrono = ["dep:chrono"] | 51 | chrono = ["dep:chrono"] |
| 52 | 52 | ||
| 53 | ## Configure the [`critical-section`](https://docs.rs/critical-section) crate to use an implementation that is safe for multicore use on rp2040. | 53 | ## Configure the [`critical-section`](https://docs.rs/critical-section) crate to use an implementation that is safe for multicore use on rp2040. |
| @@ -159,7 +159,6 @@ embassy-futures = { version = "0.1.2", path = "../embassy-futures" } | |||
| 159 | embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } | 159 | embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } |
| 160 | embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } | 160 | embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } |
| 161 | embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } | 161 | embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } |
| 162 | atomic-polyfill = "1.0.1" | ||
| 163 | defmt = { version = "1.0.1", optional = true } | 162 | defmt = { version = "1.0.1", optional = true } |
| 164 | log = { version = "0.4.14", optional = true } | 163 | log = { version = "0.4.14", optional = true } |
| 165 | nb = "1.1.0" | 164 | nb = "1.1.0" |
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index 92b2c603e..fd0b4c072 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | //! PIO driver. | 1 | //! PIO driver. |
| 2 | use core::cell::Cell; | ||
| 2 | use core::future::Future; | 3 | use core::future::Future; |
| 3 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 4 | use core::pin::Pin as FuturePin; | 5 | use core::pin::Pin as FuturePin; |
| 5 | use core::sync::atomic::{Ordering, compiler_fence}; | 6 | use core::sync::atomic::{AtomicU8, Ordering, compiler_fence}; |
| 6 | use core::task::{Context, Poll}; | 7 | use core::task::{Context, Poll}; |
| 7 | 8 | ||
| 8 | use atomic_polyfill::{AtomicU8, AtomicU64}; | ||
| 9 | use embassy_hal_internal::{Peri, PeripheralType}; | 9 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | use fixed::FixedU32; | 11 | use fixed::FixedU32; |
| @@ -1232,7 +1232,10 @@ impl<'d, PIO: Instance> Common<'d, PIO> { | |||
| 1232 | w.set_pde(false); | 1232 | w.set_pde(false); |
| 1233 | }); | 1233 | }); |
| 1234 | // we can be relaxed about this because we're &mut here and nothing is cached | 1234 | // we can be relaxed about this because we're &mut here and nothing is cached |
| 1235 | PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed); | 1235 | critical_section::with(|_| { |
| 1236 | let val = PIO::state().used_pins.get(); | ||
| 1237 | PIO::state().used_pins.set(val | 1 << pin.pin_bank()); | ||
| 1238 | }); | ||
| 1236 | Pin { | 1239 | Pin { |
| 1237 | pin: pin.into(), | 1240 | pin: pin.into(), |
| 1238 | pio: PhantomData::default(), | 1241 | pio: PhantomData::default(), |
| @@ -1369,7 +1372,7 @@ impl<'d, PIO: Instance> Pio<'d, PIO> { | |||
| 1369 | /// Create a new instance of a PIO peripheral. | 1372 | /// Create a new instance of a PIO peripheral. |
| 1370 | pub fn new(_pio: Peri<'d, PIO>, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { | 1373 | pub fn new(_pio: Peri<'d, PIO>, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { |
| 1371 | PIO::state().users.store(5, Ordering::Release); | 1374 | PIO::state().users.store(5, Ordering::Release); |
| 1372 | PIO::state().used_pins.store(0, Ordering::Release); | 1375 | critical_section::with(|_| PIO::state().used_pins.set(0)); |
| 1373 | PIO::Interrupt::unpend(); | 1376 | PIO::Interrupt::unpend(); |
| 1374 | 1377 | ||
| 1375 | unsafe { PIO::Interrupt::enable() }; | 1378 | unsafe { PIO::Interrupt::enable() }; |
| @@ -1413,13 +1416,20 @@ impl<'d, PIO: Instance> Pio<'d, PIO> { | |||
| 1413 | // other way. | 1416 | // other way. |
| 1414 | pub struct State { | 1417 | pub struct State { |
| 1415 | users: AtomicU8, | 1418 | users: AtomicU8, |
| 1416 | used_pins: AtomicU64, | 1419 | used_pins: Cell<u64>, |
| 1417 | } | 1420 | } |
| 1418 | 1421 | ||
| 1422 | unsafe impl Sync for State {} | ||
| 1423 | |||
| 1419 | fn on_pio_drop<PIO: Instance>() { | 1424 | fn on_pio_drop<PIO: Instance>() { |
| 1420 | let state = PIO::state(); | 1425 | let state = PIO::state(); |
| 1421 | if state.users.fetch_sub(1, Ordering::AcqRel) == 1 { | 1426 | let users_state = critical_section::with(|_| { |
| 1422 | let used_pins = state.used_pins.load(Ordering::Relaxed); | 1427 | let val = state.users.load(Ordering::Acquire) - 1; |
| 1428 | state.users.store(val, Ordering::Release); | ||
| 1429 | val | ||
| 1430 | }); | ||
| 1431 | if users_state == 1 { | ||
| 1432 | let used_pins = critical_section::with(|_| state.used_pins.get()); | ||
| 1423 | let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; | 1433 | let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; |
| 1424 | for i in 0..crate::gpio::BANK0_PIN_COUNT { | 1434 | for i in 0..crate::gpio::BANK0_PIN_COUNT { |
| 1425 | if used_pins & (1 << i) != 0 { | 1435 | if used_pins & (1 << i) != 0 { |
| @@ -1444,7 +1454,7 @@ trait SealedInstance { | |||
| 1444 | fn state() -> &'static State { | 1454 | fn state() -> &'static State { |
| 1445 | static STATE: State = State { | 1455 | static STATE: State = State { |
| 1446 | users: AtomicU8::new(0), | 1456 | users: AtomicU8::new(0), |
| 1447 | used_pins: AtomicU64::new(0), | 1457 | used_pins: Cell::new(0), |
| 1448 | }; | 1458 | }; |
| 1449 | 1459 | ||
| 1450 | &STATE | 1460 | &STATE |
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 02649ad81..fdb8ce776 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | //! Buffered UART driver. | 1 | //! Buffered UART driver. |
| 2 | use core::future::Future; | 2 | use core::future::Future; |
| 3 | use core::slice; | 3 | use core::slice; |
| 4 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 4 | 5 | ||
| 5 | use atomic_polyfill::AtomicU8; | ||
| 6 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; | 6 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; |
| 7 | 7 | ||
| 8 | use super::*; | 8 | use super::*; |
| @@ -241,7 +241,11 @@ impl BufferedUartRx { | |||
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | fn get_rx_error(state: &State) -> Option<Error> { | 243 | fn get_rx_error(state: &State) -> Option<Error> { |
| 244 | let errs = state.rx_error.swap(0, Ordering::Relaxed); | 244 | let errs = critical_section::with(|_| { |
| 245 | let val = state.rx_error.load(Ordering::Relaxed); | ||
| 246 | state.rx_error.store(0, Ordering::Relaxed); | ||
| 247 | val | ||
| 248 | }); | ||
| 245 | if errs & RXE_OVERRUN != 0 { | 249 | if errs & RXE_OVERRUN != 0 { |
| 246 | Some(Error::Overrun) | 250 | Some(Error::Overrun) |
| 247 | } else if errs & RXE_BREAK != 0 { | 251 | } else if errs & RXE_BREAK != 0 { |
| @@ -555,7 +559,10 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterr | |||
| 555 | } | 559 | } |
| 556 | let dr = r.uartdr().read(); | 560 | let dr = r.uartdr().read(); |
| 557 | if (dr.0 >> 8) != 0 { | 561 | if (dr.0 >> 8) != 0 { |
| 558 | s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); | 562 | critical_section::with(|_| { |
| 563 | let val = s.rx_error.load(Ordering::Relaxed); | ||
| 564 | s.rx_error.store(val | ((dr.0 >> 8) as u8), Ordering::Relaxed); | ||
| 565 | }); | ||
| 559 | error = true; | 566 | error = true; |
| 560 | // only fill the buffer with valid characters. the current character is fine | 567 | // only fill the buffer with valid characters. the current character is fine |
| 561 | // if the error is an overrun, but if we add it to the buffer we'll report | 568 | // if the error is an overrun, but if we add it to the buffer we'll report |
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 8be87a5d2..b7b569dd5 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | //! UART driver. | 1 | //! UART driver. |
| 2 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 3 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 4 | use core::sync::atomic::{AtomicU16, Ordering}; | ||
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use atomic_polyfill::{AtomicU16, Ordering}; | ||
| 7 | use embassy_futures::select::{Either, select}; | 7 | use embassy_futures::select::{Either, select}; |
| 8 | use embassy_hal_internal::{Peri, PeripheralType}; | 8 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| @@ -456,7 +456,12 @@ impl<'d> UartRx<'d, Async> { | |||
| 456 | transfer, | 456 | transfer, |
| 457 | poll_fn(|cx| { | 457 | poll_fn(|cx| { |
| 458 | self.dma_state.rx_err_waker.register(cx.waker()); | 458 | self.dma_state.rx_err_waker.register(cx.waker()); |
| 459 | match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) { | 459 | let rx_errs = critical_section::with(|_| { |
| 460 | let val = self.dma_state.rx_errs.load(Ordering::Relaxed); | ||
| 461 | self.dma_state.rx_errs.store(0, Ordering::Relaxed); | ||
| 462 | val | ||
| 463 | }); | ||
| 464 | match rx_errs { | ||
| 460 | 0 => Poll::Pending, | 465 | 0 => Poll::Pending, |
| 461 | e => Poll::Ready(Uartris(e as u32)), | 466 | e => Poll::Ready(Uartris(e as u32)), |
| 462 | } | 467 | } |
| @@ -468,7 +473,11 @@ impl<'d> UartRx<'d, Async> { | |||
| 468 | Either::First(()) => { | 473 | Either::First(()) => { |
| 469 | // We're here because the DMA finished, BUT if an error occurred on the LAST | 474 | // We're here because the DMA finished, BUT if an error occurred on the LAST |
| 470 | // byte, then we may still need to grab the error state! | 475 | // byte, then we may still need to grab the error state! |
| 471 | Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32) | 476 | Uartris(critical_section::with(|_| { |
| 477 | let val = self.dma_state.rx_errs.load(Ordering::Relaxed); | ||
| 478 | self.dma_state.rx_errs.store(0, Ordering::Relaxed); | ||
| 479 | val | ||
| 480 | }) as u32) | ||
| 472 | } | 481 | } |
| 473 | Either::Second(e) => { | 482 | Either::Second(e) => { |
| 474 | // We're here because we errored, which means this is the error that | 483 | // We're here because we errored, which means this is the error that |
| @@ -616,7 +625,12 @@ impl<'d> UartRx<'d, Async> { | |||
| 616 | transfer, | 625 | transfer, |
| 617 | poll_fn(|cx| { | 626 | poll_fn(|cx| { |
| 618 | self.dma_state.rx_err_waker.register(cx.waker()); | 627 | self.dma_state.rx_err_waker.register(cx.waker()); |
| 619 | match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) { | 628 | let rx_errs = critical_section::with(|_| { |
| 629 | let val = self.dma_state.rx_errs.load(Ordering::Relaxed); | ||
| 630 | self.dma_state.rx_errs.store(0, Ordering::Relaxed); | ||
| 631 | val | ||
| 632 | }); | ||
| 633 | match rx_errs { | ||
| 620 | 0 => Poll::Pending, | 634 | 0 => Poll::Pending, |
| 621 | e => Poll::Ready(Uartris(e as u32)), | 635 | e => Poll::Ready(Uartris(e as u32)), |
| 622 | } | 636 | } |
| @@ -629,7 +643,11 @@ impl<'d> UartRx<'d, Async> { | |||
| 629 | Either::First(()) => { | 643 | Either::First(()) => { |
| 630 | // We're here because the DMA finished, BUT if an error occurred on the LAST | 644 | // We're here because the DMA finished, BUT if an error occurred on the LAST |
| 631 | // byte, then we may still need to grab the error state! | 645 | // byte, then we may still need to grab the error state! |
| 632 | Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32) | 646 | Uartris(critical_section::with(|_| { |
| 647 | let val = self.dma_state.rx_errs.load(Ordering::Relaxed); | ||
| 648 | self.dma_state.rx_errs.store(0, Ordering::Relaxed); | ||
| 649 | val | ||
| 650 | }) as u32) | ||
| 633 | } | 651 | } |
| 634 | Either::Second(e) => { | 652 | Either::Second(e) => { |
| 635 | // We're here because we errored, which means this is the error that | 653 | // We're here because we errored, which means this is the error that |
