mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-24 05:01:31 +11:00
Implements interrupts for GPIO pins.
This commit is contained in:
parent
da89888ccb
commit
dbd4c7dfea
|
@ -63,6 +63,19 @@ pub enum OutputSlewRate {
|
||||||
Fast,
|
Fast,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||||
|
/// Interrupt kind
|
||||||
|
pub enum Interrupt {
|
||||||
|
/// While low
|
||||||
|
LevelLow,
|
||||||
|
/// While high
|
||||||
|
LevelHigh,
|
||||||
|
/// On falling edge
|
||||||
|
EdgeLow,
|
||||||
|
/// On rising edge
|
||||||
|
EdgeHigh,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||||
/// Interrupt override state.
|
/// Interrupt override state.
|
||||||
pub enum InterruptOverride {
|
pub enum InterruptOverride {
|
||||||
|
|
|
@ -94,8 +94,8 @@
|
||||||
//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
|
//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
|
||||||
use super::dynpin::{DynDisabled, DynInput, DynOutput, DynPinId, DynPinMode};
|
use super::dynpin::{DynDisabled, DynInput, DynOutput, DynPinId, DynPinMode};
|
||||||
use super::{
|
use super::{
|
||||||
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
|
InputOverride, Interrupt, InterruptOverride, OutputDriveStrength, OutputEnableOverride,
|
||||||
OutputSlewRate,
|
OutputOverride, OutputSlewRate,
|
||||||
};
|
};
|
||||||
use crate::gpio::reg::RegisterInterface;
|
use crate::gpio::reg::RegisterInterface;
|
||||||
use crate::typelevel::{Is, NoneT, Sealed};
|
use crate::typelevel::{Is, NoneT, Sealed};
|
||||||
|
@ -547,6 +547,42 @@ where
|
||||||
self.regs.write_slew_rate(rate)
|
self.regs.write_slew_rate(rate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear interrupt.
|
||||||
|
#[inline]
|
||||||
|
pub fn clear_interrupt(&mut self, interrupt: Interrupt) {
|
||||||
|
self.regs.clear_interrupt(interrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt status.
|
||||||
|
#[inline]
|
||||||
|
pub fn interrupt_status(&self, interrupt: Interrupt) -> bool {
|
||||||
|
self.regs.interrupt_status(interrupt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is interrupt enabled.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_interrupt_enabled(&self, interrupt: Interrupt) -> bool {
|
||||||
|
self.regs.is_interrupt_enabled(interrupt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable or disable interrupt.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_interrupt_enabled(&self, interrupt: Interrupt, enabled: bool) {
|
||||||
|
self.regs.set_interrupt_enabled(interrupt, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is interrupt forced.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_interrupt_forced(&self, interrupt: Interrupt) -> bool {
|
||||||
|
self.regs.is_interrupt_forced(interrupt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Force or release interrupt.
|
||||||
|
#[inline]
|
||||||
|
pub fn set_interrupt_forced(&self, interrupt: Interrupt, forced: bool) {
|
||||||
|
self.regs.set_interrupt_forced(interrupt, forced);
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the interrupt override.
|
/// Set the interrupt override.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_interrupt_override(&mut self, override_value: InterruptOverride) {
|
pub fn set_interrupt_override(&mut self, override_value: InterruptOverride) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Based heavily on and in some places copied from `atsamd-hal` gpio::v2
|
// Based heavily on and in some places copied from `atsamd-hal` gpio::v2
|
||||||
use super::dynpin::{DynGroup, DynPinId};
|
use super::dynpin::{DynGroup, DynPinId};
|
||||||
use super::{
|
use super::{
|
||||||
InputOverride, InterruptOverride, OutputDriveStrength, OutputEnableOverride, OutputOverride,
|
InputOverride, Interrupt, InterruptOverride, OutputDriveStrength, OutputEnableOverride,
|
||||||
OutputSlewRate,
|
OutputOverride, OutputSlewRate,
|
||||||
};
|
};
|
||||||
use crate::gpio::dynpin::{DynDisabled, DynFunction, DynInput, DynOutput, DynPinMode};
|
use crate::gpio::dynpin::{DynDisabled, DynFunction, DynInput, DynOutput, DynPinMode};
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
@ -255,6 +255,101 @@ pub(super) unsafe trait RegisterInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear interrupt.
|
||||||
|
#[inline]
|
||||||
|
fn clear_interrupt(&self, interrupt: Interrupt) {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.intr0).as_ptr().add(num / 8);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
*reg |= 1 << bit_in_reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt status.
|
||||||
|
#[inline]
|
||||||
|
fn interrupt_status(&self, interrupt: Interrupt) -> bool {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.proc0_ints0)
|
||||||
|
.as_ptr()
|
||||||
|
.add(num / 8 + cpuid as usize * 12);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
(*reg & (1 << bit_in_reg)) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is interrupt enabled.
|
||||||
|
#[inline]
|
||||||
|
fn is_interrupt_enabled(&self, interrupt: Interrupt) -> bool {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.proc0_inte0)
|
||||||
|
.as_ptr()
|
||||||
|
.add(num / 8 + cpuid as usize * 12);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
(*reg & (1 << bit_in_reg)) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable or disable interrupt.
|
||||||
|
#[inline]
|
||||||
|
fn set_interrupt_enabled(&self, interrupt: Interrupt, enabled: bool) {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.proc0_inte0)
|
||||||
|
.as_ptr()
|
||||||
|
.add(num / 8 + cpuid as usize * 12);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
if enabled {
|
||||||
|
*reg |= 1 << bit_in_reg;
|
||||||
|
} else {
|
||||||
|
*reg &= !(1 << bit_in_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is interrupt forced.
|
||||||
|
#[inline]
|
||||||
|
fn is_interrupt_forced(&self, interrupt: Interrupt) -> bool {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.proc0_intf0)
|
||||||
|
.as_ptr()
|
||||||
|
.add(num / 8 + cpuid as usize * 12);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
(*reg & (1 << bit_in_reg)) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Force or release interrupt.
|
||||||
|
#[inline]
|
||||||
|
fn set_interrupt_forced(&self, interrupt: Interrupt, forced: bool) {
|
||||||
|
let num = self.id().num as usize;
|
||||||
|
unsafe {
|
||||||
|
let cpuid = *(pac::SIO::ptr() as *const u32);
|
||||||
|
let io = &(*pac::IO_BANK0::ptr());
|
||||||
|
let reg = (&io.proc0_intf0)
|
||||||
|
.as_ptr()
|
||||||
|
.add(num / 8 + cpuid as usize * 12);
|
||||||
|
let bit_in_reg = num % 8 * 4 + interrupt as usize;
|
||||||
|
if forced {
|
||||||
|
*reg |= 1 << bit_in_reg;
|
||||||
|
} else {
|
||||||
|
*reg &= !(1 << bit_in_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the interrupt override.
|
/// Set the interrupt override.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_interrupt_override(&self, override_value: InterruptOverride) {
|
fn set_interrupt_override(&self, override_value: InterruptOverride) {
|
||||||
|
|
Loading…
Reference in a new issue