diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml index 292cccf666..f52788ba33 100644 --- a/cyw43-pio/Cargo.toml +++ b/cyw43-pio/Cargo.toml @@ -12,8 +12,8 @@ documentation = "https://docs.embassy.dev/cyw43-pio" [dependencies] cyw43 = { version = "0.3.0", path = "../cyw43" } embassy-rp = { version = "0.3.0", path = "../embassy-rp" } -pio-proc = "0.2" -pio = "0.2.1" +pio-proc = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } +pio = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } fixed = "1.23.1" defmt = { version = "0.3", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 56cc39bbff..120e058eda 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -139,8 +139,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" } embedded-hal-async = { version = "1.0" } embedded-hal-nb = { version = "1.0" } -pio-proc = { version= "0.2" } -pio = { version= "0.2.1" } +pio-proc = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } +pio = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } rp2040-boot2 = "0.3" document-features = "0.2.10" sha2-const-stable = "0.1" diff --git a/embassy-rp/src/pio/mod.rs b/embassy-rp/src/pio/mod.rs index 8916cbef05..7632d31682 100644 --- a/embassy-rp/src/pio/mod.rs +++ b/embassy-rp/src/pio/mod.rs @@ -50,6 +50,18 @@ pub enum FifoJoin { RxOnly, /// Tx fifo twice as deep. RX fifo disabled TxOnly, + /// Enable random writes (`FJOIN_RX_PUT`) from the state machine (through ISR), + /// and random reads from the system (using [`StateMachine::get_rxf_entry`]). + #[cfg(feature = "_rp235x")] + RxAsStatus, + /// Enable random reads (`FJOIN_RX_GET`) from the state machine (through OSR), + /// and random writes from the system (using [`StateMachine::set_rxf_entry`]). + #[cfg(feature = "_rp235x")] + RxAsControl, + /// FJOIN_RX_PUT | FJOIN_RX_GET: RX can be used as a scratch register, + /// not accesible from the CPU + #[cfg(feature = "_rp235x")] + PioScratch, } /// Shift direction. @@ -730,6 +742,17 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right); w.set_autopull(config.shift_out.auto_fill); w.set_autopush(config.shift_in.auto_fill); + + #[cfg(feature = "_rp235x")] + { + w.set_fjoin_rx_get( + config.fifo_join == FifoJoin::RxAsControl || config.fifo_join == FifoJoin::PioScratch, + ); + w.set_fjoin_rx_put( + config.fifo_join == FifoJoin::RxAsStatus || config.fifo_join == FifoJoin::PioScratch, + ); + w.set_in_count(config.in_count); + } }); #[cfg(feature = "rp2040")] @@ -907,6 +930,20 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn rx_tx(&mut self) -> (&mut StateMachineRx<'d, PIO, SM>, &mut StateMachineTx<'d, PIO, SM>) { (&mut self.rx, &mut self.tx) } + + /// Return the contents of the nth entry of the RX FIFO + /// (should be used only when the FIFO config is set to [`FifoJoin::RxAsStatus`]) + #[cfg(feature = "_rp235x")] + pub fn get_rxf_entry(&self, n: usize) -> u32 { + PIO::PIO.rxf_putget(SM).putget(n).read() + } + + /// Set the contents of the nth entry of the RX FIFO + /// (should be used only when the FIFO config is set to [`FifoJoin::RxAsControl`]) + #[cfg(feature = "_rp235x")] + pub fn set_rxf_entry(&self, n: usize, val: u32) { + PIO::PIO.rxf_putget(SM).putget(n).write_value(val) + } } /// PIO handle. @@ -993,6 +1030,9 @@ impl<'d, PIO: Instance> Common<'d, PIO> { prog: &Program, origin: u8, ) -> Result, usize> { + #[cfg(not(feature = "_rp235x"))] + assert!(prog.version == pio::PioVersion::V0); + let prog = RelocatedProgram::new_with_origin(prog, origin); let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?; Ok(LoadedProgram { @@ -1053,6 +1093,12 @@ impl<'d, PIO: Instance> Common<'d, PIO> { /// of [`Pio`] do not keep pin registrations alive.** pub fn make_pio_pin(&mut self, pin: impl Peripheral

+ 'd) -> Pin<'d, PIO> { into_ref!(pin); + + // enable the outputs + pin.pad_ctrl().write(|w| w.set_od(false)); + // especially important on the 235x, where IE defaults to 0 + pin.pad_ctrl().write(|w| w.set_ie(true)); + pin.gpio().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL as _)); pin.pad_ctrl().write(|w| { #[cfg(feature = "_rp235x")] diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index d9decc2b03..5294ec477f 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -55,8 +55,8 @@ embedded-storage = { version = "0.3" } static_cell = "2.1" portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" -pio-proc = "0.2" -pio = "0.2.1" +pio-proc = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } +pio = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } rand = { version = "0.8.5", default-features = false } embedded-sdmmc = "0.7.0" diff --git a/examples/rp23/Cargo.toml b/examples/rp23/Cargo.toml index 4d99ecc722..8f9c14c5c2 100644 --- a/examples/rp23/Cargo.toml +++ b/examples/rp23/Cargo.toml @@ -55,8 +55,8 @@ embedded-storage = { version = "0.3" } static_cell = "2.1" portable-atomic = { version = "1.5", features = ["critical-section"] } log = "0.4" -pio-proc = "0.2" -pio = "0.2.1" +pio-proc = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } +pio = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } rand = { version = "0.8.5", default-features = false } embedded-sdmmc = "0.7.0" diff --git a/examples/rp23/src/bin/pio_rotary_encoder_rxf.rs b/examples/rp23/src/bin/pio_rotary_encoder_rxf.rs new file mode 100644 index 0000000000..7a1046610a --- /dev/null +++ b/examples/rp23/src/bin/pio_rotary_encoder_rxf.rs @@ -0,0 +1,116 @@ +//! This example shows how to use the PIO module in the RP235x to read a quadrature rotary encoder. +//! It differs from the other example in that it uses the RX FIFO as a status register + +#![no_std] +#![no_main] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_rp::block::ImageDef; +use embassy_rp::gpio::Pull; +use embassy_rp::peripherals::PIO0; +use embassy_rp::{bind_interrupts, pio}; +use embassy_time::Timer; +use fixed::traits::ToFixed; +use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine}; +use {defmt_rtt as _, panic_probe as _}; + +#[link_section = ".start_block"] +#[used] +pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); + +// Program metadata for `picotool info` +#[link_section = ".bi_entries"] +#[used] +pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ + embassy_rp::binary_info::rp_program_name!(c"example_pio_rotary_encoder_rxf"), + embassy_rp::binary_info::rp_cargo_version!(), + embassy_rp::binary_info::rp_program_description!(c"Rotary encoder (RXF)"), + embassy_rp::binary_info::rp_program_build_attribute!(), +]; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +pub struct PioEncoder<'d, T: Instance, const SM: usize> { + sm: StateMachine<'d, T, SM>, +} + +impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> { + pub fn new( + pio: &mut Common<'d, T>, + mut sm: StateMachine<'d, T, SM>, + pin_a: impl PioPin, + pin_b: impl PioPin, + ) -> Self { + let mut pin_a = pio.make_pio_pin(pin_a); + let mut pin_b = pio.make_pio_pin(pin_b); + pin_a.set_pull(Pull::Up); + pin_b.set_pull(Pull::Up); + + sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]); + + let prg = pio_proc::pio_asm!( + "start:" + // encoder count is stored in X + "mov isr, x" + // and then moved to the RX FIFO register + "mov rxfifo[0], isr" + + // wait for encoder transition + "wait 1 pin 1" + "wait 0 pin 1" + + "set y, 0" + "mov y, pins[1]" + + // update X depending on pin 1 + "jmp !y decr" + + // this is just a clever way of doing x++ + "mov x, ~x" + "jmp x--, incr" + "incr:" + "mov x, ~x" + "jmp start" + + // and this is x-- + "decr:" + "jmp x--, start" + ); + + let mut cfg = Config::default(); + cfg.set_in_pins(&[&pin_a, &pin_b]); + cfg.fifo_join = FifoJoin::RxAsStatus; + cfg.shift_in.direction = ShiftDirection::Left; + cfg.clock_divider = 10_000.to_fixed(); + cfg.use_program(&pio.load_program(&prg.program), &[]); + sm.set_config(&cfg); + + sm.set_enable(true); + Self { sm } + } + + pub async fn read(&mut self) -> u32 { + self.sm.get_rxf_entry(0) + } +} + +pub enum Direction { + Clockwise, + CounterClockwise, +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); + + let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5); + + loop { + info!("Count: {}", encoder.read().await); + Timer::after_millis(1000).await; + } +} diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 4278f7b2c0..26f3f21f6b 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -33,8 +33,8 @@ embedded-io-async = { version = "0.6.1" } embedded-storage = { version = "0.3" } static_cell = "2" portable-atomic = { version = "1.5", features = ["critical-section"] } -pio = "0.2" -pio-proc = "0.2" +pio-proc = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } +pio = { git = "https://github.com/rp-rs/pio-rs", rev = "fa586448b0b223217eec8c92c19fe6823dd04cc4" } rand = { version = "0.8.5", default-features = false } [profile.dev]