aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/pio/mod.rs56
1 files changed, 46 insertions, 10 deletions
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs
index fd0b4c072..1c370fdfc 100644
--- a/embassy-rp/src/pio/mod.rs
+++ b/embassy-rp/src/pio/mod.rs
@@ -1,9 +1,8 @@
1//! PIO driver. 1//! PIO driver.
2use core::cell::Cell;
3use core::future::Future; 2use core::future::Future;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use core::pin::Pin as FuturePin; 4use core::pin::Pin as FuturePin;
6use core::sync::atomic::{AtomicU8, Ordering, compiler_fence}; 5use core::sync::atomic::{AtomicU8, AtomicU32, Ordering, compiler_fence};
7use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
8 7
9use embassy_hal_internal::{Peri, PeripheralType}; 8use embassy_hal_internal::{Peri, PeripheralType};
@@ -1233,9 +1232,12 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
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 critical_section::with(|_| { 1234 critical_section::with(|_| {
1236 let val = PIO::state().used_pins.get(); 1235 let val = PIO::state().used_pins.load(Ordering::Relaxed);
1237 PIO::state().used_pins.set(val | 1 << pin.pin_bank()); 1236 PIO::state()
1237 .used_pins
1238 .store(val | 1 << pin.pin_bank(), Ordering::Relaxed);
1238 }); 1239 });
1240
1239 Pin { 1241 Pin {
1240 pin: pin.into(), 1242 pin: pin.into(),
1241 pio: PhantomData::default(), 1243 pio: PhantomData::default(),
@@ -1372,7 +1374,7 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1372 /// Create a new instance of a PIO peripheral. 1374 /// Create a new instance of a PIO peripheral.
1373 pub fn new(_pio: Peri<'d, PIO>, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { 1375 pub fn new(_pio: Peri<'d, PIO>, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self {
1374 PIO::state().users.store(5, Ordering::Release); 1376 PIO::state().users.store(5, Ordering::Release);
1375 critical_section::with(|_| PIO::state().used_pins.set(0)); 1377 PIO::state().used_pins.store(0, Ordering::Release);
1376 PIO::Interrupt::unpend(); 1378 PIO::Interrupt::unpend();
1377 1379
1378 unsafe { PIO::Interrupt::enable() }; 1380 unsafe { PIO::Interrupt::enable() };
@@ -1407,6 +1409,42 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1407 } 1409 }
1408} 1410}
1409 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
1410/// 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
1411/// each PIO. 1449/// each PIO.
1412// 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
@@ -1416,11 +1454,9 @@ impl<'d, PIO: Instance> Pio<'d, PIO> {
1416// other way. 1454// other way.
1417pub struct State { 1455pub struct State {
1418 users: AtomicU8, 1456 users: AtomicU8,
1419 used_pins: Cell<u64>, 1457 used_pins: AtomicU64,
1420} 1458}
1421 1459
1422unsafe impl Sync for State {}
1423
1424fn on_pio_drop<PIO: Instance>() { 1460fn on_pio_drop<PIO: Instance>() {
1425 let state = PIO::state(); 1461 let state = PIO::state();
1426 let users_state = critical_section::with(|_| { 1462 let users_state = critical_section::with(|_| {
@@ -1429,7 +1465,7 @@ fn on_pio_drop<PIO: Instance>() {
1429 val 1465 val
1430 }); 1466 });
1431 if users_state == 1 { 1467 if users_state == 1 {
1432 let used_pins = critical_section::with(|_| state.used_pins.get()); 1468 let used_pins = state.used_pins.load(Ordering::Relaxed);
1433 let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; 1469 let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _;
1434 for i in 0..crate::gpio::BANK0_PIN_COUNT { 1470 for i in 0..crate::gpio::BANK0_PIN_COUNT {
1435 if used_pins & (1 << i) != 0 { 1471 if used_pins & (1 << i) != 0 {
@@ -1454,7 +1490,7 @@ trait SealedInstance {
1454 fn state() -> &'static State { 1490 fn state() -> &'static State {
1455 static STATE: State = State { 1491 static STATE: State = State {
1456 users: AtomicU8::new(0), 1492 users: AtomicU8::new(0),
1457 used_pins: Cell::new(0), 1493 used_pins: AtomicU64::new(0),
1458 }; 1494 };
1459 1495
1460 &STATE 1496 &STATE