diff options
Diffstat (limited to 'embassy-rp/src/pio/mod.rs')
| -rw-r--r-- | embassy-rp/src/pio/mod.rs | 26 |
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. |
| 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 |
