embassy/examples/rp/src/bin/pio_dma.rs
pennae 41ec4170a5 rp/pio: add load_program, use_program
programs contain information we could pull from them directly and use to
validate other configuration of the state machine instead of asking the
user to pull them out and hand them to us bit by bit. unfortunately
programs do not specify how many in or out bits they use, so we can only
handle side-set and wrapping jumps like this. it's still something though.
2023-05-06 11:44:04 +02:00

72 lines
1.9 KiB
Rust

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::info;
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_rp::pio::{Pio, ShiftDirection};
use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::Peripheral;
use {defmt_rtt as _, panic_probe as _};
fn swap_nibbles(v: u32) -> u32 {
let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4;
let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8;
(v & 0x0000_ffff) << 16 | (v & 0xffff_0000) >> 16
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let pio = p.PIO0;
let Pio {
mut common,
sm0: mut sm,
..
} = Pio::new(pio);
let prg = pio_proc::pio_asm!(
".origin 0",
"set pindirs,1",
".wrap_target",
"set y,7",
"loop:",
"out x,4",
"in x,4",
"jmp y--, loop",
".wrap",
);
let relocated = RelocatedProgram::new(&prg.program);
sm.use_program(&common.load_program(&relocated), &[]);
sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
sm.set_autopull(true);
sm.set_autopush(true);
sm.set_pull_threshold(32);
sm.set_push_threshold(32);
sm.set_out_shift_dir(ShiftDirection::Right);
sm.set_in_shift_dir(ShiftDirection::Left);
sm.set_enable(true);
let mut dma_out_ref = p.DMA_CH0.into_ref();
let mut dma_in_ref = p.DMA_CH1.into_ref();
let mut dout = [0x12345678u32; 29];
for i in 1..dout.len() {
dout[i] = (dout[i - 1] & 0x0fff_ffff) * 13 + 7;
}
let mut din = [0u32; 29];
loop {
let (rx, tx) = sm.rx_tx();
join(
tx.dma_push(dma_out_ref.reborrow(), &dout),
rx.dma_pull(dma_in_ref.reborrow(), &mut din),
)
.await;
for i in 0..din.len() {
assert_eq!(din[i], swap_nibbles(dout[i]));
}
info!("Swapped {} words", dout.len());
}
}