embassy/examples/rp/src/bin/pio_dma.rs
pennae 8e4d65e163 rp/pio: configure state machines with Config struct
the many individual sets aren't very efficient, and almost no checks
were done to ensure that the configuration written to the hardware was
actually valid. this adresses both of these.
2023-05-06 17:23:41 +02:00

81 lines
2.2 KiB
Rust

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::info;
use embassy_embedded_hal::SetConfig;
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection};
use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::Peripheral;
use fixed::traits::ToFixed;
use fixed_macro::types::U56F8;
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);
let mut cfg = Config::default();
cfg.use_program(&common.load_program(&relocated), &[]);
cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed();
cfg.shift_in = ShiftConfig {
auto_fill: true,
threshold: 32,
direction: ShiftDirection::Left,
};
cfg.shift_out = ShiftConfig {
auto_fill: true,
threshold: 32,
direction: ShiftDirection::Right,
};
sm.set_config(&cfg);
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());
}
}