diff options
| author | Simon Berg <[email protected]> | 2022-07-27 22:45:46 +0200 |
|---|---|---|
| committer | Simon Berg <[email protected]> | 2022-12-09 20:18:41 +0100 |
| commit | 35db6e639bf5de017551164e9cbfaa2e5e46fca3 (patch) | |
| tree | e6baf3d884cea78a59c3044cf9ad82b1642f6594 /examples/rp/src | |
| parent | e94ca0efd68924075d090368393f4dacbda64487 (diff) | |
PIO support for RPi Pico
Diffstat (limited to 'examples/rp/src')
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 105 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 67 |
2 files changed, 172 insertions, 0 deletions
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs new file mode 100644 index 000000000..e9211db3b --- /dev/null +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_rp::gpio::{AnyPin, Pin}; | ||
| 7 | use embassy_rp::pio::{Pio0, PioPeripherial, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; | ||
| 8 | use embassy_rp::pio_instr_util; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::task] | ||
| 12 | async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) { | ||
| 13 | // Setup sm0 | ||
| 14 | |||
| 15 | // Send data serially to pin | ||
| 16 | let prg = pio_proc::pio_asm!( | ||
| 17 | ".origin 16", | ||
| 18 | "set pindirs, 1", | ||
| 19 | ".wrap_target", | ||
| 20 | "out pins,1 [19]", | ||
| 21 | ".wrap", | ||
| 22 | ); | ||
| 23 | |||
| 24 | let origin = prg.program.origin.unwrap_or(0); | ||
| 25 | let out_pin = sm.make_pio_pin(pin); | ||
| 26 | let pio_pins = [&out_pin]; | ||
| 27 | sm.set_out_pins(&pio_pins); | ||
| 28 | sm.write_instr(origin as usize, &prg.program.code); | ||
| 29 | pio_instr_util::exec_jmp(&mut sm, origin); | ||
| 30 | sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); | ||
| 31 | sm.set_set_range(0, 1); | ||
| 32 | sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); | ||
| 33 | sm.set_autopull(true); | ||
| 34 | sm.set_out_shift_dir(ShiftDirection::Left); | ||
| 35 | |||
| 36 | sm.set_enable(true); | ||
| 37 | |||
| 38 | let mut v = 0x0f0caffa; | ||
| 39 | loop { | ||
| 40 | sm.wait_push(v).await; | ||
| 41 | v ^= 0xffff; | ||
| 42 | info!("Pushed {:032b} to FIFO", v); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | #[embassy_executor::task] | ||
| 47 | async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { | ||
| 48 | // Setupm sm1 | ||
| 49 | |||
| 50 | // Read 0b10101 repeatedly until ISR is full | ||
| 51 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); | ||
| 52 | |||
| 53 | let origin = prg.program.origin.unwrap_or(0); | ||
| 54 | sm.write_instr(origin as usize, &prg.program.code); | ||
| 55 | pio_instr_util::exec_jmp(&mut sm, origin); | ||
| 56 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | ||
| 57 | sm.set_set_range(0, 0); | ||
| 58 | sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); | ||
| 59 | sm.set_autopush(true); | ||
| 60 | sm.set_in_shift_dir(ShiftDirection::Right); | ||
| 61 | sm.set_enable(true); | ||
| 62 | loop { | ||
| 63 | let rx = sm.wait_pull().await; | ||
| 64 | info!("Pulled {:032b} from FIFO", rx); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | #[embassy_executor::task] | ||
| 69 | async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { | ||
| 70 | // Setup sm2 | ||
| 71 | |||
| 72 | // Repeatedly trigger IRQ 3 | ||
| 73 | let prg = pio_proc::pio_asm!( | ||
| 74 | ".origin 0", | ||
| 75 | ".wrap_target", | ||
| 76 | "set x,10", | ||
| 77 | "delay:", | ||
| 78 | "jmp x-- delay [15]", | ||
| 79 | "irq 3 [15]", | ||
| 80 | ".wrap", | ||
| 81 | ); | ||
| 82 | let origin = prg.program.origin.unwrap_or(0); | ||
| 83 | |||
| 84 | sm.write_instr(origin as usize, &prg.program.code); | ||
| 85 | sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); | ||
| 86 | pio_instr_util::exec_jmp(&mut sm, origin); | ||
| 87 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | ||
| 88 | sm.set_enable(true); | ||
| 89 | loop { | ||
| 90 | sm.wait_irq(3).await; | ||
| 91 | info!("IRQ trigged"); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | #[embassy_executor::main] | ||
| 96 | async fn main(spawner: Spawner) { | ||
| 97 | let p = embassy_rp::init(Default::default()); | ||
| 98 | let pio = p.PIO0; | ||
| 99 | |||
| 100 | let (_, sm0, sm1, sm2, ..) = pio.split(); | ||
| 101 | |||
| 102 | spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); | ||
| 103 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); | ||
| 104 | spawner.spawn(pio_task_sm2(sm2)).unwrap(); | ||
| 105 | } | ||
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs new file mode 100644 index 000000000..bdcdf200c --- /dev/null +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_futures::join::join; | ||
| 7 | use embassy_rp::pio::{PioPeripherial, PioStateMachine, ShiftDirection}; | ||
| 8 | use embassy_rp::{pio_instr_util, Peripheral}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | fn swap_nibbles(v: u32) -> u32 { | ||
| 12 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; | ||
| 13 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; | ||
| 14 | (v & 0x0000_ffff) << 16 | (v & 0xffff_0000) >> 16 | ||
| 15 | } | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async fn main(_spawner: Spawner) { | ||
| 19 | let p = embassy_rp::init(Default::default()); | ||
| 20 | let pio = p.PIO0; | ||
| 21 | let (_, mut sm, ..) = pio.split(); | ||
| 22 | |||
| 23 | let prg = pio_proc::pio_asm!( | ||
| 24 | ".origin 0", | ||
| 25 | "set pindirs,1", | ||
| 26 | ".wrap_target", | ||
| 27 | "set y,7", | ||
| 28 | "loop:", | ||
| 29 | "out x,4", | ||
| 30 | "in x,4", | ||
| 31 | "jmp y--, loop", | ||
| 32 | ".wrap", | ||
| 33 | ); | ||
| 34 | |||
| 35 | let origin = prg.program.origin.unwrap_or(0); | ||
| 36 | sm.write_instr(origin as usize, &prg.program.code); | ||
| 37 | pio_instr_util::exec_jmp(&mut sm, origin); | ||
| 38 | sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); | ||
| 39 | sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); | ||
| 40 | sm.set_autopull(true); | ||
| 41 | sm.set_autopush(true); | ||
| 42 | sm.set_pull_threshold(32); | ||
| 43 | sm.set_push_threshold(32); | ||
| 44 | sm.set_out_shift_dir(ShiftDirection::Right); | ||
| 45 | sm.set_in_shift_dir(ShiftDirection::Left); | ||
| 46 | |||
| 47 | sm.set_enable(true); | ||
| 48 | |||
| 49 | let mut dma_out_ref = p.DMA_CH0.into_ref(); | ||
| 50 | let mut dma_in_ref = p.DMA_CH1.into_ref(); | ||
| 51 | let mut dout = [0x12345678u32; 29]; | ||
| 52 | for i in 1..dout.len() { | ||
| 53 | dout[i] = (dout[i - 1] & 0x0fff_ffff) * 13 + 7; | ||
| 54 | } | ||
| 55 | let mut din = [0u32; 29]; | ||
| 56 | loop { | ||
| 57 | join( | ||
| 58 | sm.dma_push(dma_out_ref.reborrow(), &dout), | ||
| 59 | sm.dma_pull(dma_in_ref.reborrow(), &mut din), | ||
| 60 | ) | ||
| 61 | .await; | ||
| 62 | for i in 0..din.len() { | ||
| 63 | assert_eq!(din[i], swap_nibbles(dout[i])); | ||
| 64 | } | ||
| 65 | info!("Swapped {} words", dout.len()); | ||
| 66 | } | ||
| 67 | } | ||
