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 | |
| parent | e94ca0efd68924075d090368393f4dacbda64487 (diff) | |
PIO support for RPi Pico
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/Cargo.toml | 7 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 105 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 67 |
3 files changed, 178 insertions, 1 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 60a8ba94d..b07c471af 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" | |||
| 9 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } | 9 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } |
| 10 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } | 10 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } |
| 11 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 11 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 12 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } | 12 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio"] } |
| 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | 14 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| @@ -34,6 +34,11 @@ embedded-io = { version = "0.4.0", features = ["async", "defmt"] } | |||
| 34 | embedded-storage = { version = "0.3" } | 34 | embedded-storage = { version = "0.3" } |
| 35 | static_cell = "1.0.0" | 35 | static_cell = "1.0.0" |
| 36 | log = "0.4" | 36 | log = "0.4" |
| 37 | pio-proc = "0.2" | ||
| 38 | pio = "0.2" | ||
| 37 | 39 | ||
| 38 | [profile.release] | 40 | [profile.release] |
| 39 | debug = true | 41 | debug = true |
| 42 | |||
| 43 | [patch.crates-io] | ||
| 44 | pio = {git = "https://github.com/rp-rs/pio-rs.git"} \ No newline at end of file | ||
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 | } | ||
