diff options
Diffstat (limited to 'embassy-rp/src/pio/mod.rs')
| -rw-r--r-- | embassy-rp/src/pio/mod.rs | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index 5f554dfe3..1c370fdfc 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs | |||
| @@ -2,21 +2,20 @@ | |||
| 2 | use core::future::Future; | 2 | use core::future::Future; |
| 3 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 4 | use core::pin::Pin as FuturePin; | 4 | use core::pin::Pin as FuturePin; |
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 5 | use core::sync::atomic::{AtomicU8, AtomicU32, Ordering, compiler_fence}; |
| 6 | use core::task::{Context, Poll}; | 6 | use core::task::{Context, Poll}; |
| 7 | 7 | ||
| 8 | use atomic_polyfill::{AtomicU64, AtomicU8}; | ||
| 9 | use embassy_hal_internal::{Peri, PeripheralType}; | 8 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | use fixed::types::extra::U8; | ||
| 12 | use fixed::FixedU32; | 10 | use fixed::FixedU32; |
| 11 | use fixed::types::extra::U8; | ||
| 13 | use pio::{Program, SideSet, Wrap}; | 12 | use pio::{Program, SideSet, Wrap}; |
| 14 | 13 | ||
| 15 | use crate::dma::{self, Channel, Transfer, Word}; | 14 | use crate::dma::{self, Channel, Transfer, Word}; |
| 16 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate}; | 15 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate}; |
| 17 | use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; | 16 | use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; |
| 18 | use crate::relocate::RelocatedProgram; | 17 | use crate::relocate::RelocatedProgram; |
| 19 | use crate::{pac, peripherals, RegExt}; | 18 | use crate::{RegExt, pac, peripherals}; |
| 20 | 19 | ||
| 21 | mod instr; | 20 | mod instr; |
| 22 | 21 | ||
| @@ -62,7 +61,7 @@ pub enum FifoJoin { | |||
| 62 | #[cfg(feature = "_rp235x")] | 61 | #[cfg(feature = "_rp235x")] |
| 63 | RxAsControl, | 62 | RxAsControl, |
| 64 | /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register, | 63 | /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register, |
| 65 | /// not accesible from the CPU | 64 | /// not accessible from the CPU |
| 66 | #[cfg(feature = "_rp235x")] | 65 | #[cfg(feature = "_rp235x")] |
| 67 | PioScratch, | 66 | PioScratch, |
| 68 | } | 67 | } |
| @@ -984,11 +983,7 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { | |||
| 984 | 983 | ||
| 985 | #[cfg(feature = "_rp235x")] | 984 | #[cfg(feature = "_rp235x")] |
| 986 | fn pin_base() -> u8 { | 985 | fn pin_base() -> u8 { |
| 987 | if PIO::PIO.gpiobase().read().gpiobase() { | 986 | if PIO::PIO.gpiobase().read().gpiobase() { 16 } else { 0 } |
| 988 | 16 | ||
| 989 | } else { | ||
| 990 | 0 | ||
| 991 | } | ||
| 992 | } | 987 | } |
| 993 | 988 | ||
| 994 | /// Sets pin directions. This pauses the current state machine to run `SET` commands | 989 | /// Sets pin directions. This pauses the current state machine to run `SET` commands |
| @@ -1236,7 +1231,13 @@ impl<'d, PIO: Instance> Common<'d, PIO> { | |||
| 1236 | w.set_pde(false); | 1231 | w.set_pde(false); |
| 1237 | }); | 1232 | }); |
| 1238 | // 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 |
| 1239 | 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 | |||
| 1240 | Pin { | 1241 | Pin { |
| 1241 | pin: pin.into(), | 1242 | pin: pin.into(), |
| 1242 | pio: PhantomData::default(), | 1243 | pio: PhantomData::default(), |
| @@ -1408,6 +1409,42 @@ impl<'d, PIO: Instance> Pio<'d, PIO> { | |||
| 1408 | } | 1409 | } |
| 1409 | } | 1410 | } |
| 1410 | 1411 | ||
| 1412 | struct AtomicU64 { | ||
| 1413 | upper_32: AtomicU32, | ||
| 1414 | lower_32: AtomicU32, | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | impl 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 | |||
| 1411 | /// 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 |
| 1412 | /// each PIO. | 1449 | /// each PIO. |
| 1413 | // 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 |
| @@ -1422,7 +1459,12 @@ pub struct State { | |||
| 1422 | 1459 | ||
| 1423 | fn on_pio_drop<PIO: Instance>() { | 1460 | fn on_pio_drop<PIO: Instance>() { |
| 1424 | let state = PIO::state(); | 1461 | let state = PIO::state(); |
| 1425 | 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 { | ||
| 1426 | let used_pins = state.used_pins.load(Ordering::Relaxed); | 1468 | let used_pins = state.used_pins.load(Ordering::Relaxed); |
| 1427 | let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; | 1469 | let null = pac::io::vals::Gpio0ctrlFuncsel::NULL as _; |
| 1428 | for i in 0..crate::gpio::BANK0_PIN_COUNT { | 1470 | for i in 0..crate::gpio::BANK0_PIN_COUNT { |
