aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/CHANGELOG.md2
-rw-r--r--embassy-rp/Cargo.toml3
-rw-r--r--embassy-rp/src/pio/mod.rs54
-rw-r--r--embassy-rp/src/uart/buffered.rs13
-rw-r--r--embassy-rp/src/uart/mod.rs28
5 files changed, 85 insertions, 15 deletions
diff --git a/embassy-rp/CHANGELOG.md b/embassy-rp/CHANGELOG.md
index fa8609bbf..7480b729f 100644
--- a/embassy-rp/CHANGELOG.md
+++ b/embassy-rp/CHANGELOG.md
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
19- Add fix #4822 in PIO onewire. Change to disable the state machine before setting y register ([#4824](https://github.com/embassy-rs/embassy/pull/4824)) 19- Add fix #4822 in PIO onewire. Change to disable the state machine before setting y register ([#4824](https://github.com/embassy-rs/embassy/pull/4824))
20- Add PIO::Ws2812 color order support 20- Add PIO::Ws2812 color order support
21- Add TX-only, no SCK SPI support 21- Add TX-only, no SCK SPI support
22- Remove atomic-polyfill with critical-section instead ([#4948](https://github.com/embassy-rs/embassy/pull/4948))
22 23
23## 0.8.0 - 2025-08-26 24## 0.8.0 - 2025-08-26
24 25
@@ -116,4 +117,3 @@ Small release fixing a few gnarly bugs, upgrading is strongly recommended.
116- rename the Channel trait to Slice and the PwmPin to PwmChannel 117- rename the Channel trait to Slice and the PwmPin to PwmChannel
117- i2c: Fix race condition that appears on fast repeated transfers. 118- i2c: Fix race condition that appears on fast repeated transfers.
118- Add a basic "read to break" function 119- Add a basic "read to break" function
119
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" ]
47defmt = ["dep:defmt", "embassy-usb-driver/defmt", "embassy-hal-internal/defmt"] 47defmt = ["dep:defmt", "embassy-usb-driver/defmt", "embassy-hal-internal/defmt"]
48## Enable log support 48## Enable log support
49log = ["dep:log"] 49log = ["dep:log"]
50## Enable chrono support 50## Enable chrono support
51chrono = ["dep:chrono"] 51chrono = ["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" }
159embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } 159embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
160embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } 160embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" }
161embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" } 161embassy-usb-driver = { version = "0.2.0", path = "../embassy-usb-driver" }
162atomic-polyfill = "1.0.1"
163defmt = { version = "1.0.1", optional = true } 162defmt = { version = "1.0.1", optional = true }
164log = { version = "0.4.14", optional = true } 163log = { version = "0.4.14", optional = true }
165nb = "1.1.0" 164nb = "1.1.0"
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index 92b2c603e..1c370fdfc 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -2,10 +2,9 @@
2use core::future::Future; 2use core::future::Future;
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::pin::Pin as FuturePin; 4use core::pin::Pin as FuturePin;
5use core::sync::atomic::{Ordering, compiler_fence}; 5use core::sync::atomic::{AtomicU8, AtomicU32, Ordering, compiler_fence};
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use atomic_polyfill::{AtomicU8, AtomicU64};
9use embassy_hal_internal::{Peri, PeripheralType}; 8use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
11use fixed::FixedU32; 10use fixed::FixedU32;
@@ -1232,7 +1231,13 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
1232 w.set_pde(false); 1231 w.set_pde(false);
1233 }); 1232 });
1234 // we can be relaxed about this because we're &mut here and nothing is cached 1233 // 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); 1234 critical_section::with(|_| {
1235 let val = PIO::state().used_pins.load(Ordering::Relaxed);
1236 PIO::state()
1237 .used_pins
1238 .store(val | 1 << pin.pin_bank(), Ordering::Relaxed);
1239 });
1240
1236 Pin { 1241 Pin {
1237 pin: pin.into(), 1242 pin: pin.into(),
1238 pio: PhantomData::default(), 1243 pio: PhantomData::default(),
@@ -1404,6 +1409,42 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1404 } 1409 }
1405} 1410}
1406 1411
1412struct AtomicU64 {
1413 upper_32: AtomicU32,
1414 lower_32: AtomicU32,
1415}
1416
1417impl AtomicU64 {
1418 const fn new(val: u64) -> Self {
1419 let upper_32 = (val >> 32) as u32;
1420 let lower_32 = val as u32;
1421
1422 Self {
1423 upper_32: AtomicU32::new(upper_32),
1424 lower_32: AtomicU32::new(lower_32),
1425 }
1426 }
1427
1428 fn load(&self, order: Ordering) -> u64 {
1429 let (upper, lower) = critical_section::with(|_| (self.upper_32.load(order), self.lower_32.load(order)));
1430
1431 let upper = (upper as u64) << 32;
1432 let lower = lower as u64;
1433
1434 upper | lower
1435 }
1436
1437 fn store(&self, val: u64, order: Ordering) {
1438 let upper_32 = (val >> 32) as u32;
1439 let lower_32 = val as u32;
1440
1441 critical_section::with(|_| {
1442 self.upper_32.store(upper_32, order);
1443 self.lower_32.store(lower_32, order);
1444 });
1445 }
1446}
1447
1407/// Representation of the PIO state keeping a record of which pins are assigned to 1448/// Representation of the PIO state keeping a record of which pins are assigned to
1408/// each PIO. 1449/// each PIO.
1409// make_pio_pin notionally takes ownership of the pin it is given, but the wrapped pin 1450// make_pio_pin notionally takes ownership of the pin it is given, but the wrapped pin
@@ -1418,7 +1459,12 @@ pub struct State {
1418 1459
1419fn on_pio_drop<PIO: Instance>() { 1460fn on_pio_drop<PIO: Instance>() {
1420 let state = PIO::state(); 1461 let state = PIO::state();
1421 if state.users.fetch_sub(1, Ordering::AcqRel) == 1 { 1462 let users_state = critical_section::with(|_| {
1463 let val = state.users.load(Ordering::Acquire) - 1;
1464 state.users.store(val, Ordering::Release);
1465 val
1466 });
1467 if users_state == 1 {
1422 let used_pins = state.used_pins.load(Ordering::Relaxed); 1468 let used_pins = state.used_pins.load(Ordering::Relaxed);
1423 let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; 1469 let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _;
1424 for i in 0..crate::gpio::BANK0_PIN_COUNT { 1470 for i in 0..crate::gpio::BANK0_PIN_COUNT {
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.
2use core::future::Future; 2use core::future::Future;
3use core::slice; 3use core::slice;
4use core::sync::atomic::{AtomicU8, Ordering};
4 5
5use atomic_polyfill::AtomicU8;
6use embassy_hal_internal::atomic_ring_buffer::RingBuffer; 6use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
7 7
8use super::*; 8use 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.
2use core::future::poll_fn; 2use core::future::poll_fn;
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::sync::atomic::{AtomicU16, Ordering};
4use core::task::Poll; 5use core::task::Poll;
5 6
6use atomic_polyfill::{AtomicU16, Ordering};
7use embassy_futures::select::{Either, select}; 7use embassy_futures::select::{Either, select};
8use embassy_hal_internal::{Peri, PeripheralType}; 8use embassy_hal_internal::{Peri, PeripheralType};
9use embassy_sync::waitqueue::AtomicWaker; 9use 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