rp/pio: move non-sm-specific methods to PioCommon
pin and irq operations affect the entire pio block. with pins this is not very problematic since pins themselves are resources, but irqs are not treated like that and can thus interfere across state machines. the ability to wait for an irq on a state machine is kept to make synchronization with user code easier, and since we can't inspect loaded programs at build time we wouldn't gain much from disallowing waits from state machines anyway.
This commit is contained in:
parent
4cd5ed81aa
commit
58e727d3b9
@ -677,26 +677,6 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
|
||||
unsafe {
|
||||
pin.io().ctrl().write(|w| {
|
||||
w.set_funcsel(
|
||||
if Self::Pio::PIO_NO == 1 {
|
||||
pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
|
||||
} else {
|
||||
// PIO == 0
|
||||
pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
|
||||
}
|
||||
.0,
|
||||
);
|
||||
});
|
||||
}
|
||||
PioPin {
|
||||
pin_bank: pin.pin_bank(),
|
||||
pio: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_sideset_base_pin(&mut self, base_pin: &PioPin<Self::Pio>) {
|
||||
unsafe {
|
||||
Self::Pio::PIO
|
||||
@ -815,19 +795,6 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin {
|
||||
);
|
||||
}
|
||||
|
||||
fn is_irq_set(&self, irq_no: u8) -> bool {
|
||||
assert!(irq_no < 8);
|
||||
unsafe {
|
||||
let irq_flags = Self::Pio::PIO.irq();
|
||||
irq_flags.read().0 & (1 << irq_no) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_irq(&mut self, irq_no: usize) {
|
||||
assert!(irq_no < 8);
|
||||
unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
|
||||
}
|
||||
|
||||
fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> {
|
||||
FifoOutFuture::new(self, value)
|
||||
}
|
||||
@ -990,6 +957,14 @@ pub trait PioCommon: sealed::PioCommon + Sized {
|
||||
write_instr(Self::Pio::PIO, Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON);
|
||||
}
|
||||
|
||||
fn is_irq_set(&self, irq_no: u8) -> bool {
|
||||
assert!(irq_no < 8);
|
||||
unsafe {
|
||||
let irq_flags = Self::Pio::PIO.irq();
|
||||
irq_flags.read().0 & (1 << irq_no) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_irq(&mut self, irq_no: usize) {
|
||||
assert!(irq_no < 8);
|
||||
unsafe { Self::Pio::PIO.irq().write(|w| w.set_irq(1 << irq_no)) }
|
||||
@ -1015,6 +990,26 @@ pub trait PioCommon: sealed::PioCommon + Sized {
|
||||
fn get_input_sync_bypass(&self) -> u32 {
|
||||
unsafe { Self::Pio::PIO.input_sync_bypass().read() }
|
||||
}
|
||||
|
||||
fn make_pio_pin(&self, pin: impl Pin) -> PioPin<Self::Pio> {
|
||||
unsafe {
|
||||
pin.io().ctrl().write(|w| {
|
||||
w.set_funcsel(
|
||||
if Self::Pio::PIO_NO == 1 {
|
||||
pac::io::vals::Gpio0ctrlFuncsel::PIO1_0
|
||||
} else {
|
||||
// PIO == 0
|
||||
pac::io::vals::Gpio0ctrlFuncsel::PIO0_0
|
||||
}
|
||||
.0,
|
||||
);
|
||||
});
|
||||
}
|
||||
PioPin {
|
||||
pin_bank: pin.pin_bank(),
|
||||
pio: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Identifies a specific state machine inside a PIO device
|
||||
|
@ -4,13 +4,15 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{AnyPin, Pin};
|
||||
use embassy_rp::pio::{Pio0, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2};
|
||||
use embassy_rp::pio::{
|
||||
Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0,
|
||||
Sm1, Sm2,
|
||||
};
|
||||
use embassy_rp::pio_instr_util;
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
|
||||
fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
|
||||
// Setup sm0
|
||||
|
||||
// Send data serially to pin
|
||||
@ -23,11 +25,11 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
|
||||
);
|
||||
|
||||
let relocated = RelocatedProgram::new(&prg.program);
|
||||
let out_pin = sm.make_pio_pin(pin);
|
||||
let out_pin = pio.make_pio_pin(pin);
|
||||
let pio_pins = [&out_pin];
|
||||
sm.set_out_pins(&pio_pins);
|
||||
sm.write_instr(relocated.origin() as usize, relocated.code());
|
||||
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||
pio_instr_util::exec_jmp(sm, relocated.origin());
|
||||
sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32);
|
||||
sm.set_set_range(0, 1);
|
||||
let pio::Wrap { source, target } = relocated.wrap();
|
||||
@ -35,7 +37,10 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
|
||||
|
||||
sm.set_autopull(true);
|
||||
sm.set_out_shift_dir(ShiftDirection::Left);
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
|
||||
sm.set_enable(true);
|
||||
|
||||
let mut v = 0x0f0caffa;
|
||||
@ -104,9 +109,10 @@ async fn main(spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
let pio = p.PIO0;
|
||||
|
||||
let (_, sm0, sm1, sm2, ..) = pio.split();
|
||||
let (mut pio0, mut sm0, sm1, sm2, ..) = pio.split();
|
||||
|
||||
spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap();
|
||||
setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade());
|
||||
spawner.spawn(pio_task_sm0(sm0)).unwrap();
|
||||
spawner.spawn(pio_task_sm1(sm1)).unwrap();
|
||||
spawner.spawn(pio_task_sm2(sm2)).unwrap();
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{self, Pin};
|
||||
use embassy_rp::pio::{
|
||||
FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance,
|
||||
FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance,
|
||||
ShiftDirection, SmInstance,
|
||||
};
|
||||
use embassy_rp::pio_instr_util;
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
@ -18,7 +19,7 @@ pub struct Ws2812<P: PioInstance, S: SmInstance> {
|
||||
}
|
||||
|
||||
impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
||||
pub fn new(mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self {
|
||||
pub fn new(pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self {
|
||||
// Setup sm0
|
||||
|
||||
// prepare the PIO program
|
||||
@ -53,7 +54,7 @@ impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
||||
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||
|
||||
// Pin config
|
||||
let out_pin = sm.make_pio_pin(pin);
|
||||
let out_pin = pio.make_pio_pin(pin);
|
||||
sm.set_set_pins(&[&out_pin]);
|
||||
sm.set_sideset_base_pin(&out_pin);
|
||||
sm.set_sideset_count(1);
|
||||
@ -115,7 +116,7 @@ async fn main(_spawner: Spawner) {
|
||||
info!("Start");
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
||||
let (_pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split();
|
||||
let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split();
|
||||
|
||||
// This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
|
||||
// feather boards for the 2040 both have one built in.
|
||||
@ -124,7 +125,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
// For the thing plus, use pin 8
|
||||
// For the feather, use pin 16
|
||||
let mut ws2812 = Ws2812::new(sm0, p.PIN_8.degrade());
|
||||
let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade());
|
||||
|
||||
// Loop forever making RGB values and pushing them out to the WS2812.
|
||||
loop {
|
||||
|
Loading…
Reference in New Issue
Block a user