mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-01-26 03:06:32 +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
3 changed files with 74 additions and 48 deletions
|
@ -57,7 +57,7 @@ fn main() -> ! {
|
||||||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let installed = pio.install(&program).unwrap();
|
let installed = pio.install(&program).unwrap();
|
||||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
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)
|
.set_pins(led_pin_id, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor(div)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn main() -> ! {
|
||||||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let installed = pio.install(&program.program).unwrap();
|
let installed = pio.install(&program.program).unwrap();
|
||||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
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)
|
.set_pins(led_pin_id, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor(div)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
|
|
|
@ -225,9 +225,9 @@ impl<P: PIOExt> PIO<P> {
|
||||||
/// // Install a program in instruction memory.
|
/// // Install a program in instruction memory.
|
||||||
/// let installed = pio.install(&program).unwrap();
|
/// let installed = pio.install(&program).unwrap();
|
||||||
/// // Configure a state machine to use the program.
|
/// // 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.
|
/// // 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.
|
/// // Uninstall the program to free instruction memory.
|
||||||
/// pio.uninstall(installed);
|
/// 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
|
/// The program can be uninstalled to free space once it is no longer used by any state
|
||||||
/// machine.
|
/// 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.set_enabled(false);
|
||||||
(self.sm, self.program)
|
(self.sm, self.program)
|
||||||
}
|
}
|
||||||
|
@ -471,44 +475,6 @@ impl<SM: ValidStateMachine, State> StateMachine<SM, State> {
|
||||||
pub fn stalled(&self) -> bool {
|
pub fn stalled(&self) -> bool {
|
||||||
self.sm.sm().sm_execctrl.read().exec_stalled().bits()
|
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> {
|
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.
|
/// PIO Interrupt controller.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Interrupt<P: PIOExt> {
|
pub struct Interrupt<P: PIOExt> {
|
||||||
|
@ -1140,7 +1154,7 @@ impl<P: PIOExt> PIOBuilder<P> {
|
||||||
pub fn build<SM: StateMachineIndex>(
|
pub fn build<SM: StateMachineIndex>(
|
||||||
self,
|
self,
|
||||||
mut sm: UninitStateMachine<(P, SM)>,
|
mut sm: UninitStateMachine<(P, SM)>,
|
||||||
) -> StateMachine<(P, SM), Stopped> {
|
) -> (StateMachine<(P, SM), Stopped>, Rx<(P, SM)>, Tx<(P, SM)>) {
|
||||||
let offset = self.program.offset;
|
let offset = self.program.offset;
|
||||||
|
|
||||||
// Stop the SM
|
// Stop the SM
|
||||||
|
@ -1244,10 +1258,22 @@ impl<P: PIOExt> PIOBuilder<P> {
|
||||||
.encode(),
|
.encode(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let rx = Rx {
|
||||||
|
block: sm.block,
|
||||||
|
_phantom: core::marker::PhantomData,
|
||||||
|
};
|
||||||
|
let tx = Tx {
|
||||||
|
block: sm.block,
|
||||||
|
_phantom: core::marker::PhantomData,
|
||||||
|
};
|
||||||
|
(
|
||||||
StateMachine {
|
StateMachine {
|
||||||
sm: sm,
|
sm: sm,
|
||||||
program: self.program,
|
program: self.program,
|
||||||
_phantom: core::marker::PhantomData,
|
_phantom: core::marker::PhantomData,
|
||||||
}
|
},
|
||||||
|
rx,
|
||||||
|
tx,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue