aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio')
-rw-r--r--embassy-rp/src/pio/instr.rs16
-rw-r--r--embassy-rp/src/pio/mod.rs66
2 files changed, 70 insertions, 12 deletions
diff --git a/embassy-rp/src/pio/instr.rs b/embassy-rp/src/pio/instr.rs
index b15d507de..304ddb20a 100644
--- a/embassy-rp/src/pio/instr.rs
+++ b/embassy-rp/src/pio/instr.rs
@@ -5,6 +5,10 @@ use crate::pio::{Instance, StateMachine};
5 5
6impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> { 6impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
7 /// Set value of scratch register X. 7 /// Set value of scratch register X.
8 ///
9 /// SAFETY: autopull enabled else it will write undefined data.
10 /// Make sure to have setup the according configuration see
11 /// [shift_out](crate::pio::Config::shift_out) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
8 pub unsafe fn set_x(&mut self, value: u32) { 12 pub unsafe fn set_x(&mut self, value: u32) {
9 const OUT: u16 = InstructionOperands::OUT { 13 const OUT: u16 = InstructionOperands::OUT {
10 destination: OutDestination::X, 14 destination: OutDestination::X,
@@ -16,6 +20,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
16 } 20 }
17 21
18 /// Get value of scratch register X. 22 /// Get value of scratch register X.
23 ///
24 /// SAFETY: autopush enabled else it will read undefined data.
25 /// Make sure to have setup the according configurations see
26 /// [shift_in](crate::pio::Config::shift_in) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
19 pub unsafe fn get_x(&mut self) -> u32 { 27 pub unsafe fn get_x(&mut self) -> u32 {
20 const IN: u16 = InstructionOperands::IN { 28 const IN: u16 = InstructionOperands::IN {
21 source: InSource::X, 29 source: InSource::X,
@@ -27,6 +35,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
27 } 35 }
28 36
29 /// Set value of scratch register Y. 37 /// Set value of scratch register Y.
38 ///
39 /// SAFETY: autopull enabled else it will write undefined data.
40 /// Make sure to have setup the according configuration see
41 /// [shift_out](crate::pio::Config::shift_out) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
30 pub unsafe fn set_y(&mut self, value: u32) { 42 pub unsafe fn set_y(&mut self, value: u32) {
31 const OUT: u16 = InstructionOperands::OUT { 43 const OUT: u16 = InstructionOperands::OUT {
32 destination: OutDestination::Y, 44 destination: OutDestination::Y,
@@ -38,6 +50,10 @@ impl<'d, PIO: Instance, const SM: usize> StateMachine<'d, PIO, SM> {
38 } 50 }
39 51
40 /// Get value of scratch register Y. 52 /// Get value of scratch register Y.
53 ///
54 /// SAFETY: autopush enabled else it will read undefined data.
55 /// Make sure to have setup the according configurations see
56 /// [shift_in](crate::pio::Config::shift_in) and [auto_fill](crate::pio::ShiftConfig::auto_fill).
41 pub unsafe fn get_y(&mut self) -> u32 { 57 pub unsafe fn get_y(&mut self) -> u32 {
42 const IN: u16 = InstructionOperands::IN { 58 const IN: u16 = InstructionOperands::IN {
43 source: InSource::Y, 59 source: InSource::Y,
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 {