mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-01-11 13:01:30 +11:00
pio: Split RX and TX FIFO functions into different types.
We need separate types for any blocking or DMA operations - otherwise, it would not be possible to perform both RX and TX transfers at the same time.
This commit is contained in:
parent
dbe7f48699
commit
207f5aebdb
|
@ -57,7 +57,7 @@ fn main() -> ! {
|
|||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||
let installed = pio.install(&program).unwrap();
|
||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
||||
let sm = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||
let (sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||
.set_pins(led_pin_id, 1)
|
||||
.clock_divisor(div)
|
||||
.build(sm0);
|
||||
|
|
|
@ -48,7 +48,7 @@ fn main() -> ! {
|
|||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||
let installed = pio.install(&program.program).unwrap();
|
||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
||||
let mut sm = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||
let (mut sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||
.set_pins(led_pin_id, 1)
|
||||
.clock_divisor(div)
|
||||
.build(sm0);
|
||||
|
|
|
@ -225,9 +225,9 @@ impl<P: PIOExt> PIO<P> {
|
|||
/// // Install a program in instruction memory.
|
||||
/// let installed = pio.install(&program).unwrap();
|
||||
/// // Configure a state machine to use the program.
|
||||
/// let sm = rp2040_hal::pio::PIOBuilder::from_program(installed).build(sm0);
|
||||
/// let (sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed).build(sm0);
|
||||
/// // Uninitialize the state machine again, freeing the program.
|
||||
/// let (sm, installed) = sm.uninit();
|
||||
/// let (sm, installed) = sm.uninit(rx, tx);
|
||||
/// // Uninstall the program to free instruction memory.
|
||||
/// pio.uninstall(installed);
|
||||
/// ```
|
||||
|
@ -451,7 +451,11 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
|
|||
///
|
||||
/// The program can be uninstalled to free space once it is no longer used by any state
|
||||
/// machine.
|
||||
pub fn uninit(mut self) -> (UninitStateMachine<SM>, InstalledProgram<SM::PIO>) {
|
||||
pub fn uninit(
|
||||
mut self,
|
||||
_rx: Rx<SM>,
|
||||
_tx: Tx<SM>,
|
||||
) -> (UninitStateMachine<SM>, InstalledProgram<SM::PIO>) {
|
||||
self.sm.set_enabled(false);
|
||||
(self.sm, self.program)
|
||||
}
|
||||
|
@ -471,44 +475,6 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
|
|||
pub fn stalled(&self) -> bool {
|
||||
self.sm.sm().sm_execctrl.read().exec_stalled().bits()
|
||||
}
|
||||
|
||||
/// Get the next element from RX FIFO.
|
||||
///
|
||||
/// Returns `None` if the FIFO is empty.
|
||||
pub fn read_rx(&mut self) -> Option<u32> {
|
||||
// Safety: The register is never written by software.
|
||||
let is_empty =
|
||||
unsafe { &*self.sm.block }.fstat.read().rxempty().bits() & (1 << SM::id()) != 0;
|
||||
|
||||
if is_empty {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Safety: The register is unique to this state machine.
|
||||
Some(
|
||||
unsafe { &*self.sm.block }.rxf[SM::id() as usize]
|
||||
.read()
|
||||
.bits(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Write an element to TX FIFO.
|
||||
///
|
||||
/// Returns `true` if the value was written to FIFO, `false` otherwise.
|
||||
pub fn write_tx(&mut self, value: u32) -> bool {
|
||||
// Safety: The register is never written by software.
|
||||
let is_full =
|
||||
unsafe { &*self.sm.block }.fstat.read().txfull().bits() & (1 << SM::id()) != 0;
|
||||
|
||||
if is_full {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Safety: The register is unique to this state machine.
|
||||
unsafe { &*self.sm.block }.txf[SM::id()].write(|w| unsafe { w.bits(value) });
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<SM: ValidStateMachine> StateMachine<SM, Stopped> {
|
||||
|
@ -650,6 +616,54 @@ impl<SM: ValidStateMachine> StateMachine<SM, Running> {
|
|||
}
|
||||
}
|
||||
|
||||
/// PIO RX FIFO handle.
|
||||
pub struct Rx<SM: ValidStateMachine> {
|
||||
block: *const rp2040_pac::pio0::RegisterBlock,
|
||||
_phantom: core::marker::PhantomData<SM>,
|
||||
}
|
||||
|
||||
impl<SM: ValidStateMachine> Rx<SM> {
|
||||
/// Get the next element from RX FIFO.
|
||||
///
|
||||
/// Returns `None` if the FIFO is empty.
|
||||
pub fn read_rx(&mut self) -> Option<u32> {
|
||||
// Safety: The register is never written by software.
|
||||
let is_empty = unsafe { &*self.block }.fstat.read().rxempty().bits() & (1 << SM::id()) != 0;
|
||||
|
||||
if is_empty {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Safety: The register is unique to this Rx instance.
|
||||
Some(unsafe { &*self.block }.rxf[SM::id() as usize].read().bits())
|
||||
}
|
||||
}
|
||||
|
||||
/// PIO TX FIFO handle.
|
||||
pub struct Tx<SM: ValidStateMachine> {
|
||||
block: *const rp2040_pac::pio0::RegisterBlock,
|
||||
_phantom: core::marker::PhantomData<SM>,
|
||||
}
|
||||
|
||||
impl<SM: ValidStateMachine> Tx<SM> {
|
||||
/// Write an element to TX FIFO.
|
||||
///
|
||||
/// Returns `true` if the value was written to FIFO, `false` otherwise.
|
||||
pub fn write_tx(&mut self, value: u32) -> bool {
|
||||
// Safety: The register is never written by software.
|
||||
let is_full = unsafe { &*self.block }.fstat.read().txfull().bits() & (1 << SM::id()) != 0;
|
||||
|
||||
if is_full {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Safety: The register is unique to this Tx instance.
|
||||
unsafe { &*self.block }.txf[SM::id()].write(|w| unsafe { w.bits(value) });
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// PIO Interrupt controller.
|
||||
#[derive(Debug)]
|
||||
pub struct Interrupt<P: PIOExt> {
|
||||
|
@ -1140,7 +1154,7 @@ impl<P: PIOExt> PIOBuilder<P> {
|
|||
pub fn build<SM: StateMachineIndex>(
|
||||
self,
|
||||
mut sm: UninitStateMachine<(P, SM)>,
|
||||
) -> StateMachine<(P, SM), Stopped> {
|
||||
) -> (StateMachine<(P, SM), Stopped>, Rx<(P, SM)>, Tx<(P, SM)>) {
|
||||
let offset = self.program.offset;
|
||||
|
||||
// Stop the SM
|
||||
|
@ -1244,10 +1258,22 @@ impl<P: PIOExt> PIOBuilder<P> {
|
|||
.encode(),
|
||||
);
|
||||
|
||||
StateMachine {
|
||||
sm: sm,
|
||||
program: self.program,
|
||||
let rx = Rx {
|
||||
block: sm.block,
|
||||
_phantom: core::marker::PhantomData,
|
||||
}
|
||||
};
|
||||
let tx = Tx {
|
||||
block: sm.block,
|
||||
_phantom: core::marker::PhantomData,
|
||||
};
|
||||
(
|
||||
StateMachine {
|
||||
sm: sm,
|
||||
program: self.program,
|
||||
_phantom: core::marker::PhantomData,
|
||||
},
|
||||
rx,
|
||||
tx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue