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.rs66
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 @@
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::{compiler_fence, Ordering}; 5use core::sync::atomic::{AtomicU8, AtomicU32, Ordering, compiler_fence};
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use atomic_polyfill::{AtomicU64, AtomicU8};
9use embassy_hal_internal::{Peri, PeripheralType}; 8use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
11use fixed::types::extra::U8;
12use fixed::FixedU32; 10use fixed::FixedU32;
11use fixed::types::extra::U8;
13use pio::{Program, SideSet, Wrap}; 12use pio::{Program, SideSet, Wrap};
14 13
15use crate::dma::{self, Channel, Transfer, Word}; 14use crate::dma::{self, Channel, Transfer, Word};
16use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate}; 15use crate::gpio::{self, AnyPin, Drive, Level, Pull, SealedPin, SlewRate};
17use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; 16use crate::interrupt::typelevel::{Binding, Handler, Interrupt};
18use crate::relocate::RelocatedProgram; 17use crate::relocate::RelocatedProgram;
19use crate::{pac, peripherals, RegExt}; 18use crate::{RegExt, pac, peripherals};
20 19
21mod instr; 20mod 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
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
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
1423fn on_pio_drop<PIO: Instance>() { 1460fn 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 {