rp/pio: add set-pin-{values,dirs} convenience functions

these are needed a lot during state machine setup, it makes sense to
provide convenience functions for them.
This commit is contained in:
pennae 2023-05-05 20:45:02 +02:00
parent 41ec4170a5
commit 37b460637d
2 changed files with 61 additions and 8 deletions

View File

@ -13,7 +13,7 @@ use pio::{SideSet, Wrap};
use crate::dma::{Channel, Transfer, Word}; use crate::dma::{Channel, Transfer, Word};
use crate::gpio::sealed::Pin as SealedPin; use crate::gpio::sealed::Pin as SealedPin;
use crate::gpio::{self, AnyPin, Drive, Pull, SlewRate}; use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate};
use crate::pac::dma::vals::TreqSel; use crate::pac::dma::vals::TreqSel;
use crate::relocate::RelocatedProgram; use crate::relocate::RelocatedProgram;
use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt}; use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt};
@ -54,6 +54,14 @@ pub enum ShiftDirection {
Left = 0, Left = 0,
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum Direction {
In = 0,
Out = 1,
}
const RXNEMPTY_MASK: u32 = 1 << 0; const RXNEMPTY_MASK: u32 = 1 << 0;
const TXNFULL_MASK: u32 = 1 << 4; const TXNFULL_MASK: u32 = 1 << 4;
const SMIRQ_MASK: u32 = 1 << 8; const SMIRQ_MASK: u32 = 1 << 8;
@ -533,6 +541,56 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
} }
} }
fn with_paused(&mut self, f: impl FnOnce(&mut Self)) {
let enabled = self.is_enabled();
self.set_enable(false);
let pincfg = unsafe { Self::this_sm().pinctrl().read() };
let execcfg = unsafe { Self::this_sm().execctrl().read() };
unsafe {
Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true));
}
f(self);
unsafe {
Self::this_sm().pinctrl().write_value(pincfg);
Self::this_sm().execctrl().write_value(execcfg);
}
self.set_enable(enabled);
}
/// Sets pin directions. This pauses the current state machine to run `SET` commands
/// and temporarily unsets the `OUT_STICKY` bit.
pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) {
self.with_paused(|sm| {
for pin in pins {
unsafe {
Self::this_sm().pinctrl().write(|w| {
w.set_set_base(pin.pin());
w.set_set_count(1);
});
// SET PINDIRS, (dir)
sm.exec_instr(0b111_00000_100_00000 | dir as u16);
}
}
});
}
/// Sets pin output values. This pauses the current state machine to run
/// `SET` commands and temporarily unsets the `OUT_STICKY` bit.
pub fn set_pins(&mut self, level: Level, pins: &[&Pin<'d, PIO>]) {
self.with_paused(|sm| {
for pin in pins {
unsafe {
Self::this_sm().pinctrl().write(|w| {
w.set_set_base(pin.pin());
w.set_set_count(1);
});
// SET PINS, (dir)
sm.exec_instr(0b111_00000_000_00000 | level as u16);
}
}
});
}
pub fn set_jmp_pin(&mut self, pin: u8) { pub fn set_jmp_pin(&mut self, pin: u8) {
unsafe { unsafe {
Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin)); Self::this_sm().execctrl().modify(|w| w.set_jmp_pin(pin));

View File

@ -7,7 +7,7 @@ use core::fmt::Write;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::dma::{AnyChannel, Channel};
use embassy_rp::peripherals::PIO0; use embassy_rp::peripherals::PIO0;
use embassy_rp::pio::{FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::pio::{Direction, FifoJoin, Pio, PioPin, ShiftDirection, StateMachine};
use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::pwm::{Config, Pwm};
use embassy_rp::relocate::RelocatedProgram; use embassy_rp::relocate::RelocatedProgram;
use embassy_rp::{into_ref, Peripheral, PeripheralRef}; use embassy_rp::{into_ref, Peripheral, PeripheralRef};
@ -115,12 +115,7 @@ impl<'l> HD44780<'l> {
let db6 = common.make_pio_pin(db6); let db6 = common.make_pio_pin(db6);
let db7 = common.make_pio_pin(db7); let db7 = common.make_pio_pin(db7);
sm0.set_set_pins(&[&rs, &rw]); sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]);
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11);
sm0.set_set_pins(&[&e]);
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1);
sm0.set_set_pins(&[&db4, &db5, &db6, &db7]);
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
let relocated = RelocatedProgram::new(&prg.program); let relocated = RelocatedProgram::new(&prg.program);
sm0.use_program(&common.load_program(&relocated), &[&e]); sm0.use_program(&common.load_program(&relocated), &[&e]);