Implement GPIO override (#123)

* Implement GPIO override

Interrupt status, input, output enable and output can be overridden.
See documentation for GPIO0_CTRL.

* Fix override enum names

* Use override_value instead of raw identifier
This commit is contained in:
Henrik Lievonen 2021-09-20 12:38:12 +03:00 committed by GitHub
parent 25e477b73e
commit 904b6f0ab9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 3 deletions

View file

@ -62,3 +62,55 @@ pub enum OutputSlewRate {
/// Slew fast
Fast,
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
/// Interrupt override state.
pub enum InterruptOverride {
/// Don't invert the interrupt.
DontInvert = 0,
/// Invert the interrupt.
Invert = 1,
/// Drive interrupt low.
AlwaysLow = 2,
/// Drive interrupt high.
AlwaysHigh = 3,
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
/// Input override state.
pub enum InputOverride {
/// Don't invert the peripheral input.
DontInvert = 0,
/// Invert the peripheral input.
Invert = 1,
/// Drive peripheral input low.
AlwaysLow = 2,
/// Drive peripheral input high.
AlwaysHigh = 3,
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
/// Output enable override state.
pub enum OutputEnableOverride {
/// Use the original output enable signal from selected peripheral.
DontInvert = 0,
/// Invert the output enable signal from selected peripheral.
Invert = 1,
/// Disable output.
Disable = 2,
/// Enable output.
Enable = 3,
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
/// Output override state.
pub enum OutputOverride {
/// Use the original output signal from selected peripheral.
DontInvert = 0,
/// Invert the output signal from selected peripheral.
Invert = 1,
/// Drive output low.
AlwaysLow = 2,
/// Drive output high.
AlwaysHigh = 3,
}

View file

@ -93,7 +93,10 @@
//! [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
use super::dynpin::{DynDisabled, DynInput, DynOutput, DynPinId, DynPinMode};
use super::{OutputDriveStrength, OutputSlewRate};
use super::{
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
OutputSlewRate,
};
use crate::gpio::reg::RegisterInterface;
use crate::typelevel::{Is, NoneT, Sealed};
use core::convert::Infallible;
@ -517,12 +520,36 @@ where
self.regs.read_slew_rate()
}
/// Set the slew rate for the pin
/// Set the slew rate for the pin.
#[inline]
pub fn set_slew_rate(&mut self, rate: OutputSlewRate) {
self.regs.write_slew_rate(rate)
}
/// Set the interrupt override.
#[inline]
pub fn set_interrupt_override(&mut self, override_value: InterruptOverride) {
self.regs.set_interrupt_override(override_value);
}
/// Set the input override.
#[inline]
pub fn set_input_override(&mut self, override_value: InputOverride) {
self.regs.set_input_override(override_value);
}
/// Set the output enable override.
#[inline]
pub fn set_output_enable_override(&mut self, override_value: OutputEnableOverride) {
self.regs.set_output_enable_override(override_value);
}
/// Set the output override.
#[inline]
pub fn set_output_override(&mut self, override_value: OutputOverride) {
self.regs.set_output_override(override_value);
}
#[inline]
#[allow(clippy::bool_comparison)] // more explicit this way
pub(crate) fn _is_low(&self) -> bool {

View file

@ -1,6 +1,9 @@
// Based heavily on and in some places copied from `atsamd-hal` gpio::v2
use super::dynpin::{DynGroup, DynPinId};
use super::{OutputDriveStrength, OutputSlewRate};
use super::{
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
OutputSlewRate,
};
use crate::gpio::dynpin::{DynDisabled, DynFunction, DynInput, DynOutput, DynPinMode};
use crate::pac;
@ -243,6 +246,42 @@ pub(super) unsafe trait RegisterInterface {
DynGroup::Qspi => qspi_change_mode(num, mode),
}
}
/// Set the interrupt override.
#[inline]
fn set_interrupt_override(&self, override_value: InterruptOverride) {
let num = self.id().num as usize;
unsafe { &(*pac::IO_BANK0::ptr()) }.gpio[num]
.gpio_ctrl
.modify(|_, w| w.irqover().bits(override_value as u8));
}
/// Set the input override.
#[inline]
fn set_input_override(&self, override_value: InputOverride) {
let num = self.id().num as usize;
unsafe { &(*pac::IO_BANK0::ptr()) }.gpio[num]
.gpio_ctrl
.modify(|_, w| w.inover().bits(override_value as u8));
}
/// Set the output enable override.
#[inline]
fn set_output_enable_override(&self, override_value: OutputEnableOverride) {
let num = self.id().num as usize;
unsafe { &(*pac::IO_BANK0::ptr()) }.gpio[num]
.gpio_ctrl
.modify(|_, w| w.oeover().bits(override_value as u8));
}
/// Set the output override.
#[inline]
fn set_output_override(&self, override_value: OutputOverride) {
let num = self.id().num as usize;
unsafe { &(*pac::IO_BANK0::ptr()) }.gpio[num]
.gpio_ctrl
.modify(|_, w| w.outover().bits(override_value as u8));
}
}
#[inline]