1043: Rpi Pico PIO driver r=Dirbaio a=fluffware

This is a driver for the two PIOs in the Pico. I've tried using the type system to get as much compile time checks as possible. There is asynchronous support for FIFOs an Irqs. No DMA support yet. There's an example that shows how to use the driver asynchronously.

1103: embassy-stm32: add rs485 driver enable to uart r=Dirbaio a=FrozenDroid



Co-authored-by: Simon Berg <ksb@fluffware.se>
Co-authored-by: Vincent Stakenburg <v.stakenburg@sinewave.nl>
This commit is contained in:
bors[bot]
2022-12-13 11:47:27 +00:00
committed by GitHub
12 changed files with 1735 additions and 7 deletions

View File

@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] }
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio"] }
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@ -34,6 +34,11 @@ embedded-io = { version = "0.4.0", features = ["async", "defmt"] }
embedded-storage = { version = "0.3" }
static_cell = "1.0.0"
log = "0.4"
pio-proc = "0.2"
pio = "0.2"
[profile.release]
debug = true
[patch.crates-io]
pio = {git = "https://github.com/rp-rs/pio-rs.git"}

View File

@ -0,0 +1,112 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use defmt::info;
use embassy_executor::Spawner;
use embassy_rp::gpio::{AnyPin, Pin};
use embassy_rp::pio::{Pio0, PioPeripherial, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2};
use embassy_rp::pio_instr_util;
use embassy_rp::relocate::RelocatedProgram;
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::task]
async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
// Setup sm0
// Send data serially to pin
let prg = pio_proc::pio_asm!(
".origin 16",
"set pindirs, 1",
".wrap_target",
"out pins,1 [19]",
".wrap",
);
let relocated = RelocatedProgram::new(&prg.program);
let out_pin = sm.make_pio_pin(pin);
let pio_pins = [&out_pin];
sm.set_out_pins(&pio_pins);
sm.write_instr(relocated.origin() as usize, relocated.code());
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32);
sm.set_set_range(0, 1);
let pio::Wrap { source, target } = relocated.wrap();
sm.set_wrap(source, target);
sm.set_autopull(true);
sm.set_out_shift_dir(ShiftDirection::Left);
sm.set_enable(true);
let mut v = 0x0f0caffa;
loop {
sm.wait_push(v).await;
v ^= 0xffff;
info!("Pushed {:032b} to FIFO", v);
}
}
#[embassy_executor::task]
async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
// Setupm sm1
// Read 0b10101 repeatedly until ISR is full
let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",);
let relocated = RelocatedProgram::new(&prg.program);
sm.write_instr(relocated.origin() as usize, relocated.code());
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
sm.set_set_range(0, 0);
let pio::Wrap { source, target } = relocated.wrap();
sm.set_wrap(source, target);
sm.set_autopush(true);
sm.set_in_shift_dir(ShiftDirection::Right);
sm.set_enable(true);
loop {
let rx = sm.wait_pull().await;
info!("Pulled {:032b} from FIFO", rx);
}
}
#[embassy_executor::task]
async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) {
// Setup sm2
// Repeatedly trigger IRQ 3
let prg = pio_proc::pio_asm!(
".origin 0",
".wrap_target",
"set x,10",
"delay:",
"jmp x-- delay [15]",
"irq 3 [15]",
".wrap",
);
let relocated = RelocatedProgram::new(&prg.program);
sm.write_instr(relocated.origin() as usize, relocated.code());
let pio::Wrap { source, target } = relocated.wrap();
sm.set_wrap(source, target);
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32);
sm.set_enable(true);
loop {
sm.wait_irq(3).await;
info!("IRQ trigged");
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let pio = p.PIO0;
let (_, sm0, sm1, sm2, ..) = pio.split();
spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap();
spawner.spawn(pio_task_sm1(sm1)).unwrap();
spawner.spawn(pio_task_sm2(sm2)).unwrap();
}

View File

@ -0,0 +1,69 @@
#![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::{PioPeripherial, PioStateMachine, ShiftDirection};
use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{pio_instr_util, 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 (_, mut sm, ..) = pio.split();
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.write_instr(relocated.origin() as usize, relocated.code());
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
let pio::Wrap { source, target } = relocated.wrap();
sm.set_wrap(source, target);
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 {
join(
sm.dma_push(dma_out_ref.reborrow(), &dout),
sm.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());
}
}