aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio/mod.rs')
-rw-r--r--embassy-rp/src/pio/mod.rs26
1 files changed, 18 insertions, 8 deletions
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.
2use core::cell::Cell;
2use core::future::Future; 3use core::future::Future;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
4use core::pin::Pin as FuturePin; 5use core::pin::Pin as FuturePin;
5use core::sync::atomic::{Ordering, compiler_fence}; 6use core::sync::atomic::{AtomicU8, Ordering, compiler_fence};
6use core::task::{Context, Poll}; 7use core::task::{Context, Poll};
7 8
8use atomic_polyfill::{AtomicU8, AtomicU64};
9use embassy_hal_internal::{Peri, PeripheralType}; 9use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_sync::waitqueue::AtomicWaker; 10use embassy_sync::waitqueue::AtomicWaker;
11use fixed::FixedU32; 11use 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.
1414pub struct State { 1417pub struct State {
1415 users: AtomicU8, 1418 users: AtomicU8,
1416 used_pins: AtomicU64, 1419 used_pins: Cell<u64>,
1417} 1420}
1418 1421
1422unsafe impl Sync for State {}
1423
1419fn on_pio_drop<PIO: Instance>() { 1424fn 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