move to updated API
This commit is contained in:
@ -102,8 +102,7 @@ impl InputPinFuture {
|
||||
) -> Self {
|
||||
let (waker_group, edge_detection_group) =
|
||||
Self::pin_group_to_waker_and_edge_detection_group(pin.id().port());
|
||||
edge_detection_group[pin.id().offset() as usize]
|
||||
.store(false, core::sync::atomic::Ordering::Relaxed);
|
||||
edge_detection_group[pin.id().offset()].store(false, core::sync::atomic::Ordering::Relaxed);
|
||||
pin.configure_edge_interrupt(edge);
|
||||
#[cfg(feature = "vor1x")]
|
||||
pin.enable_interrupt(InterruptConfig::new(irq, true, true));
|
||||
@ -128,7 +127,7 @@ impl Future for InputPinFuture {
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Self::Output> {
|
||||
let idx = self.id.offset() as usize;
|
||||
let idx = self.id.offset();
|
||||
self.waker_group[idx].register(cx.waker());
|
||||
if self.edge_detection_group[idx].swap(false, core::sync::atomic::Ordering::Relaxed) {
|
||||
return core::task::Poll::Ready(());
|
||||
|
@ -1,5 +1,7 @@
|
||||
pub use embedded_hal::digital::PinState;
|
||||
|
||||
use crate::ioconfig::FilterClkSel;
|
||||
use crate::ioconfig::FilterType;
|
||||
#[cfg(feature = "vor1x")]
|
||||
use crate::{PeripheralSelect, sysconfig::enable_peripheral_clock};
|
||||
|
||||
@ -27,15 +29,28 @@ pub enum InterruptLevel {
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PinId {
|
||||
port: Port,
|
||||
offset: usize,
|
||||
offset: u8,
|
||||
}
|
||||
|
||||
impl PinId {
|
||||
pub const fn new_unchecked(port: Port, offset: usize) -> Self {
|
||||
if offset >= port.max_offset() {
|
||||
panic!("Pin ID construction: offset is out of range");
|
||||
}
|
||||
PinId {
|
||||
port,
|
||||
offset: offset as u8,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn new(port: Port, offset: usize) -> Result<Self, InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { offset, port });
|
||||
}
|
||||
Ok(PinId { port, offset })
|
||||
Ok(PinId {
|
||||
port,
|
||||
offset: offset as u8,
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn port(&self) -> Port {
|
||||
@ -43,7 +58,7 @@ impl PinId {
|
||||
}
|
||||
|
||||
pub const fn offset(&self) -> usize {
|
||||
self.offset
|
||||
self.offset as usize
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +68,15 @@ pub struct LowLevelGpio {
|
||||
id: PinId,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for LowLevelGpio {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("LowLevelGpio")
|
||||
.field("gpio", &self.gpio.port())
|
||||
.field("id", &self.id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl LowLevelGpio {
|
||||
pub fn new(id: PinId) -> Self {
|
||||
LowLevelGpio {
|
||||
@ -78,23 +102,17 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_input_floating(&mut self) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
});
|
||||
self.gpio.modify_dir(|mut dir| {
|
||||
dir &= !(1 << self.id.offset());
|
||||
dir
|
||||
@ -102,24 +120,18 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_input_with_pull(&mut self, pull: Pull) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(pull);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(pull);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(false);
|
||||
config
|
||||
});
|
||||
self.gpio.modify_dir(|mut dir| {
|
||||
dir &= !(1 << self.id.offset());
|
||||
dir
|
||||
@ -127,23 +139,17 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_output_push_pull(&mut self, init_level: PinState) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(false);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
});
|
||||
match init_level {
|
||||
PinState::Low => self.gpio.write_clr_out(self.mask_32()),
|
||||
PinState::High => self.gpio.write_set_out(self.mask_32()),
|
||||
@ -155,24 +161,18 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_output_open_drain(&mut self, init_level: PinState) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(true);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(Pull::Up);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(FunSel::Sel0);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(true);
|
||||
config.set_pull_enable(true);
|
||||
config.set_pull_dir(Pull::Up);
|
||||
config.set_pull_when_output_active(false);
|
||||
config.set_invert_output(false);
|
||||
config.set_input_enable_when_output(true);
|
||||
config
|
||||
});
|
||||
let mask32 = self.mask_32();
|
||||
match init_level {
|
||||
PinState::Low => self.gpio.write_clr_out(mask32),
|
||||
@ -185,22 +185,16 @@ impl LowLevelGpio {
|
||||
}
|
||||
|
||||
pub fn configure_as_peripheral_pin(&mut self, fun_sel: FunSel, pull: Option<Pull>) {
|
||||
unsafe {
|
||||
self.ioconfig.modify_pin_config_unchecked(
|
||||
self.id.port(),
|
||||
self.id.offset(),
|
||||
|mut config| {
|
||||
config.set_funsel(fun_sel);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(pull.is_some());
|
||||
config.set_pull_dir(pull.unwrap_or(Pull::Up));
|
||||
config.set_invert_output(false);
|
||||
config
|
||||
},
|
||||
);
|
||||
}
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_funsel(fun_sel);
|
||||
config.set_io_disable(false);
|
||||
config.set_invert_input(false);
|
||||
config.set_open_drain(false);
|
||||
config.set_pull_enable(pull.is_some());
|
||||
config.set_pull_dir(pull.unwrap_or(Pull::Up));
|
||||
config.set_invert_output(false);
|
||||
config
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -295,6 +289,79 @@ impl LowLevelGpio {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure which edge or level type triggers an interrupt
|
||||
#[inline]
|
||||
pub fn configure_level_interrupt(&mut self, level: InterruptLevel) {
|
||||
let mask32 = self.mask_32();
|
||||
self.gpio.modify_irq_sen(|mut value| {
|
||||
value |= mask32;
|
||||
value
|
||||
});
|
||||
if level == InterruptLevel::Low {
|
||||
self.gpio.modify_irq_evt(|mut value| {
|
||||
value &= !mask32;
|
||||
value
|
||||
});
|
||||
} else {
|
||||
self.gpio.modify_irq_evt(|mut value| {
|
||||
value |= mask32;
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Only useful for input pins
|
||||
#[inline]
|
||||
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||
self.ioconfig.modify_pin_config(self.id, |mut config| {
|
||||
config.set_filter_type(filter);
|
||||
config.set_filter_clk_sel(clksel);
|
||||
config
|
||||
});
|
||||
}
|
||||
|
||||
/// Only useful for output pins.
|
||||
#[inline]
|
||||
pub fn configure_pulse_mode(&mut self, enable: bool, default_state: PinState) {
|
||||
self.gpio.modify_pulse(|mut value| {
|
||||
if enable {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
self.gpio.modify_pulsebase(|mut value| {
|
||||
if default_state == PinState::High {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
/// Only useful for output pins
|
||||
#[inline]
|
||||
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||
self.gpio.modify_delay1(|mut value| {
|
||||
if delay_1 {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
self.gpio.modify_delay2(|mut value| {
|
||||
if delay_2 {
|
||||
value |= 1 << self.id.offset;
|
||||
} else {
|
||||
value &= !(1 << self.id.offset);
|
||||
}
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
/// Configure the IRQSEL peripheral for this particular pin with the given interrupt ID.
|
||||
pub fn configure_irqsel(&mut self, id: va108xx::Interrupt) {
|
||||
@ -304,12 +371,12 @@ impl LowLevelGpio {
|
||||
// Set the correct interrupt number in the IRQSEL register
|
||||
super::Port::A => {
|
||||
irqsel
|
||||
.porta0(self.id().offset() as usize)
|
||||
.porta0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(id as u32) });
|
||||
}
|
||||
super::Port::B => {
|
||||
irqsel
|
||||
.portb0(self.id().offset() as usize)
|
||||
.portb0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(id as u32) });
|
||||
}
|
||||
}
|
||||
@ -324,12 +391,12 @@ impl LowLevelGpio {
|
||||
// Set the correct interrupt number in the IRQSEL register
|
||||
super::Port::A => {
|
||||
irqsel
|
||||
.porta0(self.id().offset() as usize)
|
||||
.porta0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(u32::MAX) });
|
||||
}
|
||||
super::Port::B => {
|
||||
irqsel
|
||||
.portb0(self.id().offset() as usize)
|
||||
.portb0(self.id().offset())
|
||||
.write(|w| unsafe { w.bits(u32::MAX) });
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,22 @@
|
||||
use core::convert::Infallible;
|
||||
|
||||
pub use crate::ioconfig::{FilterClkSel, FilterType, regs::FunSel};
|
||||
pub use embedded_hal::digital::PinState;
|
||||
pub use ll::PinId;
|
||||
pub use ll::{Port, Pull};
|
||||
|
||||
use crate::ioconfig::regs::FunSel;
|
||||
pub use ll::{InterruptEdge, InterruptLevel, PinId, Port, Pull};
|
||||
|
||||
pub mod asynch;
|
||||
pub mod ll;
|
||||
pub mod regs;
|
||||
|
||||
pub trait PinMarker {
|
||||
pub trait PinIdProvider {
|
||||
const ID: ll::PinId;
|
||||
}
|
||||
|
||||
pub struct Pin<I: PinMarker> {
|
||||
pub struct Pin<I: PinIdProvider> {
|
||||
phantom: core::marker::PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I: PinMarker> Pin<I> {
|
||||
impl<I: PinIdProvider> Pin<I> {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
@ -27,10 +25,11 @@ impl<I: PinMarker> Pin<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Output(ll::LowLevelGpio);
|
||||
|
||||
impl Output {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>, init_level: PinState) -> Self {
|
||||
pub fn new<I: PinIdProvider>(_pin: Pin<I>, init_level: PinState) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_output_push_pull(init_level);
|
||||
Output(ll)
|
||||
@ -65,6 +64,12 @@ impl Output {
|
||||
pub fn is_set_low(&self) -> bool {
|
||||
self.0.is_set_low()
|
||||
}
|
||||
|
||||
/// Toggle pin output with dedicated HW feature.
|
||||
#[inline]
|
||||
pub fn toggle(&mut self) {
|
||||
self.0.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal::digital::ErrorType for Output {
|
||||
@ -99,16 +104,17 @@ impl embedded_hal::digital::StatefulOutputPin for Output {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Input(ll::LowLevelGpio);
|
||||
|
||||
impl Input {
|
||||
pub fn new_floating<I: PinMarker>(_pin: Pin<I>) -> Self {
|
||||
pub fn new_floating<I: PinIdProvider>(_pin: Pin<I>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_floating();
|
||||
Input(ll)
|
||||
}
|
||||
|
||||
pub fn new_with_pull<I: PinMarker>(_pin: Pin<I>, pull: Pull) -> Self {
|
||||
pub fn new_with_pull<I: PinIdProvider>(_pin: Pin<I>, pull: Pull) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_with_pull(pull);
|
||||
Input(ll)
|
||||
@ -126,10 +132,25 @@ impl Input {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_edge_interrupt(&mut self, edge: ll::InterruptEdge) {
|
||||
pub fn configure_edge_interrupt(&mut self, edge: InterruptEdge) {
|
||||
self.0.configure_edge_interrupt(edge);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_level_interrupt(&mut self, edge: InterruptLevel) {
|
||||
self.0.configure_level_interrupt(edge);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_delay(&mut self, delay_1: bool, delay_2: bool) {
|
||||
self.0.configure_delay(delay_1, delay_2);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn configure_filter_type(&mut self, filter: FilterType, clksel: FilterClkSel) {
|
||||
self.0.configure_filter_type(filter, clksel);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_low(&self) -> bool {
|
||||
self.0.is_low()
|
||||
@ -155,6 +176,7 @@ impl embedded_hal::digital::InputPin for Input {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PinMode {
|
||||
InputFloating,
|
||||
InputWithPull(Pull),
|
||||
@ -172,13 +194,14 @@ impl PinMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Flex {
|
||||
ll: ll::LowLevelGpio,
|
||||
mode: PinMode,
|
||||
}
|
||||
|
||||
impl Flex {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>) -> Self {
|
||||
pub fn new<I: PinIdProvider>(_pin: Pin<I>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_input_floating();
|
||||
Flex {
|
||||
@ -287,12 +310,22 @@ pub struct IoPeriphPin {
|
||||
}
|
||||
|
||||
impl IoPeriphPin {
|
||||
pub fn new<I: PinMarker>(_pin: Pin<I>, fun_sel: FunSel, pull: Option<Pull>) -> Self {
|
||||
pub fn new_with_pin<I: PinIdProvider>(
|
||||
_pin: Pin<I>,
|
||||
fun_sel: FunSel,
|
||||
pull: Option<Pull>,
|
||||
) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(I::ID);
|
||||
ll.configure_as_peripheral_pin(fun_sel, pull);
|
||||
IoPeriphPin { ll, fun_sel }
|
||||
}
|
||||
|
||||
pub fn new(pin_id: PinId, fun_sel: FunSel, pull: Option<Pull>) -> Self {
|
||||
let mut ll = ll::LowLevelGpio::new(pin_id);
|
||||
ll.configure_as_peripheral_pin(fun_sel, pull);
|
||||
IoPeriphPin { ll, fun_sel }
|
||||
}
|
||||
|
||||
pub fn port(&self) -> Port {
|
||||
self.ll.port()
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
pub use regs::{FilterClkSel, FilterType};
|
||||
|
||||
pub mod regs;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{InvalidOffsetError, NUM_PORT_A, NUM_PORT_B};
|
||||
use crate::{NUM_PORT_A, NUM_PORT_B, gpio::PinId};
|
||||
#[cfg(feature = "vor4x")]
|
||||
use crate::{NUM_PORT_DEFAULT, NUM_PORT_G};
|
||||
|
||||
@ -73,7 +73,7 @@ pub struct Config {
|
||||
#[bit(6, rw)]
|
||||
invert_input: bool,
|
||||
#[bits(3..=5, rw)]
|
||||
filter_sel: FilterClkSel,
|
||||
filter_clk_sel: FilterClkSel,
|
||||
#[bits(0..=2, rw)]
|
||||
filter_type: Option<FilterType>,
|
||||
}
|
||||
@ -134,24 +134,9 @@ impl IoConfig {
|
||||
}
|
||||
|
||||
impl MmioIoConfig<'_> {
|
||||
pub fn read_pin_config(
|
||||
&self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
) -> Result<Config, InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
Ok(unsafe { self.read_pin_config_unchecked(port, offset) })
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn read_pin_config_unchecked(&self, port: crate::Port, offset: usize) -> Config {
|
||||
match port {
|
||||
pub fn read_pin_config(&self, id: PinId) -> Config {
|
||||
let offset = id.offset();
|
||||
match id.port() {
|
||||
crate::Port::A => unsafe { self.read_port_a_unchecked(offset) },
|
||||
crate::Port::B => unsafe { self.read_port_b_unchecked(offset) },
|
||||
#[cfg(feature = "vor4x")]
|
||||
@ -167,63 +152,14 @@ impl MmioIoConfig<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_pin_config<F: FnOnce(Config) -> Config>(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
f: F,
|
||||
) -> Result<(), InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
unsafe { self.modify_pin_config_unchecked(port, offset, f) };
|
||||
Ok(())
|
||||
pub fn modify_pin_config<F: FnOnce(Config) -> Config>(&mut self, id: PinId, f: F) {
|
||||
let config = self.read_pin_config(id);
|
||||
self.write_pin_config(id, f(config))
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn modify_pin_config_unchecked<F: FnOnce(Config) -> Config>(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
mut f: F,
|
||||
) {
|
||||
unsafe {
|
||||
let config = self.read_pin_config_unchecked(port, offset);
|
||||
self.write_pin_config_unchecked(port, offset, f(config))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_pin_config(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
config: Config,
|
||||
) -> Result<(), InvalidOffsetError> {
|
||||
if offset >= port.max_offset() {
|
||||
return Err(InvalidOffsetError { port, offset });
|
||||
}
|
||||
unsafe {
|
||||
self.write_pin_config_unchecked(port, offset, config);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function does NOT perform any bounds checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this function with an invalid offset can lead to undefined behaviour.
|
||||
pub unsafe fn write_pin_config_unchecked(
|
||||
&mut self,
|
||||
port: crate::Port,
|
||||
offset: usize,
|
||||
config: Config,
|
||||
) {
|
||||
match port {
|
||||
pub fn write_pin_config(&mut self, id: PinId, config: Config) {
|
||||
let offset = id.offset();
|
||||
match id.port() {
|
||||
crate::Port::A => unsafe { self.write_port_a_unchecked(offset, config) },
|
||||
crate::Port::B => unsafe { self.write_port_b_unchecked(offset, config) },
|
||||
#[cfg(feature = "vor4x")]
|
||||
|
0
vorago-shared-periphs/src/pins.rs
Normal file
0
vorago-shared-periphs/src/pins.rs
Normal file
@ -15,3 +15,29 @@ pub fn disable_peripheral_clock(clock: crate::PeripheralSelect) {
|
||||
.peripheral_clk_enable()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << clock as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn assert_peripheral_reset(periph_sel: crate::PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn deassert_peripheral_reset(periph_sel: crate::PeripheralSelect) {
|
||||
let syscfg = unsafe { va108xx::Sysconfig::steal() };
|
||||
syscfg
|
||||
.peripheral_reset()
|
||||
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << periph_sel as u8)) });
|
||||
}
|
||||
|
||||
#[cfg(feature = "vor1x")]
|
||||
#[inline]
|
||||
pub fn reset_peripheral_for_cycles(periph_sel: crate::PeripheralSelect, cycles: u32) {
|
||||
assert_peripheral_reset(periph_sel);
|
||||
cortex_m::asm::delay(cycles);
|
||||
deassert_peripheral_reset(periph_sel);
|
||||
}
|
||||
|
Reference in New Issue
Block a user